fetch-retrier 0.1.8 → 0.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/README.md +28 -5
- package/lib/index.d.ts +74 -7
- package/lib/index.js +112 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight wrapper around `fetch` that adds **retries**, **timeout**, and **full jitter** backoff. Useful for calling HTTP APIs that may be rate-limited (429) or temporarily unavailable (5xx).
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/fetch-retrier)
|
|
6
|
+
[](https://www.npmjs.com/package/fetch-retrier)
|
|
7
|
+
[](https://github.com/gammarers-labs/fetch-retrier/actions/workflows/build.yml)
|
|
8
|
+
[](https://github.com/gammarers-labs/fetch-retrier/actions/workflows/release.yml)
|
|
9
|
+
|
|
5
10
|
## Features
|
|
6
11
|
|
|
7
12
|
- **Configurable retries** – Set the maximum number of attempts per request.
|
|
8
13
|
- **Per-request timeout** – Abort requests that exceed a given duration.
|
|
9
14
|
- **Full jitter backoff** – Exponential backoff with random jitter (AWS-style) between retries.
|
|
10
15
|
- **Custom retry predicate** – Control which status codes trigger a retry (default: 429, 500, 502, 503, 504).
|
|
16
|
+
- **External cancellation** – Pass an `AbortSignal` to cancel an in-flight request.
|
|
11
17
|
- **TypeScript** – Exported types for `RequestOptions` and usage in TS/JS.
|
|
12
18
|
|
|
13
19
|
## Installation
|
|
@@ -54,6 +60,7 @@ if (response.ok) {
|
|
|
54
60
|
| `timeoutMs` | `number` | Yes | Timeout in milliseconds for each request. Requests are aborted when this is exceeded. |
|
|
55
61
|
| `baseBackoffMs` | `number` | Yes | Base delay in milliseconds for backoff. Delay is capped at `baseBackoffMs * 2^attempt` and randomized (full jitter). |
|
|
56
62
|
| `headers` | `Record<string, string>` | No | Headers to send with the request. |
|
|
63
|
+
| `signal` | `AbortSignal` | No | Optional external abort signal. If already aborted, `FetchRetrierAlreadyAbortedError` is thrown. If aborted during an attempt, the request is aborted and retried until `retries` is exhausted. |
|
|
57
64
|
| `shouldRetry` | `(response: Response, body: string) => boolean` | No | Custom predicate. Return `true` to retry on this response. Default: retry on status 429, 500, 502, 503, 504. |
|
|
58
65
|
|
|
59
66
|
### Custom retry logic
|
|
@@ -72,13 +79,29 @@ const response = await fetchRetrier('https://api.example.com/data', {
|
|
|
72
79
|
});
|
|
73
80
|
```
|
|
74
81
|
|
|
82
|
+
### Cancellation with `AbortController`
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
|
|
87
|
+
setTimeout(() => controller.abort(), 250);
|
|
88
|
+
|
|
89
|
+
await fetchRetrier('https://api.example.com/data', {
|
|
90
|
+
retries: 3,
|
|
91
|
+
timeoutMs: 5000,
|
|
92
|
+
baseBackoffMs: 250,
|
|
93
|
+
signal: controller.signal,
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
75
97
|
## Retry and error behavior
|
|
76
98
|
|
|
77
99
|
- **Success** – If `response.ok` is true, the response is returned immediately.
|
|
78
|
-
- **Retriable failure** – If the response is not OK and `shouldRetry(response, body)` returns true, the client waits (full jitter backoff) and retries until `retries` is exhausted. On the last attempt,
|
|
79
|
-
- **Non-retriable failure** – If `shouldRetry` returns false,
|
|
80
|
-
- **Timeout** – If a request exceeds `timeoutMs`, it is aborted and retried (same backoff) until `retries` is exhausted
|
|
81
|
-
- **Network/TypeError** – Network errors and related `TypeError`s are retried with backoff; after the last attempt, the error
|
|
100
|
+
- **Retriable failure** – If the response is not OK and `shouldRetry(response, body)` returns true, the client waits (full jitter backoff) and retries until `retries` is exhausted. On the last attempt, `FetchRetrierHttpError` is thrown (includes `status`).
|
|
101
|
+
- **Non-retriable failure** – If `shouldRetry` returns false, `FetchRetrierHttpError` is thrown immediately (e.g. message `Non-retriable HTTP error: 404`).
|
|
102
|
+
- **Timeout** – If a request exceeds `timeoutMs`, it is aborted and retried (same backoff) until `retries` is exhausted; the final failure is `FetchRetrierAbortError`.
|
|
103
|
+
- **Network/TypeError** – Network errors and related `TypeError`s are retried with backoff; after the last attempt, `FetchRetrierNetworkError` is thrown with the original error as `cause`.
|
|
104
|
+
- **Already aborted signal** – If `signal` is already aborted before an attempt starts, `FetchRetrierAlreadyAbortedError` is thrown immediately (no attempt is made).
|
|
82
105
|
|
|
83
106
|
## Requirements
|
|
84
107
|
|
|
@@ -87,4 +110,4 @@ const response = await fetchRetrier('https://api.example.com/data', {
|
|
|
87
110
|
|
|
88
111
|
## License
|
|
89
112
|
|
|
90
|
-
This project is licensed under the Apache-2.0 License.
|
|
113
|
+
This project is licensed under the (Apache-2.0) License.
|
package/lib/index.d.ts
CHANGED
|
@@ -1,21 +1,88 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Configuration for {@link fetchRetrier}.
|
|
3
3
|
*/
|
|
4
4
|
export interface RequestOptions {
|
|
5
|
+
/** Optional HTTP headers sent with each attempt. */
|
|
5
6
|
headers?: Record<string, string>;
|
|
7
|
+
/** Maximum number of attempts, including the first. */
|
|
6
8
|
retries: number;
|
|
9
|
+
/** Per-attempt timeout in milliseconds; uses an internal {@link AbortController} when exceeded. */
|
|
7
10
|
timeoutMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* Base backoff in milliseconds for full jitter. The cap for attempt `n` is `baseBackoffMs * 2^n`.
|
|
13
|
+
*/
|
|
8
14
|
baseBackoffMs: number;
|
|
9
15
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
16
|
+
* Optional external {@link AbortSignal}. When aborted, the in-flight request is aborted; on the
|
|
17
|
+
* final attempt, cancellation surfaces as {@link FetchRetrierAbortError}.
|
|
18
|
+
*/
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
/**
|
|
21
|
+
* Return `true` to schedule another attempt for this non-OK response.
|
|
22
|
+
* Default: retry on status 429, 500, 502, 503, or 504.
|
|
12
23
|
*/
|
|
13
24
|
shouldRetry?: (response: Response, body: string) => boolean;
|
|
14
25
|
}
|
|
26
|
+
/** Error thrown when a request is cancelled by timeout or an external {@link AbortSignal}. */
|
|
27
|
+
export declare class FetchRetrierAbortError extends Error {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/**
|
|
30
|
+
* @param message - Human-readable reason (default: `'Aborted'`)
|
|
31
|
+
*/
|
|
32
|
+
constructor(message?: string);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Error thrown when {@link RequestOptions.signal} is already aborted before an attempt starts.
|
|
36
|
+
*/
|
|
37
|
+
export declare class FetchRetrierAlreadyAbortedError extends FetchRetrierAbortError {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
/**
|
|
40
|
+
* @param message - Human-readable reason (default: `'Signal was already aborted'`)
|
|
41
|
+
*/
|
|
42
|
+
constructor(message?: string);
|
|
43
|
+
}
|
|
44
|
+
/** Error thrown when the server returns a non-OK HTTP status and no further retry is performed. */
|
|
45
|
+
export declare class FetchRetrierHttpError extends Error {
|
|
46
|
+
readonly status: number;
|
|
47
|
+
readonly name: string;
|
|
48
|
+
/**
|
|
49
|
+
* @param message - Error description
|
|
50
|
+
* @param status - HTTP status code from the response
|
|
51
|
+
*/
|
|
52
|
+
constructor(message: string, status: number);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Error thrown when a fetch fails with a network-level error (e.g. DNS failure, connection refused).
|
|
56
|
+
*/
|
|
57
|
+
export declare class FetchRetrierNetworkError extends Error {
|
|
58
|
+
readonly cause?: unknown | undefined;
|
|
59
|
+
readonly name: string;
|
|
60
|
+
/**
|
|
61
|
+
* @param message - Human-readable reason (default: `'Network error'`)
|
|
62
|
+
* @param cause - Original error, if any
|
|
63
|
+
*/
|
|
64
|
+
constructor(message?: string, cause?: unknown | undefined);
|
|
65
|
+
}
|
|
66
|
+
/** Error thrown when an internal invariant fails (should not happen in normal use). */
|
|
67
|
+
export declare class FetchRetrierUnreachableError extends Error {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
/**
|
|
70
|
+
* @param message - Human-readable reason (default: `'Unreachable'`)
|
|
71
|
+
*/
|
|
72
|
+
constructor(message?: string);
|
|
73
|
+
}
|
|
15
74
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
18
|
-
*
|
|
19
|
-
*
|
|
75
|
+
* Performs `fetch` with retries, a per-attempt timeout, exponential backoff with full jitter,
|
|
76
|
+
* optional {@link RequestOptions.signal} cancellation, and a configurable retry predicate for
|
|
77
|
+
* non-OK responses.
|
|
78
|
+
*
|
|
79
|
+
* @param url - Request URL
|
|
80
|
+
* @param options - Retries, backoff, timeout, optional abort signal, and optional retry predicate
|
|
81
|
+
* @returns The first successful (OK) {@link Response}
|
|
82
|
+
* @throws {FetchRetrierAlreadyAbortedError} If `options.signal` is already aborted before an attempt
|
|
83
|
+
* @throws {FetchRetrierHttpError} On a non-OK response that is not retried or after the last attempt
|
|
84
|
+
* @throws {FetchRetrierNetworkError} On a network error on the final attempt
|
|
85
|
+
* @throws {FetchRetrierAbortError} On timeout or external abort on the final attempt
|
|
86
|
+
* @throws {FetchRetrierUnreachableError} If the retry loop exits without returning (internal bug)
|
|
20
87
|
*/
|
|
21
88
|
export declare const fetchRetrier: (url: string, options: RequestOptions) => Promise<Response>;
|
package/lib/index.js
CHANGED
|
@@ -1,26 +1,116 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchRetrier = void 0;
|
|
3
|
+
exports.fetchRetrier = exports.FetchRetrierUnreachableError = exports.FetchRetrierNetworkError = exports.FetchRetrierHttpError = exports.FetchRetrierAlreadyAbortedError = exports.FetchRetrierAbortError = void 0;
|
|
4
|
+
/** Error thrown when a request is cancelled by timeout or an external {@link AbortSignal}. */
|
|
5
|
+
class FetchRetrierAbortError extends Error {
|
|
6
|
+
/**
|
|
7
|
+
* @param message - Human-readable reason (default: `'Aborted'`)
|
|
8
|
+
*/
|
|
9
|
+
constructor(message = 'Aborted') {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'FetchRetrierAbortError';
|
|
12
|
+
Object.setPrototypeOf(this, FetchRetrierAbortError.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.FetchRetrierAbortError = FetchRetrierAbortError;
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when {@link RequestOptions.signal} is already aborted before an attempt starts.
|
|
18
|
+
*/
|
|
19
|
+
class FetchRetrierAlreadyAbortedError extends FetchRetrierAbortError {
|
|
20
|
+
/**
|
|
21
|
+
* @param message - Human-readable reason (default: `'Signal was already aborted'`)
|
|
22
|
+
*/
|
|
23
|
+
constructor(message = 'Signal was already aborted') {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'FetchRetrierAlreadyAbortedError';
|
|
26
|
+
Object.setPrototypeOf(this, FetchRetrierAlreadyAbortedError.prototype);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.FetchRetrierAlreadyAbortedError = FetchRetrierAlreadyAbortedError;
|
|
30
|
+
/** Error thrown when the server returns a non-OK HTTP status and no further retry is performed. */
|
|
31
|
+
class FetchRetrierHttpError extends Error {
|
|
32
|
+
/**
|
|
33
|
+
* @param message - Error description
|
|
34
|
+
* @param status - HTTP status code from the response
|
|
35
|
+
*/
|
|
36
|
+
constructor(message, status) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.status = status;
|
|
39
|
+
this.name = 'FetchRetrierHttpError';
|
|
40
|
+
Object.setPrototypeOf(this, FetchRetrierHttpError.prototype);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.FetchRetrierHttpError = FetchRetrierHttpError;
|
|
44
|
+
/**
|
|
45
|
+
* Error thrown when a fetch fails with a network-level error (e.g. DNS failure, connection refused).
|
|
46
|
+
*/
|
|
47
|
+
class FetchRetrierNetworkError extends Error {
|
|
48
|
+
/**
|
|
49
|
+
* @param message - Human-readable reason (default: `'Network error'`)
|
|
50
|
+
* @param cause - Original error, if any
|
|
51
|
+
*/
|
|
52
|
+
constructor(message = 'Network error', cause) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.cause = cause;
|
|
55
|
+
this.name = 'FetchRetrierNetworkError';
|
|
56
|
+
Object.setPrototypeOf(this, FetchRetrierNetworkError.prototype);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.FetchRetrierNetworkError = FetchRetrierNetworkError;
|
|
60
|
+
/** Error thrown when an internal invariant fails (should not happen in normal use). */
|
|
61
|
+
class FetchRetrierUnreachableError extends Error {
|
|
62
|
+
/**
|
|
63
|
+
* @param message - Human-readable reason (default: `'Unreachable'`)
|
|
64
|
+
*/
|
|
65
|
+
constructor(message = 'Unreachable') {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = 'FetchRetrierUnreachableError';
|
|
68
|
+
Object.setPrototypeOf(this, FetchRetrierUnreachableError.prototype);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.FetchRetrierUnreachableError = FetchRetrierUnreachableError;
|
|
72
|
+
/**
|
|
73
|
+
* Default {@link RequestOptions.shouldRetry} implementation: retry on HTTP 429, 500, 502, 503, 504.
|
|
74
|
+
*/
|
|
4
75
|
const defaultShouldRetry = (res) => {
|
|
5
76
|
return [429, 500, 502, 503, 504].includes(res.status);
|
|
6
77
|
};
|
|
7
78
|
/**
|
|
8
|
-
*
|
|
9
|
-
* @
|
|
10
|
-
*
|
|
11
|
-
*
|
|
79
|
+
* Performs `fetch` with retries, a per-attempt timeout, exponential backoff with full jitter,
|
|
80
|
+
* optional {@link RequestOptions.signal} cancellation, and a configurable retry predicate for
|
|
81
|
+
* non-OK responses.
|
|
82
|
+
*
|
|
83
|
+
* @param url - Request URL
|
|
84
|
+
* @param options - Retries, backoff, timeout, optional abort signal, and optional retry predicate
|
|
85
|
+
* @returns The first successful (OK) {@link Response}
|
|
86
|
+
* @throws {FetchRetrierAlreadyAbortedError} If `options.signal` is already aborted before an attempt
|
|
87
|
+
* @throws {FetchRetrierHttpError} On a non-OK response that is not retried or after the last attempt
|
|
88
|
+
* @throws {FetchRetrierNetworkError} On a network error on the final attempt
|
|
89
|
+
* @throws {FetchRetrierAbortError} On timeout or external abort on the final attempt
|
|
90
|
+
* @throws {FetchRetrierUnreachableError} If the retry loop exits without returning (internal bug)
|
|
12
91
|
*/
|
|
13
92
|
const fetchRetrier = async (url, options) => {
|
|
14
|
-
const { headers, retries, timeoutMs, baseBackoffMs, shouldRetry = defaultShouldRetry } = options;
|
|
93
|
+
const { headers, retries, timeoutMs, baseBackoffMs, signal: externalSignal, shouldRetry = defaultShouldRetry } = options;
|
|
15
94
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
95
|
+
if (externalSignal?.aborted) {
|
|
96
|
+
throw new FetchRetrierAlreadyAbortedError();
|
|
97
|
+
}
|
|
16
98
|
const controller = new AbortController();
|
|
17
99
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
100
|
+
const onExternalAbort = () => {
|
|
101
|
+
clearTimeout(timer);
|
|
102
|
+
controller.abort();
|
|
103
|
+
};
|
|
104
|
+
if (externalSignal) {
|
|
105
|
+
externalSignal.addEventListener('abort', onExternalAbort);
|
|
106
|
+
}
|
|
18
107
|
try {
|
|
19
108
|
const res = await fetch(url, {
|
|
20
109
|
headers,
|
|
21
110
|
signal: controller.signal,
|
|
22
111
|
});
|
|
23
112
|
clearTimeout(timer);
|
|
113
|
+
externalSignal?.removeEventListener('abort', onExternalAbort);
|
|
24
114
|
if (res.ok) {
|
|
25
115
|
return res;
|
|
26
116
|
}
|
|
@@ -28,45 +118,51 @@ const fetchRetrier = async (url, options) => {
|
|
|
28
118
|
const isContinue = shouldRetry(res, text);
|
|
29
119
|
if (isContinue) {
|
|
30
120
|
if (attempt === retries) {
|
|
31
|
-
throw new
|
|
121
|
+
throw new FetchRetrierHttpError(`HTTP ${res.status}`, res.status);
|
|
32
122
|
}
|
|
33
123
|
await wait(fullJitter(baseBackoffMs, attempt));
|
|
34
124
|
}
|
|
35
125
|
else {
|
|
36
|
-
throw new
|
|
126
|
+
throw new FetchRetrierHttpError(`Non-retriable HTTP error: ${res.status}`, res.status);
|
|
37
127
|
}
|
|
38
128
|
}
|
|
39
129
|
catch (err) {
|
|
40
130
|
clearTimeout(timer);
|
|
131
|
+
externalSignal?.removeEventListener('abort', onExternalAbort);
|
|
41
132
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
42
133
|
if (attempt === retries)
|
|
43
|
-
throw err;
|
|
134
|
+
throw err instanceof FetchRetrierAbortError ? err : new FetchRetrierAbortError();
|
|
44
135
|
await wait(fullJitter(baseBackoffMs, attempt));
|
|
45
136
|
continue;
|
|
46
137
|
}
|
|
47
138
|
if (err instanceof TypeError) {
|
|
48
139
|
if (attempt === retries)
|
|
49
|
-
throw err;
|
|
140
|
+
throw new FetchRetrierNetworkError('Network error', err);
|
|
50
141
|
await wait(fullJitter(baseBackoffMs, attempt));
|
|
51
142
|
continue;
|
|
52
143
|
}
|
|
53
144
|
throw err;
|
|
54
145
|
}
|
|
55
146
|
}
|
|
56
|
-
throw new
|
|
147
|
+
throw new FetchRetrierUnreachableError();
|
|
57
148
|
};
|
|
58
149
|
exports.fetchRetrier = fetchRetrier;
|
|
150
|
+
/**
|
|
151
|
+
* @param ms - Delay in milliseconds
|
|
152
|
+
* @returns A promise that resolves after `ms`
|
|
153
|
+
*/
|
|
59
154
|
const wait = (ms) => {
|
|
60
155
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
61
156
|
};
|
|
62
157
|
/**
|
|
63
|
-
* AWS
|
|
64
|
-
*
|
|
65
|
-
* @param
|
|
66
|
-
* @
|
|
158
|
+
* Full jitter backoff: random delay in `[0, base * 2^attempt)` ms (AWS-recommended pattern).
|
|
159
|
+
*
|
|
160
|
+
* @param base - Base backoff in milliseconds
|
|
161
|
+
* @param attempt - 1-based attempt index (first retry uses `attempt === 1`)
|
|
162
|
+
* @returns Wait duration in milliseconds before the next attempt
|
|
67
163
|
*/
|
|
68
164
|
const fullJitter = (base, attempt) => {
|
|
69
165
|
const cap = base * Math.pow(2, attempt);
|
|
70
166
|
return Math.floor(Math.random() * cap);
|
|
71
167
|
};
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBZUEsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLEdBQWEsRUFBVyxFQUFFO0lBQ3BELE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN4RCxDQUFDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNJLE1BQU0sWUFBWSxHQUFHLEtBQUssRUFBRSxHQUFXLEVBQUUsT0FBdUIsRUFBcUIsRUFBRTtJQUM1RixNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFdBQVcsR0FBRyxrQkFBa0IsRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUVqRyxLQUFLLElBQUksT0FBTyxHQUFHLENBQUMsRUFBRSxPQUFPLElBQUksT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUM7UUFDcEQsTUFBTSxVQUFVLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUN6QyxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRTlELElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRTtnQkFDM0IsT0FBTztnQkFDUCxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07YUFDMUIsQ0FBQyxDQUFDO1lBRUgsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRXBCLElBQUksR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNYLE9BQU8sR0FBRyxDQUFDO1lBQ2IsQ0FBQztZQUVELE1BQU0sSUFBSSxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFMUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDZixJQUFJLE9BQU8sS0FBSyxPQUFPLEVBQUUsQ0FBQztvQkFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxRQUFRLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QyxDQUFDO2dCQUNELE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNqRCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDN0QsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEdBQVksRUFBRSxDQUFDO1lBQ3RCLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVwQixJQUFJLEdBQUcsWUFBWSxLQUFLLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztnQkFDdEQsSUFBSSxPQUFPLEtBQUssT0FBTztvQkFBRSxNQUFNLEdBQUcsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUMvQyxTQUFTO1lBQ1gsQ0FBQztZQUVELElBQUksR0FBRyxZQUFZLFNBQVMsRUFBRSxDQUFDO2dCQUM3QixJQUFJLE9BQU8sS0FBSyxPQUFPO29CQUFFLE1BQU0sR0FBRyxDQUFDO2dCQUNuQyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQy9DLFNBQVM7WUFDWCxDQUFDO1lBRUQsTUFBTSxHQUFHLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDakMsQ0FBQyxDQUFDO0FBbERXLFFBQUEsWUFBWSxnQkFrRHZCO0FBRUYsTUFBTSxJQUFJLEdBQUcsQ0FBQyxFQUFVLEVBQWlCLEVBQUU7SUFDekMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNELENBQUMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUFZLEVBQUUsT0FBZSxFQUFVLEVBQUU7SUFDM0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUM7QUFDekMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiByZXF1ZXN0IE9wdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0T3B0aW9ucyB7XG4gIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBiYXNlQmFja29mZk1zOiBudW1iZXI7XG4gIC8qKlxuICAgKiBDdXN0b20gcHJlZGljYXRlOiByZXR1cm4gdHJ1ZSB0byByZXRyeSBvbiB0aGlzIHJlc3BvbnNlLlxuICAgKiBEZWZhdWx0OiByZXRyeSBvbiA0MjksIDUwMCwgNTAyLCA1MDMsIDUwNFxuICAgKi9cbiAgc2hvdWxkUmV0cnk/OiAocmVzcG9uc2U6IFJlc3BvbnNlLCBib2R5OiBzdHJpbmcpID0+IGJvb2xlYW47XG59XG5cbmNvbnN0IGRlZmF1bHRTaG91bGRSZXRyeSA9IChyZXM6IFJlc3BvbnNlKTogYm9vbGVhbiA9PiB7XG4gIHJldHVybiBbNDI5LCA1MDAsIDUwMiwgNTAzLCA1MDRdLmluY2x1ZGVzKHJlcy5zdGF0dXMpO1xufTtcblxuLyoqXG4gKiByZXRyeSArIHRpbWVvdXQgKyBGdWxsIEppdHRlclxuICogQHBhcmFtIHVybCAtIFRoZSBVUkwgdG8gZmV0Y2hcbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBmZXRjaFxuICogQHJldHVybnMgVGhlIHJlc3BvbnNlXG4gKi9cbmV4cG9ydCBjb25zdCBmZXRjaFJldHJpZXIgPSBhc3luYyAodXJsOiBzdHJpbmcsIG9wdGlvbnM6IFJlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxSZXNwb25zZT4gPT4ge1xuICBjb25zdCB7IGhlYWRlcnMsIHJldHJpZXMsIHRpbWVvdXRNcywgYmFzZUJhY2tvZmZNcywgc2hvdWxkUmV0cnkgPSBkZWZhdWx0U2hvdWxkUmV0cnkgfSA9IG9wdGlvbnM7XG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gcmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgfSk7XG5cbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG5cbiAgICAgIGlmIChyZXMub2spIHtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlcy50ZXh0KCk7XG4gICAgICBjb25zdCBpc0NvbnRpbnVlID0gc2hvdWxkUmV0cnkocmVzLCB0ZXh0KTtcblxuICAgICAgaWYgKGlzQ29udGludWUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEhUVFAgJHtyZXMuc3RhdHVzfWApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHdhaXQoZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vbi1yZXRyaWFibGUgSFRUUCBlcnJvcjogJHtyZXMuc3RhdHVzfWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHRocm93IGVycjtcbiAgICAgICAgYXdhaXQgd2FpdChmdWxsSml0dGVyKGJhc2VCYWNrb2ZmTXMsIGF0dGVtcHQpKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBUeXBlRXJyb3IpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHRocm93IGVycjtcbiAgICAgICAgYXdhaXQgd2FpdChmdWxsSml0dGVyKGJhc2VCYWNrb2ZmTXMsIGF0dGVtcHQpKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ1VucmVhY2hhYmxlJyk7XG59O1xuXG5jb25zdCB3YWl0ID0gKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59O1xuXG4vKipcbiAqIEFXUyByZWNvbW1lbmRlZCBGdWxsIEppdHRlclxuICogQHBhcmFtIGJhc2UgLSBUaGUgYmFzZSB0aW1lIGluIG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIGF0dGVtcHQgLSBUaGUgYXR0ZW1wdCBudW1iZXJcbiAqIEByZXR1cm5zIFRoZSB0aW1lIHRvIHdhaXQgaW4gbWlsbGlzZWNvbmRzXG4gKi9cbmNvbnN0IGZ1bGxKaXR0ZXIgPSAoYmFzZTogbnVtYmVyLCBhdHRlbXB0OiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICBjb25zdCBjYXAgPSBiYXNlICogTWF0aC5wb3coMiwgYXR0ZW1wdCk7XG4gIHJldHVybiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBjYXApO1xufTtcbiJdfQ==
|
|
168
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBMEJBLDhGQUE4RjtBQUM5RixNQUFhLHNCQUF1QixTQUFRLEtBQUs7SUFFL0M7O09BRUc7SUFDSCxZQUFZLE9BQU8sR0FBRyxTQUFTO1FBQzdCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUxDLFNBQUksR0FBVyx3QkFBd0IsQ0FBQztRQU14RCxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRSxDQUFDO0NBQ0Y7QUFURCx3REFTQztBQUVEOztHQUVHO0FBQ0gsTUFBYSwrQkFBZ0MsU0FBUSxzQkFBc0I7SUFFekU7O09BRUc7SUFDSCxZQUFZLE9BQU8sR0FBRyw0QkFBNEI7UUFDaEQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBTEMsU0FBSSxHQUFXLGlDQUFpQyxDQUFDO1FBTWpFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLCtCQUErQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7Q0FDRjtBQVRELDBFQVNDO0FBRUQsbUdBQW1HO0FBQ25HLE1BQWEscUJBQXNCLFNBQVEsS0FBSztJQUU5Qzs7O09BR0c7SUFDSCxZQUNFLE9BQWUsRUFDQyxNQUFjO1FBRTlCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUZDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFQZCxTQUFJLEdBQVcsdUJBQXVCLENBQUM7UUFVdkQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUscUJBQXFCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0QsQ0FBQztDQUNGO0FBYkQsc0RBYUM7QUFFRDs7R0FFRztBQUNILE1BQWEsd0JBQXlCLFNBQVEsS0FBSztJQUVqRDs7O09BR0c7SUFDSCxZQUFZLE9BQU8sR0FBRyxlQUFlLEVBQWtCLEtBQWU7UUFDcEUs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Q3pDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMzRCxDQUFDLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxPQUFlLEVBQVUsRUFBRTtJQUMzRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQztBQUN6QyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHtAbGluayBmZXRjaFJldHJpZXJ9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcXVlc3RPcHRpb25zIHtcbiAgLyoqIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBzZW50IHdpdGggZWFjaCBhdHRlbXB0LiAqL1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgLyoqIE1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzLCBpbmNsdWRpbmcgdGhlIGZpcnN0LiAqL1xuICByZXRyaWVzOiBudW1iZXI7XG4gIC8qKiBQZXItYXR0ZW1wdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kczsgdXNlcyBhbiBpbnRlcm5hbCB7QGxpbmsgQWJvcnRDb250cm9sbGVyfSB3aGVuIGV4Y2VlZGVkLiAqL1xuICB0aW1lb3V0TXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIEJhc2UgYmFja29mZiBpbiBtaWxsaXNlY29uZHMgZm9yIGZ1bGwgaml0dGVyLiBUaGUgY2FwIGZvciBhdHRlbXB0IGBuYCBpcyBgYmFzZUJhY2tvZmZNcyAqIDJebmAuXG4gICAqL1xuICBiYXNlQmFja29mZk1zOiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBleHRlcm5hbCB7QGxpbmsgQWJvcnRTaWduYWx9LiBXaGVuIGFib3J0ZWQsIHRoZSBpbi1mbGlnaHQgcmVxdWVzdCBpcyBhYm9ydGVkOyBvbiB0aGVcbiAgICogZmluYWwgYXR0ZW1wdCwgY2FuY2VsbGF0aW9uIHN1cmZhY2VzIGFzIHtAbGluayBGZXRjaFJldHJpZXJBYm9ydEVycm9yfS5cbiAgICovXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICAvKipcbiAgICogUmV0dXJuIGB0cnVlYCB0byBzY2hlZHVsZSBhbm90aGVyIGF0dGVtcHQgZm9yIHRoaXMgbm9uLU9LIHJlc3BvbnNlLlxuICAgKiBEZWZhdWx0OiByZXRyeSBvbiBzdGF0dXMgNDI5LCA1MDAsIDUwMiwgNTAzLCBvciA1MDQuXG4gICAqL1xuICBzaG91bGRSZXRyeT86IChyZXNwb25zZTogUmVzcG9uc2UsIGJvZHk6IHN0cmluZykgPT4gYm9vbGVhbjtcbn1cblxuLyoqIEVycm9yIHRocm93biB3aGVuIGEgcmVxdWVzdCBpcyBjYW5jZWxsZWQgYnkgdGltZW91dCBvciBhbiBleHRlcm5hbCB7QGxpbmsgQWJvcnRTaWduYWx9LiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllckFib3J0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9ICdGZXRjaFJldHJpZXJBYm9ydEVycm9yJztcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgcmVhc29uIChkZWZhdWx0OiBgJ0Fib3J0ZWQnYClcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnQWJvcnRlZCcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvci5wcm90b3R5cGUpO1xuICB9XG59XG5cbi8qKlxuICogRXJyb3IgdGhyb3duIHdoZW4ge0BsaW5rIFJlcXVlc3RPcHRpb25zLnNpZ25hbH0gaXMgYWxyZWFkeSBhYm9ydGVkIGJlZm9yZSBhbiBhdHRlbXB0IHN0YXJ0cy5cbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3IgZXh0ZW5kcyBGZXRjaFJldHJpZXJBYm9ydEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3InO1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSByZWFzb24gKGRlZmF1bHQ6IGAnU2lnbmFsIHdhcyBhbHJlYWR5IGFib3J0ZWQnYClcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnU2lnbmFsIHdhcyBhbHJlYWR5IGFib3J0ZWQnKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIEZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3IucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKiogRXJyb3IgdGhyb3duIHdoZW4gdGhlIHNlcnZlciByZXR1cm5zIGEgbm9uLU9LIEhUVFAgc3RhdHVzIGFuZCBubyBmdXJ0aGVyIHJldHJ5IGlzIHBlcmZvcm1lZC4gKi9cbmV4cG9ydCBjbGFzcyBGZXRjaFJldHJpZXJIdHRwRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9ICdGZXRjaFJldHJpZXJIdHRwRXJyb3InO1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBFcnJvciBkZXNjcmlwdGlvblxuICAgKiBAcGFyYW0gc3RhdHVzIC0gSFRUUCBzdGF0dXMgY29kZSBmcm9tIHRoZSByZXNwb25zZVxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIHB1YmxpYyByZWFkb25seSBzdGF0dXM6IG51bWJlcixcbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIEZldGNoUmV0cmllckh0dHBFcnJvci5wcm90b3R5cGUpO1xuICB9XG59XG5cbi8qKlxuICogRXJyb3IgdGhyb3duIHdoZW4gYSBmZXRjaCBmYWlscyB3aXRoIGEgbmV0d29yay1sZXZlbCBlcnJvciAoZS5nLiBETlMgZmFpbHVyZSwgY29ubmVjdGlvbiByZWZ1c2VkKS5cbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllck5ldHdvcmtFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllck5ldHdvcmtFcnJvcic7XG4gIC8qKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIEh1bWFuLXJlYWRhYmxlIHJlYXNvbiAoZGVmYXVsdDogYCdOZXR3b3JrIGVycm9yJ2ApXG4gICAqIEBwYXJhbSBjYXVzZSAtIE9yaWdpbmFsIGVycm9yLCBpZiBhbnlcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnTmV0d29yayBlcnJvcicsIHB1YmxpYyByZWFkb25seSBjYXVzZT86IHVua25vd24pIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVyTmV0d29ya0Vycm9yLnByb3RvdHlwZSk7XG4gIH1cbn1cblxuLyoqIEVycm9yIHRocm93biB3aGVuIGFuIGludGVybmFsIGludmFyaWFudCBmYWlscyAoc2hvdWxkIG5vdCBoYXBwZW4gaW4gbm9ybWFsIHVzZSkuICovXG5leHBvcnQgY2xhc3MgRmV0Y2hSZXRyaWVyVW5yZWFjaGFibGVFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3InO1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSByZWFzb24gKGRlZmF1bHQ6IGAnVW5yZWFjaGFibGUnYClcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnVW5yZWFjaGFibGUnKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKipcbiAqIERlZmF1bHQge0BsaW5rIFJlcXVlc3RPcHRpb25zLnNob3VsZFJldHJ5fSBpbXBsZW1lbnRhdGlvbjogcmV0cnkgb24gSFRUUCA0MjksIDUwMCwgNTAyLCA1MDMsIDUwNC5cbiAqL1xuY29uc3QgZGVmYXVsdFNob3VsZFJldHJ5ID0gKHJlczogUmVzcG9uc2UpOiBib29sZWFuID0+IHtcbiAgcmV0dXJuIFs0MjksIDUwMCwgNTAyLCA1MDMsIDUwNF0uaW5jbHVkZXMocmVzLnN0YXR1cyk7XG59O1xuXG4vKipcbiAqIFBlcmZvcm1zIGBmZXRjaGAgd2l0aCByZXRyaWVzLCBhIHBlci1hdHRlbXB0IHRpbWVvdXQsIGV4cG9uZW50aWFsIGJhY2tvZmYgd2l0aCBmdWxsIGppdHRlcixcbiAqIG9wdGlvbmFsIHtAbGluayBSZXF1ZXN0T3B0aW9ucy5zaWduYWx9IGNhbmNlbGxhdGlvbiwgYW5kIGEgY29uZmlndXJhYmxlIHJldHJ5IHByZWRpY2F0ZSBmb3JcbiAqIG5vbi1PSyByZXNwb25zZXMuXG4gKlxuICogQHBhcmFtIHVybCAtIFJlcXVlc3QgVVJMXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFJldHJpZXMsIGJhY2tvZmYsIHRpbWVvdXQsIG9wdGlvbmFsIGFib3J0IHNpZ25hbCwgYW5kIG9wdGlvbmFsIHJldHJ5IHByZWRpY2F0ZVxuICogQHJldHVybnMgVGhlIGZpcnN0IHN1Y2Nlc3NmdWwgKE9LKSB7QGxpbmsgUmVzcG9uc2V9XG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJBbHJlYWR5QWJvcnRlZEVycm9yfSBJZiBgb3B0aW9ucy5zaWduYWxgIGlzIGFscmVhZHkgYWJvcnRlZCBiZWZvcmUgYW4gYXR0ZW1wdFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVySHR0cEVycm9yfSBPbiBhIG5vbi1PSyByZXNwb25zZSB0aGF0IGlzIG5vdCByZXRyaWVkIG9yIGFmdGVyIHRoZSBsYXN0IGF0dGVtcHRcbiAqIEB0aHJvd3Mge0ZldGNoUmV0cmllck5ldHdvcmtFcnJvcn0gT24gYSBuZXR3b3JrIGVycm9yIG9uIHRoZSBmaW5hbCBhdHRlbXB0XG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJBYm9ydEVycm9yfSBPbiB0aW1lb3V0IG9yIGV4dGVybmFsIGFib3J0IG9uIHRoZSBmaW5hbCBhdHRlbXB0XG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJVbnJlYWNoYWJsZUVycm9yfSBJZiB0aGUgcmV0cnkgbG9vcCBleGl0cyB3aXRob3V0IHJldHVybmluZyAoaW50ZXJuYWwgYnVnKVxuICovXG5leHBvcnQgY29uc3QgZmV0Y2hSZXRyaWVyID0gYXN5bmMgKHVybDogc3RyaW5nLCBvcHRpb25zOiBSZXF1ZXN0T3B0aW9ucyk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcbiAgY29uc3QgeyBoZWFkZXJzLCByZXRyaWVzLCB0aW1lb3V0TXMsIGJhc2VCYWNrb2ZmTXMsIHNpZ25hbDogZXh0ZXJuYWxTaWduYWwsIHNob3VsZFJldHJ5ID0gZGVmYXVsdFNob3VsZFJldHJ5IH0gPSBvcHRpb25zO1xuXG4gIGZvciAobGV0IGF0dGVtcHQgPSAxOyBhdHRlbXB0IDw9IHJldHJpZXM7IGF0dGVtcHQrKykge1xuICAgIGlmIChleHRlcm5hbFNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgdGhyb3cgbmV3IEZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIHRpbWVvdXRNcyk7XG5cbiAgICBjb25zdCBvbkV4dGVybmFsQWJvcnQgPSAoKTogdm9pZCA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgIH07XG5cbiAgICBpZiAoZXh0ZXJuYWxTaWduYWwpIHtcbiAgICAgIGV4dGVybmFsU2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25FeHRlcm5hbEFib3J0KTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgICB9KTtcblxuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIGV4dGVybmFsU2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uRXh0ZXJuYWxBYm9ydCk7XG5cbiAgICAgIGlmIChyZXMub2spIHtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlcy50ZXh0KCk7XG4gICAgICBjb25zdCBpc0NvbnRpbnVlID0gc2hvdWxkUmV0cnkocmVzLCB0ZXh0KTtcblxuICAgICAgaWYgKGlzQ29udGludWUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySHR0cEVycm9yKGBIVFRQICR7cmVzLnN0YXR1c31gLCByZXMuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB3YWl0KGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEZldGNoUmV0cmllckh0dHBFcnJvcihgTm9uLXJldHJpYWJsZSBIVFRQIGVycm9yOiAke3Jlcy5zdGF0dXN9YCwgcmVzLnN0YXR1cyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgZXh0ZXJuYWxTaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25FeHRlcm5hbEFib3J0KTtcblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHRocm93IGVyciBpbnN0YW5jZW9mIEZldGNoUmV0cmllckFib3J0RXJyb3IgPyBlcnIgOiBuZXcgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvcigpO1xuICAgICAgICBhd2FpdCB3YWl0KGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCkpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIFR5cGVFcnJvcikge1xuICAgICAgICBpZiAoYXR0ZW1wdCA9PT0gcmV0cmllcykgdGhyb3cgbmV3IEZldGNoUmV0cmllck5ldHdvcmtFcnJvcignTmV0d29yayBlcnJvcicsIGVycik7XG4gICAgICAgIGF3YWl0IHdhaXQoZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IoKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIG1zIC0gRGVsYXkgaW4gbWlsbGlzZWNvbmRzXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciBgbXNgXG4gKi9cbmNvbnN0IHdhaXQgPSAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn07XG5cbi8qKlxuICogRnVsbCBqaXR0ZXIgYmFja29mZjogcmFuZG9tIGRlbGF5IGluIGBbMCwgYmFzZSAqIDJeYXR0ZW1wdClgIG1zIChBV1MtcmVjb21tZW5kZWQgcGF0dGVybikuXG4gKlxuICogQHBhcmFtIGJhc2UgLSBCYXNlIGJhY2tvZmYgaW4gbWlsbGlzZWNvbmRzXG4gKiBAcGFyYW0gYXR0ZW1wdCAtIDEtYmFzZWQgYXR0ZW1wdCBpbmRleCAoZmlyc3QgcmV0cnkgdXNlcyBgYXR0ZW1wdCA9PT0gMWApXG4gKiBAcmV0dXJucyBXYWl0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgdGhlIG5leHQgYXR0ZW1wdFxuICovXG5jb25zdCBmdWxsSml0dGVyID0gKGJhc2U6IG51bWJlciwgYXR0ZW1wdDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgY29uc3QgY2FwID0gYmFzZSAqIE1hdGgucG93KDIsIGF0dGVtcHQpO1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2FwKTtcbn07XG4iXX0=
|
package/package.json
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"eslint-plugin-import": "^2.32.0",
|
|
43
43
|
"jest": "^30.3.0",
|
|
44
44
|
"jest-junit": "^16",
|
|
45
|
-
"projen": "^0.99.
|
|
45
|
+
"projen": "^0.99.21",
|
|
46
46
|
"ts-jest": "^29.4.6",
|
|
47
47
|
"ts-node": "^10.9.2",
|
|
48
48
|
"typescript": "5.9.x"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
|
-
"version": "0.
|
|
58
|
+
"version": "0.2.0",
|
|
59
59
|
"jest": {
|
|
60
60
|
"coverageProvider": "v8",
|
|
61
61
|
"testMatch": [
|