@hubspot/local-dev-lib 3.21.2-beta.0 → 4.0.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.
Files changed (45) hide show
  1. package/config/defaultAccountOverride.d.ts +2 -0
  2. package/config/defaultAccountOverride.js +57 -0
  3. package/config/index.d.ts +30 -44
  4. package/config/index.js +332 -267
  5. package/config/migrate.d.ts +12 -16
  6. package/config/migrate.js +86 -160
  7. package/config/utils.d.ts +30 -0
  8. package/config/utils.js +373 -0
  9. package/constants/config.d.ts +40 -0
  10. package/constants/config.js +41 -1
  11. package/constants/environments.d.ts +0 -11
  12. package/constants/environments.js +1 -12
  13. package/errors/index.d.ts +2 -0
  14. package/errors/index.js +6 -1
  15. package/http/getAxiosConfig.js +7 -1
  16. package/http/index.js +23 -19
  17. package/lang/en.json +89 -61
  18. package/lib/cms/themes.js +3 -1
  19. package/lib/environment.d.ts +1 -1
  20. package/lib/oauth.d.ts +2 -2
  21. package/lib/oauth.js +8 -16
  22. package/lib/personalAccessKey.d.ts +2 -2
  23. package/lib/personalAccessKey.js +43 -30
  24. package/lib/trackUsage.js +6 -3
  25. package/models/HubSpotConfigError.d.ts +6 -0
  26. package/models/HubSpotConfigError.js +34 -0
  27. package/models/OAuth2Manager.d.ts +3 -4
  28. package/models/OAuth2Manager.js +20 -29
  29. package/package.json +5 -5
  30. package/types/Accounts.d.ts +20 -109
  31. package/types/Config.d.ts +17 -26
  32. package/config/CLIConfiguration.d.ts +0 -72
  33. package/config/CLIConfiguration.js +0 -551
  34. package/config/configFile.d.ts +0 -21
  35. package/config/configFile.js +0 -100
  36. package/config/configUtils.d.ts +0 -5
  37. package/config/configUtils.js +0 -87
  38. package/config/config_DEPRECATED.d.ts +0 -87
  39. package/config/config_DEPRECATED.js +0 -738
  40. package/config/environment.d.ts +0 -2
  41. package/config/environment.js +0 -60
  42. package/config/getAccountIdentifier.d.ts +0 -2
  43. package/config/getAccountIdentifier.js +0 -15
  44. package/utils/accounts.d.ts +0 -4
  45. package/utils/accounts.js +0 -28
package/lang/en.json CHANGED
@@ -75,7 +75,8 @@
75
75
  "personalAccessKey": {
76
76
  "errors": {
77
77
  "accountNotFound": "Account with id {{ accountId }} does not exist.",
78
- "invalidPersonalAccessKey": "Error while retrieving new access token: {{ errorMessage }}"
78
+ "invalidPersonalAccessKey": "Error while retrieving new access token: {{ errorMessage }}",
79
+ "invalidAuthType": "Error fetching access token: account {{ accountId }} uses an auth type other than personalaccesskey"
79
80
  }
80
81
  },
81
82
  "crm": {
@@ -242,73 +243,96 @@
242
243
  }
243
244
  },
