@hubspot/cli 4.2.0 → 4.2.1-beta.1

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.
@@ -55,7 +55,6 @@ exports.handler = async options => {
55
55
  accountConfig.sandboxAccountType &&
56
56
  accountConfig.sandboxAccountType !== null
57
57
  ) {
58
- trackCommandUsage('sandbox-create', { successful: false }, accountId);
59
58
  logger.error(
60
59
  i18n(`${i18nKey}.failure.creatingWithinSandbox`, {
61
60
  sandboxType: getSandboxTypeAsString(accountConfig.sandboxAccountType),
@@ -73,7 +72,6 @@ exports.handler = async options => {
73
72
  typePrompt = await sandboxTypePrompt();
74
73
  } else {
75
74
  logger.error(i18n(`${i18nKey}.failure.optionMissing.type`));
76
- trackCommandUsage('sandbox-create', { successful: false }, accountId);
77
75
  process.exit(EXIT_CODES.ERROR);
78
76
  }
79
77
  }
@@ -100,7 +98,6 @@ exports.handler = async options => {
100
98
  } else {
101
99
  logErrorInstance(err);
102
100
  }
103
- trackCommandUsage('sandbox-create', { successful: false }, accountId);
104
101
  process.exit(EXIT_CODES.ERROR);
105
102
  }
106
103
 
@@ -109,7 +106,6 @@ exports.handler = async options => {
109
106
  namePrompt = await sandboxNamePrompt(sandboxType);
110
107
  } else {
111
108
  logger.error(i18n(`${i18nKey}.failure.optionMissing.name`));
112
- trackCommandUsage('sandbox-create', { successful: false }, accountId);
113
109
  process.exit(EXIT_CODES.ERROR);
114
110
  }
115
111
  }
@@ -196,7 +192,6 @@ exports.handler = async options => {
196
192
  uiFeatureHighlight(highlightItems);
197
193
  process.exit(EXIT_CODES.SUCCESS);
198
194
  } catch (error) {
199
- trackCommandUsage('sandbox-create', { successful: false }, accountId);
200
195
  // Errors are logged in util functions
201
196
  process.exit(EXIT_CODES.ERROR);
202
197
  }
@@ -44,6 +44,8 @@ exports.handler = async options => {
44
44
  const { account, force } = options;
45
45
  const config = getConfig();
46
46
 
47
+ trackCommandUsage('sandbox-delete', null);
48
+
47
49
  let accountPrompt;
48
50
  if (!account) {
49
51
  if (!force) {
@@ -68,8 +70,6 @@ exports.handler = async options => {
68
70
  const isDefaultAccount =
69
71
  sandboxAccountId === getAccountId(config.defaultPortal);
70
72
 
71
- trackCommandUsage('sandbox-delete', null, sandboxAccountId);
72
-
73
73
  const baseUrl = getHubSpotWebsiteOrigin(
74
74
  getValidEnv(getEnv(sandboxAccountId))
75
75
  );
@@ -168,12 +168,6 @@ exports.handler = async options => {
168
168
  } catch (err) {
169
169
  debugErrorAndContext(err);
170
170
 
171
- trackCommandUsage(
172
- 'sandbox-delete',
173
- { successful: false },
174
- sandboxAccountId
175
- );
176
-
177
171
  if (err instanceof HubSpotAuthError) {
178
172
  // Intercept invalid key error
179
173
  // This command uses the parent portal PAK to delete a sandbox, so we must specify which account needs a new key
@@ -44,7 +44,11 @@ exports.handler = async options => {
44
44
  const accountConfig = getAccountConfig(accountId);
45
45
  const env = getValidEnv(getEnv(accountId));
46
46
 
47
- trackCommandUsage('sandbox-sync', null, accountId);
47
+ trackCommandUsage(
48
+ 'sandbox-sync',
49
+ { type: accountConfig.sandboxAccountType },
50
+ accountId
51
+ );
48
52
 
49
53
  if (
50
54
  // Check if default account is a sandbox, otherwise exit
@@ -53,7 +57,6 @@ exports.handler = async options => {
53
57
  accountConfig.sandboxAccountType === null
54
58
  ) {
55
59
  logger.error(i18n(`${i18nKey}.failure.notSandbox`));
56
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
57
60
  process.exit(EXIT_CODES.ERROR);
58
61
  }
59
62
 
@@ -66,7 +69,6 @@ exports.handler = async options => {
66
69
  sandboxName: getAccountName(accountConfig),
67
70
  })
68
71
  );
69
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
70
72
  process.exit(EXIT_CODES.ERROR);
71
73
  }
72
74
 
@@ -98,7 +100,6 @@ exports.handler = async options => {
98
100
  } else {
99
101
  logErrorInstance(error);
100
102
  }
101
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
102
103
  process.exit(EXIT_CODES.ERROR);
103
104
  }
104
105
 
@@ -128,7 +129,6 @@ exports.handler = async options => {
128
129
  },
129
130
  ]);
130
131
  if (!confirmed) {
131
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
132
132
  process.exit(EXIT_CODES.SUCCESS);
133
133
  }
134
134
  }
@@ -166,13 +166,11 @@ exports.handler = async options => {
166
166
  },
167
167
  ]);
