@hubspot/cli 5.0.2 → 5.0.3-beta.2

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.
Files changed (69) hide show
  1. package/commands/accounts/clean.js +2 -3
  2. package/commands/accounts/info.js +2 -2
  3. package/commands/accounts/list.js +2 -2
  4. package/commands/accounts/remove.js +1 -1
  5. package/commands/accounts/rename.js +1 -1
  6. package/commands/auth.js +3 -2
  7. package/commands/cms/convertFields.js +11 -5
  8. package/commands/cms/lighthouseScore.js +1 -1
  9. package/commands/config/set/allowUsageTracking.js +1 -1
  10. package/commands/config/set/defaultMode.js +1 -1
  11. package/commands/config/set/httpTimeout.js +1 -1
  12. package/commands/customObject/create.js +1 -1
  13. package/commands/customObject/schema/create.js +6 -3
  14. package/commands/customObject/schema/fetch-all.js +7 -2
  15. package/commands/customObject/schema/fetch.js +6 -3
  16. package/commands/customObject/schema/update.js +6 -3
  17. package/commands/filemanager/upload.js +2 -2
  18. package/commands/functions/list.js +1 -1
  19. package/commands/hubdb/create.js +1 -1
  20. package/commands/init.js +14 -5
  21. package/commands/lint.js +1 -1
  22. package/commands/project/add.js +1 -1
  23. package/commands/project/create.js +1 -1
  24. package/commands/project/deploy.js +1 -1
  25. package/commands/project/dev.js +11 -5
  26. package/commands/project/download.js +10 -3
  27. package/commands/project/listBuilds.js +2 -2
  28. package/commands/project/logs.js +3 -3
  29. package/commands/project/upload.js +1 -1
  30. package/commands/sandbox/create.js +3 -3
  31. package/commands/sandbox/delete.js +7 -5
  32. package/commands/sandbox/sync.js +3 -3
  33. package/commands/upload.js +3 -3
  34. package/commands/watch.js +1 -1
  35. package/lang/en.lyaml +12 -2
  36. package/lib/DevServerManager.js +14 -0
  37. package/lib/LocalDevManager.js +17 -12
  38. package/lib/__tests__/commonOpts.js +3 -3
  39. package/lib/__tests__/projects.test.js +144 -0
  40. package/lib/__tests__/validation.js +2 -1
  41. package/lib/commonOpts.js +2 -3
  42. package/lib/errorHandlers/apiErrors.js +1 -1
  43. package/lib/errorHandlers/standardErrors.js +14 -2
  44. package/lib/filesystem.js +1 -1
  45. package/lib/links.js +3 -3
  46. package/lib/logCallbacks.js +14 -0
  47. package/lib/oauth.js +2 -2
  48. package/lib/process.js +24 -6
  49. package/lib/projectStructure.js +8 -2
  50. package/lib/projects.js +39 -9
  51. package/lib/projectsWatch.js +2 -2
  52. package/lib/prompts/accountsPrompt.js +1 -1
  53. package/lib/prompts/createProjectPrompt.js +1 -1
  54. package/lib/prompts/downloadProjectPrompt.js +1 -1
  55. package/lib/prompts/enterAccountNamePrompt.js +1 -1
  56. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  57. package/lib/prompts/projectDevTargetAccountPrompt.js +2 -2
  58. package/lib/prompts/sandboxesPrompt.js +1 -1
  59. package/lib/prompts/setAsDefaultAccountPrompt.js +1 -1
  60. package/lib/prompts/uploadPrompt.js +1 -1
  61. package/lib/sandbox-create.js +4 -4
  62. package/lib/sandbox-sync.js +3 -3
  63. package/lib/sandboxes.js +9 -9
  64. package/lib/schema.js +1 -0
  65. package/lib/ui.js +1 -1
  66. package/lib/upload.js +10 -4
  67. package/lib/usageTracking.js +6 -6
  68. package/lib/validation.js +10 -11
  69. package/package.json +6 -6
@@ -7,7 +7,7 @@ const {
7
7
  getCwd,
8
8
  convertToUnixPath,
9
9
  isAllowedExtension,
10
- } = require('@hubspot/cli-lib/path');
10
+ } = require('@hubspot/local-dev-lib/path');
11
11
  const { logger } = require('@hubspot/cli-lib/logger');