244
245
  "config": {
245
- "cliConfiguration": {
246
- "errors": {
247
- "noConfigLoaded": "No config loaded."
248
- },
249
- "load": {
250
- "configFromEnv": "Loaded config from environment variables for {{ accountId }}",
251
- "configFromFile": "Loaded config from configuration file.",
252
- "empty": "The config file was empty. Initializing an empty config."
246
+ "getDefaultConfigFilePath": {
247
+ "error": "Attempted to get config file path, but no config file was found."
248
+ },
249
+ "getConfig": {
250
+ "reading": "Reading config from {{ path }}",
251
+ "error": "No config file found.",
252
+ "errorWithPath": "No config file found at {{ path }}."
253
+ },
254
+ "validateConfig": {
255
+ "missingAccounts": "No accounts found",
256
+ "duplicateAccountIds": "Multiple accounts with accountId: {{ accountId }}",
257
+ "duplicateAccountNames": "Multiple accounts with name: {{ accountName }}",
258
+ "invalidAccountName": "Account name {{ accountName }} contains spaces"
259
+ },
260
+ "getConfigAccountById": {
261
+ "error": "No account with id {{ accountId }} exists in config"
262
+ },
263
+ "getConfigAccountByName": {
264
+ "error": "No account with name {{ accountName }} exists in config"
265
+ },
266
+ "getConfigDefaultAccount": {
267
+ "fieldMissingError": "Attempted to get default account, but no default account was found in config",
268
+ "accountMissingError": "Default account is set to {{ defaultAccount }}, but no account with that id exists in config"
269
+ },
270
+ "addConfigAccount": {
271
+ "invalidAccount": "Attempting to add account, but account is invalid",
272
+ "duplicateAccount": "Attempting to add account, but account with id {{ accountId }} already exists in config"
273
+ },
274
+ "updateConfigAccount": {
275
+ "invalidAccount": "Attempting to update account {{ name }}, but account is invalid",
276
+ "accountNotFound": "Attempting to update account with id {{ id }}, but that account was not found in config"
277
+ },
278
+ "setConfigAccountAsDefault": {
279
+ "accountNotFound": "Attempted to set account with identifier {{ identifier }} as default, but that account was not found in config"
280
+ },
281
+ "renameConfigAccount": {
282
+ "accountNotFound": "Attempted to rename account with name {{ currentName }}, but that account was not found in config",
283
+ "duplicateAccount": "Attempted to rename account {{ currentName }} to {{ newName }}, but an account with that name already exists in config"
284
+ },
285
+ "removeAccountFromConfig": {
286
+ "accountNotFound": "Attempted to remove account with id {{ accountId }}, but that account was not found in config"
287
+ },
288
+ "updateHttpTimeout": {
289
+ "invalidTimeout": "HTTP timeout must be greater than {{ minTimeout }}. Received {{ timeout }}"
290
+ },
291
+ "updateDefaultCmsPublishMode": {
292
+ "invalidCmsPublishMode": "Error updating config default CMS publish mode: CMS publish can only be set to 'draft' or 'publish'"
293
+ },
294
+ "getConfigAccountEnvironment": {
295
+ "accountNotFound": "Attempted to get environment for account with identifier {{ identifier }}, but that account was not found in config"
296
+ },
297
+ "utils": {
298
+ "handleConfigFileSystemError": {
299
+ "configNotFoundError": "No config file found at {{ path }}.",
300
+ "insufficientPermissionsError": "Insufficient permissions to access config file at {{ path }}"
253
301
  },
254
- "validate": {
255
- "noConfig": "Validation failed: No config was found.",
256
- "noConfigAccounts": "Validation failed: config.accounts[] is not defined.",
257
- "emptyAccountConfig": "Validation failed: config.accounts[] has an empty entry.",
258
- "noAccountId": "Validation failed: config.accounts[] has an entry missing accountId.",
259
- "duplicateAccountIds": "Validation failed: config.accounts[] has multiple entries with {{ accountId }}.",
260
- "duplicateAccountNames": "Validation failed: config.accounts[] has multiple entries with {{ accountName }}.",
261
- "nameContainsSpaces": "Validation failed: config.name {{ accountName }} cannot contain spaces."
302
+ "validateConfigAccount": {
303
+ "missingAccount": "At least one account in config is missing data",
304
+ "missingAuthType": "Account {{ accountId }} has no authType",
305
+ "missingAccountId": "At least one account in config is missing accountId",
306
+ "missingApiKey": "Account {{ accountId }} has authType of apikey but is missing the apiKey field",
307
+ "missingAuth": "Account {{ accountId }} has authtype of oauth2 but is missing auth data",
308
+ "missingPersonalAccessKey": "Account {{ accountId }} has authType of personalAccessKey but is missing the personalAccessKey field"
262
309
  },
263
- "updateAccount": {
264
- "noConfigToUpdate": "No config to update.",
265
- "updating": "Updating account config for {{ accountId }}",
266
- "addingConfigEntry": "Adding account config entry for {{ accountId }}",
267
- "errors": {
268
- "accountIdRequired": "An accountId is required to update the config"
269
- }
310
+ "getConfigPathEnvironmentVariables": {
311
+ "invalidEnvironmentVariables": "USE_ENVIRONMENT_HUBSPOT_CONFIG and HUBSPOT_CONFIG_PATH cannot both be set simultaneously"
270
312
  },
271
- "updateDefaultAccount": {
272
- "errors": {
273
- "invalidInput": "A 'defaultAccount' with value of number or string is required to update the config."
274
- }
313
+ "parseConfig": {
314
+ "error": "File could not be parsed. Confirm that your config file {{ configPath }} is valid YAML."
275
315
  },
276
- "getCWDAccountOverride": {
316
+ "buildConfigFromEnvironment": {
317
+ "missingAccountId": "HUBSPOT_ACCOUNT_ID is required, but not currently set",
318
+ "invalidAuthType": "Auth type is invalid. Use HUBSPOT_CLIENT_ID, HUBSPOT_CLIENT_SECRET, and HUBSPOT_REFRESH_TOKEN to authenticate with Oauth2, PERSONAL_ACCESS_KEY to authenticate with Personal Access Key, or API_KEY to authenticate with API Key."
319
+ }
320
+ },
321
+ "defaultAccountOverride": {
322
+ "getDefaultAccountOverrideAccountId": {
277
323
  "errorHeader": "Error in {{ hsAccountFile }}",
278
324
  "readFileError": "Error reading account override file."
279
- },
280
- "renameAccount": {
281
- "errors": {
282
- "invalidName": "Cannot find account with identifier {{ currentName }}"
283
- }
284
- },
285
- "removeAccountFromConfig": {
286
- "deleting": "Deleting config for {{ accountId }}",
287
- "errors": {
288
- "invalidId": "Unable to find account for {{ nameOrId }}."
289
- }
290
- },
291
- "updateDefaultCmsPublishMode": {
292
- "errors": {
293
- "invalidCmsPublishMode": "The CMS publish mode {{ defaultCmsPublishMode }} is invalid. Valid values are {{ validCmsPublishModes }}."
294
- }
295
- },
296
- "updateHttpTimeout": {
297
- "errors": {
298
- "invalidTimeout": "The value {{ timeout }} is invalid. The value must be a number greater than {{ minTimeout }}."
299
- }
300
- },
301
- "updateAllowUsageTracking": {
302
- "errors": {
303
- "invalidInput": "Unable to update allowUsageTracking. The value {{ isEnabled }} is invalid. The value must be a boolean."
304
- }
305
- },
306
- "updateAutoOpenBrowser": {
307
- "errors": {
308
- "invalidInput": "Unable to update autoOpenBrowser. The value {{ isEnabled }} is invalid. The value must be a boolean."
309
- }
310
325
  }
311
326
  },
327
+ "updateAllowUsageTracking": {
328
+ "invalidInput": "Unable to update allowUsageTracking. The value {{ isAllowed }} is invalid. The value must be a boolean."
329
+ },
330
+ "updateAllowAutoUpdates": {
331
+ "invalidInput": "Unable to update allowAutoUpdates. The value {{ isEnabled }} is invalid. The value must be a boolean."
332
+ },
333
+ "updateAutoOpenBrowser": {
334
+ "invalidInput": "Unable to update autoOpenBrowser. The value {{ isEnabled }} is invalid. The value must be a boolean."
335
+ },
312
336
  "configFile": {
313
337
  "errorReading": "Config file could not be read: {{ configPath }}",
314
338
  "writeSuccess": "Successfully wrote updated config data to {{ configPath }}",
@@ -363,6 +387,9 @@
363
387
  "missingRefreshToken": "The account {{ accountId }} has not been authenticated with Oauth2",
364
388
  "auth": "Error while retrieving new token: {{ token }}"
365
389
  }
390
+ },
391
+ "HubSpotConfigError": {
392
+ "baseMessage": "An error occurred while {{ operation }} your HubSpot config {{ configType }}{{ message }}"
366
393
  }
367
394
  },
368
395
  "utils": {
@@ -402,7 +429,8 @@
402
429
  },
403
430
  "errors": {
404
431
  "withOauth": "Oauth manager for account {{ accountId }} not found.",
405
- "withAuth": "Account with id {{ accountId }} not found."
432
+ "withAuth": "Account with id {{ accountId }} not found.",
433
+ "invalidAuthType": "Error authenticating HTTP request: account {{ accountId }} has an invalid auth type {{ authType }}"
406
434
  }
407
435
  }
408
436
  },
package/lib/cms/themes.js CHANGED
@@ -28,7 +28,9 @@ function getThemePreviewUrl(filePath, accountId) {
28
28
  const themeName = getThemeNameFromPath(filePath);
29
29
  if (!themeName)
30
30
  return;
31
- const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
31
+ const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getConfigAccountEnvironment)(accountId) === 'qa'
32
+ ? environments_1.ENVIRONMENTS.QA
33
+ : environments_1.ENVIRONMENTS.PROD);
32
34
  return `${baseUrl}/theme-previewer/${accountId}/edit/${encodeURIComponent(themeName)}`;
33
35
  }
34
36
  exports.getThemePreviewUrl = getThemePreviewUrl;
@@ -1,2 +1,2 @@
1
1
  import { Environment } from '../types/Config';
2
- export declare function getValidEnv(env?: Environment | null, maskedProductionValue?: Environment): Environment;
2
+ export declare function getValidEnv(env?: string | null, maskedProductionValue?: Environment): Environment;
package/lib/oauth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { OAuth2Manager } from '../models/OAuth2Manager';
2
- import { FlatAccountFields } from '../types/Accounts';
3
- export declare function getOauthManager(accountId: number, accountConfig: FlatAccountFields): OAuth2Manager | undefined;
2
+ import { OAuthConfigAccount } from '../types/Accounts';
3
+ export declare function getOauthManager(account: OAuthConfigAccount): OAuth2Manager | undefined;
4
4
  export declare function addOauthToAccountConfig(oauth: OAuth2Manager): void;
package/lib/oauth.js CHANGED
@@ -2,33 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addOauthToAccountConfig = exports.getOauthManager = void 0;
4
4
  const OAuth2Manager_1 = require("../models/OAuth2Manager");
5
- const auth_1 = require("../constants/auth");
6
5
  const logger_1 = require("./logger");
7
- const getAccountIdentifier_1 = require("../config/getAccountIdentifier");
8
6
  const config_1 = require("../config");
9
7
  const lang_1 = require("../utils/lang");
10
8
  const i18nKey = 'lib.oauth';
11
9
  const oauthManagers = new Map();
12
- function writeOauthTokenInfo(accountConfig) {
13
- const accountId = (0, getAccountIdentifier_1.getAccountIdentifier)(accountConfig);
14
- logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.writeTokenInfo`, { portalId: accountId || '' }));
15
- (0, config_1.updateAccountConfig)(accountConfig);
16
- (0, config_1.writeConfig)();
10
+ function writeOauthTokenInfo(account) {
11
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.writeTokenInfo`, { portalId: account.accountId }));
12
+ (0, config_1.updateConfigAccount)(account);
17
13
  }
