@hubspot/local-dev-lib 0.2.2 → 0.2.4

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.
@@ -7,6 +7,6 @@ export declare function fetchModule(accountId: number, moduleId: number, options
7
7
  export declare function fetchFileStream(accountId: number, filePath: string, destination: string, options?: FileMapperOptions): Promise<FileMapperNode>;
8
8
  export declare function download(accountId: number, filepath: string, options?: FileMapperOptions): Promise<FileMapperNode>;
9
9
  export declare function downloadDefault(accountId: number, filepath: string, options?: FileMapperOptions): Promise<FileMapperNode>;
10
- export declare function deleteFile(accountId: number, filePath: string, options?: FileMapperOptions): Promise<void>;
10
+ export declare function deleteFile(accountId: number, filePath: string): Promise<void>;
11
11
  export declare function moveFile(accountId: number, srcPath: string, destPath: string): Promise<void>;
12
- export declare function getDirectoryContentsByPath(accountId: number, path: string): Promise<void>;
12
+ export declare function getDirectoryContentsByPath(accountId: number, path: string): Promise<FileMapperNode>;
package/api/fileMapper.js CHANGED
@@ -83,10 +83,9 @@ async function downloadDefault(accountId, filepath, options = {}) {
83
83
  }
84
84
  exports.downloadDefault = downloadDefault;
85
85
  // Delete a file or folder by path
86
- async function deleteFile(accountId, filePath, options = {}) {
86
+ async function deleteFile(accountId, filePath) {
87
87
  return http_1.default.delete(accountId, {
88
88
  url: `${exports.FILE_MAPPER_API_PATH}/delete/${encodeURIComponent(filePath)}`,
89
- ...options,
90
89
  });
91
90
  }
92
91
  exports.deleteFile = deleteFile;
@@ -94,6 +93,7 @@ exports.deleteFile = deleteFile;
94
93
  async function moveFile(accountId, srcPath, destPath) {
95
94
  return http_1.default.put(accountId, {
96
95
  url: `${exports.FILE_MAPPER_API_PATH}/rename/${srcPath}?path=${destPath}`,
96
+ headers: { 'Content-Type': 'application/json' },
97
97
  });
98
98
  }
99
99
  exports.moveFile = moveFile;
@@ -1,4 +1,7 @@
1
+ import { QueryParams } from '../types/Http';
1
2
  import { GetBuildStatusResponse, GetRoutesResponse } from '../types/Functions';
2
3
  export declare function getRoutes(accountId: number): Promise<GetRoutesResponse>;
4
+ export declare function getFunctionLogs(accountId: number, route: string, query?: QueryParams): Promise<unknown>;
5
+ export declare function getLatestFunctionLog(accountId: number, route: string): Promise<unknown>;
3
6
  export declare function buildPackage(accountId: number, folderPath: string): Promise<string>;
4
- export declare function getBuildStatus(portalId: number, buildId: number): Promise<GetBuildStatusResponse>;
7
+ export declare function getBuildStatus(accountId: number, buildId: number): Promise<GetBuildStatusResponse>;
package/api/functions.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getBuildStatus = exports.buildPackage = exports.getRoutes = void 0;
6
+ exports.getBuildStatus = exports.buildPackage = exports.getLatestFunctionLog = exports.getFunctionLogs = exports.getRoutes = void 0;
7
7
  const http_1 = __importDefault(require("../http"));
8
8
  const FUNCTION_API_PATH = 'cms/v3/functions';
9
9
  async function getRoutes(accountId) {
@@ -12,6 +12,20 @@ async function getRoutes(accountId) {
12
12
  });
13
13
  }
14
14
  exports.getRoutes = getRoutes;
15
+ async function getFunctionLogs(accountId, route, query = {}) {
16
+ const { limit = 5 } = query;
17
+ return http_1.default.get(accountId, {
18
+ url: `${FUNCTION_API_PATH}/results/by-route/${encodeURIComponent(route)}`,
19
+ query: { ...query, limit },
20
+ });
21
+ }
22
+ exports.getFunctionLogs = getFunctionLogs;
23
+ async function getLatestFunctionLog(accountId, route) {
24
+ return http_1.default.get(accountId, {
25
+ url: `${FUNCTION_API_PATH}/results/by-route/${encodeURIComponent(route)}/latest`,
26
+ });
27
+ }
28
+ exports.getLatestFunctionLog = getLatestFunctionLog;
15
29
  async function buildPackage(accountId, folderPath) {
16
30
  return http_1.default.post(accountId, {
17
31
  url: `${FUNCTION_API_PATH}/build/async`,
@@ -24,8 +38,8 @@ async function buildPackage(accountId, folderPath) {
24
38
  });
25
39
  }
26
40
  exports.buildPackage = buildPackage;
27
- async function getBuildStatus(portalId, buildId) {
28
- return http_1.default.get(portalId, {
41
+ async function getBuildStatus(accountId, buildId) {
42
+ return http_1.default.get(accountId, {
29
43
  url: `${FUNCTION_API_PATH}/build/${buildId}/poll`,
30
44
  });
31
45
  }
package/api/projects.js CHANGED
@@ -50,7 +50,7 @@ async function downloadProject(accountId, projectName, buildId) {
50
50
  return http_1.default.get(accountId, {
51
51
  url: `${PROJECTS_API_PATH}/${encodeURIComponent(projectName)}/builds/${buildId}/archive-full`,
52
52
  encoding: null,
53
- headers: { accept: 'application/zip', contentType: 'application/json' },
53
+ headers: { accept: 'application/zip', 'Content-Type': 'application/json' },
54
54
  });
55
55
  }
56
56
  exports.downloadProject = downloadProject;
@@ -5,10 +5,7 @@ export declare function isMissingScopeError(err: AxiosError<any>): boolean;
5
5
  export declare function isGatingError(err: AxiosError<any>): boolean;
6
6
  export declare function isApiUploadValidationError(err: AxiosError<any>): boolean;
7
7
  export declare function isSpecifiedHubSpotAuthError(err: GenericError, { status, category, subCategory }: Partial<HubSpotAuthError>): boolean;
8
- /**
9
- * @throws
10
- */
11
- export declare function throwAxiosErrorWithContext(error: AxiosError<any>, context?: AxiosErrorContext): never;
8
+ export declare function getAxiosErrorWithContext(error: AxiosError<any>, context?: AxiosErrorContext): Error;
12
9
  /**
13
10
  * @throws
14
11
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.throwApiUploadError = exports.throwApiError = exports.throwAxiosErrorWithContext = exports.isSpecifiedHubSpotAuthError = exports.isApiUploadValidationError = exports.isGatingError = exports.isMissingScopeError = void 0;
3
+ exports.throwApiUploadError = exports.throwApiError = exports.getAxiosErrorWithContext = exports.isSpecifiedHubSpotAuthError = exports.isApiUploadValidationError = exports.isGatingError = exports.isMissingScopeError = void 0;
4
4
  const api_1 = require("../constants/api");
5
5
  const lang_1 = require("../utils/lang");
6
6
  const standardErrors_1 = require("./standardErrors");
@@ -57,37 +57,40 @@ function parseValidationErrors(responseData = { errors: [], message: '' }) {
57
57
  }
58
58
  return errorMessages;
59
59
  }
60
+ /**
61
+ * @throws
62
+ */
60
63
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
- function logValidationErrors(error) {
64
+ function throwValidationErrors(error) {
62
65
  const validationErrorMessages = parseValidationErrors(error?.response?.data);
63
66
  if (validationErrorMessages.length) {
64
67
  (0, standardErrors_1.throwError)(new Error(validationErrorMessages.join(' '), { cause: error }));
65
68
  }
66
69
  }
67
- /**
68
- * @throws
69
- */
70
- function throwAxiosErrorWithContext(
70
+ function getAxiosErrorWithContext(
71
71
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
72
  error, context = {}) {
73
73
  const { status } = error;
74
74
  const method = error.config?.method;
75
75
  const { projectName } = context;
76
- const isPutOrPost = method === 'put' || method === 'post';
77
- const action = method && (api_1.HTTP_METHOD_VERBS[method] || api_1.HTTP_METHOD_VERBS.get);
78
- const preposition = (method && api_1.HTTP_METHOD_PREPOSITIONS[method]) ||
79
- api_1.HTTP_METHOD_PREPOSITIONS.get;
80
- const request = context.request
81
- ? `${action} ${preposition} "${context.request}"`
82
- : action;
83
- const messageDetail = request && context.accountId
84
- ? (0, lang_1.i18n)(`${i18nKey}.messageDetail`, {
85
- request,
76
+ let messageDetail;
77
+ if (context.accountId) {
78
+ const action = (method && api_1.HTTP_METHOD_VERBS[method]) || api_1.HTTP_METHOD_VERBS.get;
79
+ const preposition = (method && api_1.HTTP_METHOD_PREPOSITIONS[method]) ||
80
+ api_1.HTTP_METHOD_PREPOSITIONS.get;
81
+ const requestName = context.request
82
+ ? `${action} ${preposition} '${context.request}'`
83
+ : action;
84
+ messageDetail = (0, lang_1.i18n)(`${i18nKey}.messageDetail`, {
86
85
  accountId: context.accountId,
87
- })
88
- : 'request';
86
+ requestName,
87
+ });
88
+ }
89
+ else {
90
+ messageDetail = (0, lang_1.i18n)(`${i18nKey}.genericMessageDetail`);
91
+ }
89
92
  const errorMessage = [];
90
- if (isPutOrPost && context.payload) {
93
+ if ((method === 'put' || method === 'post') && context.payload) {
91
94
  errorMessage.push((0, lang_1.i18n)(`${i18nKey}.unableToUpload`, { payload: context.payload }));
92
95
  }
93
96
  const isProjectMissingScopeError = isMissingScopeError(error) && projectName;
@@ -101,12 +104,12 @@ error, context = {}) {
101
104
  break;
102
105
  case 403:
103
106
  if (isProjectMissingScopeError) {
104
- errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.403MissingScope`, {
107
+ errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.403ProjectMissingScope`, {
105
108
  accountId: context.accountId || '',
106
109
  }));
107
110
  }
108
111
  else if (isProjectGatingError) {
109
- errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.403Gating`, {
112
+ errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.403ProjectGating`, {
110
113
  accountId: context.accountId || '',
111
114
  }));
112
115
  }
@@ -115,16 +118,7 @@ error, context = {}) {
115
118
  }
116
119
  break;
117
120
  case 404:
118
- if (context.request) {
119
- errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.404Request`, {
120
- action: action || 'request',
121
- request: context.request,
122
- account: context.accountId || '',
123
- }));
124
- }
125
- else {
126
- errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.404`, { messageDetail }));
127
- }
121
+ errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.404`, { messageDetail }));
128
122
  break;
129
123
  case 429:
130
124
  errorMessage.push((0, lang_1.i18n)(`${i18nKey}.codes.429`, { messageDetail }));
@@ -144,25 +138,28 @@ error, context = {}) {
144
138
  }
145
139
  break;
146
140
  }
147
- if (error?.response?.data?.message &&
148
- !isProjectMissingScopeError &&
149
- !isProjectGatingError) {
150
- errorMessage.push(error.response.data.message);
151
- }
152
- if (error?.response?.data?.errors) {
153
- error.response.data.errors.forEach((err) => {
154
- errorMessage.push('\n- ' + err.message);
155
- });
141
+ if (error?.response?.data) {
142
+ const { message, errors } = error.response.data;
143
+ if (message && !isProjectMissingScopeError && !isProjectGatingError) {
144
+ errorMessage.push(message);
145
+ }
146
+ if (errors) {
147
+ errors.forEach((err) => {
148
+ if (err.message) {
149
+ errorMessage.push('\n- ' + err.message);
150
+ }
151
+ });
152
+ }
156
153
  }
157
- (0, standardErrors_1.throwError)(new Error(errorMessage.join(' '), { cause: error }));
154
+ return new Error(errorMessage.join(' '), { cause: error });
158
155
  }
159
- exports.throwAxiosErrorWithContext = throwAxiosErrorWithContext;
156
+ exports.getAxiosErrorWithContext = getAxiosErrorWithContext;
160
157
  /**
161
158
  * @throws
162
159
  */
163
160
  function throwApiError(error, context = {}) {
164
161
  if (error.isAxiosError) {
165
- throwAxiosErrorWithContext(error, context);
162
+ throw getAxiosErrorWithContext(error, context);
166
163
  }
167
164
  (0, standardErrors_1.throwError)(error);
168
165
  }
@@ -172,7 +169,7 @@ exports.throwApiError = throwApiError;
172
169
  */
173
170
  function throwApiUploadError(error, context = {}) {
174
171
  if (isApiUploadValidationError(error)) {
175
- logValidationErrors(error);
172
+ throwValidationErrors(error);
176
173
  }
177
174
  throwApiError(error, context);
178
175
  }
@@ -1,4 +1,5 @@
1
1
  import { BaseError, FileSystemErrorContext } from '../types/Error';
2
+ export declare function getFileSystemError(error: BaseError, context: FileSystemErrorContext): Error;
2
3
  /**
3
4
  * @throws
4
5
  */
@@ -1,13 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.throwFileSystemError = void 0;
3
+ exports.throwFileSystemError = exports.getFileSystemError = void 0;
4
4
  const lang_1 = require("../utils/lang");
5
5
  const standardErrors_1 = require("./standardErrors");
6
6
  const i18nKey = 'errors.fileSystemErrors';
7
- /**
8
- * @throws
9
- */
10
- function throwFileSystemError(error, context) {
7
+ function getFileSystemError(error, context) {
11
8
  let fileAction = '';
12
9
  if (context.read) {
13
10
  fileAction = (0, lang_1.i18n)(`${i18nKey}.readAction`);
@@ -26,6 +23,13 @@ function throwFileSystemError(error, context) {
26
23
  if ((0, standardErrors_1.isSystemError)(error)) {
27
24
  message.push((0, lang_1.i18n)(`${i18nKey}.baseMessage`, { errorMessage: error.message }));
28
25
  }
29
- throw new Error(message.join(' '), { cause: error });
26
+ return new Error(message.join(' '), { cause: error });
27
+ }
28
+ exports.getFileSystemError = getFileSystemError;
29
+ /**
30
+ * @throws
31
+ */
32
+ function throwFileSystemError(error, context) {
33
+ throw getFileSystemError(error, context);
30
34
  }
31
35
  exports.throwFileSystemError = throwFileSystemError;
@@ -9,12 +9,6 @@ export declare function isFatalError(err: BaseError): boolean;
9
9
  export declare function throwErrorWithMessage(identifier: LangKey, interpolation?: {
10
10
  [key: string]: string | number;
11
11
  }, cause?: BaseError): never;
12
- /**
13
- * @throws
14
- */
15
- export declare function throwTypeErrorWithMessage(identifier: LangKey, interpolation?: {
16
- [key: string]: string | number;
17
- }, cause?: BaseError): never;
18
12
  /**
19
13
  * @throws
20
14
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.throwError = exports.throwAuthErrorWithMessage = exports.throwTypeErrorWithMessage = exports.throwErrorWithMessage = exports.isFatalError = exports.isSystemError = void 0;
3
+ exports.throwError = exports.throwAuthErrorWithMessage = exports.throwErrorWithMessage = exports.isFatalError = exports.isSystemError = void 0;
4
4
  const HubSpotAuthError_1 = require("../models/HubSpotAuthError");
5
5
  const lang_1 = require("../utils/lang");
6
6
  function isSystemError(err) {
@@ -25,13 +25,6 @@ function throwErrorWithMessage(identifier, interpolation, cause) {
25
25
  genericThrowErrorWithMessage(Error, identifier, interpolation, cause);
26
26
  }
27
27
  exports.throwErrorWithMessage = throwErrorWithMessage;
28
- /**
29
- * @throws
30
- */
31
- function throwTypeErrorWithMessage(identifier, interpolation, cause) {
32
- genericThrowErrorWithMessage(TypeError, identifier, interpolation, cause);
33
- }
34
- exports.throwTypeErrorWithMessage = throwTypeErrorWithMessage;
35
28
  /**
36
29
  * @throws
37
30
  */
@@ -8,12 +8,13 @@ exports.DEFAULT_USER_AGENT_HEADERS = {
8
8
  'User-Agent': `HubSpot Local Dev Lib/${package_json_1.version}`,
9
9
  };
10
10
  function getAxiosConfig(options) {
11
- const { env, localHostOverride, ...rest } = options;
11
+ const { env, localHostOverride, headers, ...rest } = options;
12
12
  const { httpTimeout, httpUseLocalhost } = (0, config_1.getAndLoadConfigIfNeeded)();
13
13
  return {
14
14
  baseURL: (0, urls_1.getHubSpotApiOrigin)(env, localHostOverride ? false : httpUseLocalhost),
15
15
  headers: {
16
16
  ...exports.DEFAULT_USER_AGENT_HEADERS,
17
+ ...(headers || {}),
17
18
  },
18
19
  timeout: httpTimeout || 15000,
19
20
  ...rest,
package/lang/en.json CHANGED
@@ -379,7 +379,8 @@
379
379
  "baseMessage": "An error occurred while {{ fileAction }} {{ filepath }}."
380
380
  },
381
381
  "apiErrors": {
382
- "messageDetail": "{{ request }} in account {{ accountId }}",
382
+ "messageDetail": "{{ requestName }} in account {{ accountId }}",
383
+ "genericMessageDetail": "request",
383
384
  "unableToUpload": "Unable to upload \"{{ payload }}.",
384
385
  "codes": {
385
386
  "400": "The {{ messageDetail }} was bad.",
@@ -388,9 +389,8 @@
388
389
  "404": "The {{ messageDetail }} was not found.",
389
390
  "429": "The {{ messageDetail }} surpassed the rate limit. Retry in one minute.",
390
391
  "503": "The {{ messageDetail }} could not be handled at this time. Please try again or visit https://help.hubspot.com/ to submit a ticket or contact HubSpot Support if the issue persists.",
391
- "403MissingScope": "Couldn't run the project command because there are scopes missing in your production account. To update scopes, deactivate your current personal access key for {{ accountId }}, and generate a new one. Then run `hs auth` to update the CLI with the new key.",
392
- "403Gating": "The current target account {{ accountId }} does not have access to HubSpot projects. To opt in to the CRM Development Beta and use projects, visit https://app.hubspot.com/l/whats-new/betas?productUpdateId=13860216.",
393
- "404Request": "The {{ action }} failed because \"{{ request }}\" was not found in account {{ accountId }}.",
392
+ "403ProjectMissingScope": "Couldn't run the project command because there are scopes missing in your production account. To update scopes, deactivate your current personal access key for {{ accountId }}, and generate a new one. Then run `hs auth` to update the CLI with the new key.",
393
+ "403ProjectGating": "The current target account {{ accountId }} does not have access to HubSpot projects. To opt in to the CRM Development Beta and use projects, visit https://app.hubspot.com/l/whats-new/betas?productUpdateId=13860216.",
394
394
  "500Generic": "The {{ messageDetail }} failed due to a server error. Please try again or visit https://help.hubspot.com/ to submit a ticket or contact HubSpot Support if the issue persists.",
395
395
  "400Generic": "The {{ messageDetail }} failed due to a client error.",
396
396
  "generic": "The {{ messageDetail }} failed."
package/lang/lang/en.json CHANGED
@@ -379,7 +379,8 @@
379
379
  "baseMessage": "An error occurred while {{ fileAction }} {{ filepath }}."
380
380
  },
381
381
  "apiErrors": {
382
- "messageDetail": "{{ request }} in account {{ accountId }}",
382
+ "messageDetail": "{{ requestName }} in account {{ accountId }}",
383
+ "genericMessageDetail": "request",
383
384
  "unableToUpload": "Unable to upload \"{{ payload }}.",
384
385
  "codes": {
385
386
  "400": "The {{ messageDetail }} was bad.",
@@ -388,9 +389,8 @@
388
389
  "404": "The {{ messageDetail }} was not found.",
389
390
  "429": "The {{ messageDetail }} surpassed the rate limit. Retry in one minute.",
390
391
  "503": "The {{ messageDetail }} could not be handled at this time. Please try again or visit https://help.hubspot.com/ to submit a ticket or contact HubSpot Support if the issue persists.",
391
- "403MissingScope": "Couldn't run the project command because there are scopes missing in your production account. To update scopes, deactivate your current personal access key for {{ accountId }}, and generate a new one. Then run `hs auth` to update the CLI with the new key.",
392
- "403Gating": "The current target account {{ accountId }} does not have access to HubSpot projects. To opt in to the CRM Development Beta and use projects, visit https://app.hubspot.com/l/whats-new/betas?productUpdateId=13860216.",
393
- "404Request": "The {{ action }} failed because \"{{ request }}\" was not found in account {{ accountId }}.",
392
+ "403ProjectMissingScope": "Couldn't run the project command because there are scopes missing in your production account. To update scopes, deactivate your current personal access key for {{ accountId }}, and generate a new one. Then run `hs auth` to update the CLI with the new key.",
393
+ "403ProjectGating": "The current target account {{ accountId }} does not have access to HubSpot projects. To opt in to the CRM Development Beta and use projects, visit https://app.hubspot.com/l/whats-new/betas?productUpdateId=13860216.",
394
394
  "500Generic": "The {{ messageDetail }} failed due to a server error. Please try again or visit https://help.hubspot.com/ to submit a ticket or contact HubSpot Support if the issue persists.",
395
395
  "400Generic": "The {{ messageDetail }} failed due to a client error.",
396
396
  "generic": "The {{ messageDetail }} failed."
package/lib/fileMapper.js CHANGED
@@ -82,7 +82,7 @@ function validateFileMapperNode(node) {
82
82
  catch (err) {
83
83
  json = node;
84
84
  }
85
- (0, standardErrors_1.throwTypeErrorWithMessage)(`${i18nKey}.errors.invalidNode`, {
85
+ (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.invalidNode`, {
86
86
  json: JSON.stringify(json),
87
87
  });
88
88
  }