12
12
  const {
13
13
  ApiErrorContext,
@@ -15,7 +15,7 @@ const {
15
15
  } = require('../lib/errorHandlers/apiErrors');
16
16
  const { logErrorInstance } = require('../lib/errorHandlers/standardErrors');
17
17
  const { validateSrcAndDestPaths } = require('@hubspot/cli-lib/modules');
18
- const { shouldIgnoreFile } = require('@hubspot/cli-lib/ignoreRules');
18
+ const { shouldIgnoreFile } = require('@hubspot/local-dev-lib/ignoreRules');
19
19
 
20
20
  const {
21
21
  addConfigOptions,
@@ -33,7 +33,7 @@ const { getUploadableFileList } = require('../lib/upload');
33
33
  const {
34
34
  getThemePreviewUrl,
35
35
  getThemeJSONPath,
36
- } = require('@hubspot/cli-lib/lib/files');
36
+ } = require('@hubspot/local-dev-lib/cms/themes');
37
37
  const { i18n } = require('../lib/lang');
38
38
  const i18nKey = 'cli.commands.upload';
39
39
  const { EXIT_CODES } = require('../lib/enums/exitCodes');
package/commands/watch.js CHANGED
@@ -2,7 +2,7 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
4
  const { watch } = require('@hubspot/cli-lib');
5
- const { getCwd } = require('@hubspot/cli-lib/path');
5
+ const { getCwd } = require('@hubspot/local-dev-lib/path');
6
6
  const { logger } = require('@hubspot/cli-lib/logger');
7
7
 
8
8
  const {
package/lang/en.lyaml CHANGED
@@ -631,6 +631,9 @@ en:
631
631
  describe: "The name of the project to download"
632
632
  dest:
633
633
  describe: "Destination folder for the project"
634
+ archiveLogCallbacks:
635
+ init: "Extracting project source..."
636
+ copy: "Copying project source..."
634
637
  open:
635
638
  describe: "Open the specified project's details page in the browser"
636
639
  options:
@@ -885,6 +888,8 @@ en:
885
888
  options:
886
889
  describe: "Options to pass to javascript fields files"
887
890
  lib:
891
+ process:
892
+ exitDebug: "Attempting to gracefully exit. Triggered by {{ signal }}"
888
893
  DevServerManager:
889
894
  portConflict: "The port {{ port }} is already in use."
890
895
  notInitialized: "The Dev Server Manager must be initialized before it is started."
@@ -917,6 +922,8 @@ en:
917
922
  startError: "Failed to start local dev server: {{ message }}"
918
923
  fileChangeError: "Failed to notify local dev server of file change: {{ message }}"
919
924
  projects:
925
+ config:
926
+ 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\""
920
927
  uploadProjectFiles:
921
928
  add: "Uploading {{#bold}}{{ projectName }}{{/bold}} project files to {{ accountIdentifier }}"
922
929
  fail: "Failed to upload {{#bold}}{{ projectName }}{{/bold}} project files to {{ accountIdentifier }}"
@@ -945,8 +952,10 @@ en:
945
952
  feedbackHeader: "We'd love to hear your feedback!"
946
953
  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"
947
954
  showPlatformVersionWarning:
948
- noPlatformVersion: "No platformVersion found in hsproject.json. Falling back to version \"{{ defaultVersion }}\"."
949
- noPlatformVersionAlt: "No platformVersion found in hsproject.json. Falling back to default version."
955
+ docsLink: "Projects platform versioning (BETA)"
956
+ noPlatformVersion: "No platformVersion found in hsproject.json. Falling back to version \"{{ defaultVersion }}\". Starting Mar 31, 2024, new project builds without a specified version will no longer be supported. To update your project to the latest version, see {{ docsLink }}."
957
+ noPlatformVersionAlt: "No platformVersion found in hsproject.json. Falling back to default version. Starting Mar 31, 2024, new project builds without a specified version will no longer be supported. To update your project to the latest version, see {{ docsLink }}."
958
+ deprecatedVersion: "Starting Mar 31, 2024, new project builds with platformVersion 2023.1 or unspecified versions will no longer be supported. It's recommended that you update your project to the latest version. For more info, see {{ docsLink }}."
950
959
  ui:
951
960
  betaTag: "{{#bold}}[BETA]{{/bold}}"
952
961
  betaWarning:
@@ -1267,6 +1276,7 @@ en:
1267
1276
  standardErrors:
1268
1277
  errorOccurred: "Error: {{ error }}"
1269
1278
  errorContext: "Context: {{ context }}"
1279
+ errorCause: "Cause: {{ cause }}"
1270
1280
  systemErrorOccurred: "A system error has occurred: {{ errorMessage }}"
1271
1281
  genericErrorOccurred: "A {{ name }} has occurred."
1272
1282
  unknownErrorOccurred: "An unknown error has occurred"
@@ -4,6 +4,12 @@ const { COMPONENT_TYPES } = require('./projectStructure');
4
4
  const { i18n } = require('./lang');
5
5
  const { promptUser } = require('./prompts/promptUtils');
6
6
  const { DevModeInterface } = require('@hubspot/ui-extensions-dev-server');
7
+ const {
8
+ startPortManagerServer,
9
+ portManagerHasActiveServers,
10
+ stopPortManagerServer,
11
+ requestPorts,
12
+ } = require('@hubspot/local-dev-lib/portManager');
7
13
 
8
14
  const i18nKey = 'cli.lib.DevServerManager';
9
15
 
@@ -61,6 +67,7 @@ class DevServerManager {
61
67
  this.debug = debug;
62
68
  this.componentsByType = this.arrangeComponentsByType(components);
63
69
 
70
+ await startPortManagerServer();
64
71
  await this.iterateDevServers(
65
72
  async (serverInterface, compatibleComponents) => {
66
73
  if (serverInterface.setup) {
@@ -86,6 +93,7 @@ class DevServerManager {
86
93
  debug: this.debug,
87
94
  httpClient,
88
95
  projectConfig,
96
+ requestPorts,
89
97
  });
90
98
  }
91
99
  });
@@ -113,6 +121,12 @@ class DevServerManager {
113
121
  await serverInterface.cleanup();
114
122
  }
115
123
  });