18
- function getOauthManager(accountId, accountConfig) {
19
- if (!oauthManagers.has(accountId)) {
20
- oauthManagers.set(accountId, OAuth2Manager_1.OAuth2Manager.fromConfig(accountConfig, () => writeOauthTokenInfo(accountConfig)));
14
+ function getOauthManager(account) {
15
+ if (!oauthManagers.has(account.accountId)) {
16
+ oauthManagers.set(account.accountId, new OAuth2Manager_1.OAuth2Manager(account, () => writeOauthTokenInfo(account)));
21
17
  }
22
- return oauthManagers.get(accountId);
18
+ return oauthManagers.get(account.accountId);
23
19
  }
24
20
  exports.getOauthManager = getOauthManager;
25
21
  function addOauthToAccountConfig(oauth) {
26
22
  logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.addOauthToAccountConfig.init`));
27
- (0, config_1.updateAccountConfig)({
28
- ...oauth.account,
29
- authType: auth_1.AUTH_METHODS.oauth.value,
30
- });
31
- (0, config_1.writeConfig)();
23
+ (0, config_1.updateConfigAccount)(oauth.account);
32
24
  logger_1.logger.success((0, lang_1.i18n)(`${i18nKey}.addOauthToAccountConfig.success`));
33
25
  }
34
26
  exports.addOauthToAccountConfig = addOauthToAccountConfig;
@@ -1,4 +1,4 @@
1
- import { CLIAccount, ScopeGroupAuthorization } from '../types/Accounts';
1
+ import { PersonalAccessKeyConfigAccount, ScopeGroupAuthorization } from '../types/Accounts';
2
2
  import { Environment } from '../types/Config';
3
3
  import { AccessToken } from '../types/Accounts';
4
4
  export declare function getAccessToken(personalAccessKey: string, env?: Environment, accountId?: number): Promise<AccessToken>;
@@ -8,4 +8,4 @@ export declare function enabledFeaturesForPersonalAccessKey(accountId: number):
8
8
  } | undefined>;
9
9
  export declare function scopesOnAccessToken(accountId: number): Promise<Array<string>>;
10
10
  export declare function authorizedScopesForPortalAndUser(accountId: number): Promise<Array<ScopeGroupAuthorization>>;
11
- export declare function updateConfigWithAccessToken(token: AccessToken, personalAccessKey: string, env?: Environment, name?: string, makeDefault?: boolean): Promise<CLIAccount | null>;
11
+ export declare function updateConfigWithAccessToken(token: AccessToken, personalAccessKey: string, env?: Environment, name?: string, makeDefault?: boolean): Promise<PersonalAccessKeyConfigAccount>;
@@ -13,7 +13,6 @@ const config_1 = require("../config");
13
13
  const config_2 = require("../constants/config");
14
14
  const developerTestAccounts_1 = require("../api/developerTestAccounts");
15
15
  const logger_1 = require("./logger");
16
- const CLIConfiguration_1 = require("../config/CLIConfiguration");
17
16
  const lang_1 = require("../utils/lang");
18
17
  const errors_1 = require("../errors");
19
18
  const i18nKey = 'lib.personalAccessKey';
@@ -36,30 +35,30 @@ async function getAccessToken(personalAccessKey, env = environments_1.ENVIRONMEN
36
35
  };
37
36
  }
38
37
  exports.getAccessToken = getAccessToken;
39
- async function refreshAccessToken(personalAccessKey, env = environments_1.ENVIRONMENTS.PROD, accountId) {
38
+ async function refreshAccessToken(account) {
39
+ const { personalAccessKey, env, accountId } = account;
40
40
  const accessTokenResponse = await getAccessToken(personalAccessKey, env, accountId);
41
41
  const { accessToken, expiresAt } = accessTokenResponse;
42
- const config = (0, config_1.getAccountConfig)(accountId);
43
- (0, config_1.updateAccountConfig)({
44
- env,
45
- ...config,
46
- accountId,
47
- tokenInfo: {
48
- accessToken,
49
- expiresAt: expiresAt,
42
+ (0, config_1.updateConfigAccount)({
43
+ ...account,
44
+ auth: {
45
+ tokenInfo: {
46
+ accessToken,
47
+ expiresAt: expiresAt,
48
+ },
50
49
  },
51
50
  });
52
- (0, config_1.writeConfig)();
53
51
  return accessTokenResponse;
54
52
  }
55
- async function getNewAccessToken(accountId, personalAccessKey, expiresAt, env) {
56
- const key = getRefreshKey(personalAccessKey, expiresAt);
53
+ async function getNewAccessToken(account) {
54
+ const { personalAccessKey, auth } = account;
55
+ const key = getRefreshKey(personalAccessKey, auth.tokenInfo.expiresAt);
57
56
  if (refreshRequests.has(key)) {
58
57
  return refreshRequests.get(key);
59
58
  }
60
59
  let accessTokenResponse;
61
60
  try {
62
- const refreshAccessPromise = refreshAccessToken(personalAccessKey, env, accountId);
61
+ const refreshAccessPromise = refreshAccessToken(account);
63
62
  if (key) {
64
63
  refreshRequests.set(key, refreshAccessPromise);
65
64
  }
@@ -74,28 +73,37 @@ async function getNewAccessToken(accountId, personalAccessKey, expiresAt, env) {
74
73
  return accessTokenResponse;
75
74
  }
76
75
  async function getNewAccessTokenByAccountId(accountId) {
77
- const account = (0, config_1.getAccountConfig)(accountId);
76
+ const account = (0, config_1.getConfigAccountById)(accountId);
78
77
  if (!account) {
79
78
  throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.accountNotFound`, { accountId }));
80
79
  }
