aws-lambda-secret-fetcher 0.2.2 โ†’ 0.3.1

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 CHANGED
@@ -1,21 +1,32 @@
1
1
  # AWS Lambda Secret Fetcher
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/aws-lambda-secret-fetcher.svg)](https://www.npmjs.com/package/aws-lambda-secret-fetcher)
4
+ [![License](https://img.shields.io/npm/l/aws-lambda-secret-fetcher.svg)](https://www.npmjs.com/package/aws-lambda-secret-fetcher)
5
+
3
6
  A lightweight TypeScript library for fetching secrets from AWS Secrets Manager using the [AWS Parameters and Secrets Lambda Extension](https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html).
4
7
 
5
8
  ## Features
6
9
 
7
- - ๐Ÿš€ Uses the local Lambda Extension API (no SDK required)
8
- - ๐Ÿ”„ Built-in retry with exponential backoff (Full Jitter)
9
- - โฑ๏ธ Configurable timeout
10
- - ๐Ÿ“ฆ Automatic JSON parsing for secret values
11
- - ๐Ÿ’ช TypeScript support with generics
10
+ - Uses the local Lambda Extension API (no AWS SDK required)
11
+ - Retry with timeout and full jitter backoff via [fetch-retrier](https://www.npmjs.com/package/fetch-retrier)
12
+ - Configurable timeout, retries, and base backoff
13
+ - Automatic JSON parsing for secret values
14
+ - TypeScript support with generics
12
15
 
13
16
  ## Installation
14
17
 
18
+ **npm**
19
+
15
20
  ```bash
16
21
  npm install aws-lambda-secret-fetcher
17
22
  ```
18
23
 
24
+ **yarn**
25
+
26
+ ```bash
27
+ yarn add aws-lambda-secret-fetcher
28
+ ```
29
+
19
30
  ## Prerequisites
20
31
 
21
32
  Your Lambda function must have the [AWS Parameters and Secrets Lambda Extension](https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html) layer attached.
@@ -47,14 +58,22 @@ console.log(credentials.username); // Type-safe access
47
58
  import { secretFetcher, type GetSecretValueOptions } from 'aws-lambda-secret-fetcher';
48
59
 
49
60
  const options: GetSecretValueOptions = {
50
- timeoutMs: 3000, // Timeout per request (default: 2000)
51
- retries: 5, // Number of retry attempts (default: 3)
52
- baseBackoffMs: 500, // Base backoff time for retries (default: 300)
61
+ timeoutMs: 3000,
62
+ retries: 5,
63
+ baseBackoffMs: 500,
53
64
  };
54
65
 
55
66
  const secret = await secretFetcher.getSecretValue('my-secret', options);
56
67
  ```
57
68
 
69
+ ## Options
70
+
71
+ | Option | Type | Default | Description |
72
+ |--------|------|---------|-------------|
73
+ | `timeoutMs` | `number` | `2000` | Request timeout in milliseconds per attempt |
74
+ | `retries` | `number` | `3` | Maximum number of attempts (including the first request) |
75
+ | `baseBackoffMs` | `number` | `300` | Base delay in milliseconds for backoff between retries |
76
+
58
77
  ## API
59
78
 
60
79
  The package exports `secretFetcher`, an object that provides:
@@ -68,28 +87,19 @@ Fetches a secret value from AWS Secrets Manager via the Lambda Extension.
68
87
  | Parameter | Type | Description |
69
88
  |-----------|------|-------------|
70
89
  | `name` | `string` | The name or ARN of the secret |
71
- | `options` | `GetSecretValueOptions` | Optional configuration |
72
-
73
- #### Options
74
-
75
- | Option | Type | Default | Description |
76
- |--------|------|---------|-------------|
77
- | `timeoutMs` | `number` | `2000` | Request timeout in milliseconds |
78
- | `retries` | `number` | `3` | Number of retry attempts |
79
- | `baseBackoffMs` | `number` | `300` | Base backoff time for exponential retry |
90
+ | `options` | `GetSecretValueOptions` | Optional timeout, retries, and backoff settings |
80
91
 
81
92
  #### Returns
82
93
 
83
- - `Promise<T>` - The secret value. If the secret is a JSON string, it will be automatically parsed.
94
+ - `Promise<T>` โ€” The secret value. If the secret is a JSON string, it is automatically parsed as `T`.
84
95
 
85
96
  #### Throws
86
97
 
87
- - `Error` - If the secret cannot be retrieved after all retries
88
- - `Error` - If the response format is invalid
98
+ - `Error` โ€” If the secret cannot be retrieved after all retries, or if the response format is invalid.
89
99
 
90
100
  ## Retry Behavior
91
101
 
92
- The library implements AWS-recommended Full Jitter exponential backoff for retries. It will retry on:
102
+ Retries use full jitter exponential backoff. The library retries on:
93
103
 
94
104
  - HTTP status codes: 429, 500, 502, 503, 504
95
105
  - Lambda Extension not ready (400 with "not ready to serve traffic")
@@ -103,4 +113,4 @@ The library implements AWS-recommended Full Jitter exponential backoff for retri
103
113
 
104
114
  ## License
105
115
 
106
- Apache-2.0
116
+ This project is licensed under the Apache-2.0 License.
package/lib/index.d.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  /**
2
- * getSecretValue Options
2
+ * Options for fetching a secret from the Secrets Manager Extension.
3
3
  */
4
4
  export interface GetSecretValueOptions {
5
+ /** Request timeout in milliseconds. Default: 2000 */
5
6
  timeoutMs?: number;
7
+ /** Maximum number of attempts (including the first request). Default: 3 */
6
8
  retries?: number;
9
+ /** Base delay in milliseconds for backoff between retries. Default: 300 */
7
10
  baseBackoffMs?: number;
8
11
  }
12
+ /**
13
+ * Client for fetching secrets from the AWS Lambda Secrets Manager Extension.
14
+ */
9
15
  export declare const secretFetcher: {
10
16
  getSecretValue: <T = string>(name: string, options?: GetSecretValueOptions) => Promise<T>;
11
17
  };
package/lib/index.js CHANGED
@@ -1,24 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.secretFetcher = void 0;
4
+ const fetch_retrier_1 = require("fetch-retrier");
4
5
  /**
5
- * Get Secret Value from Secrets Manager Extension
6
- * @param name Secret Name
7
- * @param options GetSecretValue Options
8
- * @returns SecretString as T
6
+ * Fetches a secret value from the AWS Lambda Secrets Manager Extension (localhost:2773).
7
+ * Uses retries with full jitter backoff for transient errors (e.g. 5xx, 429, or extension "not ready").
8
+ *
9
+ * @param name - Secret name (identifier) to fetch
10
+ * @param options - Optional timeout, retry, and backoff settings
11
+ * @returns The secret value as string, or parsed as T if the stored value is JSON
12
+ * @throws Error if the response format is invalid or the request fails after retries
9
13
  */
10
14
  const getSecretValue = async (name, options = {}) => {
11
- // default options
12
15
  const { timeoutMs = 2000, retries = 3, baseBackoffMs = 300 } = options;
13
16
  const url = `http://localhost:2773/secretsmanager/get?secretId=${encodeURIComponent(name)}`;
14
- const response = await request(url, {
17
+ const requestOptions = {
15
18
  headers: {
16
19
  'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN ?? '',
17
20
  },
18
21
  retries,
19
22
  timeoutMs,
20
23
  baseBackoffMs,
21
- });
24
+ shouldRetry: (res, body) => {
25
+ if ([429, 500, 502, 503, 504].includes(res.status))
26
+ return true;
27
+ // Extension may return 400 + "not ready to serve traffic" while initializing; retry in that case
28
+ if (res.status === 400 && /not\s+ready.*traffic/i.test(body))
29
+ return true;
30
+ return false;
31
+ },
32
+ };
33
+ const response = await (0, fetch_retrier_1.fetchRetrier)(url, requestOptions);
22
34
  const raw = await response.json();
23
35
  if (!isSecretResponse(raw)) {
24
36
  throw new Error('Invalid secret response format');
@@ -31,71 +43,11 @@ const getSecretValue = async (name, options = {}) => {
31
43
  return secretString;
32
44
  };
33
45
  /**
34
- * retry + timeout + Full Jitter
35
- * @param url - The URL to fetch
36
- * @param options - The options for the fetch
37
- * @returns The response
46
+ * Type guard for the Secrets Manager Extension response shape.
47
+ *
48
+ * @param value - Value to check
49
+ * @returns True if value has the shape of SecretResponse
38
50
  */
39
- const request = async (url, options) => {
40
- const { headers, retries, timeoutMs, baseBackoffMs } = options;
41
- for (let attempt = 1; attempt <= retries; attempt++) {
42
- const controller = new AbortController();
43
- const timer = setTimeout(() => controller.abort(), timeoutMs);
44
- try {
45
- const res = await fetch(url, {
46
- headers,
47
- signal: controller.signal,
48
- });
49
- clearTimeout(timer);
50
- if (res.ok) {
51
- return res;
52
- }
53
- const text = await res.text();
54
- const isContinue = (() => {
55
- // ็‰นๅฎšใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใฎๅ ดๅˆใฏใƒชใƒˆใƒฉใ‚ค
56
- if ([429, 500, 502, 503, 504].includes(res.status)) {
57
- console.log('Specific status code, retrying...');
58
- return true;
59
- }
60
- // AWS Lambda Extension API ใฎ็‰นๆฎŠใ‚ฑใƒผใ‚น๏ผš
61
- // ๆ‹กๅผตๆฉŸ่ƒฝใฎๅˆๆœŸๅŒ–ไธญใซ 400 + 'not ready to serve traffic' ใ‚’่ฟ”ใ™
62
- // ใ“ใ‚Œใฏไธ€ๆ™‚็š„ใช็Šถๆ…‹ใชใฎใงใ€ใƒชใƒˆใƒฉใ‚คใŒ้ฉๅˆ‡
63
- // ๅ‚่€ƒ: https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html
64
- if (res.status === 400 && /not\s+ready.*traffic/i.test(text)) {
65
- console.log('Extension not ready, retrying...');
66
- return true;
67
- }
68
- return false;
69
- })();
70
- if (isContinue) {
71
- if (attempt === retries) {
72
- throw new Error(`HTTP ${res.status}`);
73
- }
74
- await wait(fullJitter(baseBackoffMs, attempt));
75
- }
76
- else {
77
- throw new Error(`Non-retriable HTTP error: ${res.status}`);
78
- }
79
- }
80
- catch (err) {
81
- clearTimeout(timer);
82
- if (err instanceof Error && err.name === 'AbortError') {
83
- if (attempt === retries)
84
- throw err;
85
- await wait(fullJitter(baseBackoffMs, attempt));
86
- continue;
87
- }
88
- if (err instanceof TypeError) {
89
- if (attempt === retries)
90
- throw err;
91
- await wait(fullJitter(baseBackoffMs, attempt));
92
- continue;
93
- }
94
- throw err;
95
- }
96
- }
97
- throw new Error('Unreachable'); // TS ็”จ๏ผˆๅฎŸ้š›ใซใฏๅˆฐ้”ใ—ใชใ„๏ผ‰
98
- };
99
51
  const isSecretResponse = (value) => {
100
52
  if (typeof value !== 'object' || value === null)
101
53
  return false;
@@ -106,30 +58,18 @@ const isSecretResponse = (value) => {
106
58
  (v.VersionId === undefined || typeof v.VersionId === 'string');
107
59
  };
108
60
  /**
109
- * Wait for a given time
110
- * @param ms - The time to wait in milliseconds
111
- * @returns A promise that resolves when the time has elapsed
112
- */
113
- const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
114
- /**
115
- * AWS recommended Full Jitter
116
- * @param base - The base time in milliseconds
117
- * @param attempt - The attempt number
118
- * @returns The time to wait in milliseconds
119
- */
120
- const fullJitter = (base, attempt) => {
121
- const cap = base * Math.pow(2, attempt);
122
- return Math.floor(Math.random() * cap);
123
- };
124
- /**
125
- * Roughly JSON check
126
- * @param str - The string to check
127
- * @returns True if the string looks like JSON
61
+ * Heuristic check whether a string looks like JSON (starts with `{` after trim).
62
+ *
63
+ * @param str - String to check
64
+ * @returns True if the string appears to be JSON
128
65
  */
129
66
  const looksLikeJson = (str) => {
130
67
  return typeof str === 'string' && str.trim().startsWith('{');
131
68
  };
69
+ /**
70
+ * Client for fetching secrets from the AWS Lambda Secrets Manager Extension.
71
+ */
132
72
  exports.secretFetcher = {
133
73
  getSecretValue,
134
74
  };
135
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBNkJBOzs7OztHQUtHO0FBQ0gsTUFBTSxjQUFjLEdBQUcsS0FBSyxFQUFjLElBQVksRUFBRSxVQUFpQyxFQUFFLEVBQWMsRUFBRTtJQUN6RyxrQkFBa0I7SUFDbEIsTUFBTSxFQUFFLFNBQVMsR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLENBQUMsRUFBRSxhQUFhLEdBQUcsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBRXZFLE1BQU0sR0FBRyxHQUFHLHFEQUFxRCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBRTVGLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsRUFBRTtRQUNsQyxPQUFPLEVBQUU7WUFDUCxnQ0FBZ0MsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixJQUFJLEVBQUU7U0FDdEU7UUFDRCxPQUFPO1FBQ1AsU0FBUztRQUNULGFBQWE7S0FDZCxDQUFDLENBQUM7SUFFSCxNQUFNLEdBQUcsR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUVsQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELE1BQU0sSUFBSSxHQUFtQixHQUFHLENBQUM7SUFFakMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztJQUV2QyxJQUFJLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1FBQ2hDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQU0sQ0FBQztJQUN2QyxDQUFDO0lBRUQsT0FBTyxZQUFpQixDQUFDO0FBQzNCLENBQUMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLEdBQVcsRUFBRSxPQUF1QixFQUFxQixFQUFFO0lBQ2hGLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFFL0QsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3BELE1BQU0sVUFBVSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDekMsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUU5RCxJQUFJLENBQUM7WUFDSCxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLEVBQUU7Z0JBQzNCLE9BQU87Z0JBQ1AsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2FBQzFCLENBQUMsQ0FBQztZQUVILFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVwQixJQUFJLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDWCxPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUM7WUFFRCxNQUFNLElBQUksR0FBRyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUU5QixNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQVksRUFBRTtnQkFDaEMsc0JBQXNCO2dCQUN0QixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDbkQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO29CQUNqRCxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDO2dCQUNELG1DQUFtQztnQkFDbkMsb0RBQW9EO2dCQUNwRCx1QkFBdUI7Z0JBQ3ZCLGdGQUFnRjtnQkFDaEYsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEdBQUcsSUFBSSx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDN0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO29CQUNoRCxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDO2dCQUNELE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUVMLElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxPQUFPLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztnQkFDeEMsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDakQsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzdELENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxHQUFZLEVBQUUsQ0FBQztZQUN0QixZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFcEIsSUFBSSxHQUFHLFlBQVksS0FBSyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7Z0JBQ3RELElBQUksT0FBTyxLQUFLLE9BQU87b0JBQUUsTUFBTSxHQUFHLENBQUM7Z0JBQ25DLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDL0MsU0FBUztZQUNYLENBQUM7WUFFRCxJQUFJLEdBQUcsWUFBWSxTQUFTLEVBQUUsQ0FBQztnQkFDN0IsSUFBSSxPQUFPLEtBQUssT0FBTztvQkFBRSxNQUFNLEdBQUcsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUMvQyxTQUFTO1lBQ1gsQ0FBQztZQUVELE1BQU0sR0FBRyxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsa0JBQWtCO0FBQ3BELENBQUMsQ0FBQztBQUVGLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQTJCLEVBQUU7SUFDbkUsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLElBQUk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM5RCxNQUFNLENBQUMsR0FBRyxLQUFnQyxDQUFDO0lBRTNDLE9BQU8sT0FBTyxDQUFDLENBQUMsWUFBWSxLQUFLLFFBQVE7UUFDbEMsT0FBTyxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVE7UUFDMUIsT0FBTyxDQUFDLENBQUMsR0FBRyxLQUFLLFFBQVE7UUFDekIsQ0FBQyxDQUFDLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsQ0FBQyxTQUFTLEtBQUssUUFBUSxDQUFDLENBQUM7QUFDeEUsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBVSxFQUFpQixFQUFFLENBQ3pDLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFFcEQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxPQUFlLEVBQVUsRUFBRTtJQUMzRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQztBQUN6QyxDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsQ0FBQyxHQUFXLEVBQVcsRUFBRTtJQUM3QyxPQUFPLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQy9ELENBQUMsQ0FBQztBQUdXLFFBQUEsYUFBYSxHQUFHO0lBQzNCLGNBQWM7Q0FDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBnZXRTZWNyZXRWYWx1ZSBPcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VjcmV0VmFsdWVPcHRpb25zIHtcbiAgdGltZW91dE1zPzogbnVtYmVyOyAvLyBkZWZhdWx0OiAyMDAwXG4gIHJldHJpZXM/OiBudW1iZXI7IC8vIGRlZmF1bHQ6IDNcbiAgYmFzZUJhY2tvZmZNcz86IG51bWJlcjsgLy8gZGVmYXVsdDogMzAwXG59XG5cbi8qKlxuICogZmV0Y2hXaXRoUmV0cnkgT3B0aW9uc1xuICovXG5pbnRlcmZhY2UgUmVxdWVzdE9wdGlvbnMge1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgcmV0cmllczogbnVtYmVyO1xuICB0aW1lb3V0TXM6IG51bWJlcjtcbiAgYmFzZUJhY2tvZmZNczogbnVtYmVyO1xufVxuXG4vKipcbiAqIFNlY3JldHMgTWFuYWdlciBFeHRlbnNpb24gUmVzcG9uc2VcbiAqL1xuaW50ZXJmYWNlIFNlY3JldFJlc3BvbnNlIHtcbiAgQVJOOiBzdHJpbmc7XG4gIE5hbWU6IHN0cmluZztcbiAgU2VjcmV0U3RyaW5nOiBzdHJpbmc7XG4gIFZlcnNpb25JZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBHZXQgU2VjcmV0IFZhbHVlIGZyb20gU2VjcmV0cyBNYW5hZ2VyIEV4dGVuc2lvblxuICogQHBhcmFtIG5hbWUgU2VjcmV0IE5hbWVcbiAqIEBwYXJhbSBvcHRpb25zIEdldFNlY3JldFZhbHVlIE9wdGlvbnNcbiAqIEByZXR1cm5zIFNlY3JldFN0cmluZyBhcyBUXG4gKi9cbmNvbnN0IGdldFNlY3JldFZhbHVlID0gYXN5bmMgPFQgPSBzdHJpbmc+KG5hbWU6IHN0cmluZywgb3B0aW9uczogR2V0U2VjcmV0VmFsdWVPcHRpb25zID0ge30pOiBQcm9taXNlPFQ+ID0+IHtcbiAgLy8gZGVmYXVsdCBvcHRpb25zXG4gIGNvbnN0IHsgdGltZW91dE1zID0gMjAwMCwgcmV0cmllcyA9IDMsIGJhc2VCYWNrb2ZmTXMgPSAzMDAgfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgdXJsID0gYGh0dHA6Ly9sb2NhbGhvc3Q6Mjc3My9zZWNyZXRzbWFuYWdlci9nZXQ/c2VjcmV0SWQ9JHtlbmNvZGVVUklDb21wb25lbnQobmFtZSl9YDtcblxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QodXJsLCB7XG4gICAgaGVhZGVyczoge1xuICAgICAgJ1gtQXdzLVBhcmFtZXRlcnMtU2VjcmV0cy1Ub2tlbic6IHByb2Nlc3MuZW52LkFXU19TRVNTSU9OX1RPS0VOID8/ICcnLFxuICAgIH0sXG4gICAgcmV0cmllcyxcbiAgICB0aW1lb3V0TXMsXG4gICAgYmFzZUJhY2tvZmZNcyxcbiAgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuXG4gIGlmICghaXNTZWNyZXRSZXNwb25zZShyYXcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNlY3JldCByZXNwb25zZSBmb3JtYXQnKTtcbiAgfVxuXG4gIGNvbnN0IGRhdGE6IFNlY3JldFJlc3BvbnNlID0gcmF3O1xuXG4gIGNvbnN0IHNlY3JldFN0cmluZyA9IGRhdGEuU2VjcmV0U3RyaW5nO1xuXG4gIGlmIChsb29rc0xpa2VKc29uKHNlY3JldFN0cmluZykpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzZWNyZXRTdHJpbmcpIGFzIFQ7XG4gIH1cblxuICByZXR1cm4gc2VjcmV0U3RyaW5nIGFzIFQ7XG59O1xuXG4vKipcbiAqIHJldHJ5ICsgdGltZW91dCArIEZ1bGwgSml0dGVyXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCB0byBmZXRjaFxuICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgdGhlIGZldGNoXG4gKiBAcmV0dXJucyBUaGUgcmVzcG9uc2VcbiAqL1xuY29uc3QgcmVxdWVzdCA9IGFzeW5jICh1cmw6IHN0cmluZywgb3B0aW9uczogUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPFJlc3BvbnNlPiA9PiB7XG4gIGNvbnN0IHsgaGVhZGVycywgcmV0cmllcywgdGltZW91dE1zLCBiYXNlQmFja29mZk1zIH0gPSBvcHRpb25zO1xuXG4gIGZvciAobGV0IGF0dGVtcHQgPSAxOyBhdHRlbXB0IDw9IHJldHJpZXM7IGF0dGVtcHQrKykge1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgdGltZW91dE1zKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIH0pO1xuXG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuXG4gICAgICBpZiAocmVzLm9rKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXMudGV4dCgpO1xuXG4gICAgICBjb25zdCBpc0NvbnRpbnVlID0gKCgpOiBib29sZWFuID0+IHtcbiAgICAgICAgLy8g54m55a6a44Gu44K544OG44O844K/44K544Kz44O844OJ44Gu5aC05ZCI44Gv44Oq44OI44Op44KkXG4gICAgICAgIGlmIChbNDI5LCA1MDAsIDUwMiwgNTAzLCA1MDRdLmluY2x1ZGVzKHJlcy5zdGF0dXMpKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ1NwZWNpZmljIHN0YXR1cyBjb2RlLCByZXRyeWluZy4uLicpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFXUyBMYW1iZGEgRXh0ZW5zaW9uIEFQSSDjga7nibnmrorjgrHjg7zjgrnvvJpcbiAgICAgICAgLy8g5ouh5by15qmf6IO944Gu5Yid5pyf5YyW5Lit44GrIDQwMCArICdub3QgcmVhZHkgdG8gc2VydmUgdHJhZmZpYycg44KS6L+U44GZXG4gICAgICAgIC8vIOOBk+OCjOOBr+S4gOaZgueahOOBqueKtuaFi+OBquOBruOBp+OAgeODquODiOODqeOCpOOBjOmBqeWIh1xuICAgICAgICAvLyDlj4LogIM6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL3J1bnRpbWVzLWV4dGVuc2lvbnMtYXBpLmh0bWxcbiAgICAgICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMCAmJiAvbm90XFxzK3JlYWR5Lip0cmFmZmljL2kudGVzdCh0ZXh0KSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdFeHRlbnNpb24gbm90IHJlYWR5LCByZXRyeWluZy4uLicpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pKCk7XG5cbiAgICAgIGlmIChpc0NvbnRpbnVlKSB7XG4gICAgICAgIGlmIChhdHRlbXB0ID09PSByZXRyaWVzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQICR7cmVzLnN0YXR1c31gKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB3YWl0KGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb24tcmV0cmlhYmxlIEhUVFAgZXJyb3I6ICR7cmVzLnN0YXR1c31gKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnI6IHVua25vd24pIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG5cbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgICAgIGlmIChhdHRlbXB0ID09PSByZXRyaWVzKSB0aHJvdyBlcnI7XG4gICAgICAgIGF3YWl0IHdhaXQoZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXJyIGluc3RhbmNlb2YgVHlwZUVycm9yKSB7XG4gICAgICAgIGlmIChhdHRlbXB0ID09PSByZXRyaWVzKSB0aHJvdyBlcnI7XG4gICAgICAgIGF3YWl0IHdhaXQoZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdVbnJlYWNoYWJsZScpOyAvLyBUUyDnlKjvvIjlrp/pmpvjgavjga/liLDpgZTjgZfjgarjgYTvvIlcbn07XG5cbmNvbnN0IGlzU2VjcmV0UmVzcG9uc2UgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTZWNyZXRSZXNwb25zZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHYgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICByZXR1cm4gdHlwZW9mIHYuU2VjcmV0U3RyaW5nID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgdHlwZW9mIHYuTmFtZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgIHR5cGVvZiB2LkFSTiA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICh2LlZlcnNpb25JZCA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiB2LlZlcnNpb25JZCA9PT0gJ3N0cmluZycpO1xufTtcblxuLyoqXG4gKiBXYWl0IGZvciBhIGdpdmVuIHRpbWVcbiAqIEBwYXJhbSBtcyAtIFRoZSB0aW1lIHRvIHdhaXQgaW4gbWlsbGlzZWNvbmRzXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB0aW1lIGhhcyBlbGFwc2VkXG4gKi9cbmNvbnN0IHdhaXQgPSAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT5cbiAgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcblxuLyoqXG4gKiBBV1MgcmVjb21tZW5kZWQgRnVsbCBKaXR0ZXJcbiAqIEBwYXJhbSBiYXNlIC0gVGhlIGJhc2UgdGltZSBpbiBtaWxsaXNlY29uZHNcbiAqIEBwYXJhbSBhdHRlbXB0IC0gVGhlIGF0dGVtcHQgbnVtYmVyXG4gKiBAcmV0dXJucyBUaGUgdGltZSB0byB3YWl0IGluIG1pbGxpc2Vjb25kc1xuICovXG5jb25zdCBmdWxsSml0dGVyID0gKGJhc2U6IG51bWJlciwgYXR0ZW1wdDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgY29uc3QgY2FwID0gYmFzZSAqIE1hdGgucG93KDIsIGF0dGVtcHQpO1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2FwKTtcbn07XG5cbi8qKlxuICogUm91Z2hseSBKU09OIGNoZWNrXG4gKiBAcGFyYW0gc3RyIC0gVGhlIHN0cmluZyB0byBjaGVja1xuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgc3RyaW5nIGxvb2tzIGxpa2UgSlNPTlxuICovXG5jb25zdCBsb29rc0xpa2VKc29uID0gKHN0cjogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gIHJldHVybiB0eXBlb2Ygc3RyID09PSAnc3RyaW5nJyAmJiBzdHIudHJpbSgpLnN0YXJ0c1dpdGgoJ3snKTtcbn07XG5cblxuZXhwb3J0IGNvbnN0IHNlY3JldEZldGNoZXIgPSB7XG4gIGdldFNlY3JldFZhbHVlLFxufTtcbiJdfQ==
75
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaURBQWtFO0FBNEJsRTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBYyxJQUFZLEVBQUUsVUFBaUMsRUFBRSxFQUFjLEVBQUU7SUFDekcsTUFBTSxFQUFFLFNBQVMsR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLENBQUMsRUFBRSxhQUFhLEdBQUcsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBRXZFLE1BQU0sR0FBRyxHQUFHLHFEQUFxRCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBRTVGLE1BQU0sY0FBYyxHQUFtQjtRQUNyQyxPQUFPLEVBQUU7WUFDUCxnQ0FBZ0MsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixJQUFJLEVBQUU7U0FDdEU7UUFDRCxPQUFPO1FBQ1AsU0FBUztRQUNULGFBQWE7UUFDYixXQUFXLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDekIsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUNoRSxpR0FBaUc7WUFDakcsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEdBQUcsSUFBSSx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQzFFLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztLQUNGLENBQUM7SUFFRixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsNEJBQVksRUFBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFFekQsTUFBTSxHQUFHLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFbEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFRCxNQUFNLElBQUksR0FBbUIsR0FBRyxDQUFDO0lBRWpDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7SUFFdkMsSUFBSSxhQUFhLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztRQUNoQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFNLENBQUM7SUFDdkMsQ0FBQztJQUVELE9BQU8sWUFBaUIsQ0FBQztBQUMzQixDQUFDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQTJCLEVBQUU7SUFDbkUsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLElBQUk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM5RCxNQUFNLENBQUMsR0FBRyxLQUFnQyxDQUFDO0lBRTNDLE9BQU8sT0FBTyxDQUFDLENBQUMsWUFBWSxLQUFLLFFBQVE7UUFDbEMsT0FBTyxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVE7UUFDMUIsT0FBTyxDQUFDLENBQUMsR0FBRyxLQUFLLFFBQVE7UUFDekIsQ0FBQyxDQUFDLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsQ0FBQyxTQUFTLEtBQUssUUFBUSxDQUFDLENBQUM7QUFDeEUsQ0FBQyxDQUFDO0FBRUY7Ozs7O0dBS0c7QUFDSCxNQUFNLGFBQWEsR0FBRyxDQUFDLEdBQVcsRUFBVyxFQUFFO0lBQzdDLE9BQU8sT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDL0QsQ0FBQyxDQUFDO0FBR0Y7O0dBRUc7QUFDVSxRQUFBLGFBQWEsR0FBRztJQUMzQixjQUFjO0NBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGZldGNoUmV0cmllciwgdHlwZSBSZXF1ZXN0T3B0aW9ucyB9IGZyb20gJ2ZldGNoLXJldHJpZXInO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGZldGNoaW5nIGEgc2VjcmV0IGZyb20gdGhlIFNlY3JldHMgTWFuYWdlciBFeHRlbnNpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VjcmV0VmFsdWVPcHRpb25zIHtcbiAgLyoqIFJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuIERlZmF1bHQ6IDIwMDAgKi9cbiAgdGltZW91dE1zPzogbnVtYmVyO1xuICAvKiogTWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgKGluY2x1ZGluZyB0aGUgZmlyc3QgcmVxdWVzdCkuIERlZmF1bHQ6IDMgKi9cbiAgcmV0cmllcz86IG51bWJlcjtcbiAgLyoqIEJhc2UgZGVsYXkgaW4gbWlsbGlzZWNvbmRzIGZvciBiYWNrb2ZmIGJldHdlZW4gcmV0cmllcy4gRGVmYXVsdDogMzAwICovXG4gIGJhc2VCYWNrb2ZmTXM/OiBudW1iZXI7XG59XG5cbi8qKlxuICogUmVzcG9uc2Ugc2hhcGUgcmV0dXJuZWQgYnkgdGhlIFNlY3JldHMgTWFuYWdlciBFeHRlbnNpb24gQVBJLlxuICovXG5pbnRlcmZhY2UgU2VjcmV0UmVzcG9uc2Uge1xuICAvKiogQVJOIG9mIHRoZSBzZWNyZXQgKi9cbiAgQVJOOiBzdHJpbmc7XG4gIC8qKiBOYW1lIG9mIHRoZSBzZWNyZXQgKi9cbiAgTmFtZTogc3RyaW5nO1xuICAvKiogU2VjcmV0IHZhbHVlIGFzIHN0cmluZyAobWF5IGJlIEpTT04pICovXG4gIFNlY3JldFN0cmluZzogc3RyaW5nO1xuICAvKiogT3B0aW9uYWwgdmVyc2lvbiBpZGVudGlmaWVyICovXG4gIFZlcnNpb25JZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBGZXRjaGVzIGEgc2VjcmV0IHZhbHVlIGZyb20gdGhlIEFXUyBMYW1iZGEgU2VjcmV0cyBNYW5hZ2VyIEV4dGVuc2lvbiAobG9jYWxob3N0OjI3NzMpLlxuICogVXNlcyByZXRyaWVzIHdpdGggZnVsbCBqaXR0ZXIgYmFja29mZiBmb3IgdHJhbnNpZW50IGVycm9ycyAoZS5nLiA1eHgsIDQyOSwgb3IgZXh0ZW5zaW9uIFwibm90IHJlYWR5XCIpLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gU2VjcmV0IG5hbWUgKGlkZW50aWZpZXIpIHRvIGZldGNoXG4gKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbmFsIHRpbWVvdXQsIHJldHJ5LCBhbmQgYmFja29mZiBzZXR0aW5nc1xuICogQHJldHVybnMgVGhlIHNlY3JldCB2YWx1ZSBhcyBzdHJpbmcsIG9yIHBhcnNlZCBhcyBUIGlmIHRoZSBzdG9yZWQgdmFsdWUgaXMgSlNPTlxuICogQHRocm93cyBFcnJvciBpZiB0aGUgcmVzcG9uc2UgZm9ybWF0IGlzIGludmFsaWQgb3IgdGhlIHJlcXVlc3QgZmFpbHMgYWZ0ZXIgcmV0cmllc1xuICovXG5jb25zdCBnZXRTZWNyZXRWYWx1ZSA9IGFzeW5jIDxUID0gc3RyaW5nPihuYW1lOiBzdHJpbmcsIG9wdGlvbnM6IEdldFNlY3JldFZhbHVlT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxUPiA9PiB7XG4gIGNvbnN0IHsgdGltZW91dE1zID0gMjAwMCwgcmV0cmllcyA9IDMsIGJhc2VCYWNrb2ZmTXMgPSAzMDAgfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgdXJsID0gYGh0dHA6Ly9sb2NhbGhvc3Q6Mjc3My9zZWNyZXRzbWFuYWdlci9nZXQ/c2VjcmV0SWQ9JHtlbmNvZGVVUklDb21wb25lbnQobmFtZSl9YDtcblxuICBjb25zdCByZXF1ZXN0T3B0aW9uczogUmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgaGVhZGVyczoge1xuICAgICAgJ1gtQXdzLVBhcmFtZXRlcnMtU2VjcmV0cy1Ub2tlbic6IHByb2Nlc3MuZW52LkFXU19TRVNTSU9OX1RPS0VOID8/ICcnLFxuICAgIH0sXG4gICAgcmV0cmllcyxcbiAgICB0aW1lb3V0TXMsXG4gICAgYmFzZUJhY2tvZmZNcyxcbiAgICBzaG91bGRSZXRyeTogKHJlcywgYm9keSkgPT4ge1xuICAgICAgaWYgKFs0MjksIDUwMCwgNTAyLCA1MDMsIDUwNF0uaW5jbHVkZXMocmVzLnN0YXR1cykpIHJldHVybiB0cnVlO1xuICAgICAgLy8gRXh0ZW5zaW9uIG1heSByZXR1cm4gNDAwICsgXCJub3QgcmVhZHkgdG8gc2VydmUgdHJhZmZpY1wiIHdoaWxlIGluaXRpYWxpemluZzsgcmV0cnkgaW4gdGhhdCBjYXNlXG4gICAgICBpZiAocmVzLnN0YXR1cyA9PT0gNDAwICYmIC9ub3RcXHMrcmVhZHkuKnRyYWZmaWMvaS50ZXN0KGJvZHkpKSByZXR1cm4gdHJ1ZTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICB9O1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hSZXRyaWVyKHVybCwgcmVxdWVzdE9wdGlvbnMpO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcblxuICBpZiAoIWlzU2VjcmV0UmVzcG9uc2UocmF3KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzZWNyZXQgcmVzcG9uc2UgZm9ybWF0Jyk7XG4gIH1cblxuICBjb25zdCBkYXRhOiBTZWNyZXRSZXNwb25zZSA9IHJhdztcblxuICBjb25zdCBzZWNyZXRTdHJpbmcgPSBkYXRhLlNlY3JldFN0cmluZztcblxuICBpZiAobG9va3NMaWtlSnNvbihzZWNyZXRTdHJpbmcpKSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uoc2VjcmV0U3RyaW5nKSBhcyBUO1xuICB9XG5cbiAgcmV0dXJuIHNlY3JldFN0cmluZyBhcyBUO1xufTtcblxuLyoqXG4gKiBUeXBlIGd1YXJkIGZvciB0aGUgU2VjcmV0cyBNYW5hZ2VyIEV4dGVuc2lvbiByZXNwb25zZSBzaGFwZS5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMgVHJ1ZSBpZiB2YWx1ZSBoYXMgdGhlIHNoYXBlIG9mIFNlY3JldFJlc3BvbnNlXG4gKi9cbmNvbnN0IGlzU2VjcmV0UmVzcG9uc2UgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTZWNyZXRSZXNwb25zZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHYgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICByZXR1cm4gdHlwZW9mIHYuU2VjcmV0U3RyaW5nID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgdHlwZW9mIHYuTmFtZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgIHR5cGVvZiB2LkFSTiA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICh2LlZlcnNpb25JZCA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiB2LlZlcnNpb25JZCA9PT0gJ3N0cmluZycpO1xufTtcblxuLyoqXG4gKiBIZXVyaXN0aWMgY2hlY2sgd2hldGhlciBhIHN0cmluZyBsb29rcyBsaWtlIEpTT04gKHN0YXJ0cyB3aXRoIGB7YCBhZnRlciB0cmltKS5cbiAqXG4gKiBAcGFyYW0gc3RyIC0gU3RyaW5nIHRvIGNoZWNrXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBzdHJpbmcgYXBwZWFycyB0byBiZSBKU09OXG4gKi9cbmNvbnN0IGxvb2tzTGlrZUpzb24gPSAoc3RyOiBzdHJpbmcpOiBib29sZWFuID0+IHtcbiAgcmV0dXJuIHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnICYmIHN0ci50cmltKCkuc3RhcnRzV2l0aCgneycpO1xufTtcblxuXG4vKipcbiAqIENsaWVudCBmb3IgZmV0Y2hpbmcgc2VjcmV0cyBmcm9tIHRoZSBBV1MgTGFtYmRhIFNlY3JldHMgTWFuYWdlciBFeHRlbnNpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBzZWNyZXRGZXRjaGVyID0ge1xuICBnZXRTZWNyZXRWYWx1ZSxcbn07XG4iXX0=
package/package.json CHANGED
@@ -37,11 +37,14 @@
37
37
  "eslint-plugin-import": "^2.32.0",
38
38
  "jest": "^30.2.0",
39
39
  "jest-junit": "^16",
40
- "projen": "^0.99.12",
40
+ "projen": "^0.99.16",
41
41
  "ts-jest": "^29.4.6",
42
42
  "ts-node": "^10.9.2",
43
43
  "typescript": "5.9.x"
44
44
  },
45
+ "dependencies": {
46
+ "fetch-retrier": "^0.1"
47
+ },
45
48
  "engines": {
46
49
  "node": ">= 20.0.0"
47
50
  },
@@ -50,7 +53,7 @@
50
53
  "publishConfig": {
51
54
  "access": "public"
52
55
  },
53
- "version": "0.2.2",
56
+ "version": "0.3.1",
54
57
  "jest": {
55
58
  "coverageProvider": "v8",
56
59
  "testMatch": [