124
+
125
+ const hasActiveServers = await portManagerHasActiveServers();
126
+
127
+ if (!hasActiveServers) {
128
+ await stopPortManagerServer();
129
+ }
116
130
  }
117
131
  }
118
132
  }
@@ -7,7 +7,7 @@ const { logger } = require('@hubspot/cli-lib/logger');
7
7
  const {
8
8
  getAccountId,
9
9
  getConfigDefaultAccount,
10
- } = require('@hubspot/cli-lib/lib/config');
10
+ } = require('@hubspot/local-dev-lib/config');
11
11
  const { PROJECT_CONFIG_FILE } = require('@hubspot/cli-lib/lib/constants');
12
12
  const SpinniesManager = require('./SpinniesManager');
13
13
  const DevServerManager = require('./DevServerManager');
@@ -141,25 +141,30 @@ class LocalDevManager {
141
141
  this.compareLocalProjectToDeployed(runnableComponents);
142
142
  }
143
143
 
144
- async stop() {
145
- SpinniesManager.add('cleanupMessage', {
146
- text: i18n(`${i18nKey}.exitingStart`),
147
- });
148
-
144
+ async stop(showProgress = true) {
145
+ if (showProgress) {
146
+ SpinniesManager.add('cleanupMessage', {
147
+ text: i18n(`${i18nKey}.exitingStart`),
148
+ });
149
+ }
149
150
  await this.stopWatching();
150
151
 
151
152
  const cleanupSucceeded = await this.devServerCleanup();
152
153
 
153
154
  if (!cleanupSucceeded) {
154
- SpinniesManager.fail('cleanupMessage', {
155
- text: i18n(`${i18nKey}.exitingFail`),
156
- });
155
+ if (showProgress) {
156
+ SpinniesManager.fail('cleanupMessage', {
157
+ text: i18n(`${i18nKey}.exitingFail`),
158
+ });
159
+ }
157
160
  process.exit(EXIT_CODES.ERROR);
158
161
  }
159
162
 
160
- SpinniesManager.succeed('cleanupMessage', {
161
- text: i18n(`${i18nKey}.exitingSucceed`),
162
- });
163
+ if (showProgress) {
164
+ SpinniesManager.succeed('cleanupMessage', {
165
+ text: i18n(`${i18nKey}.exitingSucceed`),
166
+ });
167
+ }
163
168
  process.exit(EXIT_CODES.SUCCESS);
164
169
  }
165
170
 
@@ -1,14 +1,14 @@
1
+ const { Mode, DEFAULT_MODE } = require('@hubspot/cli-lib');
1
2
  const {
2
- Mode,
3
- DEFAULT_MODE,
4
3
  getAndLoadConfigIfNeeded,
5
4
  getAccountId,
6
5
  getAccountConfig,
7
6
  loadConfigFromEnvironment,
8
- } = require('@hubspot/cli-lib');
7
+ } = require('@hubspot/local-dev-lib/config');
9
8
  const { getMode } = require('../commonOpts');