81
- const { auth, personalAccessKey, env } = account;
82
- const accessTokenResponse = await getNewAccessToken(accountId, personalAccessKey, auth?.tokenInfo?.expiresAt, env);
80
+ if (account.authType !== auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value) {
81
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidAuthType`, {
82
+ accountId,
83
+ }));
84
+ }
85
+ const accessTokenResponse = await getNewAccessToken(account);
83
86
  return accessTokenResponse;
84
87
  }
85
88
  async function accessTokenForPersonalAccessKey(accountId, forceRefresh = false) {
86
- const account = (0, config_1.getAccountConfig)(accountId);
89
+ const account = (0, config_1.getConfigAccountById)(accountId);
87
90
  if (!account) {
88
91
  throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.accountNotFound`, { accountId }));
89
92
  }
90
- const { auth, personalAccessKey, env } = account;
93
+ if (account.authType !== auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value) {
94
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidAuthType`, {
95
+ accountId,
96
+ }));
97
+ }
98
+ const { auth } = account;
91
99
  const authTokenInfo = auth && auth.tokenInfo;
92
100
  const authDataExists = authTokenInfo && auth?.tokenInfo?.accessToken;
93
101
  if (!authDataExists ||
94
102
  forceRefresh ||
95
103
  (0, moment_1.default)().add(5, 'minutes').isAfter((0, moment_1.default)(authTokenInfo.expiresAt))) {
96
- return getNewAccessToken(accountId, personalAccessKey, authTokenInfo && authTokenInfo.expiresAt, env).then(tokenInfo => tokenInfo.accessToken);
104
+ return getNewAccessToken(account).then(tokenInfo => tokenInfo.accessToken);
97
105
  }
98
- return auth?.tokenInfo?.accessToken;
106
+ return auth.tokenInfo?.accessToken;
99
107
  }
100
108
  exports.accessTokenForPersonalAccessKey = accessTokenForPersonalAccessKey;
101
109
  async function enabledFeaturesForPersonalAccessKey(accountId) {
@@ -113,7 +121,8 @@ async function authorizedScopesForPortalAndUser(accountId) {
113
121
  exports.authorizedScopesForPortalAndUser = authorizedScopesForPortalAndUser;
114
122
  async function updateConfigWithAccessToken(token, personalAccessKey, env, name, makeDefault = false) {
115
123
  const { portalId, accessToken, expiresAt, accountType } = token;
116
- const accountEnv = env || (0, config_1.getEnv)(name);
124
+ const account = (0, config_1.getConfigAccountIfExists)(portalId);
125
+ const accountEnv = env || account?.env || environments_1.ENVIRONMENTS.PROD;
117
126
  let parentAccountId;
118
127
  try {
119
128
  if (accountType === config_2.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX ||
@@ -146,21 +155,25 @@ async function updateConfigWithAccessToken(token, personalAccessKey, env, name,
146
155
  }
147
156
  logger_1.logger.debug(err);
148
157
  }
149
- const updatedAccount = (0, config_1.updateAccountConfig)({
158
+ const updatedAccount = {
150
159
  accountId: portalId,
151
160
  accountType,
152
161
  personalAccessKey,
153
- name,
162
+ name: name || account?.name,
154
163
  authType: auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value,
155
- tokenInfo: { accessToken, expiresAt },
164
+ auth: { tokenInfo: { accessToken, expiresAt } },
156
165
  parentAccountId,
157
166
  env: accountEnv,
158
- });
159
- if (!CLIConfiguration_1.CLIConfiguration.isActive()) {
160
- (0, config_1.writeConfig)();
167
+ }; // Account may temporarily not have a name before prompted to add one in the CLI
168
+ // Add new account if it doesn't exist, otherwise update existing account
169
+ if (account) {
170
+ (0, config_1.updateConfigAccount)(updatedAccount);
171
+ }
172
+ else {
173
+ (0, config_1.addConfigAccount)(updatedAccount);
161
174
  }
162
- if (makeDefault && name) {
163
- (0, config_1.updateDefaultAccount)(name);
175
+ if (makeDefault) {
176
+ (0, config_1.setConfigAccountAsDefault)(updatedAccount.accountId);
164
177
  }
165
178
  return updatedAccount;
166
179
  }
package/lib/trackUsage.js CHANGED
@@ -11,6 +11,7 @@ const http_1 = require("../http");
11
11
  const config_1 = require("../config");
12
12
  const fileMapper_1 = require("../api/fileMapper");
13
13
  const lang_1 = require("../utils/lang");
14
+ const environment_1 = require("./environment");
14
15
  const i18nKey = 'lib.trackUsage';
15
16
  exports.CMS_CLI_USAGE_PATH = `${fileMapper_1.FILE_MAPPER_API_PATH}/cms-cli-usage`;
16
17
  exports.VSCODE_USAGE_PATH = `${fileMapper_1.FILE_MAPPER_API_PATH}/vscode-extension-usage`;
@@ -36,8 +37,8 @@ async function trackUsage(eventName, eventClass, meta = {}, accountId) {
36
37
  default:
37
38
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.invalidEvent`, { eventName }));
38
39
  }
