dynamodb-refresh-token-provider 0.3.6 → 0.4.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 +46 -8
- package/lib/index.d.ts +11 -4
- package/lib/index.js +9 -3
- package/lib/stores/dynamodb.d.ts +33 -6
- package/lib/stores/dynamodb.js +102 -7
- package/lib/stores/refresh-token-errors.d.ts +23 -2
- package/lib/stores/refresh-token-errors.js +12 -3
- package/lib/types/index.d.ts +58 -5
- package/lib/types/index.js +1 -1
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/gammarers-aws-sdk-modules/dynamodb-refresh-token-provider/blob/main/LICENSE)
|
|
5
5
|
[](https://github.com/gammarers-aws-sdk-modules/dynamodb-refresh-token-provider/actions/workflows/build.yml)
|
|
6
6
|
|
|
7
|
-
TypeScript library that stores **opaque refresh tokens** in **Amazon DynamoDB** using AWS SDK for JavaScript v3. Tokens are persisted under a hash of the plaintext value; **issue**, **rotate** (with reuse detection via a transactional write),
|
|
7
|
+
TypeScript library that stores **opaque refresh tokens** in **Amazon DynamoDB** using AWS SDK for JavaScript v3. Tokens are persisted under a hash of the plaintext value; **issue**, **rotate** (with reuse detection via a transactional write), **revoke** (idempotent), and **revokeSession** (session-wide family revocation) are supported.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -13,7 +13,8 @@ TypeScript library that stores **opaque refresh tokens** in **Amazon DynamoDB**
|
|
|
13
13
|
- **DynamoDB TTL** — writes `ttl` (Unix seconds) on `Put` and `TransactWriteItems` so expired and rotated rows can be removed automatically when table TTL is enabled.
|
|
14
14
|
- **Logical expiration** — `expiresAt` drives validation; `ttl` is for storage cleanup only.
|
|
15
15
|
- **Rotation safety** — marks the old row as rotated and inserts the successor in one transaction; detects reuse and conflicting updates.
|
|
16
|
-
- **
|
|
16
|
+
- **Session revocation (OAuth 2.0 BCP)** — `revokeSession({ sessionId })` revokes all tokens for a session via a `sessionId` GSI; optional `revokeSessionOnReuse` cascades on reuse detection.
|
|
17
|
+
- **Structured errors** — `RefreshTokenError`, `RefreshTokenInvalidError`, `RefreshTokenExpiredError`, `RefreshTokenRevokedError`, `RefreshTokenReusedError` (with optional `subjectId` / `sessionId`), and `RefreshTokenRotateFailedError` for `instanceof` handling.
|
|
17
18
|
- **Utilities** — `sha256hex` and `randomtoken` for hashing and token generation aligned with the store.
|
|
18
19
|
|
|
19
20
|
## Installation
|
|
@@ -28,7 +29,7 @@ yarn add dynamodb-refresh-token-provider
|
|
|
28
29
|
|
|
29
30
|
## Usage
|
|
30
31
|
|
|
31
|
-
Create a store with your table name, AWS region, and optional `StoreOptions`. Your DynamoDB table needs a **string partition key** named `pk`,
|
|
32
|
+
Create a store with your table name, AWS region, and optional `StoreOptions`. Your DynamoDB table needs a **string partition key** named `pk`, **TTL enabled** on attribute `ttl` (see [DynamoDB TTL](#dynamodb-ttl)), and a **GSI** on `sessionId` for session revocation (see [Session GSI](#session-gsi)).
|
|
32
33
|
|
|
33
34
|
```typescript
|
|
34
35
|
import {
|
|
@@ -42,6 +43,9 @@ import {
|
|
|
42
43
|
const store = new DynamodbRefreshTokenProvider('your-refresh-token-table', 'us-east-1', {
|
|
43
44
|
ttlDays: 60,
|
|
44
45
|
pkPrefix: 'rt#',
|
|
46
|
+
// Optional: revoke every token in the session when reuse is detected (OAuth 2.0 BCP)
|
|
47
|
+
// revokeSessionOnReuse: true,
|
|
48
|
+
// sessionIdIndexName: 'sessionId-index',
|
|
45
49
|
});
|
|
46
50
|
|
|
47
51
|
// Issue a new refresh token for a subject/session
|
|
@@ -59,6 +63,10 @@ try {
|
|
|
59
63
|
} catch (e) {
|
|
60
64
|
if (e instanceof RefreshTokenReusedError) {
|
|
61
65
|
// already rotated or lost a transactional race
|
|
66
|
+
// e.sessionId / e.subjectId are set when the store row was loaded
|
|
67
|
+
if (e.sessionId) {
|
|
68
|
+
await store.revokeSession({ sessionId: e.sessionId, subjectId: e.subjectId });
|
|
69
|
+
}
|
|
62
70
|
}
|
|
63
71
|
if (e instanceof RefreshTokenInvalidError) {
|
|
64
72
|
// unknown or malformed token
|
|
@@ -72,8 +80,11 @@ try {
|
|
|
72
80
|
throw e;
|
|
73
81
|
}
|
|
74
82
|
|
|
75
|
-
// Revoke: idempotent; succeeds even if the row does not exist
|
|
83
|
+
// Revoke one token: idempotent; succeeds even if the row does not exist
|
|
76
84
|
await store.revoke({ refreshToken: issued.refreshToken });
|
|
85
|
+
|
|
86
|
+
// Revoke all tokens for a session (requires sessionId GSI)
|
|
87
|
+
await store.revokeSession({ sessionId: 'session-456', subjectId: 'user-123' });
|
|
77
88
|
```
|
|
78
89
|
|
|
79
90
|
### DynamoDB TTL
|
|
@@ -85,7 +96,7 @@ Each item includes:
|
|
|
85
96
|
| `expiresAt` | Logical expiration (Unix seconds); used by the library for validation. |
|
|
86
97
|
| `ttl` | DynamoDB TTL attribute (Unix seconds); enable table TTL on this name for automatic deletion. |
|
|
87
98
|
|
|
88
|
-
On **issue**, both are set to the same value. On **rotate**, the successor `Put` sets both to the new expiration; the previous row’s `ttl` is updated to its existing `expiresAt`. **Revoke**
|
|
99
|
+
On **issue**, both are set to the same value. On **rotate**, the successor `Put` sets both to the new expiration; the previous row’s `ttl` is updated to its existing `expiresAt`. **Revoke** / **revokeSession** do not change `ttl` (the value from issue/rotate still applies).
|
|
89
100
|
|
|
90
101
|
Enable TTL on your table once (per table/region). The TTL attribute name must be **`ttl`**.
|
|
91
102
|
|
|
@@ -104,6 +115,31 @@ aws dynamodb update-time-to-live \
|
|
|
104
115
|
|
|
105
116
|
DynamoDB deletes items asynchronously, typically within 48 hours after `ttl` is in the past.
|
|
106
117
|
|
|
118
|
+
### Session GSI
|
|
119
|
+
|
|
120
|
+
`revokeSession` (and `revokeSessionOnReuse`) query token rows by `sessionId`. Create a GSI whose **partition key** is the attribute **`sessionId`** (String). `KEYS_ONLY` projection is enough (base-table `pk` is always projected).
|
|
121
|
+
|
|
122
|
+
| Setting | Value |
|
|
123
|
+
|---------|--------|
|
|
124
|
+
| Index name | `sessionId-index` (override with `sessionIdIndexName`) |
|
|
125
|
+
| Partition key | `sessionId` (S) |
|
|
126
|
+
| Projection | `KEYS_ONLY` (or `ALL`) |
|
|
127
|
+
|
|
128
|
+
**AWS CLI** (example; adjust billing mode / capacity as needed)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
aws dynamodb update-table \
|
|
132
|
+
--table-name your-refresh-token-table \
|
|
133
|
+
--attribute-definitions AttributeName=sessionId,AttributeType=S \
|
|
134
|
+
--global-secondary-index-updates '[{
|
|
135
|
+
"Create": {
|
|
136
|
+
"IndexName": "sessionId-index",
|
|
137
|
+
"KeySchema": [{"AttributeName": "sessionId", "KeyType": "HASH"}],
|
|
138
|
+
"Projection": {"ProjectionType": "KEYS_ONLY"}
|
|
139
|
+
}
|
|
140
|
+
}]'
|
|
141
|
+
```
|
|
142
|
+
|
|
107
143
|
## Options
|
|
108
144
|
|
|
109
145
|
Constructor: `new DynamodbRefreshTokenProvider(tableName, region, options?)`.
|
|
@@ -114,14 +150,16 @@ Constructor: `new DynamodbRefreshTokenProvider(tableName, region, options?)`.
|
|
|
114
150
|
| `pkPrefix` | `string` | `'rt#'` | Partition key prefix; full `pk` is `prefix` + SHA-256 hex of the plaintext token. |
|
|
115
151
|
| `consistentRead` | `boolean` | `true` | Use strongly consistent reads on `GetItem` when loading a token row. |
|
|
116
152
|
| `endpoint` | `string` | (none) | Custom DynamoDB API endpoint (e.g. LocalStack or DynamoDB Local). |
|
|
153
|
+
| `sessionIdIndexName` | `string` | `'sessionId-index'` | GSI name whose partition key is `sessionId` (required for `revokeSession`). |
|
|
154
|
+
| `revokeSessionOnReuse` | `boolean` | `false` | When true, `rotate` calls `revokeSession` for the token’s session before throwing `RefreshTokenReusedError`. |
|
|
117
155
|
|
|
118
|
-
`issue`, `rotate`, and `
|
|
156
|
+
`issue`, `rotate`, `revoke`, and `revokeSession` accept an optional `now?: Date` for testing or clock injection.
|
|
119
157
|
|
|
120
158
|
## Requirements
|
|
121
159
|
|
|
122
160
|
- **Node.js** 20.0.0 or later.
|
|
123
|
-
- A **DynamoDB table** with a string partition key **`pk
|
|
124
|
-
- **AWS credentials** and permissions for `PutItem`, `GetItem`, `UpdateItem`, and `TransactWriteItems` on that table (and the configured `endpoint` if used).
|
|
161
|
+
- A **DynamoDB table** with a string partition key **`pk`**, **TTL enabled** on attribute **`ttl`** (see [DynamoDB TTL](#dynamodb-ttl)), and a **GSI** on **`sessionId`** for session revocation (see [Session GSI](#session-gsi)).
|
|
162
|
+
- **AWS credentials** and permissions for `PutItem`, `GetItem`, `UpdateItem`, `Query`, and `TransactWriteItems` on that table (and the configured `endpoint` if used).
|
|
125
163
|
|
|
126
164
|
## License
|
|
127
165
|
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public API: refresh token store types, DynamoDB-backed implementation, structured errors, and crypto helpers.
|
|
3
3
|
*
|
|
4
|
-
* Enable DynamoDB TTL on attribute `ttl` when using
|
|
4
|
+
* Enable DynamoDB TTL on attribute `ttl`, and a `sessionId` GSI for session revocation, when using
|
|
5
|
+
* {@link DynamodbRefreshTokenProvider}.
|
|
6
|
+
*/
|
|
7
|
+
export type { RefreshTokenStore, IssueParams, IssueResult, RotateParams, RotateResult, RevokeParams, RevokeSessionParams, RevokeSessionResult, StoreOptions, TokenRecord, EpochSec, } from './types/index';
|
|
8
|
+
/**
|
|
9
|
+
* DynamoDB-backed {@link RefreshTokenStore} with rotation reuse detection and optional
|
|
10
|
+
* session-wide revocation (`revokeSession` / `revokeSessionOnReuse`).
|
|
5
11
|
*/
|
|
6
|
-
export type { RefreshTokenStore, IssueParams, IssueResult, RotateParams, RotateResult, RevokeParams, StoreOptions, TokenRecord, EpochSec, } from './types/index';
|
|
7
|
-
/** DynamoDB-backed {@link RefreshTokenStore} with rotation reuse detection. */
|
|
8
12
|
export { DynamodbRefreshTokenProvider } from './stores/dynamodb';
|
|
9
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Structured errors for `instanceof` handling in auth flows.
|
|
15
|
+
* {@link RefreshTokenReusedError} may carry `subjectId` / `sessionId` for session revoke.
|
|
16
|
+
*/
|
|
10
17
|
export { RefreshTokenError, RefreshTokenExpiredError, RefreshTokenInvalidError, RefreshTokenReusedError, RefreshTokenRevokedError, RefreshTokenRotateFailedError, } from './stores/refresh-token-errors';
|
|
11
18
|
/** SHA-256 hex hashing and cryptographically secure token generation. */
|
|
12
19
|
export { sha256hex, randomtoken } from './utils/hash';
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.randomtoken = exports.sha256hex = exports.RefreshTokenRotateFailedError = exports.RefreshTokenRevokedError = exports.RefreshTokenReusedError = exports.RefreshTokenInvalidError = exports.RefreshTokenExpiredError = exports.RefreshTokenError = exports.DynamodbRefreshTokenProvider = void 0;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* DynamoDB-backed {@link RefreshTokenStore} with rotation reuse detection and optional
|
|
6
|
+
* session-wide revocation (`revokeSession` / `revokeSessionOnReuse`).
|
|
7
|
+
*/
|
|
5
8
|
var dynamodb_1 = require("./stores/dynamodb");
|
|
6
9
|
Object.defineProperty(exports, "DynamodbRefreshTokenProvider", { enumerable: true, get: function () { return dynamodb_1.DynamodbRefreshTokenProvider; } });
|
|
7
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Structured errors for `instanceof` handling in auth flows.
|
|
12
|
+
* {@link RefreshTokenReusedError} may carry `subjectId` / `sessionId` for session revoke.
|
|
13
|
+
*/
|
|
8
14
|
var refresh_token_errors_1 = require("./stores/refresh-token-errors");
|
|
9
15
|
Object.defineProperty(exports, "RefreshTokenError", { enumerable: true, get: function () { return refresh_token_errors_1.RefreshTokenError; } });
|
|
10
16
|
Object.defineProperty(exports, "RefreshTokenExpiredError", { enumerable: true, get: function () { return refresh_token_errors_1.RefreshTokenExpiredError; } });
|
|
@@ -16,4 +22,4 @@ Object.defineProperty(exports, "RefreshTokenRotateFailedError", { enumerable: tr
|
|
|
16
22
|
var hash_1 = require("./utils/hash");
|
|
17
23
|
Object.defineProperty(exports, "sha256hex", { enumerable: true, get: function () { return hash_1.sha256hex; } });
|
|
18
24
|
Object.defineProperty(exports, "randomtoken", { enumerable: true, get: function () { return hash_1.randomtoken; } });
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBb0JBOzs7R0FHRztBQUNILDhDQUFpRTtBQUF4RCx3SEFBQSw0QkFBNEIsT0FBQTtBQUVyQzs7O0dBR0c7QUFDSCxzRUFPdUM7QUFOckMseUhBQUEsaUJBQWlCLE9BQUE7QUFDakIsZ0lBQUEsd0JBQXdCLE9BQUE7QUFDeEIsZ0lBQUEsd0JBQXdCLE9BQUE7QUFDeEIsK0hBQUEsdUJBQXVCLE9BQUE7QUFDdkIsZ0lBQUEsd0JBQXdCLE9BQUE7QUFDeEIscUlBQUEsNkJBQTZCLE9BQUE7QUFHL0IseUVBQXlFO0FBQ3pFLHFDQUFzRDtBQUE3QyxpR0FBQSxTQUFTLE9BQUE7QUFBRSxtR0FBQSxXQUFXLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFB1YmxpYyBBUEk6IHJlZnJlc2ggdG9rZW4gc3RvcmUgdHlwZXMsIER5bmFtb0RCLWJhY2tlZCBpbXBsZW1lbnRhdGlvbiwgc3RydWN0dXJlZCBlcnJvcnMsIGFuZCBjcnlwdG8gaGVscGVycy5cbiAqXG4gKiBFbmFibGUgRHluYW1vREIgVFRMIG9uIGF0dHJpYnV0ZSBgdHRsYCwgYW5kIGEgYHNlc3Npb25JZGAgR1NJIGZvciBzZXNzaW9uIHJldm9jYXRpb24sIHdoZW4gdXNpbmdcbiAqIHtAbGluayBEeW5hbW9kYlJlZnJlc2hUb2tlblByb3ZpZGVyfS5cbiAqL1xuZXhwb3J0IHR5cGUge1xuICBSZWZyZXNoVG9rZW5TdG9yZSxcbiAgSXNzdWVQYXJhbXMsXG4gIElzc3VlUmVzdWx0LFxuICBSb3RhdGVQYXJhbXMsXG4gIFJvdGF0ZVJlc3VsdCxcbiAgUmV2b2tlUGFyYW1zLFxuICBSZXZva2VTZXNzaW9uUGFyYW1zLFxuICBSZXZva2VTZXNzaW9uUmVzdWx0LFxuICBTdG9yZU9wdGlvbnMsXG4gIFRva2VuUmVjb3JkLFxuICBFcG9jaFNlYyxcbn0gZnJvbSAnLi90eXBlcy9pbmRleCc7XG5cbi8qKlxuICogRHluYW1vREItYmFja2VkIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZX0gd2l0aCByb3RhdGlvbiByZXVzZSBkZXRlY3Rpb24gYW5kIG9wdGlvbmFsXG4gKiBzZXNzaW9uLXdpZGUgcmV2b2NhdGlvbiAoYHJldm9rZVNlc3Npb25gIC8gYHJldm9rZVNlc3Npb25PblJldXNlYCkuXG4gKi9cbmV4cG9ydCB7IER5bmFtb2RiUmVmcmVzaFRva2VuUHJvdmlkZXIgfSBmcm9tICcuL3N0b3Jlcy9keW5hbW9kYic7XG5cbi8qKlxuICogU3RydWN0dXJlZCBlcnJvcnMgZm9yIGBpbnN0YW5jZW9mYCBoYW5kbGluZyBpbiBhdXRoIGZsb3dzLlxuICoge0BsaW5rIFJlZnJlc2hUb2tlblJldXNlZEVycm9yfSBtYXkgY2FycnkgYHN1YmplY3RJZGAgLyBgc2Vzc2lvbklkYCBmb3Igc2Vzc2lvbiByZXZva2UuXG4gKi9cbmV4cG9ydCB7XG4gIFJlZnJlc2hUb2tlbkVycm9yLFxuICBSZWZyZXNoVG9rZW5FeHBpcmVkRXJyb3IsXG4gIFJlZnJlc2hUb2tlbkludmFsaWRFcnJvcixcbiAgUmVmcmVzaFRva2VuUmV1c2VkRXJyb3IsXG4gIFJlZnJlc2hUb2tlblJldm9rZWRFcnJvcixcbiAgUmVmcmVzaFRva2VuUm90YXRlRmFpbGVkRXJyb3IsXG59IGZyb20gJy4vc3RvcmVzL3JlZnJlc2gtdG9rZW4tZXJyb3JzJztcblxuLyoqIFNIQS0yNTYgaGV4IGhhc2hpbmcgYW5kIGNyeXB0b2dyYXBoaWNhbGx5IHNlY3VyZSB0b2tlbiBnZW5lcmF0aW9uLiAqL1xuZXhwb3J0IHsgc2hhMjU2aGV4LCByYW5kb210b2tlbiB9IGZyb20gJy4vdXRpbHMvaGFzaCc7XG4iXX0=
|
package/lib/stores/dynamodb.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { RefreshTokenStore, StoreOptions, TokenRecord, IssueParams, RotateParams, RevokeParams, IssueResult, RotateResult } from '../types/index';
|
|
1
|
+
import type { RefreshTokenStore, StoreOptions, TokenRecord, IssueParams, RotateParams, RevokeParams, RevokeSessionParams, RevokeSessionResult, IssueResult, RotateResult } from '../types/index';
|
|
2
2
|
/** Re-exported types for consumers that import the DynamoDB store module. */
|
|
3
|
-
export { RefreshTokenStore, StoreOptions, TokenRecord, IssueParams, RotateParams, RevokeParams, IssueResult, RotateResult };
|
|
3
|
+
export { RefreshTokenStore, StoreOptions, TokenRecord, IssueParams, RotateParams, RevokeParams, RevokeSessionParams, RevokeSessionResult, IssueResult, RotateResult, };
|
|
4
4
|
/**
|
|
5
5
|
* {@link RefreshTokenStore} implementation backed by a single DynamoDB table.
|
|
6
6
|
*
|
|
7
7
|
* Items use partition key `pk`, logical expiration `expiresAt`, and DynamoDB TTL attribute `ttl`
|
|
8
8
|
* (Unix seconds). Enable table TTL on attribute `ttl` so expired and rotated rows are removed
|
|
9
|
-
* asynchronously.
|
|
10
|
-
*
|
|
9
|
+
* asynchronously. Session-wide revocation requires a GSI whose partition key is `sessionId`
|
|
10
|
+
* (see {@link StoreOptions.sessionIdIndexName}). This class owns the DynamoDB client; callers
|
|
11
|
+
* supply `tableName`, `region`, and optional {@link StoreOptions}.
|
|
11
12
|
*/
|
|
12
13
|
export declare class DynamodbRefreshTokenProvider implements RefreshTokenStore {
|
|
13
14
|
private readonly tableName;
|
|
@@ -20,7 +21,7 @@ export declare class DynamodbRefreshTokenProvider implements RefreshTokenStore {
|
|
|
20
21
|
/**
|
|
21
22
|
* @param tableName - DynamoDB table name for refresh token items.
|
|
22
23
|
* @param region - AWS region for the DynamoDB client.
|
|
23
|
-
* @param options - Token lifetime, PK prefix,
|
|
24
|
+
* @param options - Token lifetime, PK prefix, GSI name, reuse revocation, or custom endpoint.
|
|
24
25
|
*/
|
|
25
26
|
constructor(tableName: string, region: string, options?: StoreOptions | undefined);
|
|
26
27
|
/**
|
|
@@ -36,12 +37,17 @@ export declare class DynamodbRefreshTokenProvider implements RefreshTokenStore {
|
|
|
36
37
|
* Updates the previous row’s `ttl` to its `expiresAt` and sets `ttl` on the new Put to the
|
|
37
38
|
* successor’s expiration so DynamoDB can delete both when appropriate.
|
|
38
39
|
*
|
|
40
|
+
* When reuse is detected and {@link StoreOptions.revokeSessionOnReuse} is true, all tokens for
|
|
41
|
+
* the same `sessionId` and `subjectId` are revoked via {@link DynamodbRefreshTokenProvider.revokeSession}
|
|
42
|
+
* before throwing.
|
|
43
|
+
*
|
|
39
44
|
* @param params - Client refresh token and optional clock (`now`).
|
|
40
45
|
* @returns Subject, session, new plaintext token, and new expiration.
|
|
41
46
|
* @throws {@link RefreshTokenInvalidError} When the token format is invalid or no row exists.
|
|
42
47
|
* @throws {@link RefreshTokenExpiredError} When `expiresAt` is not after `now`.
|
|
43
48
|
* @throws {@link RefreshTokenRevokedError} When the token row has `revokedAt` set.
|
|
44
|
-
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
49
|
+
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
50
|
+
* indicates reuse. Includes `subjectId` and `sessionId` from the loaded row.
|
|
45
51
|
*/
|
|
46
52
|
rotate: (params: RotateParams) => Promise<RotateResult>;
|
|
47
53
|
/**
|
|
@@ -54,6 +60,27 @@ export declare class DynamodbRefreshTokenProvider implements RefreshTokenStore {
|
|
|
54
60
|
* @throws {@link RefreshTokenInvalidError} When the token string format is invalid.
|
|
55
61
|
*/
|
|
56
62
|
revoke: (params: RevokeParams) => Promise<true>;
|
|
63
|
+
/**
|
|
64
|
+
* Sets `revokedAt` on every token row for the given `sessionId` (optionally filtered by `subjectId`).
|
|
65
|
+
*
|
|
66
|
+
* Queries the session GSI (partition key `sessionId`; `KEYS_ONLY` is enough), then updates each
|
|
67
|
+
* base-table item. When `subjectId` is set, it is required in the `UpdateItem` condition.
|
|
68
|
+
* Missing or non-matching items are skipped (idempotent). Paginate with `LastEvaluatedKey`.
|
|
69
|
+
*
|
|
70
|
+
* @param params - Session id, optional subject filter, and optional clock.
|
|
71
|
+
* @returns Count of rows updated with `revokedAt` in this call.
|
|
72
|
+
*/
|
|
73
|
+
revokeSession: (params: RevokeSessionParams) => Promise<RevokeSessionResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Handles refresh-token reuse detection: optionally cascades {@link DynamodbRefreshTokenProvider.revokeSession}
|
|
76
|
+
* when {@link StoreOptions.revokeSessionOnReuse} is true, then throws {@link RefreshTokenReusedError}
|
|
77
|
+
* populated with `subjectId` / `sessionId` from `current`.
|
|
78
|
+
*
|
|
79
|
+
* @param current - Token row that indicated reuse (`rotatedAt` set or transaction canceled).
|
|
80
|
+
* @param now - Clock used for `revokedAt` when cascading revoke is enabled.
|
|
81
|
+
* @throws {@link RefreshTokenReusedError} Always (return type is `never`).
|
|
82
|
+
*/
|
|
83
|
+
private handleRefreshTokenReuse;
|
|
57
84
|
/**
|
|
58
85
|
* Returns the cached {@link DynamoDBDocumentClient}, creating it on first use.
|
|
59
86
|
*
|
package/lib/stores/dynamodb.js
CHANGED
|
@@ -8,19 +8,22 @@ const hash_1 = require("../utils/hash");
|
|
|
8
8
|
const time_1 = require("../utils/time");
|
|
9
9
|
/** Default partition key prefix for refresh token items. */
|
|
10
10
|
const DEFAULT_PRIMARY_KEY_PREFIX = 'rt#';
|
|
11
|
+
/** Default GSI name for querying token rows by `sessionId`. */
|
|
12
|
+
const DEFAULT_SESSION_ID_INDEX_NAME = 'sessionId-index';
|
|
11
13
|
/**
|
|
12
14
|
* {@link RefreshTokenStore} implementation backed by a single DynamoDB table.
|
|
13
15
|
*
|
|
14
16
|
* Items use partition key `pk`, logical expiration `expiresAt`, and DynamoDB TTL attribute `ttl`
|
|
15
17
|
* (Unix seconds). Enable table TTL on attribute `ttl` so expired and rotated rows are removed
|
|
16
|
-
* asynchronously.
|
|
17
|
-
*
|
|
18
|
+
* asynchronously. Session-wide revocation requires a GSI whose partition key is `sessionId`
|
|
19
|
+
* (see {@link StoreOptions.sessionIdIndexName}). This class owns the DynamoDB client; callers
|
|
20
|
+
* supply `tableName`, `region`, and optional {@link StoreOptions}.
|
|
18
21
|
*/
|
|
19
22
|
class DynamodbRefreshTokenProvider {
|
|
20
23
|
/**
|
|
21
24
|
* @param tableName - DynamoDB table name for refresh token items.
|
|
22
25
|
* @param region - AWS region for the DynamoDB client.
|
|
23
|
-
* @param options - Token lifetime, PK prefix,
|
|
26
|
+
* @param options - Token lifetime, PK prefix, GSI name, reuse revocation, or custom endpoint.
|
|
24
27
|
*/
|
|
25
28
|
constructor(tableName, region, options) {
|
|
26
29
|
this.tableName = tableName;
|
|
@@ -67,12 +70,17 @@ class DynamodbRefreshTokenProvider {
|
|
|
67
70
|
* Updates the previous row’s `ttl` to its `expiresAt` and sets `ttl` on the new Put to the
|
|
68
71
|
* successor’s expiration so DynamoDB can delete both when appropriate.
|
|
69
72
|
*
|
|
73
|
+
* When reuse is detected and {@link StoreOptions.revokeSessionOnReuse} is true, all tokens for
|
|
74
|
+
* the same `sessionId` and `subjectId` are revoked via {@link DynamodbRefreshTokenProvider.revokeSession}
|
|
75
|
+
* before throwing.
|
|
76
|
+
*
|
|
70
77
|
* @param params - Client refresh token and optional clock (`now`).
|
|
71
78
|
* @returns Subject, session, new plaintext token, and new expiration.
|
|
72
79
|
* @throws {@link RefreshTokenInvalidError} When the token format is invalid or no row exists.
|
|
73
80
|
* @throws {@link RefreshTokenExpiredError} When `expiresAt` is not after `now`.
|
|
74
81
|
* @throws {@link RefreshTokenRevokedError} When the token row has `revokedAt` set.
|
|
75
|
-
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
82
|
+
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
83
|
+
* indicates reuse. Includes `subjectId` and `sessionId` from the loaded row.
|
|
76
84
|
*/
|
|
77
85
|
this.rotate = async (params) => {
|
|
78
86
|
// validate refresh token
|
|
@@ -93,7 +101,7 @@ class DynamodbRefreshTokenProvider {
|
|
|
93
101
|
throw new refresh_token_errors_1.RefreshTokenRevokedError();
|
|
94
102
|
}
|
|
95
103
|
if (current.rotatedAt) {
|
|
96
|
-
|
|
104
|
+
await this.handleRefreshTokenReuse(current, now);
|
|
97
105
|
}
|
|
98
106
|
const nextRefreshTokenExpiresAt = this.makeExpiresAt(nowSec);
|
|
99
107
|
const nextRefreshToken = (0, hash_1.randomtoken)(this.tokenBytes);
|
|
@@ -138,7 +146,7 @@ class DynamodbRefreshTokenProvider {
|
|
|
138
146
|
catch (error) {
|
|
139
147
|
if (error instanceof Error && error.name === 'TransactionCanceledException') {
|
|
140
148
|
// Treat conditional transaction failure as token reuse.
|
|
141
|
-
|
|
149
|
+
await this.handleRefreshTokenReuse(current, now);
|
|
142
150
|
}
|
|
143
151
|
throw error;
|
|
144
152
|
}
|
|
@@ -186,6 +194,93 @@ class DynamodbRefreshTokenProvider {
|
|
|
186
194
|
}
|
|
187
195
|
return true;
|
|
188
196
|
};
|
|
197
|
+
/**
|
|
198
|
+
* Sets `revokedAt` on every token row for the given `sessionId` (optionally filtered by `subjectId`).
|
|
199
|
+
*
|
|
200
|
+
* Queries the session GSI (partition key `sessionId`; `KEYS_ONLY` is enough), then updates each
|
|
201
|
+
* base-table item. When `subjectId` is set, it is required in the `UpdateItem` condition.
|
|
202
|
+
* Missing or non-matching items are skipped (idempotent). Paginate with `LastEvaluatedKey`.
|
|
203
|
+
*
|
|
204
|
+
* @param params - Session id, optional subject filter, and optional clock.
|
|
205
|
+
* @returns Count of rows updated with `revokedAt` in this call.
|
|
206
|
+
*/
|
|
207
|
+
this.revokeSession = async (params) => {
|
|
208
|
+
const ddb = this.getddb();
|
|
209
|
+
const now = params.now ?? new Date();
|
|
210
|
+
const nowSec = (0, time_1.epochsec)(now);
|
|
211
|
+
const indexName = this.options?.sessionIdIndexName ?? DEFAULT_SESSION_ID_INDEX_NAME;
|
|
212
|
+
let revokedCount = 0;
|
|
213
|
+
let exclusiveStartKey;
|
|
214
|
+
/** Whether another Query page is available after the previous response. */
|
|
215
|
+
const shouldContinuePaging = () => exclusiveStartKey !== undefined;
|
|
216
|
+
do {
|
|
217
|
+
const res = await ddb.send(new lib_dynamodb_1.QueryCommand({
|
|
218
|
+
TableName: this.tableName,
|
|
219
|
+
IndexName: indexName,
|
|
220
|
+
KeyConditionExpression: 'sessionId = :sessionId',
|
|
221
|
+
ExpressionAttributeValues: {
|
|
222
|
+
':sessionId': params.sessionId,
|
|
223
|
+
},
|
|
224
|
+
ProjectionExpression: 'pk',
|
|
225
|
+
ExclusiveStartKey: exclusiveStartKey,
|
|
226
|
+
}));
|
|
227
|
+
const items = res.Items ?? [];
|
|
228
|
+
for (const item of items) {
|
|
229
|
+
const pk = item.pk;
|
|
230
|
+
if (typeof pk !== 'string') {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
const expressionAttributeValues = {
|
|
234
|
+
':now': nowSec,
|
|
235
|
+
};
|
|
236
|
+
let conditionExpression = 'attribute_exists(pk)';
|
|
237
|
+
if (params.subjectId) {
|
|
238
|
+
conditionExpression = 'attribute_exists(pk) AND subjectId = :subjectId';
|
|
239
|
+
expressionAttributeValues[':subjectId'] = params.subjectId;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
await ddb.send(new lib_dynamodb_1.UpdateCommand({
|
|
243
|
+
TableName: this.tableName,
|
|
244
|
+
Key: { pk },
|
|
245
|
+
UpdateExpression: 'SET revokedAt = :now',
|
|
246
|
+
ConditionExpression: conditionExpression,
|
|
247
|
+
ExpressionAttributeValues: expressionAttributeValues,
|
|
248
|
+
}));
|
|
249
|
+
revokedCount += 1;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (error instanceof Error && error.name === 'ConditionalCheckFailedException') {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
exclusiveStartKey = res.LastEvaluatedKey;
|
|
259
|
+
} while (shouldContinuePaging());
|
|
260
|
+
return { revokedCount };
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* Handles refresh-token reuse detection: optionally cascades {@link DynamodbRefreshTokenProvider.revokeSession}
|
|
264
|
+
* when {@link StoreOptions.revokeSessionOnReuse} is true, then throws {@link RefreshTokenReusedError}
|
|
265
|
+
* populated with `subjectId` / `sessionId` from `current`.
|
|
266
|
+
*
|
|
267
|
+
* @param current - Token row that indicated reuse (`rotatedAt` set or transaction canceled).
|
|
268
|
+
* @param now - Clock used for `revokedAt` when cascading revoke is enabled.
|
|
269
|
+
* @throws {@link RefreshTokenReusedError} Always (return type is `never`).
|
|
270
|
+
*/
|
|
271
|
+
this.handleRefreshTokenReuse = async (current, now) => {
|
|
272
|
+
if (this.options?.revokeSessionOnReuse) {
|
|
273
|
+
await this.revokeSession({
|
|
274
|
+
sessionId: current.sessionId,
|
|
275
|
+
subjectId: current.subjectId,
|
|
276
|
+
now,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
throw new refresh_token_errors_1.RefreshTokenReusedError(undefined, {
|
|
280
|
+
subjectId: current.subjectId,
|
|
281
|
+
sessionId: current.sessionId,
|
|
282
|
+
});
|
|
283
|
+
};
|
|
189
284
|
/**
|
|
190
285
|
* Returns the cached {@link DynamoDBDocumentClient}, creating it on first use.
|
|
191
286
|
*
|
|
@@ -261,4 +356,4 @@ class DynamodbRefreshTokenProvider {
|
|
|
261
356
|
}
|
|
262
357
|
}
|
|
263
358
|
exports.DynamodbRefreshTokenProvider = DynamodbRefreshTokenProvider;
|
|
264
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL2R5bmFtb2RiLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDhEQUEwRDtBQUMxRCx3REFBNEg7QUFFNUgsaUVBS2dDO0FBRWhDLHdDQUF1RDtBQUN2RCx3Q0FBeUM7QUFLekMsNERBQTREO0FBQzVELE1BQU0sMEJBQTBCLEdBQUcsS0FBSyxDQUFDO0FBRXpDOzs7Ozs7O0dBT0c7QUFDSCxNQUFhLDRCQUE0QjtJQU92Qzs7OztPQUlHO0lBQ0gsWUFDbUIsU0FBaUIsRUFDakIsTUFBYyxFQUNkLE9BQXNCO1FBRnRCLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFDakIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFlBQU8sR0FBUCxPQUFPLENBQWU7UUFkekMscURBQXFEO1FBQzdDLFFBQUcsR0FBa0MsSUFBSSxDQUFDO1FBRWxELDhFQUE4RTtRQUM3RCxlQUFVLEdBQUcsRUFBRSxDQUFDO1FBYWpDOzs7OztXQUtHO1FBQ0ksVUFBSyxHQUFHLEtBQUssRUFBRSxNQUFtQixFQUF3QixFQUFFO1lBQ2pFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUUxQixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7WUFDckMsTUFBTSxNQUFNLEdBQUcsSUFBQSxlQUFRLEVBQUMsR0FBRyxDQUFDLENBQUM7WUFDN0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUU3QyxNQUFNLFlBQVksR0FBRyxJQUFBLGtCQUFXLEVBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2xELE1BQU0sSUFBSSxHQUFHLElBQUEsZ0JBQVMsRUFBQyxZQUFZLENBQUMsQ0FBQztZQUNyQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXBDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FDWixJQUFJLHlCQUFVLENBQUM7Z0JBQ2IsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2dCQUN6QixJQUFJLEVBQUU7b0JBQ0osRUFBRTtvQkFDRixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7b0JBQzNCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztvQkFDM0IsU0FBUyxFQUFFLE1BQU07b0JBQ2pCLFNBQVM7b0JBQ1QsR0FBRyxFQUFFLFNBQVM7aUJBQ2Y7Z0JBQ0QsbUJBQW1CLEVBQUUsMEJBQTBCO2FBQ2hELENBQUMsQ0FDSCxDQUFDO1lBRUYsT0FBTztnQkFDTCxZQUFZO2dCQUNaLHFCQUFxQixFQUFFLFNBQVM7YUFDakMsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVGOzs7Ozs7Ozs7Ozs7V0FZRztRQUNJLFdBQU0sR0FBRyxLQUFLLEVBQUUsTUFBb0IsRUFBeUIsRUFBRTtZQUNwRSx5QkFBeUI7WUFDekIsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUUvQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFMUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3JDLE1BQU0sTUFBTSxHQUFHLElBQUEsZUFBUSxFQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRTdCLE1BQU0sV0FBVyxHQUFHLElBQUEsZ0JBQVMsRUFBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDbkQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUVsRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNiLE1BQU0sSUFBSSwrQ0FBd0IsRUFBRSxDQUFDO1lBQ3ZDLENBQUM7WUFDRCxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sSUFBSSwrQ0FBd0IsRUFBRSxDQUFDO1lBQ3ZDLENBQUM7WUFDRCxJQUFJLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDdEIsTUFBTSxJQUFJLCtDQUF3QixFQUFFLENBQUM7WUFDdkMsQ0FBQztZQUNELElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUN0QixNQUFNLElBQUksOENBQXVCLEVBQUUsQ0FBQztZQUN0QyxDQUFDO1lBRUQsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzdELE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSxrQkFBVyxFQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFBLGdCQUFTLEVBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUM3QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRTVDLElBQUksQ0FBQztnQkFDSCxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxtQ0FBb0IsQ0FBQztvQkFDdEMsYUFBYSxFQUFFO3dCQUNiOzRCQUNFLE1BQU0sRUFBRTtnQ0FDTixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7Z0NBQ3pCLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUU7Z0NBQ3RCLGdCQUFnQixFQUFFLDJEQUEyRDtnQ0FDN0UsbUJBQW1CLEVBQUUsOEZBQThGO2dDQUNuSCx3QkFBd0IsRUFBRTtvQ0FDeEIsTUFBTSxFQUFFLEtBQUs7aUNBQ2Q7Z0NBQ0QseUJBQXlCLEVBQUU7b0NBQ3pCLE1BQU0sRUFBRSxNQUFNO29DQUNkLFNBQVMsRUFBRSxNQUFNO29DQUNqQixNQUFNLEVBQUUsT0FBTyxDQUFDLFNBQVM7aUNBQzFCOzZCQUNGO3lCQUNGO3dCQUNEOzRCQUNFLEdBQUcsRUFBRTtnQ0FDSCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7Z0NBQ3pCLElBQUksRUFBRTtvQ0FDSixFQUFFLEVBQUUsTUFBTTtvQ0FDVixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7b0NBQzVCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztvQ0FDNUIsU0FBUyxFQUFFLE1BQU07b0NBQ2pCLFNBQVMsRUFBRSx5QkFBeUI7b0NBQ3BDLEdBQUcsRUFBRSx5QkFBeUI7aUNBQy9CO2dDQUNELG1CQUFtQixFQUFFLDBCQUEwQjs2QkFDaEQ7eUJBQ0Y7cUJBQ0Y7aUJBQ0YsQ0FBQyxDQUFDLENBQUM7WUFFTixDQUFDO1lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxLQUFLLFlBQVksS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssOEJBQThCLEVBQUUsQ0FBQztvQkFDNUUsd0RBQXdEO29CQUN4RCxNQUFNLElBQUksOENBQXVCLEVBQUUsQ0FBQztnQkFDdEMsQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxPQUFPO2dCQUNMLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztnQkFDNUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO2dCQUM1QixZQUFZLEVBQUUsZ0JBQWdCO2dCQUM5QixxQkFBcUIsRUFBRSx5QkFBeUI7YUFDakQsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVGOzs7Ozs7OztXQVFHO1FBQ0ksV0FBTSxHQUFHLEtBQUssRUFBRSxNQUFvQixFQUFpQixFQUFFO1lBQzVELHlCQUF5QjtZQUN6QixJQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRS9DLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUUxQixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7WUFDckMsTUFBTSxNQUFNLEdBQUcsSUFBQSxlQUFRLEVBQUMsR0FBRyxDQUFDLENBQUM7WUFFN0IsTUFBTSxJQUFJLEdBQUcsSUFBQSxnQkFBUyxFQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUM1QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXBDLElBQUksQ0FBQztnQkFDSCxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQ1osSUFBSSw0QkFBYSxDQUFDO29CQUNoQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7b0JBQ3pCLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRTtvQkFDWCxnQkFBZ0IsRUFBRSxzQkFBc0I7b0JBQ3hDLG1CQUFtQixFQUFFLHNCQUFzQjtvQkFDM0MseUJBQXlCLEVBQUU7d0JBQ3pCLE1BQU0sRUFBRSxNQUFNO3FCQUNmO2lCQUNGLENBQUMsQ0FDSCxDQUFDO1lBQ0osQ0FBQztZQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7Z0JBQ3hCLHNEQUFzRDtnQkFDdEQsSUFBSSxLQUFLLFlBQVksS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssaUNBQWlDLEVBQUUsQ0FBQztvQkFDL0UsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSyxXQUFNLEdBQUcsR0FBMkIsRUFBRTtZQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNkLE1BQU0sTUFBTSxHQUFHLElBQUksZ0NBQWMsQ0FBQztvQkFDaEMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO29CQUNuQixRQUFRLEVBQUUsQ0FBQyxHQUFHLEVBQUU7d0JBQ2QsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDOzRCQUMzQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO3dCQUMvQixDQUFDO3dCQUNELE9BQU8sb0JBQW9CLElBQUksQ0FBQyxNQUFNLGdCQUFnQixDQUFDO29CQUN6RCxDQUFDLENBQUMsRUFBRTtpQkFDTCxDQUFDLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLEdBQUcsR0FBRyxxQ0FBc0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDakQsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNsQixDQUFDLENBQUM7UUFFRjs7Ozs7V0FLRztRQUNLLG1CQUFjLEdBQUcsS0FBSyxFQUFFLEVBQVUsRUFBK0IsRUFBRTtZQUN6RSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFMUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUN4QixJQUFJLHlCQUFVLENBQUM7Z0JBQ2IsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2dCQUN6QixHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUU7Z0JBQ1gsY0FBYyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxJQUFJLElBQUk7YUFDckQsQ0FBQyxDQUNILENBQUM7WUFDRixPQUFRLEdBQUcsQ0FBQyxJQUFvQixJQUFJLElBQUksQ0FBQztRQUMzQyxDQUFDLENBQUM7UUFFRjs7OztXQUlHO1FBQ0ssd0JBQW1CLEdBQUcsR0FBVyxFQUFFO1lBQ3pDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsSUFBSSwwQkFBMEIsRUFBRSxDQUFDO1FBQ25FLENBQUMsQ0FBQztRQUVGOzs7OztXQUtHO1FBQ0ssa0JBQWEsR0FBRyxDQUFDLElBQVksRUFBVSxFQUFFO1lBQy9DLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNoRCxDQUFDLENBQUM7UUFFRjs7Ozs7V0FLRztRQUNLLGtCQUFhLEdBQUcsQ0FBQyxNQUFjLEVBQVUsRUFBRTtZQUNqRCxPQUFPLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQy9ELENBQUMsQ0FBQztJQXRQQyxDQUFDO0lBd1BKOzs7OztPQUtHO0lBQ0ssb0JBQW9CLENBQUMsS0FBYTtRQUN4QyxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sSUFBSSwrQ0FBd0IsRUFBRSxDQUFDO1FBQ3ZDLENBQUM7SUFDSCxDQUFDO0NBRUY7QUFwUkQsb0VBb1JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHluYW1vREJDbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtZHluYW1vZGInO1xuaW1wb3J0IHsgRHluYW1vREJEb2N1bWVudENsaWVudCwgR2V0Q29tbWFuZCwgUHV0Q29tbWFuZCwgVXBkYXRlQ29tbWFuZCwgVHJhbnNhY3RXcml0ZUNvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9saWItZHluYW1vZGInO1xuXG5pbXBvcnQge1xuICBSZWZyZXNoVG9rZW5FeHBpcmVkRXJyb3IsXG4gIFJlZnJlc2hUb2tlbkludmFsaWRFcnJvcixcbiAgUmVmcmVzaFRva2VuUmV1c2VkRXJyb3IsXG4gIFJlZnJlc2hUb2tlblJldm9rZWRFcnJvcixcbn0gZnJvbSAnLi9yZWZyZXNoLXRva2VuLWVycm9ycyc7XG5pbXBvcnQgdHlwZSB7IFJlZnJlc2hUb2tlblN0b3JlLCBTdG9yZU9wdGlvbnMsIFRva2VuUmVjb3JkLCBJc3N1ZVBhcmFtcywgUm90YXRlUGFyYW1zLCBSZXZva2VQYXJhbXMsIElzc3VlUmVzdWx0LCBSb3RhdGVSZXN1bHQgfSBmcm9tICcuLi90eXBlcy9pbmRleCc7XG5pbXBvcnQgeyByYW5kb210b2tlbiwgc2hhMjU2aGV4IH0gZnJvbSAnLi4vdXRpbHMvaGFzaCc7XG5pbXBvcnQgeyBlcG9jaHNlYyB9IGZyb20gJy4uL3V0aWxzL3RpbWUnO1xuXG4vKiogUmUtZXhwb3J0ZWQgdHlwZXMgZm9yIGNvbnN1bWVycyB0aGF0IGltcG9ydCB0aGUgRHluYW1vREIgc3RvcmUgbW9kdWxlLiAqL1xuZXhwb3J0IHsgUmVmcmVzaFRva2VuU3RvcmUsIFN0b3JlT3B0aW9ucywgVG9rZW5SZWNvcmQsIElzc3VlUGFyYW1zLCBSb3RhdGVQYXJhbXMsIFJldm9rZVBhcmFtcywgSXNzdWVSZXN1bHQsIFJvdGF0ZVJlc3VsdCB9O1xuXG4vKiogRGVmYXVsdCBwYXJ0aXRpb24ga2V5IHByZWZpeCBmb3IgcmVmcmVzaCB0b2tlbiBpdGVtcy4gKi9cbmNvbnN0IERFRkFVTFRfUFJJTUFSWV9LRVlfUFJFRklYID0gJ3J0Iyc7XG5cbi8qKlxuICoge0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlfSBpbXBsZW1lbnRhdGlvbiBiYWNrZWQgYnkgYSBzaW5nbGUgRHluYW1vREIgdGFibGUuXG4gKlxuICogSXRlbXMgdXNlIHBhcnRpdGlvbiBrZXkgYHBrYCwgbG9naWNhbCBleHBpcmF0aW9uIGBleHBpcmVzQXRgLCBhbmQgRHluYW1vREIgVFRMIGF0dHJpYnV0ZSBgdHRsYFxuICogKFVuaXggc2Vjb25kcykuIEVuYWJsZSB0YWJsZSBUVEwgb24gYXR0cmlidXRlIGB0dGxgIHNvIGV4cGlyZWQgYW5kIHJvdGF0ZWQgcm93cyBhcmUgcmVtb3ZlZFxuICogYXN5bmNocm9ub3VzbHkuIFRoaXMgY2xhc3Mgb3ducyB0aGUgRHluYW1vREIgY2xpZW50OyBjYWxsZXJzIHN1cHBseSBgdGFibGVOYW1lYCwgYHJlZ2lvbmAsIGFuZFxuICogb3B0aW9uYWwge0BsaW5rIFN0b3JlT3B0aW9uc30uXG4gKi9cbmV4cG9ydCBjbGFzcyBEeW5hbW9kYlJlZnJlc2hUb2tlblByb3ZpZGVyIGltcGxlbWVudHMgUmVmcmVzaFRva2VuU3RvcmUge1xuICAvKiogTGF6aWx5IGluaXRpYWxpemVkIGFuZCBjYWNoZWQgZG9jdW1lbnQgY2xpZW50LiAqL1xuICBwcml2YXRlIGRkYjogRHluYW1vREJEb2N1bWVudENsaWVudCB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBSYW5kb20gYnl0ZSBsZW5ndGggZm9yIGdlbmVyYXRlZCByZWZyZXNoIHRva2VucyAoZGVmYXVsdCAzMiDihpIgMjU2LWJpdCkuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgdG9rZW5CeXRlcyA9IDMyO1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gdGFibGVOYW1lIC0gRHluYW1vREIgdGFibGUgbmFtZSBmb3IgcmVmcmVzaCB0b2tlbiBpdGVtcy5cbiAgICogQHBhcmFtIHJlZ2lvbiAtIEFXUyByZWdpb24gZm9yIHRoZSBEeW5hbW9EQiBjbGllbnQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVG9rZW4gbGlmZXRpbWUsIFBLIHByZWZpeCwgY29uc2lzdGVudCByZWFkcywgb3IgY3VzdG9tIGVuZHBvaW50LlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lvbjogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9ucz86IFN0b3JlT3B0aW9ucyxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBJbnNlcnRzIGEgbmV3IHRva2VuIHJlY29yZCB3aXRoIGBleHBpcmVzQXRgIGFuZCBtYXRjaGluZyBgdHRsYC4gRmFpbHMgdGhlIHB1dCBpZiBgcGtgIGFscmVhZHkgZXhpc3RzLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU3ViamVjdCwgc2Vzc2lvbiwgYW5kIG9wdGlvbmFsIGNsb2NrIChgbm93YCkuXG4gICAqIEByZXR1cm5zIFBsYWludGV4dCByZWZyZXNoIHRva2VuIGFuZCBleHBpcmF0aW9uIGFzIFVuaXggc2Vjb25kcy5cbiAgICovXG4gIHB1YmxpYyBpc3N1ZSA9IGFzeW5jIChwYXJhbXM6IElzc3VlUGFyYW1zKTogUHJvbWlzZTxJc3N1ZVJlc3VsdD4gPT4ge1xuICAgIGNvbnN0IGRkYiA9IHRoaXMuZ2V0ZGRiKCk7XG5cbiAgICBjb25zdCBub3cgPSBwYXJhbXMubm93ID8/IG5ldyBEYXRlKCk7XG4gICAgY29uc3Qgbm93U2VjID0gZXBvY2hzZWMobm93KTtcbiAgICBjb25zdCBleHBpcmVzQXQgPSB0aGlzLm1ha2VFeHBpcmVzQXQobm93U2VjKTtcblxuICAgIGNvbnN0IHJlZnJlc2hUb2tlbiA9IHJhbmRvbXRva2VuKHRoaXMudG9rZW5CeXRlcyk7XG4gICAgY29uc3QgaGFzaCA9IHNoYTI1NmhleChyZWZyZXNoVG9rZW4pO1xuICAgIGNvbnN0IHBrID0gdGhpcy5nZXRQcmltYXJ5S2V5KGhhc2gpO1xuXG4gICAgYXdhaXQgZGRiLnNlbmQoXG4gICAgICBuZXcgUHV0Q29tbWFuZCh7XG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICAgIEl0ZW06IHtcbiAgICAgICAgICBwayxcbiAgICAgICAgICBzdWJqZWN0SWQ6IHBhcmFtcy5zdWJqZWN0SWQsXG4gICAgICAgICAgc2Vzc2lvbklkOiBwYXJhbXMuc2Vzc2lvbklkLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93U2VjLFxuICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICB0dGw6IGV4cGlyZXNBdCxcbiAgICAgICAgfSxcbiAgICAgICAgQ29uZGl0aW9uRXhwcmVzc2lvbjogJ2F0dHJpYnV0ZV9ub3RfZXhpc3RzKHBrKScsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlZnJlc2hUb2tlbixcbiAgICAgIHJlZnJlc2hUb2tlbkV4cGlyZXNBdDogZXhwaXJlc0F0LFxuICAgIH07XG4gIH07XG5cbiAgLyoqXG4gICAqIE1hcmtzIHRoZSBjdXJyZW50IHRva2VuIGFzIHJvdGF0ZWQgYW5kIGNyZWF0ZXMgdGhlIHN1Y2Nlc3NvciByb3cgaW4gb25lIHRyYW5zYWN0aW9uLlxuICAgKlxuICAgKiBVcGRhdGVzIHRoZSBwcmV2aW91cyByb3figJlzIGB0dGxgIHRvIGl0cyBgZXhwaXJlc0F0YCBhbmQgc2V0cyBgdHRsYCBvbiB0aGUgbmV3IFB1dCB0byB0aGVcbiAgICogc3VjY2Vzc29y4oCZcyBleHBpcmF0aW9uIHNvIER5bmFtb0RCIGNhbiBkZWxldGUgYm90aCB3aGVuIGFwcHJvcHJpYXRlLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gQ2xpZW50IHJlZnJlc2ggdG9rZW4gYW5kIG9wdGlvbmFsIGNsb2NrIChgbm93YCkuXG4gICAqIEByZXR1cm5zIFN1YmplY3QsIHNlc3Npb24sIG5ldyBwbGFpbnRleHQgdG9rZW4sIGFuZCBuZXcgZXhwaXJhdGlvbi5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBmb3JtYXQgaXMgaW52YWxpZCBvciBubyByb3cgZXhpc3RzLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5FeHBpcmVkRXJyb3J9IFdoZW4gYGV4cGlyZXNBdGAgaXMgbm90IGFmdGVyIGBub3dgLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXZva2VkRXJyb3J9IFdoZW4gdGhlIHRva2VuIHJvdyBoYXMgYHJldm9rZWRBdGAgc2V0LlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcn0gV2hlbiB0aGUgdG9rZW4gd2FzIGFscmVhZHkgcm90YXRlZCBvciB0aGUgdHJhbnNhY3Rpb24gaW5kaWNhdGVzIHJldXNlLlxuICAgKi9cbiAgcHVibGljIHJvdGF0ZSA9IGFzeW5jIChwYXJhbXM6IFJvdGF0ZVBhcmFtcyk6IFByb21pc2U8Um90YXRlUmVzdWx0PiA9PiB7XG4gICAgLy8gdmFsaWRhdGUgcmVmcmVzaCB0b2tlblxuICAgIHRoaXMudmFsaWRhdGVSZWZyZXNoVG9rZW4ocGFyYW1zLnJlZnJlc2hUb2tlbik7XG5cbiAgICBjb25zdCBkZGIgPSB0aGlzLmdldGRkYigpO1xuXG4gICAgY29uc3Qgbm93ID0gcGFyYW1zLm5vdyA/PyBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IG5vd1NlYyA9IGVwb2Noc2VjKG5vdyk7XG5cbiAgICBjb25zdCBjdXJyZW50SGFzaCA9IHNoYTI1NmhleChwYXJhbXMucmVmcmVzaFRva2VuKTtcbiAgICBjb25zdCBjdXJyZW50UGsgPSB0aGlzLmdldFByaW1hcnlLZXkoY3VycmVudEhhc2gpO1xuXG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0VG9rZW5SZWNvcmQoY3VycmVudFBrKTtcbiAgICBpZiAoIWN1cnJlbnQpIHtcbiAgICAgIHRocm93IG5ldyBSZWZyZXNoVG9rZW5JbnZhbGlkRXJyb3IoKTtcbiAgICB9XG4gICAgaWYgKGN1cnJlbnQuZXhwaXJlc0F0IDw9IG5vd1NlYykge1xuICAgICAgdGhyb3cgbmV3IFJlZnJlc2hUb2tlbkV4cGlyZWRFcnJvcigpO1xuICAgIH1cbiAgICBpZiAoY3VycmVudC5yZXZva2VkQXQpIHtcbiAgICAgIHRocm93IG5ldyBSZWZyZXNoVG9rZW5SZXZva2VkRXJyb3IoKTtcbiAgICB9XG4gICAgaWYgKGN1cnJlbnQucm90YXRlZEF0KSB7XG4gICAgICB0aHJvdyBuZXcgUmVmcmVzaFRva2VuUmV1c2VkRXJyb3IoKTtcbiAgICB9XG5cbiAgICBjb25zdCBuZXh0UmVmcmVzaFRva2VuRXhwaXJlc0F0ID0gdGhpcy5tYWtlRXhwaXJlc0F0KG5vd1NlYyk7XG4gICAgY29uc3QgbmV4dFJlZnJlc2hUb2tlbiA9IHJhbmRvbXRva2VuKHRoaXMudG9rZW5CeXRlcyk7XG4gICAgY29uc3QgbmV4dEhhc2ggPSBzaGEyNTZoZXgobmV4dFJlZnJlc2hUb2tlbik7XG4gICAgY29uc3QgbmV4dFBrID0gdGhpcy5nZXRQcmltYXJ5S2V5KG5leHRIYXNoKTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBkZGIuc2VuZChuZXcgVHJhbnNhY3RXcml0ZUNvbW1hbmQoe1xuICAgICAgICBUcmFuc2FjdEl0ZW1zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgVXBkYXRlOiB7XG4gICAgICAgICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICAgICAgICAgIEtleTogeyBwazogY3VycmVudFBrIH0sXG4gICAgICAgICAgICAgIFVwZGF0ZUV4cHJlc3Npb246ICdTRVQgcm90YXRlZEF0ID0gOm5vdywgcmVwbGFjZWRCeVBrID0gOm5leHRQaywgI3R0bCA9IDp0dGwnLFxuICAgICAgICAgICAgICBDb25kaXRpb25FeHByZXNzaW9uOiAnYXR0cmlidXRlX2V4aXN0cyhwaykgQU5EIGF0dHJpYnV0ZV9ub3RfZXhpc3RzKHJvdGF0ZWRBdCkgQU5EIGF0dHJpYnV0ZV9ub3RfZXhpc3RzKHJldm9rZWRBdCknLFxuICAgICAgICAgICAgICBFeHByZXNzaW9uQXR0cmlidXRlTmFtZXM6IHtcbiAgICAgICAgICAgICAgICAnI3R0bCc6ICd0dGwnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBFeHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAgICAgJzpub3cnOiBub3dTZWMsXG4gICAgICAgICAgICAgICAgJzpuZXh0UGsnOiBuZXh0UGssXG4gICAgICAgICAgICAgICAgJzp0dGwnOiBjdXJyZW50LmV4cGlyZXNBdCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBQdXQ6IHtcbiAgICAgICAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICAgICAgSXRlbToge1xuICAgICAgICAgICAgICAgIHBrOiBuZXh0UGssXG4gICAgICAgICAgICAgICAgc3ViamVjdElkOiBjdXJyZW50LnN1YmplY3RJZCxcbiAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IGN1cnJlbnQuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93U2VjLFxuICAgICAgICAgICAgICAgIGV4cGlyZXNBdDogbmV4dFJlZnJlc2hUb2tlbkV4cGlyZXNBdCxcbiAgICAgICAgICAgICAgICB0dGw6IG5leHRSZWZyZXNoVG9rZW5FeHBpcmVzQXQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIENvbmRpdGlvbkV4cHJlc3Npb246ICdhdHRyaWJ1dGVfbm90X2V4aXN0cyhwayknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSkpO1xuXG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yICYmIGVycm9yLm5hbWUgPT09ICdUcmFuc2FjdGlvbkNhbmNlbGVkRXhjZXB0aW9uJykge1xuICAgICAgICAvLyBUcmVhdCBjb25kaXRpb25hbCB0cmFuc2FjdGlvbiBmYWlsdXJlIGFzIHRva2VuIHJldXNlLlxuICAgICAgICB0aHJvdyBuZXcgUmVmcmVzaFRva2VuUmV1c2VkRXJyb3IoKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzdWJqZWN0SWQ6IGN1cnJlbnQuc3ViamVjdElkLFxuICAgICAgc2Vzc2lvbklkOiBjdXJyZW50LnNlc3Npb25JZCxcbiAgICAgIHJlZnJlc2hUb2tlbjogbmV4dFJlZnJlc2hUb2tlbixcbiAgICAgIHJlZnJlc2hUb2tlbkV4cGlyZXNBdDogbmV4dFJlZnJlc2hUb2tlbkV4cGlyZXNBdCxcbiAgICB9O1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZXRzIGByZXZva2VkQXRgIG9uIHRoZSB0b2tlbiByb3cuIE1pc3NpbmcgaXRlbXMgc3VjY2VlZCAoaWRlbXBvdGVudCByZXZva2UpLlxuICAgKlxuICAgKiBEb2VzIG5vdCB1cGRhdGUgYHR0bGA7IGV4aXN0aW5nIGB0dGxgIGZyb20gaXNzdWUvcm90YXRlIHN0aWxsIGFwcGxpZXMgZm9yIER5bmFtb0RCIGNsZWFudXAuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBSZWZyZXNoIHRva2VuIGFuZCBvcHRpb25hbCBjbG9jayAoYG5vd2ApLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgYWZ0ZXIgYSBzdWNjZXNzZnVsIHVwZGF0ZSBvciBuby1vcCB3aGVuIHRoZSBpdGVtIGlzIGFic2VudC5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBzdHJpbmcgZm9ybWF0IGlzIGludmFsaWQuXG4gICAqL1xuICBwdWJsaWMgcmV2b2tlID0gYXN5bmMgKHBhcmFtczogUmV2b2tlUGFyYW1zKTogUHJvbWlzZTx0cnVlPiA9PiB7XG4gICAgLy8gdmFsaWRhdGUgcmVmcmVzaCB0b2tlblxuICAgIHRoaXMudmFsaWRhdGVSZWZyZXNoVG9rZW4ocGFyYW1zLnJlZnJlc2hUb2tlbik7XG5cbiAgICBjb25zdCBkZGIgPSB0aGlzLmdldGRkYigpO1xuXG4gICAgY29uc3Qgbm93ID0gcGFyYW1zLm5vdyA/PyBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IG5vd1NlYyA9IGVwb2Noc2VjKG5vdyk7XG5cbiAgICBjb25zdCBoYXNoID0gc2hhMjU2aGV4KHBhcmFtcy5yZWZyZXNoVG9rZW4pO1xuICAgIGNvbnN0IHBrID0gdGhpcy5nZXRQcmltYXJ5S2V5KGhhc2gpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGRkYi5zZW5kKFxuICAgICAgICBuZXcgVXBkYXRlQ29tbWFuZCh7XG4gICAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICBLZXk6IHsgcGsgfSxcbiAgICAgICAgICBVcGRhdGVFeHByZXNzaW9uOiAnU0VUIHJldm9rZWRBdCA9IDpub3cnLFxuICAgICAgICAgIENvbmRpdGlvbkV4cHJlc3Npb246ICdhdHRyaWJ1dGVfZXhpc3RzKHBrKScsXG4gICAgICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgJzpub3cnOiBub3dTZWMsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAvLyBNaXNzaW5nIGl0ZW06IHRyZWF0IGFzIHN1Y2Nlc3MgKGlkZW1wb3RlbnQgcmV2b2tlKS5cbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yICYmIGVycm9yLm5hbWUgPT09ICdDb25kaXRpb25hbENoZWNrRmFpbGVkRXhjZXB0aW9uJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY2FjaGVkIHtAbGluayBEeW5hbW9EQkRvY3VtZW50Q2xpZW50fSwgY3JlYXRpbmcgaXQgb24gZmlyc3QgdXNlLlxuICAgKlxuICAgKiBAcmV0dXJucyBEb2N1bWVudCBjbGllbnQgY29uZmlndXJlZCBmb3IgYHJlZ2lvbmAgYW5kIG9wdGlvbmFsIGBlbmRwb2ludGAuXG4gICAqL1xuICBwcml2YXRlIGdldGRkYiA9ICgpOiBEeW5hbW9EQkRvY3VtZW50Q2xpZW50ID0+IHtcbiAgICBpZiAoIXRoaXMuZGRiKSB7XG4gICAgICBjb25zdCBjbGllbnQgPSBuZXcgRHluYW1vREJDbGllbnQoe1xuICAgICAgICByZWdpb246IHRoaXMucmVnaW9uLFxuICAgICAgICBlbmRwb2ludDogKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zPy5lbmRwb2ludCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy5lbmRwb2ludDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGBodHRwczovL2R5bmFtb2RiLiR7dGhpcy5yZWdpb259LmFtYXpvbmF3cy5jb21gO1xuICAgICAgICB9KSgpLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmRkYiA9IER5bmFtb0RCRG9jdW1lbnRDbGllbnQuZnJvbShjbGllbnQpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kZGI7XG4gIH07XG5cbiAgLyoqXG4gICAqIExvYWRzIGEgdG9rZW4gcm93IGJ5IHBhcnRpdGlvbiBrZXkuXG4gICAqXG4gICAqIEBwYXJhbSBwayAtIEZ1bGwgcGFydGl0aW9uIGtleSAoYHByZWZpeGAgKyBoYXNoKS5cbiAgICogQHJldHVybnMgUGFyc2VkIHtAbGluayBUb2tlblJlY29yZH0sIG9yIGBudWxsYCBpZiB0aGUgaXRlbSBkb2VzIG5vdCBleGlzdC5cbiAgICovXG4gIHByaXZhdGUgZ2V0VG9rZW5SZWNvcmQgPSBhc3luYyAocGs6IHN0cmluZyk6IFByb21pc2U8VG9rZW5SZWNvcmQgfCBudWxsPiA9PiB7XG4gICAgY29uc3QgZGRiID0gdGhpcy5nZXRkZGIoKTtcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGRkYi5zZW5kKFxuICAgICAgbmV3IEdldENvbW1hbmQoe1xuICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICBLZXk6IHsgcGsgfSxcbiAgICAgICAgQ29uc2lzdGVudFJlYWQ6IHRoaXMub3B0aW9ucz8uY29uc2lzdGVudFJlYWQgPz8gdHJ1ZSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIChyZXMuSXRlbSBhcyBUb2tlblJlY29yZCkgPz8gbnVsbDtcbiAgfTtcblxuICAvKipcbiAgICogRWZmZWN0aXZlIHBhcnRpdGlvbiBrZXkgcHJlZml4IGZyb20ge0BsaW5rIFN0b3JlT3B0aW9uc30gb3Ige0BsaW5rIERFRkFVTFRfUFJJTUFSWV9LRVlfUFJFRklYfS5cbiAgICpcbiAgICogQHJldHVybnMgUHJlZml4IHN0cmluZyAoZS5nLiBgcnQjYCkuXG4gICAqL1xuICBwcml2YXRlIGdldFByaW1hcnlLZXlQcmVmaXggPSAoKTogc3RyaW5nID0+IHtcbiAgICByZXR1cm4gYCR7dGhpcy5vcHRpb25zPy5wa1ByZWZpeCA/PyBERUZBVUxUX1BSSU1BUllfS0VZX1BSRUZJWH1gO1xuICB9O1xuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGZ1bGwgcGFydGl0aW9uIGtleSBmb3IgYSB0b2tlbiBoYXNoLlxuICAgKlxuICAgKiBAcGFyYW0gaGFzaCAtIFNIQS0yNTYgaGV4IGRpZ2VzdCBvZiB0aGUgcGxhaW50ZXh0IHRva2VuLlxuICAgKiBAcmV0dXJucyBgcHJlZml4YCArIGBoYXNoYC5cbiAgICovXG4gIHByaXZhdGUgZ2V0UHJpbWFyeUtleSA9IChoYXNoOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiBgJHt0aGlzLmdldFByaW1hcnlLZXlQcmVmaXgoKX0ke2hhc2h9YDtcbiAgfTtcblxuICAvKipcbiAgICogQ29tcHV0ZXMgbG9naWNhbCBleHBpcmF0aW9uIChgZXhwaXJlc0F0YCAvIGB0dGxgKSBhcyBgbm93U2VjYCBwbHVzIHtAbGluayBTdG9yZU9wdGlvbnMudHRsRGF5c30uXG4gICAqXG4gICAqIEBwYXJhbSBub3dTZWMgLSBDdXJyZW50IHRpbWUgYXMgVW5peCBzZWNvbmRzLlxuICAgKiBAcmV0dXJucyBFeHBpcmF0aW9uIHRpbWVzdGFtcCBpbiBVbml4IHNlY29uZHMgKGRlZmF1bHQgbGlmZXRpbWU6IDYwIGRheXMpLlxuICAgKi9cbiAgcHJpdmF0ZSBtYWtlRXhwaXJlc0F0ID0gKG5vd1NlYzogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gbm93U2VjICsgKHRoaXMub3B0aW9ucz8udHRsRGF5cyA/PyA2MCkgKiAyNCAqIDYwICogNjA7XG4gIH07XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlIHRva2VuIGlzIG5vbi1lbXB0eSBhbmQgbWF0Y2hlcyB0aGUgZXhwZWN0ZWQgYmFzZTY0dXJsIGxlbmd0aCBmb3IgYHRva2VuQnl0ZXNgLlxuICAgKlxuICAgKiBAcGFyYW0gdG9rZW4gLSBQbGFpbnRleHQgcmVmcmVzaCB0b2tlbiBmcm9tIHRoZSBjbGllbnQuXG4gICAqIEB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlbkludmFsaWRFcnJvcn0gV2hlbiB2YWxpZGF0aW9uIGZhaWxzLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVJlZnJlc2hUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0b2tlbiB8fCB0b2tlbi5sZW5ndGggIT09IE1hdGguY2VpbCh0aGlzLnRva2VuQnl0ZXMgKiA4IC8gNikpIHtcbiAgICAgIHRocm93IG5ldyBSZWZyZXNoVG9rZW5JbnZhbGlkRXJyb3IoKTtcbiAgICB9XG4gIH1cblxufVxuIl19
|
|
359
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL2R5bmFtb2RiLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDhEQUEwRDtBQUMxRCx3REFBMEk7QUFFMUksaUVBS2dDO0FBYWhDLHdDQUF1RDtBQUN2RCx3Q0FBeUM7QUFnQnpDLDREQUE0RDtBQUM1RCxNQUFNLDBCQUEwQixHQUFHLEtBQUssQ0FBQztBQUV6QywrREFBK0Q7QUFDL0QsTUFBTSw2QkFBNkIsR0FBRyxpQkFBaUIsQ0FBQztBQUV4RDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsNEJBQTRCO0lBT3ZDOzs7O09BSUc7SUFDSCxZQUNtQixTQUFpQixFQUNqQixNQUFjLEVBQ2QsT0FBc0I7UUFGdEIsY0FBUyxHQUFULFNBQVMsQ0FBUTtRQUNqQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsWUFBTyxHQUFQLE9BQU8sQ0FBZTtRQWR6QyxxREFBcUQ7UUFDN0MsUUFBRyxHQUFrQyxJQUFJLENBQUM7UUFFbEQsOEVBQThFO1FBQzdELGVBQVUsR0FBRyxFQUFFLENBQUM7UUFhakM7Ozs7O1dBS0c7UUFDSSxVQUFLLEdBQUcsS0FBSyxFQUFFLE1BQW1CLEVBQXdCLEVBQUU7WUFDakUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBRTFCLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNyQyxNQUFNLE1BQU0sR0FBRyxJQUFBLGVBQVEsRUFBQyxHQUFHLENBQUMsQ0FBQztZQUM3QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTdDLE1BQU0sWUFBWSxHQUFHLElBQUEsa0JBQVcsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDbEQsTUFBTSxJQUFJLEdBQUcsSUFBQSxnQkFBUyxFQUFDLFlBQVksQ0FB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QUcsR0FBVyxFQUFFO1lBQ3pDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsSUFBSSwwQkFBMEIsRUFBRSxDQUFDO1FBQ25FLENBQUMsQ0FBQztRQUVGOzs7OztXQUtHO1FBQ0ssa0JBQWEsR0FBRyxDQUFDLElBQVksRUFBVSxFQUFFO1lBQy9DLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNoRCxDQUFDLENBQUM7UUFFRjs7Ozs7V0FLRztRQUNLLGtCQUFhLEdBQUcsQ0FBQyxNQUFjLEVBQVUsRUFBRTtZQUNqRCxPQUFPLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQy9ELENBQUMsQ0FBQztJQWpXQyxDQUFDO0lBbVdKOzs7OztPQUtHO0lBQ0ssb0JBQW9CLENBQUMsS0FBYTtRQUN4QyxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sSUFBSSwrQ0FBd0IsRUFBRSxDQUFDO1FBQ3ZDLENBQUM7SUFDSCxDQUFDO0NBRUY7QUEvWEQsb0VBK1hDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHluYW1vREJDbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtZHluYW1vZGInO1xuaW1wb3J0IHsgRHluYW1vREJEb2N1bWVudENsaWVudCwgR2V0Q29tbWFuZCwgUHV0Q29tbWFuZCwgUXVlcnlDb21tYW5kLCBVcGRhdGVDb21tYW5kLCBUcmFuc2FjdFdyaXRlQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2xpYi1keW5hbW9kYic7XG5cbmltcG9ydCB7XG4gIFJlZnJlc2hUb2tlbkV4cGlyZWRFcnJvcixcbiAgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yLFxuICBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcixcbiAgUmVmcmVzaFRva2VuUmV2b2tlZEVycm9yLFxufSBmcm9tICcuL3JlZnJlc2gtdG9rZW4tZXJyb3JzJztcbmltcG9ydCB0eXBlIHtcbiAgUmVmcmVzaFRva2VuU3RvcmUsXG4gIFN0b3JlT3B0aW9ucyxcbiAgVG9rZW5SZWNvcmQsXG4gIElzc3VlUGFyYW1zLFxuICBSb3RhdGVQYXJhbXMsXG4gIFJldm9rZVBhcmFtcyxcbiAgUmV2b2tlU2Vzc2lvblBhcmFtcyxcbiAgUmV2b2tlU2Vzc2lvblJlc3VsdCxcbiAgSXNzdWVSZXN1bHQsXG4gIFJvdGF0ZVJlc3VsdCxcbn0gZnJvbSAnLi4vdHlwZXMvaW5kZXgnO1xuaW1wb3J0IHsgcmFuZG9tdG9rZW4sIHNoYTI1NmhleCB9IGZyb20gJy4uL3V0aWxzL2hhc2gnO1xuaW1wb3J0IHsgZXBvY2hzZWMgfSBmcm9tICcuLi91dGlscy90aW1lJztcblxuLyoqIFJlLWV4cG9ydGVkIHR5cGVzIGZvciBjb25zdW1lcnMgdGhhdCBpbXBvcnQgdGhlIER5bmFtb0RCIHN0b3JlIG1vZHVsZS4gKi9cbmV4cG9ydCB7XG4gIFJlZnJlc2hUb2tlblN0b3JlLFxuICBTdG9yZU9wdGlvbnMsXG4gIFRva2VuUmVjb3JkLFxuICBJc3N1ZVBhcmFtcyxcbiAgUm90YXRlUGFyYW1zLFxuICBSZXZva2VQYXJhbXMsXG4gIFJldm9rZVNlc3Npb25QYXJhbXMsXG4gIFJldm9rZVNlc3Npb25SZXN1bHQsXG4gIElzc3VlUmVzdWx0LFxuICBSb3RhdGVSZXN1bHQsXG59O1xuXG4vKiogRGVmYXVsdCBwYXJ0aXRpb24ga2V5IHByZWZpeCBmb3IgcmVmcmVzaCB0b2tlbiBpdGVtcy4gKi9cbmNvbnN0IERFRkFVTFRfUFJJTUFSWV9LRVlfUFJFRklYID0gJ3J0Iyc7XG5cbi8qKiBEZWZhdWx0IEdTSSBuYW1lIGZvciBxdWVyeWluZyB0b2tlbiByb3dzIGJ5IGBzZXNzaW9uSWRgLiAqL1xuY29uc3QgREVGQVVMVF9TRVNTSU9OX0lEX0lOREVYX05BTUUgPSAnc2Vzc2lvbklkLWluZGV4JztcblxuLyoqXG4gKiB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmV9IGltcGxlbWVudGF0aW9uIGJhY2tlZCBieSBhIHNpbmdsZSBEeW5hbW9EQiB0YWJsZS5cbiAqXG4gKiBJdGVtcyB1c2UgcGFydGl0aW9uIGtleSBgcGtgLCBsb2dpY2FsIGV4cGlyYXRpb24gYGV4cGlyZXNBdGAsIGFuZCBEeW5hbW9EQiBUVEwgYXR0cmlidXRlIGB0dGxgXG4gKiAoVW5peCBzZWNvbmRzKS4gRW5hYmxlIHRhYmxlIFRUTCBvbiBhdHRyaWJ1dGUgYHR0bGAgc28gZXhwaXJlZCBhbmQgcm90YXRlZCByb3dzIGFyZSByZW1vdmVkXG4gKiBhc3luY2hyb25vdXNseS4gU2Vzc2lvbi13aWRlIHJldm9jYXRpb24gcmVxdWlyZXMgYSBHU0kgd2hvc2UgcGFydGl0aW9uIGtleSBpcyBgc2Vzc2lvbklkYFxuICogKHNlZSB7QGxpbmsgU3RvcmVPcHRpb25zLnNlc3Npb25JZEluZGV4TmFtZX0pLiBUaGlzIGNsYXNzIG93bnMgdGhlIER5bmFtb0RCIGNsaWVudDsgY2FsbGVyc1xuICogc3VwcGx5IGB0YWJsZU5hbWVgLCBgcmVnaW9uYCwgYW5kIG9wdGlvbmFsIHtAbGluayBTdG9yZU9wdGlvbnN9LlxuICovXG5leHBvcnQgY2xhc3MgRHluYW1vZGJSZWZyZXNoVG9rZW5Qcm92aWRlciBpbXBsZW1lbnRzIFJlZnJlc2hUb2tlblN0b3JlIHtcbiAgLyoqIExhemlseSBpbml0aWFsaXplZCBhbmQgY2FjaGVkIGRvY3VtZW50IGNsaWVudC4gKi9cbiAgcHJpdmF0ZSBkZGI6IER5bmFtb0RCRG9jdW1lbnRDbGllbnQgfCBudWxsID0gbnVsbDtcblxuICAvKiogUmFuZG9tIGJ5dGUgbGVuZ3RoIGZvciBnZW5lcmF0ZWQgcmVmcmVzaCB0b2tlbnMgKGRlZmF1bHQgMzIg4oaSIDI1Ni1iaXQpLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHRva2VuQnl0ZXMgPSAzMjtcblxuICAvKipcbiAgICogQHBhcmFtIHRhYmxlTmFtZSAtIER5bmFtb0RCIHRhYmxlIG5hbWUgZm9yIHJlZnJlc2ggdG9rZW4gaXRlbXMuXG4gICAqIEBwYXJhbSByZWdpb24gLSBBV1MgcmVnaW9uIGZvciB0aGUgRHluYW1vREIgY2xpZW50LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRva2VuIGxpZmV0aW1lLCBQSyBwcmVmaXgsIEdTSSBuYW1lLCByZXVzZSByZXZvY2F0aW9uLCBvciBjdXN0b20gZW5kcG9pbnQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zPzogU3RvcmVPcHRpb25zLFxuICApIHt9XG5cbiAgLyoqXG4gICAqIEluc2VydHMgYSBuZXcgdG9rZW4gcmVjb3JkIHdpdGggYGV4cGlyZXNBdGAgYW5kIG1hdGNoaW5nIGB0dGxgLiBGYWlscyB0aGUgcHV0IGlmIGBwa2AgYWxyZWFkeSBleGlzdHMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTdWJqZWN0LCBzZXNzaW9uLCBhbmQgb3B0aW9uYWwgY2xvY2sgKGBub3dgKS5cbiAgICogQHJldHVybnMgUGxhaW50ZXh0IHJlZnJlc2ggdG9rZW4gYW5kIGV4cGlyYXRpb24gYXMgVW5peCBzZWNvbmRzLlxuICAgKi9cbiAgcHVibGljIGlzc3VlID0gYXN5bmMgKHBhcmFtczogSXNzdWVQYXJhbXMpOiBQcm9taXNlPElzc3VlUmVzdWx0PiA9PiB7XG4gICAgY29uc3QgZGRiID0gdGhpcy5nZXRkZGIoKTtcblxuICAgIGNvbnN0IG5vdyA9IHBhcmFtcy5ub3cgPz8gbmV3IERhdGUoKTtcbiAgICBjb25zdCBub3dTZWMgPSBlcG9jaHNlYyhub3cpO1xuICAgIGNvbnN0IGV4cGlyZXNBdCA9IHRoaXMubWFrZUV4cGlyZXNBdChub3dTZWMpO1xuXG4gICAgY29uc3QgcmVmcmVzaFRva2VuID0gcmFuZG9tdG9rZW4odGhpcy50b2tlbkJ5dGVzKTtcbiAgICBjb25zdCBoYXNoID0gc2hhMjU2aGV4KHJlZnJlc2hUb2tlbik7XG4gICAgY29uc3QgcGsgPSB0aGlzLmdldFByaW1hcnlLZXkoaGFzaCk7XG5cbiAgICBhd2FpdCBkZGIuc2VuZChcbiAgICAgIG5ldyBQdXRDb21tYW5kKHtcbiAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgSXRlbToge1xuICAgICAgICAgIHBrLFxuICAgICAgICAgIHN1YmplY3RJZDogcGFyYW1zLnN1YmplY3RJZCxcbiAgICAgICAgICBzZXNzaW9uSWQ6IHBhcmFtcy5zZXNzaW9uSWQsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3dTZWMsXG4gICAgICAgICAgZXhwaXJlc0F0LFxuICAgICAgICAgIHR0bDogZXhwaXJlc0F0LFxuICAgICAgICB9LFxuICAgICAgICBDb25kaXRpb25FeHByZXNzaW9uOiAnYXR0cmlidXRlX25vdF9leGlzdHMocGspJyxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVmcmVzaFRva2VuLFxuICAgICAgcmVmcmVzaFRva2VuRXhwaXJlc0F0OiBleHBpcmVzQXQsXG4gICAgfTtcbiAgfTtcblxuICAvKipcbiAgICogTWFya3MgdGhlIGN1cnJlbnQgdG9rZW4gYXMgcm90YXRlZCBhbmQgY3JlYXRlcyB0aGUgc3VjY2Vzc29yIHJvdyBpbiBvbmUgdHJhbnNhY3Rpb24uXG4gICAqXG4gICAqIFVwZGF0ZXMgdGhlIHByZXZpb3VzIHJvd+KAmXMgYHR0bGAgdG8gaXRzIGBleHBpcmVzQXRgIGFuZCBzZXRzIGB0dGxgIG9uIHRoZSBuZXcgUHV0IHRvIHRoZVxuICAgKiBzdWNjZXNzb3LigJlzIGV4cGlyYXRpb24gc28gRHluYW1vREIgY2FuIGRlbGV0ZSBib3RoIHdoZW4gYXBwcm9wcmlhdGUuXG4gICAqXG4gICAqIFdoZW4gcmV1c2UgaXMgZGV0ZWN0ZWQgYW5kIHtAbGluayBTdG9yZU9wdGlvbnMucmV2b2tlU2Vzc2lvbk9uUmV1c2V9IGlzIHRydWUsIGFsbCB0b2tlbnMgZm9yXG4gICAqIHRoZSBzYW1lIGBzZXNzaW9uSWRgIGFuZCBgc3ViamVjdElkYCBhcmUgcmV2b2tlZCB2aWEge0BsaW5rIER5bmFtb2RiUmVmcmVzaFRva2VuUHJvdmlkZXIucmV2b2tlU2Vzc2lvbn1cbiAgICogYmVmb3JlIHRocm93aW5nLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gQ2xpZW50IHJlZnJlc2ggdG9rZW4gYW5kIG9wdGlvbmFsIGNsb2NrIChgbm93YCkuXG4gICAqIEByZXR1cm5zIFN1YmplY3QsIHNlc3Npb24sIG5ldyBwbGFpbnRleHQgdG9rZW4sIGFuZCBuZXcgZXhwaXJhdGlvbi5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBmb3JtYXQgaXMgaW52YWxpZCBvciBubyByb3cgZXhpc3RzLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5FeHBpcmVkRXJyb3J9IFdoZW4gYGV4cGlyZXNBdGAgaXMgbm90IGFmdGVyIGBub3dgLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXZva2VkRXJyb3J9IFdoZW4gdGhlIHRva2VuIHJvdyBoYXMgYHJldm9rZWRBdGAgc2V0LlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcn0gV2hlbiB0aGUgdG9rZW4gd2FzIGFscmVhZHkgcm90YXRlZCBvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogICBpbmRpY2F0ZXMgcmV1c2UuIEluY2x1ZGVzIGBzdWJqZWN0SWRgIGFuZCBgc2Vzc2lvbklkYCBmcm9tIHRoZSBsb2FkZWQgcm93LlxuICAgKi9cbiAgcHVibGljIHJvdGF0ZSA9IGFzeW5jIChwYXJhbXM6IFJvdGF0ZVBhcmFtcyk6IFByb21pc2U8Um90YXRlUmVzdWx0PiA9PiB7XG4gICAgLy8gdmFsaWRhdGUgcmVmcmVzaCB0b2tlblxuICAgIHRoaXMudmFsaWRhdGVSZWZyZXNoVG9rZW4ocGFyYW1zLnJlZnJlc2hUb2tlbik7XG5cbiAgICBjb25zdCBkZGIgPSB0aGlzLmdldGRkYigpO1xuXG4gICAgY29uc3Qgbm93ID0gcGFyYW1zLm5vdyA/PyBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IG5vd1NlYyA9IGVwb2Noc2VjKG5vdyk7XG5cbiAgICBjb25zdCBjdXJyZW50SGFzaCA9IHNoYTI1NmhleChwYXJhbXMucmVmcmVzaFRva2VuKTtcbiAgICBjb25zdCBjdXJyZW50UGsgPSB0aGlzLmdldFByaW1hcnlLZXkoY3VycmVudEhhc2gpO1xuXG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0VG9rZW5SZWNvcmQoY3VycmVudFBrKTtcbiAgICBpZiAoIWN1cnJlbnQpIHtcbiAgICAgIHRocm93IG5ldyBSZWZyZXNoVG9rZW5JbnZhbGlkRXJyb3IoKTtcbiAgICB9XG4gICAgaWYgKGN1cnJlbnQuZXhwaXJlc0F0IDw9IG5vd1NlYykge1xuICAgICAgdGhyb3cgbmV3IFJlZnJlc2hUb2tlbkV4cGlyZWRFcnJvcigpO1xuICAgIH1cbiAgICBpZiAoY3VycmVudC5yZXZva2VkQXQpIHtcbiAgICAgIHRocm93IG5ldyBSZWZyZXNoVG9rZW5SZXZva2VkRXJyb3IoKTtcbiAgICB9XG4gICAgaWYgKGN1cnJlbnQucm90YXRlZEF0KSB7XG4gICAgICBhd2FpdCB0aGlzLmhhbmRsZVJlZnJlc2hUb2tlblJldXNlKGN1cnJlbnQsIG5vdyk7XG4gICAgfVxuXG4gICAgY29uc3QgbmV4dFJlZnJlc2hUb2tlbkV4cGlyZXNBdCA9IHRoaXMubWFrZUV4cGlyZXNBdChub3dTZWMpO1xuICAgIGNvbnN0IG5leHRSZWZyZXNoVG9rZW4gPSByYW5kb210b2tlbih0aGlzLnRva2VuQnl0ZXMpO1xuICAgIGNvbnN0IG5leHRIYXNoID0gc2hhMjU2aGV4KG5leHRSZWZyZXNoVG9rZW4pO1xuICAgIGNvbnN0IG5leHRQayA9IHRoaXMuZ2V0UHJpbWFyeUtleShuZXh0SGFzaCk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGRiLnNlbmQobmV3IFRyYW5zYWN0V3JpdGVDb21tYW5kKHtcbiAgICAgICAgVHJhbnNhY3RJdGVtczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIFVwZGF0ZToge1xuICAgICAgICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgICAgICBLZXk6IHsgcGs6IGN1cnJlbnRQayB9LFxuICAgICAgICAgICAgICBVcGRhdGVFeHByZXNzaW9uOiAnU0VUIHJvdGF0ZWRBdCA9IDpub3csIHJlcGxhY2VkQnlQayA9IDpuZXh0UGssICN0dGwgPSA6dHRsJyxcbiAgICAgICAgICAgICAgQ29uZGl0aW9uRXhwcmVzc2lvbjogJ2F0dHJpYnV0ZV9leGlzdHMocGspIEFORCBhdHRyaWJ1dGVfbm90X2V4aXN0cyhyb3RhdGVkQXQpIEFORCBhdHRyaWJ1dGVfbm90X2V4aXN0cyhyZXZva2VkQXQpJyxcbiAgICAgICAgICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZU5hbWVzOiB7XG4gICAgICAgICAgICAgICAgJyN0dGwnOiAndHRsJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgICAgICc6bm93Jzogbm93U2VjLFxuICAgICAgICAgICAgICAgICc6bmV4dFBrJzogbmV4dFBrLFxuICAgICAgICAgICAgICAgICc6dHRsJzogY3VycmVudC5leHBpcmVzQXQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgUHV0OiB7XG4gICAgICAgICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICAgICAgICAgIEl0ZW06IHtcbiAgICAgICAgICAgICAgICBwazogbmV4dFBrLFxuICAgICAgICAgICAgICAgIHN1YmplY3RJZDogY3VycmVudC5zdWJqZWN0SWQsXG4gICAgICAgICAgICAgICAgc2Vzc2lvbklkOiBjdXJyZW50LnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICBjcmVhdGVkQXQ6IG5vd1NlYyxcbiAgICAgICAgICAgICAgICBleHBpcmVzQXQ6IG5leHRSZWZyZXNoVG9rZW5FeHBpcmVzQXQsXG4gICAgICAgICAgICAgICAgdHRsOiBuZXh0UmVmcmVzaFRva2VuRXhwaXJlc0F0LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBDb25kaXRpb25FeHByZXNzaW9uOiAnYXR0cmlidXRlX25vdF9leGlzdHMocGspJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pKTtcblxuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5uYW1lID09PSAnVHJhbnNhY3Rpb25DYW5jZWxlZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgLy8gVHJlYXQgY29uZGl0aW9uYWwgdHJhbnNhY3Rpb24gZmFpbHVyZSBhcyB0b2tlbiByZXVzZS5cbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVSZWZyZXNoVG9rZW5SZXVzZShjdXJyZW50LCBub3cpO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1YmplY3RJZDogY3VycmVudC5zdWJqZWN0SWQsXG4gICAgICBzZXNzaW9uSWQ6IGN1cnJlbnQuc2Vzc2lvbklkLFxuICAgICAgcmVmcmVzaFRva2VuOiBuZXh0UmVmcmVzaFRva2VuLFxuICAgICAgcmVmcmVzaFRva2VuRXhwaXJlc0F0OiBuZXh0UmVmcmVzaFRva2VuRXhwaXJlc0F0LFxuICAgIH07XG4gIH07XG5cbiAgLyoqXG4gICAqIFNldHMgYHJldm9rZWRBdGAgb24gdGhlIHRva2VuIHJvdy4gTWlzc2luZyBpdGVtcyBzdWNjZWVkIChpZGVtcG90ZW50IHJldm9rZSkuXG4gICAqXG4gICAqIERvZXMgbm90IHVwZGF0ZSBgdHRsYDsgZXhpc3RpbmcgYHR0bGAgZnJvbSBpc3N1ZS9yb3RhdGUgc3RpbGwgYXBwbGllcyBmb3IgRHluYW1vREIgY2xlYW51cC5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFJlZnJlc2ggdG9rZW4gYW5kIG9wdGlvbmFsIGNsb2NrIChgbm93YCkuXG4gICAqIEByZXR1cm5zIGB0cnVlYCBhZnRlciBhIHN1Y2Nlc3NmdWwgdXBkYXRlIG9yIG5vLW9wIHdoZW4gdGhlIGl0ZW0gaXMgYWJzZW50LlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5JbnZhbGlkRXJyb3J9IFdoZW4gdGhlIHRva2VuIHN0cmluZyBmb3JtYXQgaXMgaW52YWxpZC5cbiAgICovXG4gIHB1YmxpYyByZXZva2UgPSBhc3luYyAocGFyYW1zOiBSZXZva2VQYXJhbXMpOiBQcm9taXNlPHRydWU+ID0+IHtcbiAgICAvLyB2YWxpZGF0ZSByZWZyZXNoIHRva2VuXG4gICAgdGhpcy52YWxpZGF0ZVJlZnJlc2hUb2tlbihwYXJhbXMucmVmcmVzaFRva2VuKTtcblxuICAgIGNvbnN0IGRkYiA9IHRoaXMuZ2V0ZGRiKCk7XG5cbiAgICBjb25zdCBub3cgPSBwYXJhbXMubm93ID8/IG5ldyBEYXRlKCk7XG4gICAgY29uc3Qgbm93U2VjID0gZXBvY2hzZWMobm93KTtcblxuICAgIGNvbnN0IGhhc2ggPSBzaGEyNTZoZXgocGFyYW1zLnJlZnJlc2hUb2tlbik7XG4gICAgY29uc3QgcGsgPSB0aGlzLmdldFByaW1hcnlLZXkoaGFzaCk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGRiLnNlbmQoXG4gICAgICAgIG5ldyBVcGRhdGVDb21tYW5kKHtcbiAgICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgIEtleTogeyBwayB9LFxuICAgICAgICAgIFVwZGF0ZUV4cHJlc3Npb246ICdTRVQgcmV2b2tlZEF0ID0gOm5vdycsXG4gICAgICAgICAgQ29uZGl0aW9uRXhwcmVzc2lvbjogJ2F0dHJpYnV0ZV9leGlzdHMocGspJyxcbiAgICAgICAgICBFeHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAnOm5vdyc6IG5vd1NlYyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIC8vIE1pc3NpbmcgaXRlbTogdHJlYXQgYXMgc3VjY2VzcyAoaWRlbXBvdGVudCByZXZva2UpLlxuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IubmFtZSA9PT0gJ0NvbmRpdGlvbmFsQ2hlY2tGYWlsZWRFeGNlcHRpb24nKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZXRzIGByZXZva2VkQXRgIG9uIGV2ZXJ5IHRva2VuIHJvdyBmb3IgdGhlIGdpdmVuIGBzZXNzaW9uSWRgIChvcHRpb25hbGx5IGZpbHRlcmVkIGJ5IGBzdWJqZWN0SWRgKS5cbiAgICpcbiAgICogUXVlcmllcyB0aGUgc2Vzc2lvbiBHU0kgKHBhcnRpdGlvbiBrZXkgYHNlc3Npb25JZGA7IGBLRVlTX09OTFlgIGlzIGVub3VnaCksIHRoZW4gdXBkYXRlcyBlYWNoXG4gICAqIGJhc2UtdGFibGUgaXRlbS4gV2hlbiBgc3ViamVjdElkYCBpcyBzZXQsIGl0IGlzIHJlcXVpcmVkIGluIHRoZSBgVXBkYXRlSXRlbWAgY29uZGl0aW9uLlxuICAgKiBNaXNzaW5nIG9yIG5vbi1tYXRjaGluZyBpdGVtcyBhcmUgc2tpcHBlZCAoaWRlbXBvdGVudCkuIFBhZ2luYXRlIHdpdGggYExhc3RFdmFsdWF0ZWRLZXlgLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU2Vzc2lvbiBpZCwgb3B0aW9uYWwgc3ViamVjdCBmaWx0ZXIsIGFuZCBvcHRpb25hbCBjbG9jay5cbiAgICogQHJldHVybnMgQ291bnQgb2Ygcm93cyB1cGRhdGVkIHdpdGggYHJldm9rZWRBdGAgaW4gdGhpcyBjYWxsLlxuICAgKi9cbiAgcHVibGljIHJldm9rZVNlc3Npb24gPSBhc3luYyAocGFyYW1zOiBSZXZva2VTZXNzaW9uUGFyYW1zKTogUHJvbWlzZTxSZXZva2VTZXNzaW9uUmVzdWx0PiA9PiB7XG4gICAgY29uc3QgZGRiID0gdGhpcy5nZXRkZGIoKTtcblxuICAgIGNvbnN0IG5vdyA9IHBhcmFtcy5ub3cgPz8gbmV3IERhdGUoKTtcbiAgICBjb25zdCBub3dTZWMgPSBlcG9jaHNlYyhub3cpO1xuICAgIGNvbnN0IGluZGV4TmFtZSA9IHRoaXMub3B0aW9ucz8uc2Vzc2lvbklkSW5kZXhOYW1lID8/IERFRkFVTFRfU0VTU0lPTl9JRF9JTkRFWF9OQU1FO1xuXG4gICAgbGV0IHJldm9rZWRDb3VudCA9IDA7XG4gICAgbGV0IGV4Y2x1c2l2ZVN0YXJ0S2V5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcblxuICAgIC8qKiBXaGV0aGVyIGFub3RoZXIgUXVlcnkgcGFnZSBpcyBhdmFpbGFibGUgYWZ0ZXIgdGhlIHByZXZpb3VzIHJlc3BvbnNlLiAqL1xuICAgIGNvbnN0IHNob3VsZENvbnRpbnVlUGFnaW5nID0gKCk6IGJvb2xlYW4gPT4gZXhjbHVzaXZlU3RhcnRLZXkgIT09IHVuZGVmaW5lZDtcblxuICAgIGRvIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGRkYi5zZW5kKFxuICAgICAgICBuZXcgUXVlcnlDb21tYW5kKHtcbiAgICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgIEluZGV4TmFtZTogaW5kZXhOYW1lLFxuICAgICAgICAgIEtleUNvbmRpdGlvbkV4cHJlc3Npb246ICdzZXNzaW9uSWQgPSA6c2Vzc2lvbklkJyxcbiAgICAgICAgICBFeHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAnOnNlc3Npb25JZCc6IHBhcmFtcy5zZXNzaW9uSWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBQcm9qZWN0aW9uRXhwcmVzc2lvbjogJ3BrJyxcbiAgICAgICAgICBFeGNsdXNpdmVTdGFydEtleTogZXhjbHVzaXZlU3RhcnRLZXksXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgaXRlbXMgPSByZXMuSXRlbXMgPz8gW107XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgICAgY29uc3QgcGsgPSBpdGVtLnBrO1xuICAgICAgICBpZiAodHlwZW9mIHBrICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPiA9IHtcbiAgICAgICAgICAnOm5vdyc6IG5vd1NlYyxcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IGNvbmRpdGlvbkV4cHJlc3Npb24gPSAnYXR0cmlidXRlX2V4aXN0cyhwayknO1xuICAgICAgICBpZiAocGFyYW1zLnN1YmplY3RJZCkge1xuICAgICAgICAgIGNvbmRpdGlvbkV4cHJlc3Npb24gPSAnYXR0cmlidXRlX2V4aXN0cyhwaykgQU5EIHN1YmplY3RJZCA9IDpzdWJqZWN0SWQnO1xuICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXNbJzpzdWJqZWN0SWQnXSA9IHBhcmFtcy5zdWJqZWN0SWQ7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGRkYi5zZW5kKFxuICAgICAgICAgICAgbmV3IFVwZGF0ZUNvbW1hbmQoe1xuICAgICAgICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgICAgICBLZXk6IHsgcGsgfSxcbiAgICAgICAgICAgICAgVXBkYXRlRXhwcmVzc2lvbjogJ1NFVCByZXZva2VkQXQgPSA6bm93JyxcbiAgICAgICAgICAgICAgQ29uZGl0aW9uRXhwcmVzc2lvbjogY29uZGl0aW9uRXhwcmVzc2lvbixcbiAgICAgICAgICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczogZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlcyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV2b2tlZENvdW50ICs9IDE7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IubmFtZSA9PT0gJ0NvbmRpdGlvbmFsQ2hlY2tGYWlsZWRFeGNlcHRpb24nKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZXhjbHVzaXZlU3RhcnRLZXkgPSByZXMuTGFzdEV2YWx1YXRlZEtleSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcbiAgICB9IHdoaWxlIChzaG91bGRDb250aW51ZVBhZ2luZygpKTtcblxuICAgIHJldHVybiB7IHJldm9rZWRDb3VudCB9O1xuICB9O1xuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHJlZnJlc2gtdG9rZW4gcmV1c2UgZGV0ZWN0aW9uOiBvcHRpb25hbGx5IGNhc2NhZGVzIHtAbGluayBEeW5hbW9kYlJlZnJlc2hUb2tlblByb3ZpZGVyLnJldm9rZVNlc3Npb259XG4gICAqIHdoZW4ge0BsaW5rIFN0b3JlT3B0aW9ucy5yZXZva2VTZXNzaW9uT25SZXVzZX0gaXMgdHJ1ZSwgdGhlbiB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlblJldXNlZEVycm9yfVxuICAgKiBwb3B1bGF0ZWQgd2l0aCBgc3ViamVjdElkYCAvIGBzZXNzaW9uSWRgIGZyb20gYGN1cnJlbnRgLlxuICAgKlxuICAgKiBAcGFyYW0gY3VycmVudCAtIFRva2VuIHJvdyB0aGF0IGluZGljYXRlZCByZXVzZSAoYHJvdGF0ZWRBdGAgc2V0IG9yIHRyYW5zYWN0aW9uIGNhbmNlbGVkKS5cbiAgICogQHBhcmFtIG5vdyAtIENsb2NrIHVzZWQgZm9yIGByZXZva2VkQXRgIHdoZW4gY2FzY2FkaW5nIHJldm9rZSBpcyBlbmFibGVkLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcn0gQWx3YXlzIChyZXR1cm4gdHlwZSBpcyBgbmV2ZXJgKS5cbiAgICovXG4gIHByaXZhdGUgaGFuZGxlUmVmcmVzaFRva2VuUmV1c2UgPSBhc3luYyAoY3VycmVudDogVG9rZW5SZWNvcmQsIG5vdzogRGF0ZSk6IFByb21pc2U8bmV2ZXI+ID0+IHtcbiAgICBpZiAodGhpcy5vcHRpb25zPy5yZXZva2VTZXNzaW9uT25SZXVzZSkge1xuICAgICAgYXdhaXQgdGhpcy5yZXZva2VTZXNzaW9uKHtcbiAgICAgICAgc2Vzc2lvbklkOiBjdXJyZW50LnNlc3Npb25JZCxcbiAgICAgICAgc3ViamVjdElkOiBjdXJyZW50LnN1YmplY3RJZCxcbiAgICAgICAgbm93LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFJlZnJlc2hUb2tlblJldXNlZEVycm9yKHVuZGVmaW5lZCwge1xuICAgICAgc3ViamVjdElkOiBjdXJyZW50LnN1YmplY3RJZCxcbiAgICAgIHNlc3Npb25JZDogY3VycmVudC5zZXNzaW9uSWQsXG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNhY2hlZCB7QGxpbmsgRHluYW1vREJEb2N1bWVudENsaWVudH0sIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAgICpcbiAgICogQHJldHVybnMgRG9jdW1lbnQgY2xpZW50IGNvbmZpZ3VyZWQgZm9yIGByZWdpb25gIGFuZCBvcHRpb25hbCBgZW5kcG9pbnRgLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRkZGIgPSAoKTogRHluYW1vREJEb2N1bWVudENsaWVudCA9PiB7XG4gICAgaWYgKCF0aGlzLmRkYikge1xuICAgICAgY29uc3QgY2xpZW50ID0gbmV3IER5bmFtb0RCQ2xpZW50KHtcbiAgICAgICAgcmVnaW9uOiB0aGlzLnJlZ2lvbixcbiAgICAgICAgZW5kcG9pbnQ6ICgoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucz8uZW5kcG9pbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMuZW5kcG9pbnQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgaHR0cHM6Ly9keW5hbW9kYi4ke3RoaXMucmVnaW9ufS5hbWF6b25hd3MuY29tYDtcbiAgICAgICAgfSkoKSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5kZGIgPSBEeW5hbW9EQkRvY3VtZW50Q2xpZW50LmZyb20oY2xpZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZGRiO1xuICB9O1xuXG4gIC8qKlxuICAgKiBMb2FkcyBhIHRva2VuIHJvdyBieSBwYXJ0aXRpb24ga2V5LlxuICAgKlxuICAgKiBAcGFyYW0gcGsgLSBGdWxsIHBhcnRpdGlvbiBrZXkgKGBwcmVmaXhgICsgaGFzaCkuXG4gICAqIEByZXR1cm5zIFBhcnNlZCB7QGxpbmsgVG9rZW5SZWNvcmR9LCBvciBgbnVsbGAgaWYgdGhlIGl0ZW0gZG9lcyBub3QgZXhpc3QuXG4gICAqL1xuICBwcml2YXRlIGdldFRva2VuUmVjb3JkID0gYXN5bmMgKHBrOiBzdHJpbmcpOiBQcm9taXNlPFRva2VuUmVjb3JkIHwgbnVsbD4gPT4ge1xuICAgIGNvbnN0IGRkYiA9IHRoaXMuZ2V0ZGRiKCk7XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBkZGIuc2VuZChcbiAgICAgIG5ldyBHZXRDb21tYW5kKHtcbiAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgS2V5OiB7IHBrIH0sXG4gICAgICAgIENvbnNpc3RlbnRSZWFkOiB0aGlzLm9wdGlvbnM/LmNvbnNpc3RlbnRSZWFkID8/IHRydWUsXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiAocmVzLkl0ZW0gYXMgVG9rZW5SZWNvcmQpID8/IG51bGw7XG4gIH07XG5cbiAgLyoqXG4gICAqIEVmZmVjdGl2ZSBwYXJ0aXRpb24ga2V5IHByZWZpeCBmcm9tIHtAbGluayBTdG9yZU9wdGlvbnN9IG9yIHtAbGluayBERUZBVUxUX1BSSU1BUllfS0VZX1BSRUZJWH0uXG4gICAqXG4gICAqIEByZXR1cm5zIFByZWZpeCBzdHJpbmcgKGUuZy4gYHJ0I2ApLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRQcmltYXJ5S2V5UHJlZml4ID0gKCk6IHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIGAke3RoaXMub3B0aW9ucz8ucGtQcmVmaXggPz8gREVGQVVMVF9QUklNQVJZX0tFWV9QUkVGSVh9YDtcbiAgfTtcblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBmdWxsIHBhcnRpdGlvbiBrZXkgZm9yIGEgdG9rZW4gaGFzaC5cbiAgICpcbiAgICogQHBhcmFtIGhhc2ggLSBTSEEtMjU2IGhleCBkaWdlc3Qgb2YgdGhlIHBsYWludGV4dCB0b2tlbi5cbiAgICogQHJldHVybnMgYHByZWZpeGAgKyBgaGFzaGAuXG4gICAqL1xuICBwcml2YXRlIGdldFByaW1hcnlLZXkgPSAoaGFzaDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICByZXR1cm4gYCR7dGhpcy5nZXRQcmltYXJ5S2V5UHJlZml4KCl9JHtoYXNofWA7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvbXB1dGVzIGxvZ2ljYWwgZXhwaXJhdGlvbiAoYGV4cGlyZXNBdGAgLyBgdHRsYCkgYXMgYG5vd1NlY2AgcGx1cyB7QGxpbmsgU3RvcmVPcHRpb25zLnR0bERheXN9LlxuICAgKlxuICAgKiBAcGFyYW0gbm93U2VjIC0gQ3VycmVudCB0aW1lIGFzIFVuaXggc2Vjb25kcy5cbiAgICogQHJldHVybnMgRXhwaXJhdGlvbiB0aW1lc3RhbXAgaW4gVW5peCBzZWNvbmRzIChkZWZhdWx0IGxpZmV0aW1lOiA2MCBkYXlzKS5cbiAgICovXG4gIHByaXZhdGUgbWFrZUV4cGlyZXNBdCA9IChub3dTZWM6IG51bWJlcik6IG51bWJlciA9PiB7XG4gICAgcmV0dXJuIG5vd1NlYyArICh0aGlzLm9wdGlvbnM/LnR0bERheXMgPz8gNjApICogMjQgKiA2MCAqIDYwO1xuICB9O1xuXG4gIC8qKlxuICAgKiBFbnN1cmVzIHRoZSB0b2tlbiBpcyBub24tZW1wdHkgYW5kIG1hdGNoZXMgdGhlIGV4cGVjdGVkIGJhc2U2NHVybCBsZW5ndGggZm9yIGB0b2tlbkJ5dGVzYC5cbiAgICpcbiAgICogQHBhcmFtIHRva2VuIC0gUGxhaW50ZXh0IHJlZnJlc2ggdG9rZW4gZnJvbSB0aGUgY2xpZW50LlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5JbnZhbGlkRXJyb3J9IFdoZW4gdmFsaWRhdGlvbiBmYWlscy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVSZWZyZXNoVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdG9rZW4gfHwgdG9rZW4ubGVuZ3RoICE9PSBNYXRoLmNlaWwodGhpcy50b2tlbkJ5dGVzICogOCAvIDYpKSB7XG4gICAgICB0aHJvdyBuZXcgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yKCk7XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==
|
|
@@ -36,13 +36,34 @@ export declare class RefreshTokenRevokedError extends RefreshTokenError {
|
|
|
36
36
|
constructor(message?: string);
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Optional identifiers attached when refresh token reuse is detected, so callers can
|
|
40
|
+
* revoke the whole session (e.g. via {@link RefreshTokenStore.revokeSession}).
|
|
41
|
+
*/
|
|
42
|
+
export type RefreshTokenReusedErrorContext = {
|
|
43
|
+
/** Subject identifier from the reused token row, when known. */
|
|
44
|
+
subjectId?: string;
|
|
45
|
+
/** Session identifier from the reused token row, when known. */
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Thrown when a refresh token is presented after it has already been rotated (reuse detection),
|
|
50
|
+
* or when a rotate transaction is canceled under reuse-safe conditions.
|
|
51
|
+
*
|
|
52
|
+
* When `subjectId` / `sessionId` are present, callers can revoke the whole session
|
|
53
|
+
* (e.g. via {@link RefreshTokenStore.revokeSession}) per OAuth 2.0 BCP family revocation.
|
|
54
|
+
* If the store was constructed with `revokeSessionOnReuse: true`, the session may already
|
|
55
|
+
* have been revoked before this error is thrown.
|
|
40
56
|
*/
|
|
41
57
|
export declare class RefreshTokenReusedError extends RefreshTokenError {
|
|
58
|
+
/** Subject identifier from the reused token row, when known. */
|
|
59
|
+
readonly subjectId?: string;
|
|
60
|
+
/** Session identifier from the reused token row, when known. */
|
|
61
|
+
readonly sessionId?: string;
|
|
42
62
|
/**
|
|
43
63
|
* @param message - Human-readable error description.
|
|
64
|
+
* @param context - Subject/session from the store row to support session-wide revocation.
|
|
44
65
|
*/
|
|
45
|
-
constructor(message?: string);
|
|
66
|
+
constructor(message?: string, context?: RefreshTokenReusedErrorContext);
|
|
46
67
|
}
|
|
47
68
|
/**
|
|
48
69
|
* Thrown when rotation fails for a reason other than reuse (e.g. transient store failure).
|
|
@@ -52,14 +52,23 @@ class RefreshTokenRevokedError extends RefreshTokenError {
|
|
|
52
52
|
}
|
|
53
53
|
exports.RefreshTokenRevokedError = RefreshTokenRevokedError;
|
|
54
54
|
/**
|
|
55
|
-
* Thrown when a refresh token is presented after it has already been rotated (reuse detection)
|
|
55
|
+
* Thrown when a refresh token is presented after it has already been rotated (reuse detection),
|
|
56
|
+
* or when a rotate transaction is canceled under reuse-safe conditions.
|
|
57
|
+
*
|
|
58
|
+
* When `subjectId` / `sessionId` are present, callers can revoke the whole session
|
|
59
|
+
* (e.g. via {@link RefreshTokenStore.revokeSession}) per OAuth 2.0 BCP family revocation.
|
|
60
|
+
* If the store was constructed with `revokeSessionOnReuse: true`, the session may already
|
|
61
|
+
* have been revoked before this error is thrown.
|
|
56
62
|
*/
|
|
57
63
|
class RefreshTokenReusedError extends RefreshTokenError {
|
|
58
64
|
/**
|
|
59
65
|
* @param message - Human-readable error description.
|
|
66
|
+
* @param context - Subject/session from the store row to support session-wide revocation.
|
|
60
67
|
*/
|
|
61
|
-
constructor(message = 'This refresh token has already been rotated and cannot be used again.') {
|
|
68
|
+
constructor(message = 'This refresh token has already been rotated and cannot be used again.', context) {
|
|
62
69
|
super(message);
|
|
70
|
+
this.subjectId = context?.subjectId;
|
|
71
|
+
this.sessionId = context?.sessionId;
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
74
|
exports.RefreshTokenReusedError = RefreshTokenReusedError;
|
|
@@ -75,4 +84,4 @@ class RefreshTokenRotateFailedError extends RefreshTokenError {
|
|
|
75
84
|
}
|
|
76
85
|
}
|
|
77
86
|
exports.RefreshTokenRotateFailedError = RefreshTokenRotateFailedError;
|
|
78
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmcmVzaC10b2tlbi1lcnJvcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL3JlZnJlc2gtdG9rZW4tZXJyb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7R0FHRztBQUNILE1BQXNCLGlCQUFrQixTQUFRLEtBQUs7SUFDbkQ7O09BRUc7SUFDSCxZQUFzQixPQUFlO1FBQ25DLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDOUIsQ0FBQztDQUNGO0FBUkQsOENBUUM7QUFFRDs7R0FFRztBQUNILE1BQWEsd0JBQXlCLFNBQVEsaUJBQWlCO0lBQzdEOztPQUVHO0lBQ0gsWUFDRSxPQUFPLEdBQUcsNkRBQTZEO1FBRXZFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqQixDQUFDO0NBQ0Y7QUFURCw0REFTQztBQUVEOztHQUVHO0FBQ0gsTUFBYSx3QkFBeUIsU0FBUSxpQkFBaUI7SUFDN0Q7O09BRUc7SUFDSCxZQUFZLE9BQU8sR0FBRyxzREFBc0Q7UUFDMUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pCLENBQUM7Q0FDRjtBQVBELDREQU9DO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLHdCQUF5QixTQUFRLGlCQUFpQjtJQUM3RDs7T0FFRztJQUNILFlBQVksT0FBTyxHQUFHLHFDQUFxQztRQUN6RCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakIsQ0FBQztDQUNGO0FBUEQsNERBT0M7QUFhRDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsdUJBQXdCLFNBQVEsaUJBQWlCO0lBTzVEOzs7T0FHRztJQUNILFlBQ0UsT0FBTyxHQUFHLHVFQUF1RSxFQUNqRixPQUF3QztRQUV4QyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLENBQUM7UUFDcEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsU0FBUyxDQUFDO0lBQ3RDLENBQUM7Q0FDRjtBQW5CRCwwREFtQkM7QUFFRDs7R0FFRztBQUNILE1BQWEsNkJBQThCLFNBQVEsaUJBQWlCO0lBQ2xFOztPQUVHO0lBQ0gsWUFDRSxPQUFPLEdBQUcsc0VBQXNFO1FBRWhGLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqQixDQUFDO0NBQ0Y7QUFURCxzRUFTQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQmFzZSBjbGFzcyBmb3IgcmVmcmVzaCB0b2tlbiBzdG9yZSBlcnJvcnMuXG4gKiBVc2UgYGluc3RhbmNlb2ZgIG9uIGNvbmNyZXRlIGNsYXNzZXMgb3IgdGhpcyBiYXNlIGZvciBoYW5kbGluZy5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlZnJlc2hUb2tlbkVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSBlcnJvciBkZXNjcmlwdGlvbi5cbiAgICovXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBuZXcudGFyZ2V0Lm5hbWU7XG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd24gd2hlbiB0aGUgcmVmcmVzaCB0b2tlbiBpcyBtaXNzaW5nLCBtYWxmb3JtZWQsIG9yIG5vdCByZWNvZ25pemVkLlxuICovXG5leHBvcnQgY2xhc3MgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yIGV4dGVuZHMgUmVmcmVzaFRva2VuRXJyb3Ige1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSBlcnJvciBkZXNjcmlwdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2UgPSAnVGhlIHJlZnJlc2ggdG9rZW4gaXMgbWlzc2luZywgbWFsZm9ybWVkLCBvciBub3QgcmVjb2duaXplZC4nLFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxufVxuXG4vKipcbiAqIFRocm93biB3aGVuIHRoZSByZWZyZXNoIHRva2VuIGhhcyBwYXNzZWQgaXRzIGxvZ2ljYWwgZXhwaXJhdGlvbiAoYGV4cGlyZXNBdGApLlxuICovXG5leHBvcnQgY2xhc3MgUmVmcmVzaFRva2VuRXhwaXJlZEVycm9yIGV4dGVuZHMgUmVmcmVzaFRva2VuRXJyb3Ige1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSBlcnJvciBkZXNjcmlwdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnVGhlIHJlZnJlc2ggdG9rZW4gaGFzIGV4cGlyZWQuIFBsZWFzZSBzaWduIGluIGFnYWluLicpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxufVxuXG4vKipcbiAqIFRocm93biB3aGVuIHRoZSByZWZyZXNoIHRva2VuIGhhcyBiZWVuIGV4cGxpY2l0bHkgcmV2b2tlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlZnJlc2hUb2tlblJldm9rZWRFcnJvciBleHRlbmRzIFJlZnJlc2hUb2tlbkVycm9yIHtcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgZXJyb3IgZGVzY3JpcHRpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlID0gJ1RoZSByZWZyZXNoIHRva2VuIGhhcyBiZWVuIHJldm9rZWQuJykge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICB9XG59XG5cbi8qKlxuICogT3B0aW9uYWwgaWRlbnRpZmllcnMgYXR0YWNoZWQgd2hlbiByZWZyZXNoIHRva2VuIHJldXNlIGlzIGRldGVjdGVkLCBzbyBjYWxsZXJzIGNhblxuICogcmV2b2tlIHRoZSB3aG9sZSBzZXNzaW9uIChlLmcuIHZpYSB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUucmV2b2tlU2Vzc2lvbn0pLlxuICovXG5leHBvcnQgdHlwZSBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvckNvbnRleHQgPSB7XG4gIC8qKiBTdWJqZWN0IGlkZW50aWZpZXIgZnJvbSB0aGUgcmV1c2VkIHRva2VuIHJvdywgd2hlbiBrbm93bi4gKi9cbiAgc3ViamVjdElkPzogc3RyaW5nO1xuICAvKiogU2Vzc2lvbiBpZGVudGlmaWVyIGZyb20gdGhlIHJldXNlZCB0b2tlbiByb3csIHdoZW4ga25vd24uICovXG4gIHNlc3Npb25JZD86IHN0cmluZztcbn07XG5cbi8qKlxuICogVGhyb3duIHdoZW4gYSByZWZyZXNoIHRva2VuIGlzIHByZXNlbnRlZCBhZnRlciBpdCBoYXMgYWxyZWFkeSBiZWVuIHJvdGF0ZWQgKHJldXNlIGRldGVjdGlvbiksXG4gKiBvciB3aGVuIGEgcm90YXRlIHRyYW5zYWN0aW9uIGlzIGNhbmNlbGVkIHVuZGVyIHJldXNlLXNhZmUgY29uZGl0aW9ucy5cbiAqXG4gKiBXaGVuIGBzdWJqZWN0SWRgIC8gYHNlc3Npb25JZGAgYXJlIHByZXNlbnQsIGNhbGxlcnMgY2FuIHJldm9rZSB0aGUgd2hvbGUgc2Vzc2lvblxuICogKGUuZy4gdmlhIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZS5yZXZva2VTZXNzaW9ufSkgcGVyIE9BdXRoIDIuMCBCQ1AgZmFtaWx5IHJldm9jYXRpb24uXG4gKiBJZiB0aGUgc3RvcmUgd2FzIGNvbnN0cnVjdGVkIHdpdGggYHJldm9rZVNlc3Npb25PblJldXNlOiB0cnVlYCwgdGhlIHNlc3Npb24gbWF5IGFscmVhZHlcbiAqIGhhdmUgYmVlbiByZXZva2VkIGJlZm9yZSB0aGlzIGVycm9yIGlzIHRocm93bi5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlZnJlc2hUb2tlblJldXNlZEVycm9yIGV4dGVuZHMgUmVmcmVzaFRva2VuRXJyb3Ige1xuICAvKiogU3ViamVjdCBpZGVudGlmaWVyIGZyb20gdGhlIHJldXNlZCB0b2tlbiByb3csIHdoZW4ga25vd24uICovXG4gIHJlYWRvbmx5IHN1YmplY3RJZD86IHN0cmluZztcblxuICAvKiogU2Vzc2lvbiBpZGVudGlmaWVyIGZyb20gdGhlIHJldXNlZCB0b2tlbiByb3csIHdoZW4ga25vd24uICovXG4gIHJlYWRvbmx5IHNlc3Npb25JZD86IHN0cmluZztcblxuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSBlcnJvciBkZXNjcmlwdGlvbi5cbiAgICogQHBhcmFtIGNvbnRleHQgLSBTdWJqZWN0L3Nlc3Npb24gZnJvbSB0aGUgc3RvcmUgcm93IHRvIHN1cHBvcnQgc2Vzc2lvbi13aWRlIHJldm9jYXRpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBtZXNzYWdlID0gJ1RoaXMgcmVmcmVzaCB0b2tlbiBoYXMgYWxyZWFkeSBiZWVuIHJvdGF0ZWQgYW5kIGNhbm5vdCBiZSB1c2VkIGFnYWluLicsXG4gICAgY29udGV4dD86IFJlZnJlc2hUb2tlblJldXNlZEVycm9yQ29udGV4dCxcbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5zdWJqZWN0SWQgPSBjb250ZXh0Py5zdWJqZWN0SWQ7XG4gICAgdGhpcy5zZXNzaW9uSWQgPSBjb250ZXh0Py5zZXNzaW9uSWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd24gd2hlbiByb3RhdGlvbiBmYWlscyBmb3IgYSByZWFzb24gb3RoZXIgdGhhbiByZXVzZSAoZS5nLiB0cmFuc2llbnQgc3RvcmUgZmFpbHVyZSkuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWZyZXNoVG9rZW5Sb3RhdGVGYWlsZWRFcnJvciBleHRlbmRzIFJlZnJlc2hUb2tlbkVycm9yIHtcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgZXJyb3IgZGVzY3JpcHRpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBtZXNzYWdlID0gJ1RoZSByZWZyZXNoIHRva2VuIGNvdWxkIG5vdCBiZSByb3RhdGVkLiBQbGVhc2UgdHJ5IHNpZ25pbmcgaW4gYWdhaW4uJyxcbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gIH1cbn1cbiJdfQ==
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export type EpochSec = number;
|
|
|
4
4
|
* Configuration for the DynamoDB refresh token provider constructor.
|
|
5
5
|
*
|
|
6
6
|
* Token lifetime (`ttlDays`) drives both logical expiration (`expiresAt`) and the
|
|
7
|
-
* DynamoDB TTL attribute (`ttl`) written on Put / Transact.
|
|
7
|
+
* DynamoDB TTL attribute (`ttl`) written on Put / Transact. Session revocation options
|
|
8
|
+
* (`sessionIdIndexName`, `revokeSessionOnReuse`) require a GSI whose partition key is
|
|
9
|
+
* `sessionId`.
|
|
8
10
|
*/
|
|
9
11
|
export type StoreOptions = {
|
|
10
12
|
/**
|
|
@@ -26,6 +28,20 @@ export type StoreOptions = {
|
|
|
26
28
|
* Custom DynamoDB API endpoint (e.g. LocalStack or DynamoDB Local).
|
|
27
29
|
*/
|
|
28
30
|
endpoint?: string;
|
|
31
|
+
/**
|
|
32
|
+
* DynamoDB GSI name whose partition key attribute is `sessionId` (String).
|
|
33
|
+
* Required for {@link RefreshTokenStore.revokeSession} and for `revokeSessionOnReuse`.
|
|
34
|
+
* `KEYS_ONLY` projection is sufficient.
|
|
35
|
+
* @defaultValue `'sessionId-index'`
|
|
36
|
+
*/
|
|
37
|
+
sessionIdIndexName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* When true, {@link RefreshTokenStore.rotate} calls {@link RefreshTokenStore.revokeSession}
|
|
40
|
+
* for the token’s `sessionId` and `subjectId` before throwing {@link RefreshTokenReusedError}.
|
|
41
|
+
* Aligns with OAuth 2.0 BCP refresh-token family revocation on reuse detection.
|
|
42
|
+
* @defaultValue false
|
|
43
|
+
*/
|
|
44
|
+
revokeSessionOnReuse?: boolean;
|
|
29
45
|
};
|
|
30
46
|
/** Parameters for {@link RefreshTokenStore.issue}. */
|
|
31
47
|
export type IssueParams = {
|
|
@@ -68,6 +84,24 @@ export type RevokeParams = {
|
|
|
68
84
|
/** Clock override for tests; defaults to `new Date()`. */
|
|
69
85
|
now?: Date;
|
|
70
86
|
};
|
|
87
|
+
/** Parameters for {@link RefreshTokenStore.revokeSession}. */
|
|
88
|
+
export type RevokeSessionParams = {
|
|
89
|
+
/** Session whose refresh token rows should all be revoked. */
|
|
90
|
+
sessionId: string;
|
|
91
|
+
/**
|
|
92
|
+
* When set, only rows matching this subject are revoked.
|
|
93
|
+
* Applied as an `UpdateItem` condition on the base table (not a GSI filter), so a
|
|
94
|
+
* `KEYS_ONLY` session GSI is sufficient.
|
|
95
|
+
*/
|
|
96
|
+
subjectId?: string;
|
|
97
|
+
/** Clock override for tests; defaults to `new Date()`. */
|
|
98
|
+
now?: Date;
|
|
99
|
+
};
|
|
100
|
+
/** Result of {@link RefreshTokenStore.revokeSession}. */
|
|
101
|
+
export type RevokeSessionResult = {
|
|
102
|
+
/** Number of token rows successfully updated with `revokedAt` in this call. */
|
|
103
|
+
revokedCount: number;
|
|
104
|
+
};
|
|
71
105
|
/**
|
|
72
106
|
* DynamoDB item shape for a stored refresh token (hash-keyed by `pk`).
|
|
73
107
|
*
|
|
@@ -77,9 +111,12 @@ export type RevokeParams = {
|
|
|
77
111
|
export type TokenRecord = {
|
|
78
112
|
/** Partition key: prefix + SHA-256 hex of the plaintext token. */
|
|
79
113
|
pk: string;
|
|
80
|
-
/** Subject (user) identifier. */
|
|
114
|
+
/** Subject (user) identifier; also used when cascading session revoke on reuse. */
|
|
81
115
|
subjectId: string;
|
|
82
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Session identifier. Partition key of the session GSI used by
|
|
118
|
+
* {@link RefreshTokenStore.revokeSession}.
|
|
119
|
+
*/
|
|
83
120
|
sessionId: string;
|
|
84
121
|
/** Row creation time as Unix seconds. */
|
|
85
122
|
createdAt: EpochSec;
|
|
@@ -97,7 +134,7 @@ export type TokenRecord = {
|
|
|
97
134
|
revokedAt?: EpochSec | null;
|
|
98
135
|
};
|
|
99
136
|
/**
|
|
100
|
-
* Persistence abstraction for opaque refresh tokens: issue, rotate, and revoke.
|
|
137
|
+
* Persistence abstraction for opaque refresh tokens: issue, rotate, revoke, and session revoke.
|
|
101
138
|
*/
|
|
102
139
|
export interface RefreshTokenStore {
|
|
103
140
|
/**
|
|
@@ -110,20 +147,36 @@ export interface RefreshTokenStore {
|
|
|
110
147
|
/**
|
|
111
148
|
* Validates the current token, marks it rotated, inserts the successor row, and returns the new token.
|
|
112
149
|
*
|
|
150
|
+
* When reuse is detected and {@link StoreOptions.revokeSessionOnReuse} is enabled, the
|
|
151
|
+
* implementation may revoke the whole session before throwing.
|
|
152
|
+
*
|
|
113
153
|
* @param params - Current token and optional clock.
|
|
114
154
|
* @returns Subject, session, new token, and new expiration.
|
|
115
155
|
* @throws {@link RefreshTokenInvalidError} When the token is invalid or no row exists.
|
|
116
156
|
* @throws {@link RefreshTokenExpiredError} When `expiresAt` is not after `now`.
|
|
117
157
|
* @throws {@link RefreshTokenRevokedError} When the row has `revokedAt` set.
|
|
118
|
-
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
158
|
+
* @throws {@link RefreshTokenReusedError} When the token was already rotated or the transaction
|
|
159
|
+
* failed conditionally. May include `subjectId` / `sessionId` from the store row.
|
|
119
160
|
*/
|
|
120
161
|
rotate(params: RotateParams): Promise<RotateResult>;
|
|
121
162
|
/**
|
|
122
163
|
* Sets `revokedAt` on the token row. Idempotent if the row does not exist.
|
|
123
164
|
*
|
|
165
|
+
* Does not change DynamoDB TTL (`ttl`); cleanup still follows the value from issue/rotate.
|
|
166
|
+
*
|
|
124
167
|
* @param params - Token to revoke and optional clock.
|
|
125
168
|
* @returns `true` after a successful update or no-op when the item is absent.
|
|
126
169
|
* @throws {@link RefreshTokenInvalidError} When the token string format is invalid.
|
|
127
170
|
*/
|
|
128
171
|
revoke(params: RevokeParams): Promise<true>;
|
|
172
|
+
/**
|
|
173
|
+
* Sets `revokedAt` on every refresh token row for the given session (OAuth 2.0 BCP family revocation).
|
|
174
|
+
*
|
|
175
|
+
* Requires a DynamoDB GSI whose partition key is `sessionId` (see {@link StoreOptions.sessionIdIndexName}).
|
|
176
|
+
* Optional `subjectId` is enforced on each base-table update condition.
|
|
177
|
+
*
|
|
178
|
+
* @param params - Session id, optional subject filter, and optional clock.
|
|
179
|
+
* @returns Count of rows updated with `revokedAt`.
|
|
180
|
+
*/
|
|
181
|
+
revokeSession(params: RevokeSessionParams): Promise<RevokeSessionResult>;
|
|
129
182
|
}
|
package/lib/types/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBVbml4IHRpbWVzdGFtcCBpbiB3aG9sZSBzZWNvbmRzLiAqL1xuZXhwb3J0IHR5cGUgRXBvY2hTZWMgPSBudW1iZXI7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIER5bmFtb0RCIHJlZnJlc2ggdG9rZW4gcHJvdmlkZXIgY29uc3RydWN0b3IuXG4gKlxuICogVG9rZW4gbGlmZXRpbWUgKGB0dGxEYXlzYCkgZHJpdmVzIGJvdGggbG9naWNhbCBleHBpcmF0aW9uIChgZXhwaXJlc0F0YCkgYW5kIHRoZVxuICogRHluYW1vREIgVFRMIGF0dHJpYnV0ZSAoYHR0bGApIHdyaXR0ZW4gb24gUHV0IC8gVHJhbnNhY3QuXG4gKi9cbmV4cG9ydCB0eXBlIFN0b3JlT3B0aW9ucyA9IHtcbiAgLyoqXG4gICAqIFJlZnJlc2ggdG9rZW4gbGlmZXRpbWUgaW4gZGF5cyAoYWRkZWQgdG8gYG5vd2Agd2hlbiBjb21wdXRpbmcgYGV4cGlyZXNBdGAgLyBgdHRsYCkuXG4gICAqIEBkZWZhdWx0VmFsdWUgNjBcbiAgICovXG4gIHR0bERheXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFBhcnRpdGlvbiBrZXkgcHJlZml4IGZvciBEeW5hbW9EQiBpdGVtczsgZnVsbCBgcGtgIGlzIGBwcmVmaXhgICsgU0hBLTI1NiBoZXggb2YgdGhlIHRva2VuLlxuICAgKiBAZGVmYXVsdFZhbHVlIGAncnQjJ2BcbiAgICovXG4gIHBrUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHVzZSBzdHJvbmdseSBjb25zaXN0ZW50IHJlYWRzIG9uIGBHZXRJdGVtYC5cbiAgICogQGRlZmF1bHRWYWx1ZSB0cnVlXG4gICAqL1xuICBjb25zaXN0ZW50UmVhZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBEeW5hbW9EQiBBUEkgZW5kcG9pbnQgKGUuZy4gTG9jYWxTdGFjayBvciBEeW5hbW9EQiBMb2NhbCkuXG4gICAqL1xuICBlbmRwb2ludD86IHN0cmluZztcbn07XG5cbi8qKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUuaXNzdWV9LiAqL1xuZXhwb3J0IHR5cGUgSXNzdWVQYXJhbXMgPSB7XG4gIC8qKiBTdWJqZWN0ICh1c2VyKSBpZGVudGlmaWVyIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSB0b2tlbi4gKi9cbiAgc3ViamVjdElkOiBzdHJpbmc7XG4gIC8qKiBTZXNzaW9uIGlkZW50aWZpZXIgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHRva2VuLiAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqIENsb2NrIG92ZXJyaWRlIGZvciB0ZXN0czsgZGVmYXVsdHMgdG8gYG5ldyBEYXRlKClgLiAqL1xuICBub3c/OiBEYXRlO1xufTtcblxuLyoqIFJlc3VsdCBvZiB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUuaXNzdWV9LiAqL1xuZXhwb3J0IHR5cGUgSXNzdWVSZXN1bHQgPSB7XG4gIC8qKiBPcGFxdWUgcmVmcmVzaCB0b2tlbiBzdHJpbmcgKHBsYWludGV4dDsgb25seSBhIGhhc2ggaXMgc3RvcmVkIGF0IHJlc3QpLiAqL1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbiAgLyoqIExvZ2ljYWwgZXhwaXJhdGlvbiB0aW1lIGFzIFVuaXggc2Vjb25kcyAoc2FtZSB2YWx1ZSB3cml0dGVuIHRvIGBleHBpcmVzQXRgIC8gYHR0bGApLiAqL1xuICByZWZyZXNoVG9rZW5FeHBpcmVzQXQ6IEVwb2NoU2VjO1xufTtcblxuLyoqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZS5yb3RhdGV9LiAqL1xuZXhwb3J0IHR5cGUgUm90YXRlUGFyYW1zID0ge1xuICAvKiogQ3VycmVudCByZWZyZXNoIHRva2VuIGZyb20gdGhlIGNsaWVudC4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBDbG9jayBvdmVycmlkZSBmb3IgdGVzdHM7IGRlZmF1bHRzIHRvIGBuZXcgRGF0ZSgpYC4gKi9cbiAgbm93PzogRGF0ZTtcbn07XG5cbi8qKiBSZXN1bHQgb2Yge0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlLnJvdGF0ZX0uICovXG5leHBvcnQgdHlwZSBSb3RhdGVSZXN1bHQgPSB7XG4gIC8qKiBTdWJqZWN0IGlkZW50aWZpZXIgZnJvbSB0aGUgcm90YXRlZCB0b2tlbiByb3cuICovXG4gIHN1YmplY3RJZDogc3RyaW5nO1xuICAvKiogU2Vzc2lvbiBpZGVudGlmaWVyIGZyb20gdGhlIHJvdGF0ZWQgdG9rZW4gcm93LiAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqIE5ldyBvcGFxdWUgcmVmcmVzaCB0b2tlbiBhZnRlciByb3RhdGlvbi4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBMb2dpY2FsIGV4cGlyYXRpb24gb2YgdGhlIG5ldyB0b2tlbiBhcyBVbml4IHNlY29uZHMuICovXG4gIHJlZnJlc2hUb2tlbkV4cGlyZXNBdDogRXBvY2hTZWM7XG59O1xuXG4vKiogUGFyYW1ldGVycyBmb3Ige0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlLnJldm9rZX0uICovXG5leHBvcnQgdHlwZSBSZXZva2VQYXJhbXMgPSB7XG4gIC8qKiBSZWZyZXNoIHRva2VuIHRvIHJldm9rZS4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBDbG9jayBvdmVycmlkZSBmb3IgdGVzdHM7IGRlZmF1bHRzIHRvIGBuZXcgRGF0ZSgpYC4gKi9cbiAgbm93PzogRGF0ZTtcbn07XG5cbi8qKlxuICogRHluYW1vREIgaXRlbSBzaGFwZSBmb3IgYSBzdG9yZWQgcmVmcmVzaCB0b2tlbiAoaGFzaC1rZXllZCBieSBgcGtgKS5cbiAqXG4gKiBgZXhwaXJlc0F0YCBpcyB1c2VkIGZvciBhcHBsaWNhdGlvbi1sZXZlbCB2YWxpZGF0aW9uOyBgdHRsYCBpcyB0aGUgRHluYW1vREIgVFRMXG4gKiBhdHRyaWJ1dGUgZm9yIGFzeW5jaHJvbm91cyBpdGVtIGRlbGV0aW9uIChlbmFibGUgVFRMIG9uIHRoZSB0YWJsZSBmb3IgYXR0cmlidXRlIGB0dGxgKS5cbiAqL1xuZXhwb3J0IHR5cGUgVG9rZW5SZWNvcmQgPSB7XG4gIC8qKiBQYXJ0aXRpb24ga2V5OiBwcmVmaXggKyBTSEEtMjU2IGhleCBvZiB0aGUgcGxhaW50ZXh0IHRva2VuLiAqL1xuICBwazogc3RyaW5nO1xuICAvKiogU3ViamVjdCAodXNlcikgaWRlbnRpZmllci4gKi9cbiAgc3ViamVjdElkOiBzdHJpbmc7XG4gIC8qKiBTZXNzaW9uIGlkZW50aWZpZXIuICovXG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICAvKiogUm93IGNyZWF0aW9uIHRpbWUgYXMgVW5peCBzZWNvbmRzLiAqL1xuICBjcmVhdGVkQXQ6IEVwb2NoU2VjO1xuICAvKiogTG9naWNhbCBleHBpcmF0aW9uIHRpbWUgYXMgVW5peCBzZWNvbmRzLiAqL1xuICBleHBpcmVzQXQ6IEVwb2NoU2VjO1xuICAvKipcbiAgICogRHluYW1vREIgVFRMIGF0dHJpYnV0ZSAoVW5peCBzZWNvbmRzKS4gU2V0IG9uIHdyaXRlOyB0YWJsZSBUVEwgbXVzdCB0YXJnZXQgdGhpcyBhdHRyaWJ1dGUgbmFtZS5cbiAgICovXG4gIHR0bDogRXBvY2hTZWM7XG4gIC8qKiBUaW1lIHRoZSB0b2tlbiB3YXMgcm90YXRlZCwgaWYgYXBwbGljYWJsZS4gKi9cbiAgcm90YXRlZEF0PzogRXBvY2hTZWMgfCBudWxsO1xuICAvKiogUGFydGl0aW9uIGtleSBvZiB0aGUgc3VjY2Vzc29yIHRva2VuIGFmdGVyIHJvdGF0aW9uLiAqL1xuICByZXBsYWNlZEJ5UGs/OiBzdHJpbmcgfCBudWxsO1xuICAvKiogVGltZSB0aGUgdG9rZW4gd2FzIHJldm9rZWQsIGlmIGFwcGxpY2FibGUuICovXG4gIHJldm9rZWRBdD86IEVwb2NoU2VjIHwgbnVsbDtcbn07XG5cbi8qKlxuICogUGVyc2lzdGVuY2UgYWJzdHJhY3Rpb24gZm9yIG9wYXF1ZSByZWZyZXNoIHRva2VuczogaXNzdWUsIHJvdGF0ZSwgYW5kIHJldm9rZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWZyZXNoVG9rZW5TdG9yZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHJlZnJlc2ggdG9rZW4gcm93IGFuZCByZXR1cm5zIHRoZSBwbGFpbnRleHQgdG9rZW4uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTdWJqZWN0LCBzZXNzaW9uLCBhbmQgb3B0aW9uYWwgY2xvY2suXG4gICAqIEByZXR1cm5zIFBsYWludGV4dCB0b2tlbiBhbmQgZXhwaXJhdGlvbiBhcyBVbml4IHNlY29uZHMuXG4gICAqL1xuICBpc3N1ZShwYXJhbXM6IElzc3VlUGFyYW1zKTogUHJvbWlzZTxJc3N1ZVJlc3VsdD47XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGUgY3VycmVudCB0b2tlbiwgbWFya3MgaXQgcm90YXRlZCwgaW5zZXJ0cyB0aGUgc3VjY2Vzc29yIHJvdywgYW5kIHJldHVybnMgdGhlIG5ldyB0b2tlbi5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIEN1cnJlbnQgdG9rZW4gYW5kIG9wdGlvbmFsIGNsb2NrLlxuICAgKiBAcmV0dXJucyBTdWJqZWN0LCBzZXNzaW9uLCBuZXcgdG9rZW4sIGFuZCBuZXcgZXhwaXJhdGlvbi5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBpcyBpbnZhbGlkIG9yIG5vIHJvdyBleGlzdHMuXG4gICAqIEB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlbkV4cGlyZWRFcnJvcn0gV2hlbiBgZXhwaXJlc0F0YCBpcyBub3QgYWZ0ZXIgYG5vd2AuXG4gICAqIEB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlblJldm9rZWRFcnJvcn0gV2hlbiB0aGUgcm93IGhhcyBgcmV2b2tlZEF0YCBzZXQuXG4gICAqIEB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlblJldXNlZEVycm9yfSBXaGVuIHRoZSB0b2tlbiB3YXMgYWxyZWFkeSByb3RhdGVkIG9yIHRoZSB0cmFuc2FjdGlvbiBmYWlsZWQgY29uZGl0aW9uYWxseS5cbiAgICovXG4gIHJvdGF0ZShwYXJhbXM6IFJvdGF0ZVBhcmFtcyk6IFByb21pc2U8Um90YXRlUmVzdWx0PjtcblxuICAvKipcbiAgICogU2V0cyBgcmV2b2tlZEF0YCBvbiB0aGUgdG9rZW4gcm93LiBJZGVtcG90ZW50IGlmIHRoZSByb3cgZG9lcyBub3QgZXhpc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUb2tlbiB0byByZXZva2UgYW5kIG9wdGlvbmFsIGNsb2NrLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgYWZ0ZXIgYSBzdWNjZXNzZnVsIHVwZGF0ZSBvciBuby1vcCB3aGVuIHRoZSBpdGVtIGlzIGFic2VudC5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBzdHJpbmcgZm9ybWF0IGlzIGludmFsaWQuXG4gICAqL1xuICByZXZva2UocGFyYW1zOiBSZXZva2VQYXJhbXMpOiBQcm9taXNlPHRydWU+O1xufVxuIl19
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBVbml4IHRpbWVzdGFtcCBpbiB3aG9sZSBzZWNvbmRzLiAqL1xuZXhwb3J0IHR5cGUgRXBvY2hTZWMgPSBudW1iZXI7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIER5bmFtb0RCIHJlZnJlc2ggdG9rZW4gcHJvdmlkZXIgY29uc3RydWN0b3IuXG4gKlxuICogVG9rZW4gbGlmZXRpbWUgKGB0dGxEYXlzYCkgZHJpdmVzIGJvdGggbG9naWNhbCBleHBpcmF0aW9uIChgZXhwaXJlc0F0YCkgYW5kIHRoZVxuICogRHluYW1vREIgVFRMIGF0dHJpYnV0ZSAoYHR0bGApIHdyaXR0ZW4gb24gUHV0IC8gVHJhbnNhY3QuIFNlc3Npb24gcmV2b2NhdGlvbiBvcHRpb25zXG4gKiAoYHNlc3Npb25JZEluZGV4TmFtZWAsIGByZXZva2VTZXNzaW9uT25SZXVzZWApIHJlcXVpcmUgYSBHU0kgd2hvc2UgcGFydGl0aW9uIGtleSBpc1xuICogYHNlc3Npb25JZGAuXG4gKi9cbmV4cG9ydCB0eXBlIFN0b3JlT3B0aW9ucyA9IHtcbiAgLyoqXG4gICAqIFJlZnJlc2ggdG9rZW4gbGlmZXRpbWUgaW4gZGF5cyAoYWRkZWQgdG8gYG5vd2Agd2hlbiBjb21wdXRpbmcgYGV4cGlyZXNBdGAgLyBgdHRsYCkuXG4gICAqIEBkZWZhdWx0VmFsdWUgNjBcbiAgICovXG4gIHR0bERheXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFBhcnRpdGlvbiBrZXkgcHJlZml4IGZvciBEeW5hbW9EQiBpdGVtczsgZnVsbCBgcGtgIGlzIGBwcmVmaXhgICsgU0hBLTI1NiBoZXggb2YgdGhlIHRva2VuLlxuICAgKiBAZGVmYXVsdFZhbHVlIGAncnQjJ2BcbiAgICovXG4gIHBrUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHVzZSBzdHJvbmdseSBjb25zaXN0ZW50IHJlYWRzIG9uIGBHZXRJdGVtYC5cbiAgICogQGRlZmF1bHRWYWx1ZSB0cnVlXG4gICAqL1xuICBjb25zaXN0ZW50UmVhZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBEeW5hbW9EQiBBUEkgZW5kcG9pbnQgKGUuZy4gTG9jYWxTdGFjayBvciBEeW5hbW9EQiBMb2NhbCkuXG4gICAqL1xuICBlbmRwb2ludD86IHN0cmluZztcblxuICAvKipcbiAgICogRHluYW1vREIgR1NJIG5hbWUgd2hvc2UgcGFydGl0aW9uIGtleSBhdHRyaWJ1dGUgaXMgYHNlc3Npb25JZGAgKFN0cmluZykuXG4gICAqIFJlcXVpcmVkIGZvciB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUucmV2b2tlU2Vzc2lvbn0gYW5kIGZvciBgcmV2b2tlU2Vzc2lvbk9uUmV1c2VgLlxuICAgKiBgS0VZU19PTkxZYCBwcm9qZWN0aW9uIGlzIHN1ZmZpY2llbnQuXG4gICAqIEBkZWZhdWx0VmFsdWUgYCdzZXNzaW9uSWQtaW5kZXgnYFxuICAgKi9cbiAgc2Vzc2lvbklkSW5kZXhOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIHRydWUsIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZS5yb3RhdGV9IGNhbGxzIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZS5yZXZva2VTZXNzaW9ufVxuICAgKiBmb3IgdGhlIHRva2Vu4oCZcyBgc2Vzc2lvbklkYCBhbmQgYHN1YmplY3RJZGAgYmVmb3JlIHRocm93aW5nIHtAbGluayBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcn0uXG4gICAqIEFsaWducyB3aXRoIE9BdXRoIDIuMCBCQ1AgcmVmcmVzaC10b2tlbiBmYW1pbHkgcmV2b2NhdGlvbiBvbiByZXVzZSBkZXRlY3Rpb24uXG4gICAqIEBkZWZhdWx0VmFsdWUgZmFsc2VcbiAgICovXG4gIHJldm9rZVNlc3Npb25PblJldXNlPzogYm9vbGVhbjtcbn07XG5cbi8qKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUuaXNzdWV9LiAqL1xuZXhwb3J0IHR5cGUgSXNzdWVQYXJhbXMgPSB7XG4gIC8qKiBTdWJqZWN0ICh1c2VyKSBpZGVudGlmaWVyIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSB0b2tlbi4gKi9cbiAgc3ViamVjdElkOiBzdHJpbmc7XG4gIC8qKiBTZXNzaW9uIGlkZW50aWZpZXIgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHRva2VuLiAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqIENsb2NrIG92ZXJyaWRlIGZvciB0ZXN0czsgZGVmYXVsdHMgdG8gYG5ldyBEYXRlKClgLiAqL1xuICBub3c/OiBEYXRlO1xufTtcblxuLyoqIFJlc3VsdCBvZiB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUuaXNzdWV9LiAqL1xuZXhwb3J0IHR5cGUgSXNzdWVSZXN1bHQgPSB7XG4gIC8qKiBPcGFxdWUgcmVmcmVzaCB0b2tlbiBzdHJpbmcgKHBsYWludGV4dDsgb25seSBhIGhhc2ggaXMgc3RvcmVkIGF0IHJlc3QpLiAqL1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbiAgLyoqIExvZ2ljYWwgZXhwaXJhdGlvbiB0aW1lIGFzIFVuaXggc2Vjb25kcyAoc2FtZSB2YWx1ZSB3cml0dGVuIHRvIGBleHBpcmVzQXRgIC8gYHR0bGApLiAqL1xuICByZWZyZXNoVG9rZW5FeHBpcmVzQXQ6IEVwb2NoU2VjO1xufTtcblxuLyoqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBSZWZyZXNoVG9rZW5TdG9yZS5yb3RhdGV9LiAqL1xuZXhwb3J0IHR5cGUgUm90YXRlUGFyYW1zID0ge1xuICAvKiogQ3VycmVudCByZWZyZXNoIHRva2VuIGZyb20gdGhlIGNsaWVudC4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBDbG9jayBvdmVycmlkZSBmb3IgdGVzdHM7IGRlZmF1bHRzIHRvIGBuZXcgRGF0ZSgpYC4gKi9cbiAgbm93PzogRGF0ZTtcbn07XG5cbi8qKiBSZXN1bHQgb2Yge0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlLnJvdGF0ZX0uICovXG5leHBvcnQgdHlwZSBSb3RhdGVSZXN1bHQgPSB7XG4gIC8qKiBTdWJqZWN0IGlkZW50aWZpZXIgZnJvbSB0aGUgcm90YXRlZCB0b2tlbiByb3cuICovXG4gIHN1YmplY3RJZDogc3RyaW5nO1xuICAvKiogU2Vzc2lvbiBpZGVudGlmaWVyIGZyb20gdGhlIHJvdGF0ZWQgdG9rZW4gcm93LiAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqIE5ldyBvcGFxdWUgcmVmcmVzaCB0b2tlbiBhZnRlciByb3RhdGlvbi4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBMb2dpY2FsIGV4cGlyYXRpb24gb2YgdGhlIG5ldyB0b2tlbiBhcyBVbml4IHNlY29uZHMuICovXG4gIHJlZnJlc2hUb2tlbkV4cGlyZXNBdDogRXBvY2hTZWM7XG59O1xuXG4vKiogUGFyYW1ldGVycyBmb3Ige0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlLnJldm9rZX0uICovXG5leHBvcnQgdHlwZSBSZXZva2VQYXJhbXMgPSB7XG4gIC8qKiBSZWZyZXNoIHRva2VuIHRvIHJldm9rZS4gKi9cbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIC8qKiBDbG9jayBvdmVycmlkZSBmb3IgdGVzdHM7IGRlZmF1bHRzIHRvIGBuZXcgRGF0ZSgpYC4gKi9cbiAgbm93PzogRGF0ZTtcbn07XG5cbi8qKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUucmV2b2tlU2Vzc2lvbn0uICovXG5leHBvcnQgdHlwZSBSZXZva2VTZXNzaW9uUGFyYW1zID0ge1xuICAvKiogU2Vzc2lvbiB3aG9zZSByZWZyZXNoIHRva2VuIHJvd3Mgc2hvdWxkIGFsbCBiZSByZXZva2VkLiAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFdoZW4gc2V0LCBvbmx5IHJvd3MgbWF0Y2hpbmcgdGhpcyBzdWJqZWN0IGFyZSByZXZva2VkLlxuICAgKiBBcHBsaWVkIGFzIGFuIGBVcGRhdGVJdGVtYCBjb25kaXRpb24gb24gdGhlIGJhc2UgdGFibGUgKG5vdCBhIEdTSSBmaWx0ZXIpLCBzbyBhXG4gICAqIGBLRVlTX09OTFlgIHNlc3Npb24gR1NJIGlzIHN1ZmZpY2llbnQuXG4gICAqL1xuICBzdWJqZWN0SWQ/OiBzdHJpbmc7XG4gIC8qKiBDbG9jayBvdmVycmlkZSBmb3IgdGVzdHM7IGRlZmF1bHRzIHRvIGBuZXcgRGF0ZSgpYC4gKi9cbiAgbm93PzogRGF0ZTtcbn07XG5cbi8qKiBSZXN1bHQgb2Yge0BsaW5rIFJlZnJlc2hUb2tlblN0b3JlLnJldm9rZVNlc3Npb259LiAqL1xuZXhwb3J0IHR5cGUgUmV2b2tlU2Vzc2lvblJlc3VsdCA9IHtcbiAgLyoqIE51bWJlciBvZiB0b2tlbiByb3dzIHN1Y2Nlc3NmdWxseSB1cGRhdGVkIHdpdGggYHJldm9rZWRBdGAgaW4gdGhpcyBjYWxsLiAqL1xuICByZXZva2VkQ291bnQ6IG51bWJlcjtcbn07XG5cbi8qKlxuICogRHluYW1vREIgaXRlbSBzaGFwZSBmb3IgYSBzdG9yZWQgcmVmcmVzaCB0b2tlbiAoaGFzaC1rZXllZCBieSBgcGtgKS5cbiAqXG4gKiBgZXhwaXJlc0F0YCBpcyB1c2VkIGZvciBhcHBsaWNhdGlvbi1sZXZlbCB2YWxpZGF0aW9uOyBgdHRsYCBpcyB0aGUgRHluYW1vREIgVFRMXG4gKiBhdHRyaWJ1dGUgZm9yIGFzeW5jaHJvbm91cyBpdGVtIGRlbGV0aW9uIChlbmFibGUgVFRMIG9uIHRoZSB0YWJsZSBmb3IgYXR0cmlidXRlIGB0dGxgKS5cbiAqL1xuZXhwb3J0IHR5cGUgVG9rZW5SZWNvcmQgPSB7XG4gIC8qKiBQYXJ0aXRpb24ga2V5OiBwcmVmaXggKyBTSEEtMjU2IGhleCBvZiB0aGUgcGxhaW50ZXh0IHRva2VuLiAqL1xuICBwazogc3RyaW5nO1xuICAvKiogU3ViamVjdCAodXNlcikgaWRlbnRpZmllcjsgYWxzbyB1c2VkIHdoZW4gY2FzY2FkaW5nIHNlc3Npb24gcmV2b2tlIG9uIHJldXNlLiAqL1xuICBzdWJqZWN0SWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFNlc3Npb24gaWRlbnRpZmllci4gUGFydGl0aW9uIGtleSBvZiB0aGUgc2Vzc2lvbiBHU0kgdXNlZCBieVxuICAgKiB7QGxpbmsgUmVmcmVzaFRva2VuU3RvcmUucmV2b2tlU2Vzc2lvbn0uXG4gICAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgLyoqIFJvdyBjcmVhdGlvbiB0aW1lIGFzIFVuaXggc2Vjb25kcy4gKi9cbiAgY3JlYXRlZEF0OiBFcG9jaFNlYztcbiAgLyoqIExvZ2ljYWwgZXhwaXJhdGlvbiB0aW1lIGFzIFVuaXggc2Vjb25kcy4gKi9cbiAgZXhwaXJlc0F0OiBFcG9jaFNlYztcbiAgLyoqXG4gICAqIER5bmFtb0RCIFRUTCBhdHRyaWJ1dGUgKFVuaXggc2Vjb25kcykuIFNldCBvbiB3cml0ZTsgdGFibGUgVFRMIG11c3QgdGFyZ2V0IHRoaXMgYXR0cmlidXRlIG5hbWUuXG4gICAqL1xuICB0dGw6IEVwb2NoU2VjO1xuICAvKiogVGltZSB0aGUgdG9rZW4gd2FzIHJvdGF0ZWQsIGlmIGFwcGxpY2FibGUuICovXG4gIHJvdGF0ZWRBdD86IEVwb2NoU2VjIHwgbnVsbDtcbiAgLyoqIFBhcnRpdGlvbiBrZXkgb2YgdGhlIHN1Y2Nlc3NvciB0b2tlbiBhZnRlciByb3RhdGlvbi4gKi9cbiAgcmVwbGFjZWRCeVBrPzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFRpbWUgdGhlIHRva2VuIHdhcyByZXZva2VkLCBpZiBhcHBsaWNhYmxlLiAqL1xuICByZXZva2VkQXQ/OiBFcG9jaFNlYyB8IG51bGw7XG59O1xuXG4vKipcbiAqIFBlcnNpc3RlbmNlIGFic3RyYWN0aW9uIGZvciBvcGFxdWUgcmVmcmVzaCB0b2tlbnM6IGlzc3VlLCByb3RhdGUsIHJldm9rZSwgYW5kIHNlc3Npb24gcmV2b2tlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZnJlc2hUb2tlblN0b3JlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcmVmcmVzaCB0b2tlbiByb3cgYW5kIHJldHVybnMgdGhlIHBsYWludGV4dCB0b2tlbi5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFN1YmplY3QsIHNlc3Npb24sIGFuZCBvcHRpb25hbCBjbG9jay5cbiAgICogQHJldHVybnMgUGxhaW50ZXh0IHRva2VuIGFuZCBleHBpcmF0aW9uIGFzIFVuaXggc2Vjb25kcy5cbiAgICovXG4gIGlzc3VlKHBhcmFtczogSXNzdWVQYXJhbXMpOiBQcm9taXNlPElzc3VlUmVzdWx0PjtcblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBjdXJyZW50IHRva2VuLCBtYXJrcyBpdCByb3RhdGVkLCBpbnNlcnRzIHRoZSBzdWNjZXNzb3Igcm93LCBhbmQgcmV0dXJucyB0aGUgbmV3IHRva2VuLlxuICAgKlxuICAgKiBXaGVuIHJldXNlIGlzIGRldGVjdGVkIGFuZCB7QGxpbmsgU3RvcmVPcHRpb25zLnJldm9rZVNlc3Npb25PblJldXNlfSBpcyBlbmFibGVkLCB0aGVcbiAgICogaW1wbGVtZW50YXRpb24gbWF5IHJldm9rZSB0aGUgd2hvbGUgc2Vzc2lvbiBiZWZvcmUgdGhyb3dpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBDdXJyZW50IHRva2VuIGFuZCBvcHRpb25hbCBjbG9jay5cbiAgICogQHJldHVybnMgU3ViamVjdCwgc2Vzc2lvbiwgbmV3IHRva2VuLCBhbmQgbmV3IGV4cGlyYXRpb24uXG4gICAqIEB0aHJvd3Mge0BsaW5rIFJlZnJlc2hUb2tlbkludmFsaWRFcnJvcn0gV2hlbiB0aGUgdG9rZW4gaXMgaW52YWxpZCBvciBubyByb3cgZXhpc3RzLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5FeHBpcmVkRXJyb3J9IFdoZW4gYGV4cGlyZXNBdGAgaXMgbm90IGFmdGVyIGBub3dgLlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXZva2VkRXJyb3J9IFdoZW4gdGhlIHJvdyBoYXMgYHJldm9rZWRBdGAgc2V0LlxuICAgKiBAdGhyb3dzIHtAbGluayBSZWZyZXNoVG9rZW5SZXVzZWRFcnJvcn0gV2hlbiB0aGUgdG9rZW4gd2FzIGFscmVhZHkgcm90YXRlZCBvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogICBmYWlsZWQgY29uZGl0aW9uYWxseS4gTWF5IGluY2x1ZGUgYHN1YmplY3RJZGAgLyBgc2Vzc2lvbklkYCBmcm9tIHRoZSBzdG9yZSByb3cuXG4gICAqL1xuICByb3RhdGUocGFyYW1zOiBSb3RhdGVQYXJhbXMpOiBQcm9taXNlPFJvdGF0ZVJlc3VsdD47XG5cbiAgLyoqXG4gICAqIFNldHMgYHJldm9rZWRBdGAgb24gdGhlIHRva2VuIHJvdy4gSWRlbXBvdGVudCBpZiB0aGUgcm93IGRvZXMgbm90IGV4aXN0LlxuICAgKlxuICAgKiBEb2VzIG5vdCBjaGFuZ2UgRHluYW1vREIgVFRMIChgdHRsYCk7IGNsZWFudXAgc3RpbGwgZm9sbG93cyB0aGUgdmFsdWUgZnJvbSBpc3N1ZS9yb3RhdGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUb2tlbiB0byByZXZva2UgYW5kIG9wdGlvbmFsIGNsb2NrLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgYWZ0ZXIgYSBzdWNjZXNzZnVsIHVwZGF0ZSBvciBuby1vcCB3aGVuIHRoZSBpdGVtIGlzIGFic2VudC5cbiAgICogQHRocm93cyB7QGxpbmsgUmVmcmVzaFRva2VuSW52YWxpZEVycm9yfSBXaGVuIHRoZSB0b2tlbiBzdHJpbmcgZm9ybWF0IGlzIGludmFsaWQuXG4gICAqL1xuICByZXZva2UocGFyYW1zOiBSZXZva2VQYXJhbXMpOiBQcm9taXNlPHRydWU+O1xuXG4gIC8qKlxuICAgKiBTZXRzIGByZXZva2VkQXRgIG9uIGV2ZXJ5IHJlZnJlc2ggdG9rZW4gcm93IGZvciB0aGUgZ2l2ZW4gc2Vzc2lvbiAoT0F1dGggMi4wIEJDUCBmYW1pbHkgcmV2b2NhdGlvbikuXG4gICAqXG4gICAqIFJlcXVpcmVzIGEgRHluYW1vREIgR1NJIHdob3NlIHBhcnRpdGlvbiBrZXkgaXMgYHNlc3Npb25JZGAgKHNlZSB7QGxpbmsgU3RvcmVPcHRpb25zLnNlc3Npb25JZEluZGV4TmFtZX0pLlxuICAgKiBPcHRpb25hbCBgc3ViamVjdElkYCBpcyBlbmZvcmNlZCBvbiBlYWNoIGJhc2UtdGFibGUgdXBkYXRlIGNvbmRpdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFNlc3Npb24gaWQsIG9wdGlvbmFsIHN1YmplY3QgZmlsdGVyLCBhbmQgb3B0aW9uYWwgY2xvY2suXG4gICAqIEByZXR1cm5zIENvdW50IG9mIHJvd3MgdXBkYXRlZCB3aXRoIGByZXZva2VkQXRgLlxuICAgKi9cbiAgcmV2b2tlU2Vzc2lvbihwYXJhbXM6IFJldm9rZVNlc3Npb25QYXJhbXMpOiBQcm9taXNlPFJldm9rZVNlc3Npb25SZXN1bHQ+O1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dynamodb-refresh-token-provider",
|
|
3
|
-
"description": "TypeScript library that stores **opaque refresh tokens** in **Amazon DynamoDB** using AWS SDK for JavaScript v3. Tokens are persisted under a hash of the plaintext value; **issue**, **rotate** (with reuse detection via a transactional write),
|
|
3
|
+
"description": "TypeScript library that stores **opaque refresh tokens** in **Amazon DynamoDB** using AWS SDK for JavaScript v3. Tokens are persisted under a hash of the plaintext value; **issue**, **rotate** (with reuse detection via a transactional write), **revoke** (idempotent), and **revokeSession** (OAuth 2.0 BCP family revocation) are supported.",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/gammarers-aws-sdk-modules/dynamodb-refresh-token-provider.git"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"projen": "^0.101.11",
|
|
47
47
|
"ts-jest": "^29.4.11",
|
|
48
48
|
"ts-node": "^10.9.2",
|
|
49
|
-
"typescript": "
|
|
49
|
+
"typescript": "6.0.x"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@aws-sdk/client-dynamodb": "^3.777.0",
|
|
@@ -57,8 +57,7 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devEngines": {
|
|
59
59
|
"packageManager": {
|
|
60
|
-
"name": "
|
|
61
|
-
"version": "1.22.22",
|
|
60
|
+
"name": "npm",
|
|
62
61
|
"onFail": "ignore"
|
|
63
62
|
}
|
|
64
63
|
},
|
|
@@ -67,7 +66,7 @@
|
|
|
67
66
|
"publishConfig": {
|
|
68
67
|
"access": "public"
|
|
69
68
|
},
|
|
70
|
-
"version": "0.
|
|
69
|
+
"version": "0.4.0",
|
|
71
70
|
"jest": {
|
|
72
71
|
"coverageProvider": "v8",
|
|
73
72
|
"testMatch": [
|
|
@@ -114,6 +113,5 @@
|
|
|
114
113
|
}
|
|
115
114
|
},
|
|
116
115
|
"types": "lib/index.d.ts",
|
|
117
|
-
"packageManager": "yarn@1.22.22",
|
|
118
116
|
"//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
|
|
119
117
|
}
|