@jupiterone/integration-sdk-http-client 12.1.0 → 12.2.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.
@@ -1,15 +1,87 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.APIError = void 0;
4
- class APIError extends Error {
5
- /**
6
- * Code associated with the error.
7
- */
8
- code;
9
- constructor(config) {
10
- super(config.message);
11
- this.code = config.code;
12
- }
13
- }
14
- exports.APIError = APIError;
3
+ exports.isRetryableRequest = exports.fatalRequestError = exports.retryableRequestError = exports.HTTPResponseError = exports.RateLimitError = exports.RetryableIntegrationProviderApiError = void 0;
4
+ const integration_sdk_core_1 = require("@jupiterone/integration-sdk-core");
5
+ class RetryableIntegrationProviderApiError extends integration_sdk_core_1.IntegrationProviderAPIError {
6
+ retryable = true;
7
+ }
8
+ exports.RetryableIntegrationProviderApiError = RetryableIntegrationProviderApiError;
9
+ class RateLimitError extends RetryableIntegrationProviderApiError {
10
+ constructor(options) {
11
+ super(options);
12
+ this.retryAfter = options.retryAfter;
13
+ }
14
+ retryAfter;
15
+ }
16
+ exports.RateLimitError = RateLimitError;
17
+ class HTTPResponseError extends Error {
18
+ response;
19
+ constructor(response) {
20
+ super(`HTTP Error Response: ${response.status} ${response.statusText}`);
21
+ this.response = response;
22
+ }
23
+ }
24
+ exports.HTTPResponseError = HTTPResponseError;
25
+ async function handleLogErrorBody(response, logger, logErrorBody) {
26
+ if (!logErrorBody) {
27
+ return;
28
+ }
29
+ let errorBody;
30
+ try {
31
+ errorBody = await response.json();
32
+ logger.error({ errBody: JSON.stringify(errorBody) }, 'Encountered error from API');
33
+ }
34
+ catch (e) {
35
+ // pass
36
+ }
37
+ }
38
+ async function retryableRequestError({ endpoint, response, logger, logErrorBody, }) {
39
+ await handleLogErrorBody(response, logger, logErrorBody);
40
+ if (response.status === 429) {
41
+ return new RateLimitError({
42
+ cause: new HTTPResponseError(response),
43
+ status: response.status,
44
+ statusText: response.statusText,
45
+ endpoint,
46
+ retryAfter: Number(response.headers.get('retry-after')),
47
+ });
48
+ }
49
+ return new RetryableIntegrationProviderApiError({
50
+ cause: new HTTPResponseError(response),
51
+ endpoint,
52
+ status: response.status,
53
+ statusText: response.statusText,
54
+ });
55
+ }
56
+ exports.retryableRequestError = retryableRequestError;
57
+ async function fatalRequestError({ endpoint, response, logger, logErrorBody, }) {
58
+ await handleLogErrorBody(response, logger, logErrorBody);
59
+ const apiErrorOptions = {
60
+ cause: new HTTPResponseError(response),
61
+ endpoint,
62
+ status: response.status,
63
+ statusText: response.statusText,
64
+ };
65
+ if (response.status === 401) {
66
+ return new integration_sdk_core_1.IntegrationProviderAuthenticationError(apiErrorOptions);
67
+ }
68
+ else if (response.status === 403) {
69
+ return new integration_sdk_core_1.IntegrationProviderAuthorizationError(apiErrorOptions);
70
+ }
71
+ else {
72
+ return new integration_sdk_core_1.IntegrationProviderAPIError(apiErrorOptions);
73
+ }
74
+ }
75
+ exports.fatalRequestError = fatalRequestError;
76
+ /**
77
+ * Function for determining if a request is retryable
78
+ * based on the returned status.
79
+ */
80
+ function isRetryableRequest({ status }) {
81
+ return (
82
+ // 5xx error from provider (their fault, might be retryable)
83
+ // 429 === too many requests, we got rate limited so safe to try again
84
+ status >= 500 || status === 429);
85
+ }
86
+ exports.isRetryableRequest = isRetryableRequest;
15
87
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;AAMA,MAAa,QAAS,SAAQ,KAAK;IACjC;;OAEG;IACM,IAAI,CAAS;IAEtB,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;CACF;AAVD,4BAUC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,3 @@
1
- import { RateLimitConfig, APIResponse, APIRequest } from './types';
2
- export declare const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig;
3
- export type APIResourceIterationCallback<T> = (resources: T[]) => boolean | void | Promise<boolean | void>;
4
- export declare class APIClient {
5
- private rateLimitConfig;
6
- private rateLimitState;
7
- executeAPIRequest(request: APIRequest): Promise<APIResponse>;
8
- /**
9
- * Get rate limit info, sleep, and then loop to retry
10
- *
11
- * @param headers
12
- */
13
- private handleRateLimitError;
14
- }
1
+ export * from './client';
2
+ export * from './errors';
3
+ export * from './types';
package/dist/src/index.js CHANGED
@@ -1,78 +1,20 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
4
15
  };