39
- const accountConfig = accountId && (0, config_1.getAccountConfig)(accountId);
40
- if (accountConfig && accountConfig.authType === 'personalaccesskey') {
40
+ const account = accountId && (0, config_1.getConfigAccountById)(accountId);
41
+ if (account && account.authType === 'personalaccesskey') {
41
42
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.sendingEventAuthenticated`));
42
43
  try {
43
44
  await http_1.http.post(accountId, {
@@ -51,7 +52,9 @@ async function trackUsage(eventName, eventClass, meta = {}, accountId) {
51
52
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.retryingEventUnauthenticated`));
52
53
  }
53
54
  }
54
- const env = (0, config_1.getEnv)(accountId);
55
+ const env = accountId
56
+ ? (0, config_1.getConfigAccountEnvironment)(accountId)
57
+ : (0, environment_1.getValidEnv)();
55
58
  const axiosConfig = (0, getAxiosConfig_1.getAxiosConfig)({
56
59
  env,
57
60
  url: path,
@@ -0,0 +1,6 @@
1
+ import { HubSpotConfigErrorType, HubSpotConfigOperation } from '../types/Config';
2
+ export declare class HubSpotConfigError extends Error {
3
+ type: HubSpotConfigErrorType;
4
+ operation: HubSpotConfigOperation;
5
+ constructor(message: string | undefined, type: HubSpotConfigErrorType, operation: HubSpotConfigOperation, options?: ErrorOptions);
6
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HubSpotConfigError = void 0;
4
+ const config_1 = require("../constants/config");
5
+ const lang_1 = require("../utils/lang");
6
+ const NAME = 'HubSpotConfigError';
7
+ const OPERATION_TEXT = {
8
+ [config_1.HUBSPOT_CONFIG_OPERATIONS.READ]: 'reading',
9
+ [config_1.HUBSPOT_CONFIG_OPERATIONS.WRITE]: 'writing to',
10
+ [config_1.HUBSPOT_CONFIG_OPERATIONS.DELETE]: 'deleting',
11
+ };
12
+ function isEnvironmentError(type) {
13
+ return type === config_1.HUBSPOT_CONFIG_ERROR_TYPES.INVALID_ENVIRONMENT_VARIABLES;
14
+ }
15
+ class HubSpotConfigError extends Error {
16
+ type;
17
+ operation;
18
+ constructor(message, type, operation, options) {
19
+ const configType = isEnvironmentError(type)
20
+ ? 'environment variables'
21
+ : 'file';
22
+ const operationText = OPERATION_TEXT[operation];
23
+ const withBaseMessage = (0, lang_1.i18n)('models.HubSpotConfigError.baseMessage', {
24
+ configType,
25
+ message: message ? `: ${message}` : '',
26
+ operation: operationText,
27
+ });
28
+ super(withBaseMessage, options);
29
+ this.name = NAME;
30
+ this.type = type;
31
+ this.operation = operation;
32
+ }
33
+ }
34
+ exports.HubSpotConfigError = HubSpotConfigError;
@@ -1,12 +1,11 @@
1
- import { FlatAccountFields, OAuth2ManagerAccountConfig, WriteTokenInfoFunction, RefreshTokenResponse, ExchangeProof } from '../types/Accounts';
1
+ import { OAuthConfigAccount, WriteTokenInfoFunction, RefreshTokenResponse, ExchangeProof } from '../types/Accounts';
2
2
  export declare class OAuth2Manager {
3
- account: OAuth2ManagerAccountConfig;
3
+ account: OAuthConfigAccount;
4
4
  writeTokenInfo?: WriteTokenInfoFunction;
5
5
  refreshTokenRequest: Promise<RefreshTokenResponse> | null;
6
- constructor(account: OAuth2ManagerAccountConfig, writeTokenInfo?: WriteTokenInfoFunction);
6
+ constructor(account: OAuthConfigAccount, writeTokenInfo?: WriteTokenInfoFunction);
7
7
  accessToken(): Promise<string | undefined>;
8
8
  fetchAccessToken(exchangeProof: ExchangeProof): Promise<void>;
9
9
  exchangeForTokens(exchangeProof: ExchangeProof): Promise<void>;
10
10
  refreshAccessToken(): Promise<void>;
11
- static fromConfig(accountConfig: FlatAccountFields, writeTokenInfo: WriteTokenInfoFunction): OAuth2Manager;
12
11
  }
@@ -9,8 +9,6 @@ const moment_1 = __importDefault(require("moment"));
9
9
  const urls_1 = require("../lib/urls");
10
10
  const environment_1 = require("../lib/environment");
11
11
  const logger_1 = require("../lib/logger");
12
- const getAccountIdentifier_1 = require("../config/getAccountIdentifier");
13
- const auth_1 = require("../constants/auth");
14
12
  const lang_1 = require("../utils/lang");
15
13
  const i18nKey = 'models.OAuth2Manager';
16
14
  class OAuth2Manager {
@@ -26,23 +24,23 @@ class OAuth2Manager {
26
24
  }
27
25
  }
28
26
  async accessToken() {
29
- if (!this.account.tokenInfo?.refreshToken) {
27
+ if (!this.account.auth.tokenInfo.refreshToken) {
30
28
  throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.missingRefreshToken`, {
31
- accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
29
+ accountId: this.account.accountId,
32
30
  }));
33
31
  }
34
- if (!this.account.tokenInfo?.accessToken ||
32
+ if (!this.account.auth.tokenInfo.accessToken ||
35
33
  (0, moment_1.default)()
36
34
  .add(5, 'minutes')
37
- .isAfter((0, moment_1.default)(new Date(this.account.tokenInfo.expiresAt || '')))) {
35
+ .isAfter((0, moment_1.default)(new Date(this.account.auth.tokenInfo.expiresAt || '')))) {
38
36
  await this.refreshAccessToken();
39
37
  }
40
- return this.account.tokenInfo.accessToken;
38
+ return this.account.auth.tokenInfo.accessToken;
41
39
  }
42
40
  async fetchAccessToken(exchangeProof) {
43
41
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.fetchingAccessToken`, {
44
- accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
45
- clientId: this.account.clientId || '',
42
+ accountId: this.account.accountId,
43
+ clientId: this.account.auth.clientId,
46
44
  }));
47
45
  try {
48
46
  const { data } = await (0, axios_1.default)({
@@ -53,20 +51,20 @@ class OAuth2Manager {
53
51
  });
54
52
  this.refreshTokenRequest = data;
55
53
  const { refresh_token: refreshToken, access_token: accessToken, expires_in: expiresIn, } = data;
56
- if (!this.account.tokenInfo) {
57
- this.account.tokenInfo = {};
54
+ if (!this.account.auth.tokenInfo) {
55
+ this.account.auth.tokenInfo = {};
58
56
  }
59
- this.account.tokenInfo.refreshToken = refreshToken;
60
- this.account.tokenInfo.accessToken = accessToken;
61
- this.account.tokenInfo.expiresAt = (0, moment_1.default)()
57
+ this.account.auth.tokenInfo.refreshToken = refreshToken;
58
+ this.account.auth.tokenInfo.accessToken = accessToken;
59
+ this.account.auth.tokenInfo.expiresAt = (0, moment_1.default)()
62
60
  .add(Math.round(parseInt(expiresIn) * 0.75), 'seconds')
63
61
  .toString();
64
62
  if (this.writeTokenInfo) {
65
63
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.updatingTokenInfo`, {
66
- accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
67
- clientId: this.account.clientId || '',
64
+ accountId: this.account.accountId,
65
+ clientId: this.account.auth.clientId,
68
66
  }));
69
- this.writeTokenInfo(this.account.tokenInfo);
67
+ this.writeTokenInfo(this.account.auth.tokenInfo);
70
68
  }
71
69
  }
72
70
  finally {
@@ -76,8 +74,8 @@ class OAuth2Manager {
76
74
  async exchangeForTokens(exchangeProof) {
77
75
  if (this.refreshTokenRequest) {
78
76
  logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.refreshingAccessToken`, {
79
- accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
80
- clientId: this.account.clientId || '',
77
+ accountId: this.account.accountId,
78
+ clientId: this.account.auth.clientId,
81
79
  }));
82
80
  await this.refreshTokenRequest;
83
81
  }
@@ -88,18 +86,11 @@ class OAuth2Manager {
88
86
  async refreshAccessToken() {
89
87
  const refreshTokenProof = {
90
88
  grant_type: 'refresh_token',
91
- client_id: this.account.clientId,
92
- client_secret: this.account.clientSecret,
93
- refresh_token: this.account.tokenInfo?.refreshToken,
89
+ client_id: this.account.auth.clientId,
90
+ client_secret: this.account.auth.clientSecret,
91
+ refresh_token: this.account.auth.tokenInfo.refreshToken,
94
92
  };
95
93
  await this.exchangeForTokens(refreshTokenProof);
96
94
  }
97
- static fromConfig(accountConfig, writeTokenInfo) {
98
- return new OAuth2Manager({
99
- ...accountConfig,
100
- authType: auth_1.AUTH_METHODS.oauth.value,
101
- ...(accountConfig.auth || {}),
102
- }, writeTokenInfo);
103
- }
104
95
  }
105
96
  exports.OAuth2Manager = OAuth2Manager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/local-dev-lib",
3
- "version": "3.21.2-beta.0",
3
+ "version": "4.0.0-beta.0",
4
4
  "description": "Provides library functionality for HubSpot local development tooling, including the HubSpot CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,11 +11,11 @@
11
11
  "access": "public"
12
12
  },
13
13
  "scripts": {
14
- "build": "ts-node ./scripts/build.ts",
14
+ "build": "tsx ./scripts/build.ts",
15
15
  "lint": "eslint --max-warnings=0 . && prettier . --check",
16
16
  "local-dev": "yarn build && cd dist && yarn link && cd .. && tsc --watch --rootDir . --outdir dist",
17
17
  "prettier:write": "prettier . --write",
18
- "release": "ts-node ./scripts/release.ts release",
18
+ "release": "tsx ./scripts/release.ts release",
19
19
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ./node_modules/.bin/jest"
20
20
  },
21
21
  "license": "Apache-2.0",
@@ -39,7 +39,7 @@
39
39
  "jest": "^29.5.0",
40
40
  "open": "^8.4.2",
41
41
  "ts-jest": "^29.0.5",
42
- "ts-node": "^10.9.2",
42
+ "tsx": "^4.20.6",
43
43
  "typescript": "^4.9.5",
44
44
  "yargs": "^17.7.2"
45
45
  },
@@ -49,7 +49,7 @@
49
49
  "./errors/*": "./errors/*.js",
50
50
  "./http": "./http/index.js",
51
51
  "./http/*": "./http/*.js",
52
- "./config/getAccountIdentifier": "./config/getAccountIdentifier.js",
52
+ "./config/defaultAccountOverride": "./config/defaultAccountOverride.js",
53
53
  "./config/migrate": "./config/migrate.js",
54
54
  "./config/state": "./config/state.js",
55
55
  "./config": "./config/index.js",