10
9
 
11
10
  jest.mock('@hubspot/cli-lib');
11
+ jest.mock('@hubspot/local-dev-lib/config');
12
12
 
13
13
  describe('@hubspot/cli/lib/commonOpts', () => {
14
14
  describe('getMode()', () => {
@@ -0,0 +1,144 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const { EXIT_CODES } = require('../enums/exitCodes');
5
+ const projects = require('../projects');
6
+
7
+ describe('@hubspot/cli/lib/projects', () => {
8
+ describe('validateProjectConfig()', () => {
9
+ let realProcess;
10
+ let projectDir;
11
+ let exitMock;
12
+ let errorSpy;
13
+
14
+ beforeAll(() => {
15
+ projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'projects-'));
16
+ fs.mkdirSync(path.join(projectDir, 'src'));
17
+
18
+ realProcess = process;
19
+ errorSpy = jest.spyOn(console, 'error');
20
+ });
21
+
22
+ beforeEach(() => {
23
+ exitMock = jest.fn();
24
+ global.process = { ...realProcess, exit: exitMock };
25
+ });
26
+
27
+ afterEach(() => {
28
+ errorSpy.mockClear();
29
+ });
30
+
31
+ afterAll(() => {
32
+ global.process = realProcess;
33
+ errorSpy.mockRestore();
34
+ });
35
+
36
+ it('rejects undefined configuration', () => {
37
+ projects.validateProjectConfig(null, projectDir);
38
+
39
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
40
+ expect(errorSpy).toHaveBeenCalledWith(
41
+ expect.stringMatching(/.*config not found.*/)
42
+ );
43
+ });
44
+
45
+ it('rejects configuration with missing name', () => {
46
+ projects.validateProjectConfig({ srcDir: '.' }, projectDir);
47
+
48
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
49
+ expect(errorSpy).toHaveBeenCalledWith(
50
+ expect.stringMatching(/.*missing required fields*/)
51
+ );
52
+ });
53
+
54
+ it('rejects configuration with missing srcDir', () => {
55
+ projects.validateProjectConfig({ name: 'hello' }, projectDir);
56
+
57
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
58
+ expect(errorSpy).toHaveBeenCalledWith(
59
+ expect.stringMatching(/.*missing required fields.*/)
60
+ );
61
+ });
62
+
63
+ describe('rejects configuration with srcDir outside project directory', () => {
64
+ it('for parent directory', () => {
65
+ projects.validateProjectConfig(
66
+ { name: 'hello', srcDir: '..' },
67
+ projectDir
68
+ );
69
+
70
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
71
+ expect(errorSpy).toHaveBeenCalledWith(
72
+ expect.stringContaining('srcDir: ".."')
73
+ );
74
+ });
75
+
76
+ it('for root directory', () => {
77
+ projects.validateProjectConfig(
78
+ { name: 'hello', srcDir: '/' },
79
+ projectDir
80
+ );
81
+
82
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
83
+ expect(errorSpy).toHaveBeenCalledWith(
84
+ expect.stringContaining('srcDir: "/"')
85
+ );
86
+ });
87
+
88
+ it('for complicated directory', () => {
89
+ const srcDir = './src/././../src/../../src';
90
+
91
+ projects.validateProjectConfig({ name: 'hello', srcDir }, projectDir);
92
+
93
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
94
+ expect(errorSpy).toHaveBeenCalledWith(
95
+ expect.stringContaining(`srcDir: "${srcDir}"`)
96
+ );
97
+ });
98
+ });
99
+
100
+ it('rejects configuration with srcDir that does not exist', () => {
101
+ projects.validateProjectConfig(
102
+ { name: 'hello', srcDir: 'foo' },
103
+ projectDir
104
+ );
105
+
106
+ expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
107
+ expect(errorSpy).toHaveBeenCalledWith(
108
+ expect.stringMatching(/.*could not be found in.*/)
109
+ );
110
+ });
111
+
112
+ describe('accepts configuration with valid srcDir', () => {
113
+ it('for current directory', () => {
114
+ projects.validateProjectConfig(
115
+ { name: 'hello', srcDir: '.' },
116
+ projectDir
117
+ );
118
+
119
+ expect(exitMock).not.toHaveBeenCalled();
120
+ expect(errorSpy).not.toHaveBeenCalled();
121
+ });
122
+
123
+ it('for relative directory', () => {
124
+ projects.validateProjectConfig(
125
+ { name: 'hello', srcDir: './src' },
126
+ projectDir
127
+ );
128
+
129
+ expect(exitMock).not.toHaveBeenCalled();
130
+ expect(errorSpy).not.toHaveBeenCalled();
131
+ });
132
+
133
+ it('for implied relative directory', () => {
134
+ projects.validateProjectConfig(
135
+ { name: 'hello', srcDir: 'src' },
136
+ projectDir
137
+ );
138
+
139
+ expect(exitMock).not.toHaveBeenCalled();
140
+ expect(errorSpy).not.toHaveBeenCalled();
141
+ });
142
+ });
143
+ });
144
+ });
@@ -1,4 +1,4 @@
1
- const { getAccountConfig } = require('@hubspot/cli-lib');
1
+ const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
2
2
  const { getOauthManager } = require('@hubspot/cli-lib/oauth');
3
3
  const {
4
4
  accessTokenForPersonalAccessKey,
@@ -8,6 +8,7 @@ const { getAccountId } = require('../commonOpts');
8
8
  const { validateAccount } = require('../validation');
9
9
 
10
10
  jest.mock('@hubspot/cli-lib');
11
+ jest.mock('@hubspot/local-dev-lib/config');
11
12
  jest.mock('@hubspot/cli-lib/logger');
12
13
  jest.mock('@hubspot/cli-lib/oauth');
13
14
  jest.mock('@hubspot/cli-lib/personalAccessKey');
package/lib/commonOpts.js CHANGED
@@ -1,11 +1,10 @@
1
1
  const Logger = require('@hubspot/cli-lib/logger');
2
+ const { DEFAULT_MODE, Mode } = require('@hubspot/cli-lib');
2
3
  const {
3
4
  getAccountId: getAccountIdFromConfig,
4
5
  getAccountConfig,
5
6
  getAndLoadConfigIfNeeded,
6
- DEFAULT_MODE,
7
- Mode,
8
- } = require('@hubspot/cli-lib');
7
+ } = require('@hubspot/local-dev-lib/config');
9
8
  const { i18n } = require('./lang');
10
9
 
11
10
  const i18nKey = 'cli.lib.commonOpts';
@@ -1,5 +1,5 @@
1
1
  const { logger } = require('@hubspot/cli-lib/logger');
2
- const { getAccountConfig } = require('@hubspot/cli-lib/lib/config');
2
+ const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
3
3
  const {
4
4
  SCOPE_GROUPS,
5
5
  PERSONAL_ACCESS_KEY_AUTH_METHOD,
@@ -1,3 +1,4 @@
1
+ const util = require('util');
1
2
  const { HubSpotAuthError } = require('@hubspot/cli-lib/lib/models/Errors');
2
3
  const { logger } = require('@hubspot/cli-lib/logger');
3
4
  const { i18n } = require('../lang');
@@ -40,7 +41,18 @@ function debugErrorAndContext(error, context) {
40
41
  } else {
41
42
  logger.debug(i18n(`${i18nKey}.errorOccurred`, { error }));
42
43
  }
43
- logger.debug(i18n(`${i18nKey}.errorContext`, { context }));
44
+ if (error.cause) {
45
+ logger.debug(
46
+ i18n(`${i18nKey}.errorCause`, {
47
+ cause: util.inspect(error.cause, false, null, true),
48
+ })
49
+ );
50
+ }
51
+ logger.debug(
52
+ i18n(`${i18nKey}.errorContext`, {
53
+ context: util.inspect(context, false, null, true),
54
+ })
55
+ );
44
56
  }
45
57
 
46
58
  /**
@@ -73,7 +85,7 @@ function logErrorInstance(error, context) {
73
85
  // Error or Error subclass
74
86
  const name = error.name || 'Error';
75
87
  const message = [i18n(`${i18nKey}.genericErrorOccurred`, { name })];
76
- [(error.message, error.reason)].forEach(msg => {
88
+ [error.message, error.reason].forEach(msg => {
77
89
  if (msg) {
78
90
  message.push(msg);
79
91
  }
package/lib/filesystem.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const path = require('path');
2
- const { getCwd } = require('@hubspot/cli-lib/path');
2
+ const { getCwd } = require('@hubspot/local-dev-lib/path');
3
3
  const { FOLDER_DOT_EXTENSIONS } = require('@hubspot/cli-lib/lib/constants');
4
4
 
5
5
  function resolveLocalPath(filepath) {
package/lib/links.js CHANGED
@@ -1,11 +1,11 @@
1
- const { getEnv } = require('@hubspot/cli-lib/lib/config');
1
+ const { getEnv } = require('@hubspot/local-dev-lib/config');
2
2
  const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
3
- const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
3
+ const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
4
4
  const { logger } = require('@hubspot/cli-lib/logger');
5
5
  const {
6
6
  getTableContents,
7
7
  getTableHeader,
8
- } = require('@hubspot/cli-lib/lib/table');
8
+ } = require('@hubspot/local-dev-lib/logging/table');
9
9
 
10
10
  const open = require('open');
11
11
 
@@ -0,0 +1,14 @@
1
+ const { logger } = require('@hubspot/cli-lib/logger');
2
+ const { i18n } = require('./lang');
3
+
4
+ function buildLogCallbacks(logData) {
5
+ const callbacksObject = {};
6
+ for (let key in logData) {
7
+ callbacksObject[key] = () => logger.log(i18n(logData[key]));
8
+ }
9
+ return callbacksObject;
10
+ }
11
+
12
+ module.exports = {
13
+ buildLogCallbacks,
14
+ };
package/lib/oauth.js CHANGED
@@ -1,10 +1,10 @@
1
1
  const express = require('express');
2
2
  const open = require('open');
3
3
  const OAuth2Manager = require('@hubspot/cli-lib/lib/models/OAuth2Manager');
4
- const { getAccountConfig } = require('@hubspot/cli-lib/lib/config');
4
+ const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
5
5
  const { addOauthToAccountConfig } = require('@hubspot/cli-lib/oauth');
6
6
  const { handleExit } = require('./process');
7
- const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
7
+ const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
8
8
  const { logger } = require('@hubspot/cli-lib/logger');
9
9
  const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
10
10
 
package/lib/process.js CHANGED
@@ -1,20 +1,38 @@
1
1
  const readline = require('readline');
2
+ const { logger, setLogLevel, LOG_LEVEL } = require('@hubspot/cli-lib/logger');
3
+ const { i18n } = require('./lang');
4
+
5
+ const i18nKey = 'cli.lib.process';
2
6
 
3
7
  const handleExit = callback => {
4
8
  const terminationSignals = [
5
9
  'beforeExit',
6
- 'SIGINT',
7
- 'SIGUSR1',
8
- 'SIGUSR2',
10
+ 'SIGINT', // Terminal trying to interrupt (Ctrl + C)
11
+ 'SIGUSR1', // Start Debugger User-defined signal 1
12
+ 'SIGUSR2', // User-defined signal 2
9
13
  'uncaughtException',
10
- 'SIGTERM',
11
- 'SIGHUP',
14
+ 'SIGTERM', // Represents a graceful termination
15
+ 'SIGHUP', // Parent terminal has been closed
12
16
  ];
17
+ let exitInProgress = false;
18
+
13
19
  terminationSignals.forEach(signal => {
14
20
  process.removeAllListeners(signal);
15
21
 
16
22
  process.on(signal, async () => {
17
- await callback();
23
+ // Prevent duplicate exit handling
24
+ if (!exitInProgress) {
25
+ exitInProgress = true;
26
+ const isSIGHUP = signal === 'SIGHUP';
27
+
28
+ // Prevent logs when terminal closes
29
+ if (isSIGHUP) {
30
+ setLogLevel(LOG_LEVEL.NONE);
31
+ }
32
+
33
+ logger.debug(i18n(`${i18nKey}.exitDebug`, { signal }));
34
+ await callback({ isSIGHUP });
35
+ }
18
36
  });
19
37
  });
20
38
  };
@@ -1,7 +1,8 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { walk } = require('@hubspot/cli-lib/lib/walk');
3
+ const { walk } = require('@hubspot/local-dev-lib/fs');
4
4
  const { logger } = require('@hubspot/cli-lib/logger');
5
+ const { logErrorInstance } = require('./errorHandlers/standardErrors');
5
6
 
6
7
  const COMPONENT_TYPES = Object.freeze({
7
8
  app: 'app',
@@ -73,8 +74,13 @@ function getIsLegacyApp(appConfig, appPath) {
73
74
 
74
75
  async function findProjectComponents(projectSourceDir) {
75
76
  const components = [];
77
+ let projectFiles = [];
76
78
 
77
- const projectFiles = await walk(projectSourceDir);
79
+ try {
80
+ projectFiles = await walk(projectSourceDir);
81
+ } catch (e) {
82
+ logErrorInstance(e);
83
+ }
78
84
 
79
85
  projectFiles.forEach(projectFile => {
80
86
  // Find app components
package/lib/projects.js CHANGED
@@ -5,8 +5,8 @@ const tmp = require('tmp');
5
5
  const chalk = require('chalk');
6
6
  const findup = require('findup-sync');
7
7
  const { logger } = require('@hubspot/cli-lib/logger');
8
- const { getEnv } = require('@hubspot/cli-lib/lib/config');
9
- const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
8
+ const { getEnv } = require('@hubspot/local-dev-lib/config');
9
+ const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
10
10
  const {
11
11
  ENVIRONMENTS,
12
12
  FEEDBACK_INTERVAL,
@@ -29,8 +29,8 @@ const {
29
29
  fetchProject,
30
30
  uploadProject,
31
31
  } = require('@hubspot/cli-lib/api/dfs');
32
- const { shouldIgnoreFile } = require('@hubspot/cli-lib/ignoreRules');
33
- const { getCwd, getAbsoluteFilePath } = require('@hubspot/cli-lib/path');
32
+ const { shouldIgnoreFile } = require('@hubspot/local-dev-lib/ignoreRules');
33
+ const { getCwd, getAbsoluteFilePath } = require('@hubspot/local-dev-lib/path');
34
34
  const { downloadGitHubRepoContents } = require('@hubspot/cli-lib/github');
35
35
  const { promptUser } = require('./prompts/promptUtils');
36
36
  const { EXIT_CODES } = require('./enums/exitCodes');
@@ -159,21 +159,36 @@ const validateProjectConfig = (projectConfig, projectDir) => {
159
159
  logger.error(
160
160
  `Project config not found. Try running 'hs project create' first.`
161
161
  );
162
- process.exit(EXIT_CODES.ERROR);
162
+ return process.exit(EXIT_CODES.ERROR);
163
163
  }
164
164
 
165
165
  if (!projectConfig.name || !projectConfig.srcDir) {
166
166
  logger.error(
167
167
  'Project config is missing required fields. Try running `hs project create`.'
168
168
  );
169
- process.exit(EXIT_CODES.ERROR);
169
+ return process.exit(EXIT_CODES.ERROR);
170
170
  }
171
171
 
172
- if (!fs.existsSync(path.resolve(projectDir, projectConfig.srcDir))) {
172
+ const resolvedPath = path.resolve(projectDir, projectConfig.srcDir);
173
+ if (!resolvedPath.startsWith(projectDir)) {
174
+ const projectConfigFile = path.relative(
175
+ '.',
176
+ path.join(projectDir, PROJECT_CONFIG_FILE)
177
+ );
178
+ logger.error(
179
+ i18n(`${i18nKey}.config.srcOutsideProjectDir`, {
180
+ srcDir: projectConfig.srcDir,
181
+ projectConfig: projectConfigFile,
182
+ })
183
+ );
184
+ return process.exit(EXIT_CODES.ERROR);
185
+ }
186
+
187
+ if (!fs.existsSync(resolvedPath)) {
173
188
  logger.error(
174
189
  `Project source directory '${projectConfig.srcDir}' could not be found in ${projectDir}.`
175
190
  );
176
- process.exit(EXIT_CODES.ERROR);
191
+ return process.exit(EXIT_CODES.ERROR);
177
192
  }
178
193
  };
179
194
 
@@ -855,6 +870,10 @@ const createProjectComponent = async (
855
870
 
856
871
  const showPlatformVersionWarning = async (accountId, projectConfig) => {
857
872
  const platformVersion = projectConfig.platformVersion;
873
+ const docsLink = uiLink(
874
+ i18n(`${i18nKey}.showPlatformVersionWarning.docsLink`),
875
+ 'https://developers.hubspot.com/docs/platform/platform-versioning'
876
+ );
858
877
 
859
878
  if (!platformVersion) {
860
879
  try {
@@ -863,17 +882,28 @@ const showPlatformVersionWarning = async (accountId, projectConfig) => {
863
882
  logger.warn(
864
883
  i18n(`${i18nKey}.showPlatformVersionWarning.noPlatformVersion`, {
865
884
  defaultVersion,
885
+ docsLink,
866
886
  })
867
887
  );
868
888
  logger.log('');
869
889
  } catch (e) {
870
890
  logger.log('');
871
891
  logger.warn(
872
- i18n(`${i18nKey}.showPlatformVersionWarning.noPlatformVersionAlt`)
892
+ i18n(`${i18nKey}.showPlatformVersionWarning.noPlatformVersionAlt`, {
893
+ docsLink,
894
+ })
873
895
  );
874
896
  logger.log('');
875
897
  logger.debug(e.error);
876
898
  }
899
+ } else if (platformVersion === '2023.1') {
900
+ logger.log('');
901
+ logger.warn(
902
+ i18n(`${i18nKey}.showPlatformVersionWarning.deprecatedVersion`, {
903
+ docsLink,
904
+ })
905
+ );
906
+ logger.log('');
877
907
  }
878
908
  };
879
909
 
@@ -8,8 +8,8 @@ const {
8
8
  } = require('./errorHandlers/apiErrors');
9
9
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
10
10
  const { logger } = require('@hubspot/cli-lib/logger');
11
- const { isAllowedExtension } = require('@hubspot/cli-lib/path');
12
- const { shouldIgnoreFile } = require('@hubspot/cli-lib/ignoreRules');
11
+ const { isAllowedExtension } = require('@hubspot/local-dev-lib/path');
12
+ const { shouldIgnoreFile } = require('@hubspot/local-dev-lib/ignoreRules');
13
13
  const {
14
14
  cancelStagedBuild,
15
15
  provisionBuild,
@@ -1,4 +1,4 @@
1
- const { updateDefaultAccount } = require('@hubspot/cli-lib/lib/config');
1
+ const { updateDefaultAccount } = require('@hubspot/local-dev-lib/config');
2
2
  const { promptUser } = require('./promptUtils');
3
3
  const { i18n } = require('../lang');
4
4
  const { getAccountName } = require('../sandboxes');
@@ -1,5 +1,5 @@
1
1
  const path = require('path');
2
- const { getCwd } = require('@hubspot/cli-lib/path');
2
+ const { getCwd } = require('@hubspot/local-dev-lib/path');
3
3
  const {
4
4
  PROJECT_COMPONENT_TYPES,
5
5
  PROJECT_PROPERTIES,