package/lib/oauth.js CHANGED
@@ -32,7 +32,7 @@ function addOauthToAccountConfig(oauth, logCallbacks) {
32
32
  logger('init', `${i18nKey}.addOauthToAccountConfig.init`);
33
33
  try {
34
34
  (0, config_1.updateAccountConfig)({
35
- ...oauth.toObj(),
35
+ ...oauth.account,
36
36
  authType: auth_1.AUTH_METHODS.oauth.value,
37
37
  });
38
38
  (0, config_1.writeConfig)();
@@ -1,4 +1,16 @@
1
- import { FlatAccountFields, OAuthAccount, TokenInfo } from '../types/Accounts';
1
+ import { FlatAccountFields, TokenInfo } from '../types/Accounts';
2
+ import { Environment } from '../types/Config';
3
+ type OAuth2ManagerAccountConfig = {
4
+ name?: string;
5
+ accountId?: number;
6
+ clientId?: string;
7
+ clientSecret?: string;
8
+ scopes?: Array<string>;
9
+ env?: Environment;
10
+ environment?: Environment;
11
+ tokenInfo?: TokenInfo;
12
+ authType?: 'oauth2';
13
+ };
2
14
  type WriteTokenInfoFunction = (tokenInfo: TokenInfo) => void;
3
15
  type RefreshTokenResponse = {
4
16
  refresh_token: string;
@@ -12,23 +24,14 @@ type ExchangeProof = {
12
24
  refresh_token?: string;
13
25
  };
14
26
  declare class OAuth2Manager {
15
- account: OAuthAccount;
16
- writeTokenInfo: WriteTokenInfoFunction;
27
+ account: OAuth2ManagerAccountConfig;
28
+ writeTokenInfo?: WriteTokenInfoFunction;
17
29
  refreshTokenRequest: Promise<RefreshTokenResponse> | null;
18
- constructor(account: OAuthAccount, writeTokenInfo: WriteTokenInfoFunction);
30
+ constructor(account: OAuth2ManagerAccountConfig, writeTokenInfo?: WriteTokenInfoFunction);
19
31
  accessToken(): Promise<string | undefined>;
20
32
  fetchAccessToken(exchangeProof: ExchangeProof): Promise<void>;
21
33
  exchangeForTokens(exchangeProof: ExchangeProof): Promise<void>;
22
34
  refreshAccessToken(): Promise<void>;
23
- toObj(): {
24
- env: import("../types/Config").Environment;
25
- clientSecret: string | undefined;
26
- clientId: string | undefined;
27
- scopes: string[] | undefined;
28
- tokenInfo: TokenInfo | undefined;
29
- name: string | undefined;
30
- accountId: number;
31
- };
32
35
  static fromConfig(accountConfig: FlatAccountFields, writeTokenInfo: WriteTokenInfoFunction): OAuth2Manager;
33
36
  }
34
37
  export default OAuth2Manager;
@@ -25,45 +25,47 @@ class OAuth2Manager {
25
25
  }
26
26
  }
27
27
  async accessToken() {
28
- if (!this.account.auth.tokenInfo?.refreshToken) {
28
+ if (!this.account.tokenInfo?.refreshToken) {
29
29
  (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.missingRefreshToken`, {
30
30
  accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
31
31
  });
32
32
  }
33
- if (!this.account.auth.tokenInfo?.accessToken ||
33
+ if (!this.account.tokenInfo?.accessToken ||
34
34
  (0, moment_1.default)()
35
35
  .add(5, 'minutes')
36
- .isAfter((0, moment_1.default)(this.account.auth?.tokenInfo.expiresAt))) {
36
+ .isAfter((0, moment_1.default)(new Date(this.account.tokenInfo.expiresAt || '')))) {
37
37
  await this.refreshAccessToken();
38
38
  }
39
- return this.account.auth?.tokenInfo.accessToken;
39
+ return this.account.tokenInfo.accessToken;
40
40
  }
41
41
  async fetchAccessToken(exchangeProof) {
42
42
  (0, logger_1.debug)(`${i18nKey}.fetchingAccessToken`, {
43
43
  accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
44
- clientId: this.account.auth.clientId || '',
44
+ clientId: this.account.clientId || '',
45
45
  });
46
46
  try {
47
- const { data } = await axios_1.default.post(`${(0, urls_1.getHubSpotApiOrigin)((0, environment_1.getValidEnv)(this.account.env))}/oauth/v1/token`, {
48
- form: exchangeProof,
49
- json: true,
47
+ const { data } = await (0, axios_1.default)({
48
+ url: `${(0, urls_1.getHubSpotApiOrigin)((0, environment_1.getValidEnv)(this.account.env))}/oauth/v1/token`,
49
+ method: 'post',
50
+ data: exchangeProof,
51
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
50
52
  });
51
53
  this.refreshTokenRequest = data;
52
54
  const { refresh_token: refreshToken, access_token: accessToken, expires_in: expiresIn, } = data;
53
- if (!this.account.auth.tokenInfo) {
54
- this.account.auth.tokenInfo = {};
55
+ if (!this.account.tokenInfo) {
56
+ this.account.tokenInfo = {};
55
57
  }
56
- this.account.auth.tokenInfo.refreshToken = refreshToken;
57
- this.account.auth.tokenInfo.accessToken = accessToken;
58
- this.account.auth.tokenInfo.expiresAt = (0, moment_1.default)()
58
+ this.account.tokenInfo.refreshToken = refreshToken;
59
+ this.account.tokenInfo.accessToken = accessToken;
60
+ this.account.tokenInfo.expiresAt = (0, moment_1.default)()
59
61
  .add(Math.round(parseInt(expiresIn) * 0.75), 'seconds')
60
62
  .toString();
61
63
  if (this.writeTokenInfo) {
62
64
  (0, logger_1.debug)(`${i18nKey}.updatingTokenInfo`, {
63
65
  accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
64
- clientId: this.account.auth.clientId || '',
66
+ clientId: this.account.clientId || '',
65
67
  });
66
- this.writeTokenInfo(this.account.auth.tokenInfo);
68
+ this.writeTokenInfo(this.account.tokenInfo);
67
69
  }
68
70
  this.refreshTokenRequest = null;
69
71
  }
@@ -77,7 +79,7 @@ class OAuth2Manager {
77
79
  if (this.refreshTokenRequest) {
78
80
  (0, logger_1.debug)(`${i18nKey}.refreshingAccessToken`, {
79
81
  accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
80
- clientId: this.account.auth.clientId || '',
82
+ clientId: this.account.clientId || '',
81
83
  });
82
84
  await this.refreshTokenRequest;
83
85
  }
@@ -100,28 +102,17 @@ class OAuth2Manager {
100
102
  async refreshAccessToken() {
101
103
  const refreshTokenProof = {
102
104
  grant_type: 'refresh_token',
103
- client_id: this.account.auth.clientId,
104
- client_secret: this.account.auth.clientSecret,
105
- refresh_token: this.account.auth.tokenInfo?.refreshToken,
105
+ client_id: this.account.clientId,
106
+ client_secret: this.account.clientSecret,
107
+ refresh_token: this.account.tokenInfo?.refreshToken,
106
108
  };
107
109
  await this.exchangeForTokens(refreshTokenProof);
108
110
  }
109
- toObj() {
110
- return {
111
- env: this.account.env,
112
- clientSecret: this.account.auth.clientSecret,
113
- clientId: this.account.auth.clientId,
114
- scopes: this.account.auth.scopes,
115
- tokenInfo: this.account.auth.tokenInfo,
116
- name: this.account.name,
117
- accountId: (0, getAccountIdentifier_1.getAccountIdentifier)(this.account),
118
- };
119
- }
120
111
  static fromConfig(accountConfig, writeTokenInfo) {
121
112
  return new OAuth2Manager({
122
113
  ...accountConfig,
123
114
  authType: auth_1.AUTH_METHODS.oauth.value,
124
- auth: accountConfig.auth || {},
115
+ ...(accountConfig.auth || {}),
125
116
  }, writeTokenInfo);
126
117
  }
127
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/local-dev-lib",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Provides library functionality for HubSpot local development tooling, including the HubSpot CLI",
5
5
  "main": "lib/index.js",
6
6
  "repository": {
@@ -54,7 +54,8 @@
54
54
  "./http": "./http/index.js",
55
55
  "./config": "./config/index.js",
56
56
  "./constants/*": "./constants/*.js",
57
- "./logger": "./lib/logging/logger.js"
57
+ "./logger": "./lib/logging/logger.js",
58
+ "./models/*": "./models/*.js"
58
59
  },
59
60
  "dependencies": {
60
61
  "address": "^2.0.1",
package/types/Http.d.ts CHANGED
@@ -15,6 +15,7 @@ export type AxiosConfigOptions = {
15
15
  data?: Data;
16
16
  resolveWithFullResponse?: boolean;
17
17
  timeout?: number;
18
+ headers?: Data;
18
19
  };
19
20
  export type FormData = {
20
21
  [key: string]: string | ReadStream;
@@ -19,7 +19,7 @@ exports.isPathInput = isPathInput;
19
19
  function throwInvalidPathInput(pathInput) {
20
20
  if (isPathInput(pathInput))
21
21
  return;
22
- (0, standardErrors_1.throwTypeErrorWithMessage)(`${i18nKey}.throwInvalidPathInput`);
22
+ (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.throwInvalidPathInput`);
23
23
  }
24
24
  function isModuleFolder(pathInput) {
25
25
  throwInvalidPathInput(pathInput);