168
168
  if (!confirmed) {
169
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
170
169
  process.exit(EXIT_CODES.SUCCESS);
171
170
  }
172
171
  }
173
172
  } else {
174
173
  logger.error('Sync must be run in a sandbox account.');
175
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
176
174
  process.exit(EXIT_CODES.ERROR);
177
175
  }
178
176
 
@@ -193,7 +191,6 @@ exports.handler = async options => {
193
191
 
194
192
  process.exit(EXIT_CODES.SUCCESS);
195
193
  } catch (error) {
196
- trackCommandUsage('sandbox-sync', { successful: false }, accountId);
197
194
  process.exit(EXIT_CODES.ERROR);
198
195
  }
199
196
  };
@@ -1,5 +1,4 @@
1
- const Spinnies = require('spinnies');
2
-
1
+ const SpinniesManager = require('../../lib/SpinniesManager');
3
2
  const {
4
3
  addConfigOptions,
5
4
  addAccountOptions,
@@ -31,8 +30,9 @@ exports.handler = async options => {
31
30
 
32
31
  trackCommandUsage('validate', null, accountId);
33
32
 
34
- const spinnies = new Spinnies();
35
- spinnies.add('marketplaceValidation', {
33
+ SpinniesManager.init();
34
+
35
+ SpinniesManager.add('marketplaceValidation', {
36
36
  text: i18n(`${i18nKey}.logs.validatingTheme`, {
37
37
  path: src,
38
38
  }),
@@ -42,7 +42,7 @@ exports.handler = async options => {
42
42
  const validationId = await kickOffValidation(accountId, assetType, src);
43
43
  await pollForValidationFinish(accountId, validationId);
44
44
 
45
- spinnies.remove('marketplaceValidation');
45
+ SpinniesManager.remove('marketplaceValidation');
46
46
 
47
47
  const validationResults = await fetchValidationResults(
48
48
  accountId,
package/lang/en.lyaml CHANGED
@@ -448,8 +448,7 @@ en:
448
448
  dev:
449
449
  describe: "Start local dev for the current project"
450
450
  logs:
451
- betaMessage: "{{#yellow}}{{#bold}}[beta]{{/bold}}{{/yellow}} HubSpot projects local development"
452
- learnMoreLink: "Learn more about the projects local dev server"
451
+ betaMessage: "HubSpot projects local development"
453
452
  nonSandboxWarning: "Testing in a sandbox is strongly recommended. To switch the target account, select an option below or run {{#bold}}`hs accounts use`{{/bold}} before running the command again."
454
453
  placeholderAccountSelection: "Using default account as target account (for now)"
455
454
  projectMustExistExplanation: "The project {{ projectName }} does not exist in the target account {{ accountIdentifier}}. This command requires the project to exist in the target account."
@@ -464,8 +463,8 @@ en:
464
463
  createProject: "Create new project {{ projectName}} in {{#bold}}[{{ accountIdentifier }}]{{/bold}}?"
465
464
  targetNonSandbox: "Continue testing in a non-sandbox account?"
466
465
  options:
467
- port:
468
- describe: "The port that the running server will listen on"
466
+ extension:
467
+ describe: "The extension that you would like to run locally"
469
468
  errors:
470
469
  noProjectConfig: "No project detected. Please run this command again from a project directory."
471
470
  projectLockedError: "Your project is locked. This may mean that another user is running the {{#bold}}`hs project dev`{{/bold}} command for this project. If this is you, unlock the project in Projects UI."
@@ -849,7 +848,20 @@ en:
849
848
  lib:
850
849
  DevServerManager:
851
850
  portConflict: "The port {{ port }} is already in use."
851
+ LocalDevManagerV2:
852
+ failedToInitialize: "Missing required arguments to initialize Local Dev"
853
+ betaMessage: "HubSpot projects local development"
854
+ running: "Running {{#bold}}{{ projectName }}{{/bold}} locally on {{ accountIdentifier }}, waiting for changes ..."
855
+ quitHelper: "Press {{#bold}}'q'{{/bold}} to stop the local dev server"
856
+ viewInHubSpotLink: "View in HubSpot"
857
+ exitingStart: "Stopping local dev server ..."
858
+ exitingSucceed: "Successfully exited"
859
+ exitingFail: "Failed to cleanup before exiting"
860
+ devServer:
861
+ cleanupError: "Failed to cleanup local dev server: {{ message }}"
862
+ startError: "Failed to start local dev server: {{ message }}"
852
863
  LocalDevManager:
864
+ failedToInitialize: "Missing required arguments to initialize Local Dev Manager"
853
865
  exitingStart: "Stopping local dev server ..."
854
866
  exitingSucceed: "Successfully exited"
855
867
  exitingFail: "Failed to clean up before exiting"
@@ -857,16 +869,16 @@ en:
857
869
  cancelledFromUI: "The dev process has been cancelled from the UI. Any changes made since cancelling have not been uploaded. To resume dev mode, rerun {{#yellow}}`hs project dev`{{/yellow}}."
858
870
  header:
859
871
  betaMessage: "{{#yellow}}{{#bold}}[beta]{{/bold}}{{/yellow}} HubSpot projects local development"
860
- learnMoreLink: "Learn more about the projects local dev server"
861
- running: "Running {{ projectName}} locally on {{ accountIdentifier }}, waiting for changes ..."
872
+ running: "Running {{#bold}}{{ projectName }}{{/bold}} locally on {{ accountIdentifier }}, waiting for changes ..."
862
873
  quitHelper: "Press {{#bold}}'q'{{/bold}} to stop the local dev server"
863
874
  viewInHubSpotLink: "View in HubSpot"
864
875
  status:
865
876
  clean: "{{#bold}}Status:{{/bold}} {{#green}}Everything up to date{{/green}}"
877
+ buildError: "{{#bold}}Status:{{/bold}} {{#red}}Latest build failed{{/red}}"
878
+ deployError: "{{#bold}}Status:{{/bold}} {{#red}}Latest deploy failed{{/red}}"
866
879
  uploadPending: "{{#bold}}Status:{{/bold}} {{#yellow}}Upload is pending{{/yellow}}"
867
880
  noUploadsAllowed: "{{#bold}}Status:{{/bold}} {{#red}}Change requires upload, but uploads are not allowed{{/red}}"
868
881
  manualUploadRequired: "{{#bold}}Status:{{/bold}} {{#yellow}}Change requires manual upload{{/yellow}}"
869
- supportedChange: "{{#bold}}Status:{{/bold}} {{#green}}Change handled by local dev server{{/green}}"
870
882
  manualUpload: "{{#bold}}Status:{{/bold}} {{#green}}Manually uploading pending changes{{/green}}"
871
883
  upload:
872
884
  noUploadsAllowed: "The change to {{ filePath }} requires an upload, but the CLI cannot upload to a project that is using a github integration."
@@ -876,6 +888,8 @@ en:
876
888
  manualUploadExplanation1: "{{#yellow}}> Dev server is running on a {{#bold}}non-sandbox account{{/bold}}.{{/yellow}}"
877
889
  manualUploadExplanation2: "{{#yellow}}> Uploading changes may overwrite production data.{{/yellow}}"
878
890
  manualUploadPrompt: "? Manually upload and deploy project? {{#green}}Y/n{{/green}}"
891
+ extensionNotAllowed: "Extension not allowed for {{ filePath }}"
892
+ fileIgnored: "File ignored: {{ filePath }}"
879
893
  uploadingAddChange: "[INFO] Uploading {{ filePath }}"
880
894
  uploadedAddChange: "[INFO] Uploaded {{ filePath }}"
881
895
  uploadingRemoveChange: "[INFO] Removing {{ filePath }}"
@@ -883,6 +897,9 @@ en:
883
897
  uploadingChanges: "{{#bold}}Building #{{ buildId }} and deploying recent changes on {{ accountIdentifier }}{{/bold}}"
884
898
  uploadedChangesSucceeded: "{{#bold}}Built #{{ buildId }} and deployed recent changes on {{ accountIdentifier }}{{/bold}}"
885
899
  uploadedChangesFailed: "{{#bold}}Failed to build #{{ buildId }} and deploy recent changes on {{ accountIdentifier }}{{/bold}}"
900
+ devServer:
901
+ startError: "{{#red}}[ERROR]{{/red}} Failed to start local dev server"
902
+ cleanupError: "{{#red}}[ERROR]{{/red}} Failed to cleanup local dev server"
886
903
  projects:
887
904
  uploadProjectFiles:
888
905
  add: "Uploading {{#bold}}{{ projectName }}{{/bold}} project files to {{ accountIdentifier }}"
@@ -909,6 +926,7 @@ en:
909
926
  feedbackHeader: "We'd love to hear your feedback!"
910
927
  feedbackMessage: "How are you liking the new projects and developer tools? \n > Run `{{#yellow}}hs feedback{{/yellow}}` to let us know what you think!\n"
911
928
  ui:
929
+ betaTag: "{{#bold}}[beta]{{/bold}}"
912
930
  betaWarning:
913
931
  header: "{{#yellow}}***************************** WARNING ****************************{{/yellow}}"
914
932
  footer: "{{#yellow}}******************************************************************{{/yellow}}"
@@ -1,8 +1,9 @@
1
1
  const express = require('express');
2
2
  const bodyParser = require('body-parser');
3
3
  const cors = require('cors');
4
- const { i18n } = require('./lang');
4
+ const { walk } = require('@hubspot/cli-lib/lib/walk');
5
5
  const { getProjectDetailUrl } = require('./projects');
6
+ const { i18n } = require('./lang');
6
7
  const { EXIT_CODES } = require('./enums/exitCodes');
7
8
  const { logger } = require('@hubspot/cli-lib/logger');
8
9
 
@@ -12,10 +13,21 @@ const DEFAULT_PORT = 8080;
12
13
 
13
14
  class DevServerManager {
14
15
  constructor() {
16
+ this.initialized = false;
15
17
  this.server = null;
18
+ this.path = null;
16
19
  this.devServers = {};
17
20
  }
18
21
 
22
+ safeLoadServer() {
23
+ try {
24
+ const { DevModeInterface } = require('@hubspot/ui-extensions-dev-server');
25
+ this.devServers['uie'] = DevModeInterface;
26
+ } catch (e) {
27
+ logger.debug('Failed to load dev server interface: ', e);
28
+ }
29
+ }
30
+
19
31
  async iterateDevServers(callback) {
20
32
  const serverKeys = Object.keys(this.devServers);
21
33
 
@@ -26,7 +38,17 @@ class DevServerManager {
26
38
  }
27
39
  }
28
40
 
29
- async start({ projectConfig, accountId, port }) {
41
+ generateURL(path) {
42
+ return this.path ? `${this.path}/${path}` : null;
43
+ }
44
+
45
+ async start({
46
+ accountId,
47
+ debug,
48
+ extension,
49
+ projectConfig,
50
+ projectSourceDir,
51
+ }) {
30
52
  const app = express();
31
53
 
32
54
  // Install Middleware
@@ -46,46 +68,49 @@ class DevServerManager {
46
68
  app.get('/hs/project', (req, res) => {
47
69
  res.redirect(getProjectDetailUrl(projectConfig.name, accountId));
48
70
  });
49
- app.get('/hs/learnMore', (req, res) => {
50
- //TODO link to docs
51
- res.redirect(getProjectDetailUrl(projectConfig.name, accountId));
52
- });
53
-
54
- // Initialize component servers
55
- await this.iterateDevServers(async (serverInterface, serverKey) => {
56
- if (serverInterface.start) {
57
- const serverApp = await serverInterface.start(serverKey);
58
- app.use(`/${serverKey}`, serverApp);
59
- }
60
- });
61
71
 
62
72
  // Start server
63
- this.server = app.listen(port || DEFAULT_PORT).on('error', err => {
73
+ this.server = await app.listen(DEFAULT_PORT).on('error', err => {
64
74
  if (err.code === 'EADDRINUSE') {
65
- logger.error(
66
- i18n(`${i18nKey}.portConflict`, { port: port || DEFAULT_PORT })
67
- );
75
+ logger.error(i18n(`${i18nKey}.portConflict`, { port: DEFAULT_PORT }));
68
76
  logger.log();
69
77
  process.exit(EXIT_CODES.ERROR);
70
78
  }
71
79
  });
72
80
 
73
- return this.server.address()
81
+ const projectFiles = await walk(projectSourceDir);
82
+
83
+ // Initialize component servers
84
+ await this.iterateDevServers(async serverInterface => {
85
+ if (serverInterface.start) {
86
+ await serverInterface.start({
87
+ accountId,
88
+ debug,
89
+ extension,
90
+ projectConfig,
91
+ projectFiles,
92
+ });
93
+ }
94
+ });
95
+
96
+ this.path = this.server.address()
74
97
  ? `http://localhost:${this.server.address().port}`
75
98
  : null;
76
- }
77
99
 
78
- async notify() {
79
- return { uploadRequired: true };
80
- }
81
-
82
- async execute() {
83
- return;
100
+ this.initialized = true;
84
101
  }
85
102
 
86
103
  async cleanup() {
87
- if (this.server) {
88
- await this.server.close();
104
+ if (this.initialized) {
105
+ await this.iterateDevServers(async serverInterface => {
106
+ if (serverInterface.cleanup) {
107
+ await serverInterface.cleanup();
108
+ }
109
+ });
110
+
111
+ if (this.server) {
112
+ await this.server.close();
113
+ }
89
114
  }
90
115
  }
91
116
  }