5
16
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.APIClient = exports.DEFAULT_RATE_LIMIT_CONFIG = void 0;
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- const util_1 = require("./util");
9
- const errors_1 = require("./errors");
10
- exports.DEFAULT_RATE_LIMIT_CONFIG = {
11
- maxAttempts: 5,
12
- reserveLimit: 30,
13
- cooldownPeriod: 1000,
14
- sleepAdditionalSeconds: 0,
15
- };
16
- class APIClient {
17
- // TODO (adam-in-ict) make rateLimitConfig configurable and only use the default values when none are provided
18
- rateLimitConfig = exports.DEFAULT_RATE_LIMIT_CONFIG;
19
- rateLimitState;
20
- async executeAPIRequest(request) {
21
- let attempts = 0;
22
- do {
23
- const response = await (0, node_fetch_1.default)(request.url, request);
24
- if ((0, util_1.isNonRetryableError)(response.status)) {
25
- const err = new errors_1.APIError({
26
- message: `API request error for ${request.url}: ${response.status} ${response.statusText}`,
27
- code: response.status,
28
- });
29
- throw err;
30
- }
31
- // TODO (adam-in-ict) make rate limit error configurable for instances where an API isn't using the default of 429
32
- if (response.status === 429) {
33
- await this.handleRateLimitError(response.headers);
34
- }
35
- else {
36
- // Successful response, so return
37
- return {
38
- data: await response.json(),
39
- headers: response.headers,
40
- status: response.status,
41
- statusText: response.statusText,
42
- };
43
- }
44
- attempts += 1;
45
- } while (attempts < this.rateLimitConfig.maxAttempts);
46
- throw new errors_1.APIError({
47
- message: `Could not complete request within ${attempts} attempts!`,
48
- code: 429,
49
- });
50
- }
51
- //TODO (adam-in-ict) abstract out which Header values we're grabbing for rate limiting.
52
- /**
53
- * Get rate limit info, sleep, and then loop to retry
54
- *
55
- * @param headers
56
- */
57
- async handleRateLimitError(headers) {
58
- this.rateLimitState = {
59
- limitRemaining: Number(headers.get('X-RateLimit-Remaining')),
60
- perMinuteLimit: Number(headers.get('X-RateLimit-Limit')),
61
- retryAfter: headers.get('X-RateLimit-RetryAfter') &&
62
- Number(headers.get('X-RateLimit-RetryAfter')),
63
- };
64
- const unixTimeNow = (0, util_1.getUnixTimeNow)();
65
- const timeToSleepInSeconds = this.rateLimitState.retryAfter
66
- ? Math.max(this.rateLimitState.retryAfter +
67
- this.rateLimitConfig.sleepAdditionalSeconds -
68
- unixTimeNow, 0)
69
- : 0;
70
- await (0, util_1.sleep)(timeToSleepInSeconds * 1000);
71
- if (this.rateLimitState.limitRemaining &&
72
- this.rateLimitState.limitRemaining <= this.rateLimitConfig.reserveLimit) {
73
- await (0, util_1.sleep)(this.rateLimitConfig.cooldownPeriod);
74
- }
75
- }
76
- }
77
- exports.APIClient = APIClient;
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./errors"), exports);
19
+ __exportStar(require("./types"), exports);
78
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,4DAA+B;AAC/B,iCAAoE;AAOpE,qCAAoC;AAEvB,QAAA,yBAAyB,GAAoB;IACxD,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,EAAE;IAChB,cAAc,EAAE,IAAI;IACpB,sBAAsB,EAAE,CAAC;CAC1B,CAAC;AAMF,MAAa,SAAS;IACpB,8GAA8G;IACtG,eAAe,GAAoB,iCAAyB,CAAC;IAC7D,cAAc,CAAiB;IAEvC,KAAK,CAAC,iBAAiB,CAAC,OAAmB;QACzC,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,GAAG;YACD,MAAM,QAAQ,GAAG,MAAM,IAAA,oBAAK,EAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAEnD,IAAI,IAAA,0BAAmB,EAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACxC,MAAM,GAAG,GAAG,IAAI,iBAAQ,CAAC;oBACvB,OAAO,EAAE,yBAAyB,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE;oBAC1F,IAAI,EAAE,QAAQ,CAAC,MAAM;iBACtB,CAAC,CAAC;gBACH,MAAM,GAAG,CAAC;aACX;YAED,kHAAkH;YAClH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;gBAC3B,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aACnD;iBAAM;gBACL,iCAAiC;gBACjC,OAAO;oBACL,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE;oBAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;iBAChC,CAAC;aACH;YAED,QAAQ,IAAI,CAAC,CAAC;SACf,QAAQ,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE;QAEtD,MAAM,IAAI,iBAAQ,CAAC;YACjB,OAAO,EAAE,qCAAqC,QAAQ,YAAY;YAClE,IAAI,EAAE,GAAG;SACV,CAAC,CAAC;IACL,CAAC;IAED,uFAAuF;IACvF;;;;OAIG;IACK,KAAK,CAAC,oBAAoB,CAAC,OAAO;QACxC,IAAI,CAAC,cAAc,GAAG;YACpB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YAC5D,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACxD,UAAU,EACR,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;gBACrC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;SAChD,CAAC;QAEF,MAAM,WAAW,GAAG,IAAA,qBAAc,GAAE,CAAC;QACrC,MAAM,oBAAoB,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU;YACzD,CAAC,CAAC,IAAI,CAAC,GAAG,CACN,IAAI,CAAC,cAAc,CAAC,UAAU;gBAC5B,IAAI,CAAC,eAAe,CAAC,sBAAsB;gBAC3C,WAAW,EACb,CAAC,CACF;YACH,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,IAAA,YAAK,EAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;QACzC,IACE,IAAI,CAAC,cAAc,CAAC,cAAc;YAClC,IAAI,CAAC,cAAc,CAAC,cAAc,IAAI,IAAI,CAAC,eAAe,CAAC,YAAY,EACvE;YACA,MAAM,IAAA,YAAK,EAAC,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;SAClD;IACH,CAAC;CACF;AAzED,8BAyEC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,0CAAwB"}
@@ -1,132 +1,42 @@
1
- export type APIRequest = {
2
- url: string;
3
- method: string;
4
- headers: Object;
5
- };
6
- export type APIResponse = {
7
- data: any;
8
- headers: any;
9
- status: number;
10
- statusText: string;
11
- };
12
- type PaginationState = {
13
- /**
14
- * Fetch limit, will be URL encoded as value of `limit` GET parameter.
15
- */
16
- limit?: number;
17
- /**
18
- * Total number of objects reported in API response. The number is affected by
19
- * the filter, if any.
20
- */
21
- total?: number;
22
- /**
23
- * Fetch offset, a number to start from or a cursor, depending on API.
24
- */
25
- offset?: number | string;
26
- /**
27
- * Offset cursor expiration time, only present for cursor based API.
28
- */
29
- expiresAt?: number;
30
- /**
31
- * Similar to "offset", a value to start from aka a cursor.
32
- */
33
- after?: number | string;
34
- /**
35
- * Number of resources returned through pagination to the point of offset.
36
- */
37
- seen: number;
38
- /**
39
- * Number of pages returned through pagination to the point of offset.
40
- */
41
- pages: number;
42
- /**
43
- * Pagination has completed according to provided pagination parameters.
44
- */
45
- finished: boolean;
46
- };
47
- export type PaginationParams = Partial<PaginationState>;
48
- export type QueryParams = {
49
- filter?: string;
50
- [name: string]: string | undefined;
51
- };
52
- export type RateLimitConfig = {
53
- /**
54
- * The limit remaining value at which the client should slow down. This
55
- * prevents the client from consuming all available requests.
56
- */
57
- reserveLimit: number;
58
- /**
59
- * A recommended period of time in milliseconds to wait between requests when
60
- * the `reserveLimit` is reached.
61
- *
62
- * This can be a value representing the refill rate of a "leaky bucket" or
63
- * just a guess about how soon another request can be made. Ideally there will
64
- * be enough information in the response headers to calculate a better value.
65
- */
66
- cooldownPeriod: number;
67
- /**
68
- * Maximum number of times to retry a request that continues to receive 429
69
- * responses.
70
- *
71
- * The client will respect `x-ratelimit-retryafter`, but should it end up in a
72
- * battle to get the next allowed request, it will give up after this many
73
- * tries.
74
- */
1
+ import { IntegrationLogger } from '@jupiterone/integration-sdk-core';
2
+ import { AttemptContext } from '@lifeomic/attempt';
3
+ export type OptionalPromise<T> = T | Promise<T>;
4
+ export interface RequestOptions {
5
+ method?: 'GET' | 'POST';
6
+ body?: Record<string, unknown>;
7
+ headers?: Record<string, string>;
8
+ authorize?: boolean;
9
+ bucketTokens?: number;
10
+ }
11
+ export interface RetryOptions {
75
12
  maxAttempts: number;
76
- /**
77
- * Optional number of additional seconds to sleep in the event of a rate limit
78
- * event.
79
- */
80
- sleepAdditionalSeconds: number;
81
- };
82
- /**
83
- * The last seen values from rate limit response headers.
84
- */
85
- export type RateLimitState = {
86
- /**
87
- * Maximum number of requests per minute that can be made by all API clients
88
- * in a customer account. Initial value assumes the published default of 100.
89
- */
90
- perMinuteLimit: number;
91
- /**
92
- * Number of requests that remain in the account's rate limiting pool. The
93
- * total number available is not known.
94
- */
95
- limitRemaining: number;
96
- /**
97
- * The next time when an account's rate limit pool will have at least one
98
- * request available.
99
- */
100
- retryAfter?: number;
101
- };
102
- /**
103
- * Metadata in API responses indicating the pagination state.
104
- */
105
- export type PaginationMeta = {
106
- limit: number;
107
- total: number;
108
- offset: number | string;
109
- expires_at?: number;
110
- };
111
- type ResponseMeta = {
112
- trace_id: string;
113
- pagination?: PaginationMeta;
114
- };
115
- type ResponseError = {
116
- code: number;
117
- message: string;
118
- };
119
- export type ResourcesResponse<T> = {
120
- meta: ResponseMeta;
121
- errors: ResponseError[];
122
- resources: T[];
123
- };
124
- export type APIClientRateLimitConfig = {
125
- limitHeader: string;
126
- limitRemainingHeader: string;
127
- retryAfterHeader: string;
128
- };
129
- export type APIClientConfiguration = {
130
- rateLimitConfig: APIClientRateLimitConfig;
131
- };
132
- export {};
13
+ delay: number;
14
+ factor: number;
15
+ timeout: number;
16
+ handleError: (err: any, context: AttemptContext, logger: IntegrationLogger) => OptionalPromise<void>;
17
+ }
18
+ export interface RateLimitHeaders {
19
+ limit: string;
20
+ remaining: string;
21
+ reset: string;
22
+ }
23
+ export interface RateLimitThrottlingOptions {
24
+ threshold: number;
25
+ rateLimitHeaders?: RateLimitHeaders;
26
+ }
27
+ export interface TokenBucketOptions {
28
+ maximumCapacity: number;
29
+ refillRate: number;
30
+ }
31
+ export interface ClientConfig {
32
+ baseUrl: string;
33
+ logger: IntegrationLogger;
34
+ retryOptions?: Partial<RetryOptions>;
35
+ logErrorBody?: boolean;
36
+ rateLimitThrottling?: RateLimitThrottlingOptions;
37
+ tokenBucket?: TokenBucketOptions;
38
+ }
39
+ export interface IterateCallbackResult {
40
+ nextUrl?: string;
41
+ nextRequestOptions?: RequestOptions;
42
+ }