@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.
- package/dist/src/client.d.ts +188 -0
- package/dist/src/client.js +358 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/errors.d.ts +28 -9
- package/dist/src/errors.js +84 -12
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +3 -14
- package/dist/src/index.js +16 -74
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +41 -131
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +8 -5
- package/dist/src/util.d.ts +0 -8
- package/dist/src/util.js +0 -25
- package/dist/src/util.js.map +0 -1
package/dist/src/errors.js
CHANGED
|
@@ -1,15 +1,87 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
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
|
package/dist/src/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export
|
|
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
|
|
3
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,0CAAwB"}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,132 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
}
|