serverless-spy 0.0.54 → 0.0.56
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/.jsii +3 -3
- package/README.md +45 -5
- package/_config.yml +13 -13
- package/dist/releasetag.txt +1 -1
- package/doc/CDK_construct.md +5 -5
- package/doc/Contributors.md +4 -0
- package/doc/DynamoDB.md +3 -3
- package/doc/EventBridge.md +3 -3
- package/doc/FAQ.md +7 -7
- package/doc/Lambda.md +3 -3
- package/doc/S3.md +2 -2
- package/doc/SNS.md +3 -3
- package/doc/SQS.md +2 -2
- package/doc/quick_start.md +8 -8
- package/doc/web_console.md +4 -4
- package/doc/writing_tests.md +5 -4
- package/lib/src/ServerlessSpy.js +1 -1
- package/logo/full_logo.png +0 -0
- package/logo/logo.png +0 -0
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -3177,7 +3177,7 @@
|
|
|
3177
3177
|
},
|
|
3178
3178
|
"name": "serverless-spy",
|
|
3179
3179
|
"readme": {
|
|
3180
|
-
"markdown": "\n\nCDK-based library for writing elegant, fast executing integration tests on AWS serverless architecture and additional web console to monitor events in real-time.\n\n# How it works\n\n**
|
|
3180
|
+
"markdown": "\n\nCDK-based library for writing elegant, fast executing integration tests on AWS serverless architecture and additional web console to monitor events in real-time.\n\n# How it works\n\n**ServerlessSpy CDK construct creates infrastructure to intercept events in Lambda, SNS, SQS, EventBridge, DynamoDB, S3... and sends it to a testing library or your local web console via API Gateway WebSocket. The testing library subscribes to events so tests can be executed fast without checking/retrying if the process has finished. The testing library is integrated with Jest but can also be used with any other testing library. The web console can be used to see and inspect events in real-time.**\n\n[](https://serverlessspy.com/)\n\n**Your test for the example above would look like something this:**\n```typescript\n(\n await serverlessSpyListener.waitForEventBridgeMyEventBus<TestData>({\n condition: (d) => d.detail.id === id,\n })\n).toMatchObject(...);\n\n(\n await serverlessSpyListener.waitForSnsTopicMyTopic<TestData>({\n condition: (d) => d.message.id === id,\n })\n).toMatchObject(...);\n\n(\n await serverlessSpyListener.waitForSqsMyQueue<TestData>({\n condition: (d) => d.body.id === id,\n })\n).toMatchObject(...);\n\n(\n await (\n await serverlessSpyListener.waitForFunctionMyLambdaRequest<TestData>({\n condition: (d) => d.request.id === id,\n })\n ).followedByResponse();\n).toMatchObject(...);\n\n(\n await serverlessSpyListener.waitForDynamoDBMyTable<TestData>({\n condition: (d) => d.keys.pk === id,\n })\n).toMatchObject({\n eventName: 'INSERT',\n newImage: ...,\n});\n```\n\n**You can see all the events in the local web console:**\n\n\n# Key benefits\n - **Easy** to write tests that are strongly typed thanks to TypeScript ❤️.\n - **Tests are executed much FASTER** 🏎️💨 No need to write tests in a way to periodically check if the process has finished because all events are pushed to the testing library.\n - **Tests can run in parallel** if you use conditions and filter events specific to your test. This drastically reduces the execution time of the CI/CD process.\n - **Web console** enables you to see all events in real time. Debugging 🕵 has never been easier. Search is supported (with regular expression).\n\n# What ServerlessSpy is not\n - ServerlessSpy can not be used if your infrastructure is not created with CDK.\n - The solution is meant only for the development and (automatic) testing environment. You should **EXCLUDE** ServerlessSpy CDK construct in any other environment, especially a production or a high-load environment. ServerlessSpy is not meant for those; it just induces costs and could contribute to hitting AWS quotas (Lambda concurrent executions, ...).\n - Only Node.js stack is supported. There are no plans to support Python or any other. Use of TypeScript is deeply encouraged.\n - Web console only runs on your local computer. No cloud hosting of any kind (for now).\n\n# Documentation\n - [Quick Start](doc/quick_start.md)\n - [CDK Construct](doc/CDK_construct.md)\n - [Writing tests](doc/writing_tests.md)\n - [Lambda](doc/Lambda.md)\n - [SQS](doc/SQS.md)\n - [SNS](doc/SNS.md)\n - [EventBridge](doc/EventBridge.md)\n - [DynamoDB](doc/DynamoDB.md)\n - [S3](doc/S3.md)\n - Kinesis (work in progress)\n - Step Functions (work in progress)\n - [Web Console](doc/web_console.md)\n - [Frequently Asked Questions (FAQ)](doc/FAQ.md)\n - [Sample Application](doc/sample_app.md)\n - [Roadmap](doc/roadmap.md)\n - [Code of Conduct](doc/CODE_OF_CONDUCT.md)\n - [Contributing Guide](doc/CONTRIBUTING.md)\n - [Contributors](doc/Contributors.md)"
|
|
3181
3181
|
},
|
|
3182
3182
|
"repository": {
|
|
3183
3183
|
"type": "git",
|
|
@@ -3554,6 +3554,6 @@
|
|
|
3554
3554
|
"symbolId": "src/ServerlessSpy:SpyFilter"
|
|
3555
3555
|
}
|
|
3556
3556
|
},
|
|
3557
|
-
"version": "0.0.
|
|
3558
|
-
"fingerprint": "
|
|
3557
|
+
"version": "0.0.56",
|
|
3558
|
+
"fingerprint": "llOV4qaw2WjBuJzC2U+TdsXjn0unWAJQeirSPZd1V2g="
|
|
3559
3559
|
}
|
package/README.md
CHANGED
|
@@ -4,21 +4,60 @@ CDK-based library for writing elegant, fast executing integration tests on AWS s
|
|
|
4
4
|
|
|
5
5
|
# How it works
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**ServerlessSpy CDK construct creates infrastructure to intercept events in Lambda, SNS, SQS, EventBridge, DynamoDB, S3... and sends it to a testing library or your local web console via API Gateway WebSocket. The testing library subscribes to events so tests can be executed fast without checking/retrying if the process has finished. The testing library is integrated with Jest but can also be used with any other testing library. The web console can be used to see and inspect events in real-time.**
|
|
8
8
|
|
|
9
|
-

|
|
9
|
+
[](https://serverlessspy.com/)
|
|
10
10
|
|
|
11
|
+
**Your test for the example above would look like something this:**
|
|
12
|
+
```typescript
|
|
13
|
+
(
|
|
14
|
+
await serverlessSpyListener.waitForEventBridgeMyEventBus<TestData>({
|
|
15
|
+
condition: (d) => d.detail.id === id,
|
|
16
|
+
})
|
|
17
|
+
).toMatchObject(...);
|
|
18
|
+
|
|
19
|
+
(
|
|
20
|
+
await serverlessSpyListener.waitForSnsTopicMyTopic<TestData>({
|
|
21
|
+
condition: (d) => d.message.id === id,
|
|
22
|
+
})
|
|
23
|
+
).toMatchObject(...);
|
|
24
|
+
|
|
25
|
+
(
|
|
26
|
+
await serverlessSpyListener.waitForSqsMyQueue<TestData>({
|
|
27
|
+
condition: (d) => d.body.id === id,
|
|
28
|
+
})
|
|
29
|
+
).toMatchObject(...);
|
|
30
|
+
|
|
31
|
+
(
|
|
32
|
+
await (
|
|
33
|
+
await serverlessSpyListener.waitForFunctionMyLambdaRequest<TestData>({
|
|
34
|
+
condition: (d) => d.request.id === id,
|
|
35
|
+
})
|
|
36
|
+
).followedByResponse();
|
|
37
|
+
).toMatchObject(...);
|
|
38
|
+
|
|
39
|
+
(
|
|
40
|
+
await serverlessSpyListener.waitForDynamoDBMyTable<TestData>({
|
|
41
|
+
condition: (d) => d.keys.pk === id,
|
|
42
|
+
})
|
|
43
|
+
).toMatchObject({
|
|
44
|
+
eventName: 'INSERT',
|
|
45
|
+
newImage: ...,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**You can see all the events in the local web console:**
|
|
11
50
|

|
|
12
51
|
|
|
13
52
|
# Key benefits
|
|
14
53
|
- **Easy** to write tests that are strongly typed thanks to TypeScript ❤️.
|
|
15
54
|
- **Tests are executed much FASTER** 🏎️💨 No need to write tests in a way to periodically check if the process has finished because all events are pushed to the testing library.
|
|
16
55
|
- **Tests can run in parallel** if you use conditions and filter events specific to your test. This drastically reduces the execution time of the CI/CD process.
|
|
17
|
-
- **Web console** enables you see all events in real
|
|
56
|
+
- **Web console** enables you to see all events in real time. Debugging 🕵 has never been easier. Search is supported (with regular expression).
|
|
18
57
|
|
|
19
58
|
# What ServerlessSpy is not
|
|
20
59
|
- ServerlessSpy can not be used if your infrastructure is not created with CDK.
|
|
21
|
-
- The solution is meant for development and (automatic) testing environment
|
|
60
|
+
- The solution is meant only for the development and (automatic) testing environment. You should **EXCLUDE** ServerlessSpy CDK construct in any other environment, especially a production or a high-load environment. ServerlessSpy is not meant for those; it just induces costs and could contribute to hitting AWS quotas (Lambda concurrent executions, ...).
|
|
22
61
|
- Only Node.js stack is supported. There are no plans to support Python or any other. Use of TypeScript is deeply encouraged.
|
|
23
62
|
- Web console only runs on your local computer. No cloud hosting of any kind (for now).
|
|
24
63
|
|
|
@@ -39,4 +78,5 @@ CDK-based library for writing elegant, fast executing integration tests on AWS s
|
|
|
39
78
|
- [Sample Application](doc/sample_app.md)
|
|
40
79
|
- [Roadmap](doc/roadmap.md)
|
|
41
80
|
- [Code of Conduct](doc/CODE_OF_CONDUCT.md)
|
|
42
|
-
- [Contributing Guide](doc/CONTRIBUTING.md)
|
|
81
|
+
- [Contributing Guide](doc/CONTRIBUTING.md)
|
|
82
|
+
- [Contributors](doc/Contributors.md)
|
package/_config.yml
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
title:
|
|
2
|
-
project:
|
|
3
|
-
description:
|
|
1
|
+
title: 'ServerlessSpy'
|
|
2
|
+
project: 'ServerlessSpy'
|
|
3
|
+
description: 'CDK-based library for writing elegant integration tests on AWS serverless architecture and additional web console to monitor events in real-time.'
|
|
4
4
|
author: Marko (ServerlessLife)
|
|
5
5
|
email: marko@serverlesslife.com
|
|
6
|
+
image: logo/full_logo.png
|
|
6
7
|
twitter_username: ServerlessL
|
|
7
|
-
github_username:
|
|
8
|
+
github_username: serverlesslife
|
|
8
9
|
show_downloads: false
|
|
9
10
|
encoding: UTF-8
|
|
10
11
|
kramdown:
|
|
11
12
|
input: GFM
|
|
12
13
|
hard_wrap: false
|
|
14
|
+
auto_ids: true # Auto-generate ID's for headings
|
|
13
15
|
future: true
|
|
14
16
|
jailed: false
|
|
15
17
|
gfm_quirks: paragraph_end
|
|
16
|
-
# theme: jekyll-theme-primer
|
|
17
|
-
# remote_theme: pages-themes/primer
|
|
18
|
-
# remote_theme: mmistakes/minimal-mistakes
|
|
19
18
|
theme: minimal-mistakes-jekyll
|
|
20
19
|
minimal_mistakes_skin: dark
|
|
21
20
|
teaser: /logo/full_logo.svg
|
|
22
21
|
logo: /logo/full_logo.svg
|
|
23
22
|
markdown: kramdown
|
|
24
|
-
kramdown:
|
|
25
|
-
input: GFM
|
|
26
|
-
auto_ids: true # Auto-generate ID's for headings
|
|
27
23
|
sass:
|
|
28
24
|
# Where you keep your scss files
|
|
29
25
|
sass_dir: assets/css/
|
|
@@ -32,10 +28,14 @@ sass:
|
|
|
32
28
|
- node_modules/
|
|
33
29
|
exclude:
|
|
34
30
|
- node_modules
|
|
35
|
-
- test/node_modules
|
|
31
|
+
- test/node_modules
|
|
36
32
|
- vendor
|
|
37
33
|
repository: ServerlessLife/serverless-spy
|
|
38
34
|
baseurl: /
|
|
39
|
-
include:
|
|
35
|
+
include:
|
|
40
36
|
- CONTRIBUTING.md
|
|
41
|
-
- CODE_OF_CONDUCT.md
|
|
37
|
+
- CODE_OF_CONDUCT.md
|
|
38
|
+
analytics:
|
|
39
|
+
provider: 'google-gtag'
|
|
40
|
+
google:
|
|
41
|
+
tracking_id: 'G-C2PHH6WYPP'
|
package/dist/releasetag.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.0.
|
|
1
|
+
v0.0.56
|
package/doc/CDK_construct.md
CHANGED
|
@@ -11,13 +11,13 @@ const serverlessSpy = new ServerlessSpy(this, 'ServerlessSpy', {
|
|
|
11
11
|
|
|
12
12
|
Parameters:
|
|
13
13
|
- `generateSpyEventsFileLocation: serverlessSpyEvents/ServerlessSpyEvents.ts`
|
|
14
|
-
is a TypeScript file that
|
|
14
|
+
is a TypeScript file that will be generated by CDK construct. It will make your tests strongly typed 💪. It just contains an interface with a list of possible events, but thanks to this file and the magic of TypeScript, every test becomes strongly typed.
|
|
15
15
|
|
|
16
16
|
- `debugMode: true`
|
|
17
|
-
|
|
17
|
+
Enable debug mode.
|
|
18
18
|
|
|
19
19
|
- `spySqsWithNoSubscriptionAndDropAllMessages`.
|
|
20
|
-
If no Lambda is subscribed to SQS, the ServerlessSpy can not intercept events. With this flag on, additional Lambda will be created that will just consume messages and throw them away (= lost forever ⛔). Of course, that is undesirable in most cases, but
|
|
20
|
+
If no Lambda is subscribed to SQS, the ServerlessSpy can not intercept events. With this flag on, additional Lambda will be created that will just consume messages and throw them away (= lost forever ⛔). Of course, that is undesirable in most cases, but it could be useful for some tests.
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
# Step 2: Star spying
|
|
@@ -49,8 +49,8 @@ All child nodes are also included in the spying.
|
|
|
49
49
|
|
|
50
50
|
You can mix&match both methods.
|
|
51
51
|
|
|
52
|
-
**Why would you exclude some of the notes
|
|
53
|
-
For DynamoDB, there could be only two Lambdas subscribed to DynamoDB Streams, and S3 can have only one. If you reach the quotas with your primary stack, you can use ServerlessSpy on those resources.
|
|
52
|
+
**Why would you exclude some of the notes**
|
|
53
|
+
For DynamoDB, there could be only two Lambdas subscribed to DynamoDB Streams, and S3 can have only one. If you reach the quotas with your primary stack, you can not use ServerlessSpy on those resources.
|
|
54
54
|
|
|
55
55
|
There could also be other reasons to exclude some of the nodes specific to your use case.
|
|
56
56
|
|
package/doc/DynamoDB.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# DynamoDB
|
|
2
2
|
|
|
3
|
-
DynamoDB integration subscribes to DynamoDb Stream and
|
|
3
|
+
DynamoDB integration subscribes to DynamoDb Stream and intercepts events. The event has the following properties:
|
|
4
4
|
- `keys`
|
|
5
5
|
- `newImage`
|
|
6
6
|
- `oldImage`
|
|
7
7
|
- `eventName` (`INSERT`, `MODIFY`, `REMOVE`)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
You can use `eventName` and compare `newImage` and `oldImage` to validate if the correct operation has been executed.
|
|
10
10
|
|
|
11
11
|
Basic example:
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ Basic example:
|
|
|
14
14
|
await serverlessSpyListener.waitForDynamoDBMyTable<TestData>();
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
You can use conditions to wait for particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
17
|
+
You can use conditions to wait for a particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
20
|
await serverlessSpyListener.waitForDynamoDBMyTable<TestData>({
|
package/doc/EventBridge.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# EventBridge
|
|
2
2
|
|
|
3
3
|
EventBridge integration has two types of methods:
|
|
4
|
-
- `waitForEventBridgeXxx()` - Intercept all events
|
|
5
|
-
- `waitForEventBridgeRuleXxxYyy` - Intercept only events
|
|
4
|
+
- `waitForEventBridgeXxx()` - Intercept all events received by EventBridge.
|
|
5
|
+
- `waitForEventBridgeRuleXxxYyy` - Intercept only events received by Rule.
|
|
6
6
|
|
|
7
7
|
Basic example:
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ await serverlessSpyListener.waitForEventBridgeMyEventBus<TestData>();
|
|
|
12
12
|
await serverlessSpyListener.waitForEventBridgeRuleMyEventBusMyRule<TestData>();
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
You can use conditions to wait for particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
15
|
+
You can use conditions to wait for a particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
18
|
await serverlessSpyListener.waitForEventBridgeMyEventBus<TestData>({
|
package/doc/FAQ.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# Frequently asked questions (FAQ)
|
|
2
2
|
|
|
3
3
|
## In which environment should ServerlessSpy be used?
|
|
4
|
-
- Development environment: so you can write tests.
|
|
5
|
-
- Automatic test environment: You execute written tests
|
|
4
|
+
- Development environment: so you can write tests. The web console helps you gain insight into what is happening in the system.
|
|
5
|
+
- Automatic test environment: You execute written tests in CI/CD.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
No. ServerlessSpy can be useful as a developer tool to see events that are
|
|
7
|
+
## Can ServerlessSpy be used as distributer tracing like XRay, Lumigo, Epsagon...
|
|
8
|
+
No. ServerlessSpy can be useful as a developer tool to see events that are occurring in the development environment. The main benefit compared to mentioned tools is that you can see events in real-time. But ServerlessSpy does not have near capabilities of those tools, especially not tracing an event through services, which is the main point of distributed tracing.
|
|
9
9
|
|
|
10
10
|
## What kind of costs does ServerlessSpy induce?
|
|
11
|
-
If you are using ServerlessSpy in low traffic environment like dev and test usually are, the
|
|
11
|
+
If you are using ServerlessSpy in low traffic environment like dev and test usually are, the costs are negligible. For high-load environments, like production, you should exclude ServerlessSpy. It has no use there, and it will just induce costs and could contribute to hitting AWS quotas & limits like Lambda concurrent executions.
|
|
12
12
|
|
|
13
13
|
## Does ServerlessSpy increase response time?
|
|
14
14
|
Negligible, and that's only when hitting Lambda. You should exclude the ServerlessSpy construct in the production environment anyway.
|
|
15
15
|
|
|
16
16
|
## I do not want a new resource created by ServerlessSpy in my stack.
|
|
17
|
-
Additional resources do not harm and do not cause any noticeable costs (in a dev or test environment). But if you still do not want them, you can add them just for the period of executing the test
|
|
17
|
+
Additional resources do not harm and do not cause any noticeable costs (in a dev or test environment). But if you still do not want them, you can add them just for the period of executing the test. Some similar testing libraries do that out of the box. Just redeploy before executing the tests with SperverlessSpy construct included via parameter and then again redeploy afterward with SperverlessSpy construct excluded.
|
|
18
18
|
|
|
19
19
|
## I want to use ServerlessSpy in a developer environment that is used by many developers.
|
|
20
|
-
The recommended way to develop serverless systems is to have a separate environment for each developer or/and each feature. You can still use ServerlessSpy if you share an environment,
|
|
20
|
+
The recommended way to develop serverless systems is to have a separate environment for each developer or/and each feature. You can still use ServerlessSpy if you share an environment, although discouraged. In the web console, you will see events that other developers triggered. And those events could also interfere with your tests if you do not use conditions that filters events by some unique attribute.
|
|
21
21
|
|
|
22
22
|
## Why API Gateway and AppSync are not supported
|
|
23
23
|
They are, but not directly. API Gateway and AppSync services do not support intercepting events, except via CloudWatch, which is slooooow 🐌🐌🐌. ServerlessSpy needs to be fast. You can intercept those events when they hit other supported services like Lambda.
|
package/doc/Lambda.md
CHANGED
|
@@ -6,7 +6,7 @@ Basic example:
|
|
|
6
6
|
await serverlessSpyListener.waitForFunctionMyLambdaRequest();
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
You can use conditions to wait for particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
9
|
+
You can use conditions to wait for a particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
await serverlessSpyListener.waitForFunctionMyLambdaRequest<TestData>({
|
|
@@ -14,13 +14,13 @@ await serverlessSpyListener.waitForFunctionMyLambdaRequest<TestData>({
|
|
|
14
14
|
});
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Lambda
|
|
17
|
+
Lambda produces three kinds of events: **Request, Console, Response**
|
|
18
18
|
```typescript
|
|
19
19
|
await serverlessSpyListener.waitForFunctionMyLambdaRequest();
|
|
20
20
|
await serverlessSpyListener.waitForFunctionMyLambdaConsole();
|
|
21
21
|
await serverlessSpyListener.waitForFunctionMyLambdaResponse();
|
|
22
22
|
```
|
|
23
|
-
Console can be useful to validate intermediate steps
|
|
23
|
+
The `Console` event can be useful to validate intermediate processing steps. You write events with a simple `console.log()` method in the Lambda code.
|
|
24
24
|
|
|
25
25
|
You can chain calls for the same request:
|
|
26
26
|
```typescript
|
package/doc/S3.md
CHANGED
|
@@ -12,7 +12,7 @@ Basic example:
|
|
|
12
12
|
await serverlessSpyListener.waitForS3MyBucket()
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
You can use conditions to wait for particular event.
|
|
15
|
+
You can use conditions to wait for a particular event.
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
18
|
await serverlessSpyListener.waitForS3MyBucket({
|
|
@@ -20,7 +20,7 @@ await serverlessSpyListener.waitForS3MyBucket({
|
|
|
20
20
|
})
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
**⚠️Warning: DynamoDB can have only one
|
|
23
|
+
**⚠️Warning: DynamoDB can have only one Lambda subscribed to notification. If your primary stack already uses it, you could not use S3 interception. You should [exclude S3 interception in your CDK stack](./CDK_construct.md):**
|
|
24
24
|
```typescript
|
|
25
25
|
serverlessSpy.spy({
|
|
26
26
|
spyS3: false,
|
package/doc/SNS.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# SNS
|
|
2
2
|
|
|
3
3
|
SNS integration has two types of methods:
|
|
4
|
-
- `waitForSnsTopicXxx()` - Intercept all events
|
|
5
|
-
- `waitForSnsSubscriptionXxxYyy` - Intercept all events
|
|
4
|
+
- `waitForSnsTopicXxx()` - Intercept all events received by SNS.
|
|
5
|
+
- `waitForSnsSubscriptionXxxYyy` - Intercept all events received by SNS subscription. If the subscription has no filters, it is the same as the previous method.
|
|
6
6
|
|
|
7
7
|
Basic example:
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ await serverlessSpyListener.waitForSnsTopicMyTopic();
|
|
|
12
12
|
await serverlessSpyListener.waitForSnsSubscriptionMyTopicMyLambda();
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
You can use conditions to wait for particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
15
|
+
You can use conditions to wait for a particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
18
|
await serverlessSpyListener.waitForSnsTopicMyTopic<TestData>({
|
package/doc/SQS.md
CHANGED
|
@@ -6,7 +6,7 @@ Basic example:
|
|
|
6
6
|
await serverlessSpyListener.waitForSqsMyQueue();
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
You can use conditions to wait for particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
9
|
+
You can use conditions to wait for a particular event. You can also use generic (`TestData`) to strongly type the event.
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
await serverlessSpyListener.waitForSqsMyQueue<TestData>({
|
|
@@ -14,7 +14,7 @@ await serverlessSpyListener.waitForSqsMyQueue<TestData>({
|
|
|
14
14
|
});
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Interception of SQS events intercepts events when Lambda consumes them. **⚠️If no Lambda is subscribed to SQS, the ServerlessSpy can not intercept events.** If you still want to catch them enable `spySqsWithNoSubscriptionAndDropAllMessages` when [creating ServerlessSpy in CDK](./CDK_construct.md). With this flag on, an additional Lambda will be created that will consume messages and throw them away (= lost forever ⛔). Of course, that is undesirable in most cases, but it could be useful for some tests.
|
|
18
18
|
|
|
19
19
|
Check [this](https://github.com/ServerlessLife/serverless-spy/blob/main/test/cdk/test/sqs.test.ts){:target="_blank"} and
|
|
20
20
|
[this](https://github.com/ServerlessLife/serverless-spy/blob/main/test/cdk/test/lambdaToSqs.test.ts){:target="_blank"} test.
|
package/doc/quick_start.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Quick Start
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- Development environment: so you can write tests.
|
|
5
|
-
- Automatic test environment: You execute written tests
|
|
3
|
+
ServerlessSpy is meant for the following environments:
|
|
4
|
+
- Development environment: so you can write tests. The web console helps you gain insight into what is happening in the system.
|
|
5
|
+
- Automatic test environment: You execute written tests in CI/CD.
|
|
6
6
|
|
|
7
7
|
## Step 1: Install
|
|
8
8
|
```bash
|
|
@@ -16,16 +16,16 @@ const serverlessSpy = new ServerlessSpy(this, 'ServerlessSpy', {
|
|
|
16
16
|
});
|
|
17
17
|
serverlessSpy.spy();
|
|
18
18
|
```
|
|
19
|
-
[more](CDK_construct.md)
|
|
19
|
+
[more](./CDK_construct.md)
|
|
20
20
|
|
|
21
21
|
## Step 3: Deploy CDK stack with exporting CloudFormation outputs
|
|
22
22
|
```bash
|
|
23
23
|
cdk deploy --outputs-file cdkOutput.json
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
The key part of the output is `ServerlessSpyWsUrl`, which is the URL to the
|
|
26
|
+
The key part of the output is `ServerlessSpyWsUrl`, which is the URL to the WebSocket where the testing library and web console receive events. Exclude the `cdkOutput.json` file from `git` (like you always do), especially if it has secrets.
|
|
27
27
|
|
|
28
|
-
Apart from CF output, the ServerlessSpy generates the TypeScript file `serverlessSpyEvents/ServerlessSpyEvents.ts` specified in the first step. This makes your
|
|
28
|
+
Apart from CF output, the ServerlessSpy generates the TypeScript file `serverlessSpyEvents/ServerlessSpyEvents.ts` specified in the first step. This makes your tests strongly typed 💪 thanks to TypeScript.
|
|
29
29
|
|
|
30
30
|
## Step 4: Write tests 🔨
|
|
31
31
|
Initialize the `ServerlessSpyListener`
|
|
@@ -53,10 +53,10 @@ afterEach(async () => {
|
|
|
53
53
|
serverlessSpyListener.stop();
|
|
54
54
|
});
|
|
55
55
|
```
|
|
56
|
-
[more](writing_tests.md)
|
|
56
|
+
[more](./writing_tests.md)
|
|
57
57
|
|
|
58
58
|
## Step 5: Start local web console to gain more insights 🕵
|
|
59
59
|
```bash
|
|
60
60
|
npx sspy --cdkoutput cdkOutput.json
|
|
61
61
|
```
|
|
62
|
-
[more](web_console.md)
|
|
62
|
+
[more](./web_console.md)
|
package/doc/web_console.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Web console
|
|
2
2
|
|
|
3
|
-
The web console runs on your local computer and displays all events that ServerlessSpy intercepts in the environment. That is useful when developing to investigate what is happening in the system. The web console receives events via
|
|
3
|
+
The web console runs on your local computer and displays all events that ServerlessSpy intercepts in the environment. That is useful when developing to investigate what is happening in the system. The web console receives events via WebSocket and displays them in the table with a timestamp, event name, and data. You can filter events by event name and data. You can use regular expressions.
|
|
4
4
|
|
|
5
|
-
If events are hierarchical like Lambda request & response, you can see an arrow from a parent to child event.
|
|
5
|
+
If events are hierarchical, like Lambda request & response, you can see an arrow from a parent to child event.
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -17,9 +17,9 @@ The browser window will open [http://localhost:3456/](http://localhost:3456/).
|
|
|
17
17
|
## Parameters:
|
|
18
18
|
`--ws <ws>` - Websocket link (optional)
|
|
19
19
|
|
|
20
|
-
`--cdkoutput <cdkoutput>` - CDK output file that contains Websocket link in a property ServerlessSpyWsUrl (optional)
|
|
20
|
+
`--cdkoutput <cdkoutput>` - CDK output file that contains Websocket link in a property `ServerlessSpyWsUrl` (optional)
|
|
21
21
|
|
|
22
|
-
`--cdkstack <cdkstack>` - CDK stack in
|
|
22
|
+
`--cdkstack <cdkstack>` - CDK stack in CDK output file. If not specified, the first one is picked (optional)
|
|
23
23
|
|
|
24
24
|
`--open <open>` - Open browser (optional, default: true)
|
|
25
25
|
|
package/doc/writing_tests.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Creating `ServerlessSpyListener`
|
|
4
4
|
|
|
5
|
-
### Include the
|
|
5
|
+
### Include the TypeScript file that was generated when deploying
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
8
|
import { ServerlessSpyEvents } from '../serverlessSpyEvents/ServerlessSpyEvents';
|
|
@@ -47,11 +47,11 @@ or
|
|
|
47
47
|
await serverlessSpyListener.waitForXXX()
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
`WaitFor` methods are generated with TypeScript. You should name your resources in CDK
|
|
50
|
+
`WaitFor` methods are generated with TypeScript. You should name your resources in CDK in a way that these methods are easy to read.
|
|
51
51
|
|
|
52
52
|
Please note that there is no order enforced on events. The same event can match with multiple `WaitFor` calls. When `WaitFor` is called, it checks for a matching event in the bucket of all received events since initializing `ServerlessSpyListener`. The matching event will not be removed. If the event is not found, it starts to wait for one. So if you write `await serverlessSpyListener.waitForXXX<TestData>()` twice, because you expect events to occur twice, it will not work. The first event will satisfy both `WaitFor` calls.
|
|
53
53
|
|
|
54
|
-
`TestData` is an optional generic argument that makes
|
|
54
|
+
`TestData` is an optional generic argument that makes all parameters strongly typed. If that is useful, decide based on your use case.
|
|
55
55
|
|
|
56
56
|
## Filtering the events
|
|
57
57
|
|
|
@@ -63,7 +63,7 @@ await serverlessSpyListener.waitForSnsTopicMyTopic<TestData>({
|
|
|
63
63
|
```
|
|
64
64
|
This way, you can run tests in parallel and handle cases when a similar event occurs multiple times as part of the same test.
|
|
65
65
|
|
|
66
|
-
**💡Recommendation: Try not to use
|
|
66
|
+
**💡Recommendation: Try not to use conditions for validating the event. Just find the event with the help of conditions and then validate it with Jest. Tests are easier to debug this way because the error shows which part of the data does not match. But if you like using just conditions, so tests are easy to read, go ahead.**
|
|
67
67
|
|
|
68
68
|
## Extracting the event data with `getData()`
|
|
69
69
|
```typescript
|
|
@@ -112,4 +112,5 @@ Tests for the same Lambda request can be chained together:
|
|
|
112
112
|
},
|
|
113
113
|
```
|
|
114
114
|
That is useful when you expect a Lambda request that will produce some data. You can also validate intermediate steps of processing with console log events.
|
|
115
|
+
|
|
115
116
|
[more on spying on Lambda](Lambda.md)
|
package/lib/src/ServerlessSpy.js
CHANGED
|
@@ -537,5 +537,5 @@ class ServerlessSpy extends constructs_1.Construct {
|
|
|
537
537
|
}
|
|
538
538
|
exports.ServerlessSpy = ServerlessSpy;
|
|
539
539
|
_a = JSII_RTTI_SYMBOL_1;
|
|
540
|
-
ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "0.0.
|
|
540
|
+
ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "0.0.56" };
|
|
541
541
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVybGVzc1NweS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2ZXJsZXNzU3B5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwyREFBMkQ7QUFDM0QsMkVBQTJFO0FBQzNFLDZDQUF5RDtBQUV6RCxxREFBcUQ7QUFDckQsaURBQWlEO0FBQ2pELDBEQUEwRDtBQUMxRCxpREFBaUQ7QUFDakQsdUVBQXVFO0FBQ3ZFLG1GQUFzRTtBQUN0RSw0REFBNEQ7QUFDNUQscUVBQStEO0FBQy9ELHlDQUF5QztBQUN6Qyw0REFBNEQ7QUFDNUQsMkNBQTJDO0FBQzNDLDZEQUE2RDtBQUM3RCwyQ0FBMkM7QUFDM0MsMkNBQW1EO0FBQ25ELGdFQUE2RDtBQW1CN0QsTUFBYSxhQUFjLFNBQVEsc0JBQVM7SUFhMUMsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ0YsS0FBMEI7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUZULFVBQUssR0FBTCxLQUFLLENBQXFCO1FBWjVCLDJCQUFzQixHQUFpQixFQUFFLENBQUM7UUFDMUMsMkJBQXNCLEdBQXlCLEVBQUUsQ0FBQztRQUVsRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFFbEMsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDMUIsZUFBVSxHQUFpQixFQUFFLENBQUM7UUFVcEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUMvRCxrQkFBa0IsRUFBRTtnQkFDbEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO2dCQUMxQixNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7Z0JBQzFCLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVzthQUMzQjtZQUNELElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztTQUM5RCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV0RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFO1lBQ2pELFlBQVksRUFBRTtnQkFDWixJQUFJLEVBQUUsY0FBYztnQkFDcEIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUMsTUFBTTthQUNwQztZQUNELFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLGVBQWU7U0FDbEQsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFN0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLG9DQUFvQyxFQUFFLENBQUM7UUFFNUQsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRTtZQUN6QixPQUFPLENBQUMsbUNBQWdCLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxDQUFDO1NBQy9DO1FBRUQsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLFVBQVUsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUN6RSxVQUFVLEVBQUUsR0FBRztZQUNmLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDNUIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxPQUFPLEVBQUUsU0FBUztZQUNsQixLQUFLLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLHdCQUF3QixDQUFDO1lBQ3RELFdBQVcsRUFBRSxPQUFPO1NBQ3JCLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRXBELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxVQUFVLENBQUMsY0FBYyxDQUN4RCxJQUFJLEVBQ0osY0FBYyxFQUNkO1lBQ0UsVUFBVSxFQUFFLEdBQUc7WUFDZixPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQzVCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDbkMsT0FBTyxFQUFFLFNBQVM7WUFDbEIsS0FBSyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQywyQkFBMkIsQ0FBQztZQUN6RCxXQUFXLEVBQUUsT0FBTztTQUNyQixDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUV2RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FDOUMsSUFBSSxFQUNKLHFCQUFxQixFQUNyQjtZQUNFLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQixTQUFTLEVBQUUsTUFBTTtZQUNqQixVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN0RCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRTtZQUMvRCxXQUFXLEVBQUUsSUFBSSxVQUFVLENBQUMsMEJBQTBCLENBQ3BELFVBQVUsRUFDVixpQkFBaUIsQ0FDbEI7U0FDRixDQUFDLENBQUM7UUFDRixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsWUFBNkIsQ0FBQyxpQkFBaUI7WUFDckUsU0FBUyxDQUFDO1FBRVosSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFO1lBQ3hDLFdBQVcsRUFBRSxJQUFJLFVBQVUsQ0FBQywwQkFBMEIsQ0FDcEQsYUFBYSxFQUNiLG9CQUFvQixDQUNyQjtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUMsOEJBQThCLEVBQUUsQ0FBQztRQUVwRSxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUU7WUFDeEMsV0FBVyxFQUFFLElBQUksVUFBVSxDQUFDLDBCQUEwQixDQUNwRCxhQUFhLEVBQ2IsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFFBQVEsQ0FDckM7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLGdCQUMzQyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUNqQixrQkFBa0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUVsRCxJQUFJLHVCQUFTLENBQUMsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsb0JBQW9CLEVBQUU7WUFDbEQsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1NBQ2xCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxvQ0FBb0M7UUFDMUMsT0FBTztZQUNMLENBQUMsbUNBQWdCLENBQUMsa0JBQWtCLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVM7WUFDM0QsWUFBWSxFQUFFLHNCQUFzQjtTQUNyQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNJLFFBQVEsQ0FBQyxLQUFtQjtRQUNqQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRTtZQUN4QixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMzQjtRQUVELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksR0FBRyxDQUFDLE1BQWtCO1FBQzNCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUU3QyxNQUFNLGtCQUFrQixHQUF3QjtZQUM5QyxTQUFTLEVBQUUsSUFBSTtZQUNmLE1BQU0sRUFBRSxJQUFJO1lBQ1osV0FBVyxFQUFFLElBQUk7WUFDakIsaUJBQWlCLEVBQUUsSUFBSTtZQUN2QixjQUFjLEVBQUUsSUFBSTtZQUNwQixrQkFBa0IsRUFBRSxJQUFJO1lBQ3hCLEtBQUssRUFBRSxJQUFJO1lBQ1gsV0FBVyxFQUFFLElBQUk7WUFDakIsR0FBRyxNQUFNO1NBQ1YsQ0FBQztRQUVGLEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDNUIsSUFBSSxrQkFBa0IsQ0FBQyxTQUFTLElBQUksSUFBSSxZQUFZLE1BQU0sQ0FBQyxRQUFRLEVBQUU7Z0JBQ25FLE9BQU8sSUFBSSxDQUFDO2FBQ2I7aUJBQU0sSUFBSSxrQkFBa0IsQ0FBQyxXQUFXLElBQUksSUFBSSxZQUFZLEdBQUcsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3RFLE9BQU8sSUFBSSxDQUFDO2FBQ2I7aUJBQU0sSUFDTCxrQkFBa0IsQ0FBQyxpQkFBaUI7Z0JBQ3BDLElBQUksWUFBWSxHQUFHLENBQUMsWUFBWSxFQUNoQztnQkFDQSxPQUFPLElBQUksQ0FBQzthQUNiO2lCQUFNLElBQUksa0JBQWtCLENBQUMsS0FBSyxJQUFJLElBQUksWUFBWSxFQUFFLENBQUMsTUFBTSxFQUFFO2dCQUNoRSxPQUFPLElBQUksQ0FBQzthQUNiO2lCQUFNLElBQ0wsa0JBQWtCLENBQUMsV0FBVztnQkFDOUIsSUFBSSxZQUFZLFFBQVEsQ0FBQyxLQUFLLEVBQzlCO2dCQUNBLE9BQU8sSUFBSSxDQUFDO2FBQ2I7aUJBQU0sSUFDTCxrQkFBa0IsQ0FBQyxjQUFjO2dCQUNqQyxJQUFJLFlBQVksTUFBTSxDQUFDLFFBQVEsRUFDL0I7Z0JBQ0EsT0FBTyxJQUFJLENBQUM7YUFDYjtpQkFBTSxJQUNMLGtCQUFrQixDQUFDLGtCQUFrQjtnQkFDckMsSUFBSSxZQUFZLE1BQU0sQ0FBQyxJQUFJLEVBQzNCO2dCQUNBLE9BQU8sSUFBSSxDQUFDO2FBQ2I7aUJBQU0sSUFDTCxrQkFBa0IsQ0FBQyxNQUFNO2dCQUN6QixJQUFJLFlBQVksTUFBTSxDQUFDLHFCQUFxQixFQUM1QztnQkFDQSxPQUFPLElBQUksQ0FBQzthQUNiO2lCQUFNLElBQ0wsa0JBQWtCLENBQUMsTUFBTTtnQkFDekIsSUFBSSxDQUFDLEtBQUssRUFBRSwwQ0FBMEM7Z0JBQ3RELElBQUksWUFBWSxHQUFHLENBQUMsS0FBSyxFQUN6QjtnQkFDQSxPQUFPLElBQUksQ0FBQzthQUNiO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVPLGdCQUFnQixDQUFDLEtBQW1CO1FBQzFDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFO1lBQ3hCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDNUI7SUFDSCxDQUFDO0lBRU8sWUFBWTtRQUNsQixtREFBbUQ7UUFDbkQsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsc0JBQXNCLEVBQUU7WUFDOUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQzFCLG1DQUFnQixDQUFDLGtCQUFrQixFQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FDN0IsQ0FBQztTQUNIO1FBRUQsa0RBQWtEO1FBQ2xELEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNwQyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FDMUIsbUNBQWdCLENBQUMsa0JBQWtCLEVBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUM3QixDQUFDO1NBQ0g7UUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsNkJBQTZCLEVBQUU7WUFDN0MsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsNkJBQTZCLENBQUMsQ0FBQztTQUNyRTtJQUNILENBQUM7SUFFTyx5QkFBeUI7UUFDL0IsSUFBSSxzQkFBc0IsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUNwQyxTQUFTLEVBQ1QseUJBQXlCLENBQzFCLENBQUM7UUFFRixNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxJQUFJLENBQ3pDLFNBQVMsRUFDVCw2QkFBNkIsQ0FDOUIsQ0FBQztRQUVGLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMseUJBQXlCLENBQUMsRUFBRTtnQkFDN0MsTUFBTSxJQUFJLEtBQUssQ0FDYix1REFBdUQsc0JBQXNCLFVBQVUseUJBQXlCLEdBQUcsQ0FDcEgsQ0FBQzthQUNIO2lCQUFNO2dCQUNMLHNCQUFzQixHQUFHLHlCQUF5QixDQUFDO2FBQ3BEO1NBQ0Y7UUFFRCxNQUFNLDRCQUE0QixHQUFHLElBQUksQ0FBQyxJQUFJLENBQzVDLHNCQUFzQixFQUN0QixhQUFhLENBQ2QsQ0FBQztRQUNGLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLDRCQUE0QixDQUFDLEVBQUU7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FDYiwrQ0FBK0Msc0JBQXNCLEVBQUUsQ0FDeEUsQ0FBQztTQUNIO1FBRUQsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUMxQyxzQkFBc0IsRUFDdEIsb0NBQW9DLENBQ3JDLENBQUM7UUFDRixJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFO1lBQzlDLE1BQU0sSUFBSSxLQUFLLENBQ2Isc0NBQXNDLDBCQUEwQixFQUFFLENBQ25FLENBQUM7U0FDSDtRQUNELE9BQU8sc0JBQXNCLENBQUM7SUFDaEMsQ0FBQztJQUVEOzs7T0FHRztJQUNLLG1CQUFtQixDQUFDLFlBQW9CO1FBQzlDLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRTlELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXO2FBQ2hDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUM7YUFDOUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRVosTUFBTSxJQUFJLEdBQUcsNkRBQTZELFVBQVUsS0FBSyxDQUFDO1FBRTFGLEVBQUUsQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFTyxXQUFXLENBQUMsTUFBa0I7UUFDcEMsTUFBTSxLQUFLLEdBQWlCLEVBQUUsQ0FBQztRQUMvQixLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDekMsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sb0JBQW9CLENBQUMsTUFBa0IsRUFBRSxLQUFtQjtRQUNsRSxLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ3ZDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakIsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN4QztJQUNILENBQUM7SUFFTyxlQUFlLENBQUMsSUFBZ0I7UUFDdEMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNsQyxPQUFPO1NBQ1I7UUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUzQixJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDOUMsT0FBTztTQUNSO1FBRUQsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxFQUFFO1lBQ2hFLE9BQU87U0FDUjtRQUVELElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUU7WUFDekIsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDMUQ7UUFFRCxJQUFJLElBQUksWUFBWSxNQUFNLENBQUMsUUFBUSxFQUFFO1lBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM5QjthQUFNLElBQUksSUFBSSxZQUFZLEdBQUcsQ0FBQyxLQUFLLEVBQUU7WUFDcEMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2hDO2FBQU0sSUFBSSxJQUFJLFlBQVksR0FBRyxDQUFDLFlBQVksRUFBRTtZQUMzQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkM7YUFBTSxJQUFJLElBQUksWUFBWSxFQUFFLENBQUMsTUFBTSxFQUFFO1lBQ3BDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDMUI7YUFBTSxJQUFJLElBQUksWUFBWSxRQUFRLENBQUMsS0FBSyxFQUFFO1lBQ3pDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUNoQzthQUFNLElBQUksSUFBSSxZQUFZLE1BQU0sQ0FBQyxRQUFRLEVBQUU7WUFDMUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2hDO2FBQU0sSUFBSSxJQUFJLFlBQVksTUFBTSxDQUFDLElBQUksRUFBRTtZQUN0QyxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDcEM7YUFBTSxJQUFJLElBQUksWUFBWSxNQUFNLENBQUMscUJBQXFCLEVBQUU7WUFDdkQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMzQjthQUFNLElBQUksSUFBSSxZQUFZLEdBQUcsQ0FBQyxLQUFLLEVBQUU7WUFDcEMsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLDBDQUEwQyxFQUFFO2dCQUMxRCxJQUFJLENBQUMsbUNBQW1DLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDaEQ7U0FDRjtJQUNILENBQUM7SUFFTyxtQ0FBbUMsQ0FBQyxLQUFnQjtRQUMxRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUNuQyxDQUFDLENBQWEsRUFBRSxFQUFFLENBQ2hCLENBQUMsWUFBWSxNQUFNLENBQUMscUJBQXFCO1lBQ3hDLENBQWtDLENBQUMsY0FBYyxLQUFLLEtBQUssQ0FBQyxRQUFRLENBQ3hFLENBQUM7UUFFRixJQUFJLFlBQVksRUFBRTtZQUNoQixPQUFPLENBQUMsMkJBQTJCO1NBQ3BDO1FBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxHQUFHLElBQUksa0NBQWMsQ0FDN0IsSUFBSSxFQUNKLEdBQUcsU0FBUyxtQ0FBbUMsRUFDL0M7WUFDRSxVQUFVLEVBQUUsR0FBRztZQUNmLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDNUIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxPQUFPLEVBQUUsU0FBUztZQUNsQixLQUFLLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUMxQixnREFBZ0QsQ0FDakQ7WUFDRCxXQUFXLEVBQUUsSUFBSSxDQUFDLG9DQUFvQyxFQUFFO1NBQ3pELENBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSx5Q0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFL0MsRUFBRTtRQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRXBDLG1EQUFtRDtRQUVuRCx5RUFBeUU7UUFDekUsSUFBSSxDQUFDLGNBQWMsQ0FBQyx5QkFBeUIsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxjQUFjLENBQ2pCLG1DQUFnQixDQUFDLGdCQUFnQixFQUNqQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQ3JCLENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFO1lBQ3pCLElBQUksQ0FBQyxjQUFjLENBQUMsbUNBQWdCLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzFEO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQyxFQUFFO1FBRUYsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUV2QyxNQUFNLFVBQVUsR0FBRyxPQUFPLFNBQVMsRUFBRSxDQUFDO1FBRXRDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUU7WUFDOUIsR0FBRyxFQUFFLEtBQUssQ0FBQyxRQUFRO1lBQ25CLEtBQUssRUFBRSxVQUFVO1NBQ2xCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxjQUFjLENBQUMsbUNBQWdCLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUVPLGNBQWMsQ0FBQyxJQUFrQztRQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUM1QixDQUFDLENBQWEsRUFBRSxFQUFFLENBQ2hCLENBQUMsWUFBWSxHQUFHLENBQUMsS0FBSztZQUNyQixDQUFlLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxjQUFjLENBQ3BELENBQUM7UUFFRixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUMzQixDQUFDLENBQWEsRUFBRSxFQUFFLENBQ2hCLENBQUMsWUFBWSxNQUFNLENBQUMsUUFBUTtZQUMzQixDQUFxQixDQUFDLFlBQVksS0FBSyxJQUFJLENBQUMsWUFBWSxDQUM1RCxDQUFDO1FBRUYsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQ2pCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUUvQyxNQUFNLFVBQVUsR0FBRyxPQUFPLFNBQVMsRUFBRSxDQUFDO1lBRXRDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUU7Z0JBQzlCLEdBQUcsRUFBRSxLQUFLLENBQUMsUUFBUTtnQkFDbkIsS0FBSyxFQUFFLFVBQVU7YUFDbEIsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxtQ0FBZ0IsQ0FBQyxzQkFBc0IsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUN0RTtJQUNILENBQUM7SUFFTyw2QkFBNkIsQ0FBQyxLQUFhO1FBQ2pELE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsZUFBZSxLQUFLLEVBQUUsRUFBRTtZQUN2RSxVQUFVLEVBQUUsR0FBRztZQUNmLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDNUIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxPQUFPLEVBQUUsU0FBUztZQUNsQixLQUFLLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLDBCQUEwQixDQUFDO1lBQ3hELFdBQVcsRUFBRTtnQkFDWCxDQUFDLG1DQUFnQixDQUFDLGtCQUFrQixDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTO2dCQUMzRCxZQUFZLEVBQUUsc0JBQXNCO2FBQ3JDO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLGNBQWMsQ0FDakIsbUNBQWdCLENBQUMsZ0JBQWdCLEVBQ2pDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FDckIsQ0FBQztRQUVGLElBQUksQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0MsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sYUFBYTtRQUNuQixPQUFPLFdBQVcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLGdCQUN2QyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUNqQixrQkFBa0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNwRCxDQUFDO0lBRU8sYUFBYSxDQUFDLFFBQW1CO1FBQ3ZDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FDM0IsRUFBRSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFDL0IsSUFBSSxPQUFPLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxDQUNwRSxDQUFDO1FBRUYsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTdDLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsVUFBVSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxLQUFxQjtRQUMvQyxzQ0FBc0M7UUFDckMsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFrQyxDQUFDLG1CQUFtQixHQUFHO1lBQ25FLGNBQWMsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLGtCQUFrQjtTQUMzRCxDQUFDO1FBQ0QsS0FBYSxDQUFDLGNBQWMsR0FDM0IsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUNaLENBQUMsYUFBYSxDQUFDO1FBRWhCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUNqRCxJQUFJLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUU7WUFDMUMsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU07WUFDaEQsU0FBUyxFQUFFLENBQUM7WUFDWixhQUFhLEVBQUUsQ0FBQztTQUNqQixDQUFDLENBQ0gsQ0FBQztRQUVGLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUxQyxNQUFNLFVBQVUsR0FBRyxZQUFZLElBQUksRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLFVBQVUsQ0FBQztRQUNqRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRU8sdUJBQXVCLENBQUMsSUFBaUI7UUFDL0MsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBOEIsQ0FBQztRQUNsRSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQW9CLENBQUMsWUFBWSxDQUM3QyxDQUFDO1FBRUYsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxZQUFZLEdBQUcsQ0FBQyxDQUFDO1NBQ3pFO1FBRUQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsOEJBQThCLENBQzlELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FDN0IsQ0FBQztRQUNGLG9CQUFvQixDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztRQUUvQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBRTFFLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0MsTUFBTSxVQUFVLEdBQUcsbUJBQW1CLFVBQVUsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUMvRCxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQztRQUN0RCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRU8sbUJBQW1CLENBQUMsUUFBeUI7UUFDbkQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsOEJBQThCLENBQzlELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FDN0IsQ0FBQztRQUNGLG9CQUFvQixDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztRQUUvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkQsTUFBTSxJQUFJLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLFVBQVUsRUFBRSxFQUFFO1lBQ3pELFFBQVE7WUFDUixZQUFZLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUNoQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDckUsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxNQUFNLFVBQVUsR0FBRyxlQUFlLFVBQVUsRUFBRSxDQUFDO1FBQy9DLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDO1FBQ3RELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxLQUFnQjtRQUMxQyxNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyw4QkFBOEIsQ0FDOUQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQzFDLENBQUM7UUFFRixNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsZUFBZSxDQUN4QyxJQUFJLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FDOUQsQ0FBQztRQUNGLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0MsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9DLE1BQU0sVUFBVSxHQUFHLFlBQVksU0FBUyxFQUFFLENBQUM7UUFDM0Msb0JBQW9CLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxVQUFVLENBQUM7UUFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEMsb0JBQW9CLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBRU8sMEJBQTBCLENBQUMsWUFBOEI7UUFDL0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQzVCLE9BQU87U0FDUjtRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBb0MsQ0FBQyxRQUFRLENBQ2pFLENBQUM7UUFFRixJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1NBQ3ZDO1FBRUQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsOEJBQThCLENBQzlELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUMxQyxDQUFDO1FBRUYsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLFlBQVksQ0FBQyxJQUFJO2FBQ3ZDLFlBQW1DLENBQUM7UUFFdkMsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUM3QyxJQUFJLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FDOUQsQ0FBQztRQUNELGlCQUFpQixDQUFDLElBQUksQ0FBQyxZQUFvQyxDQUFDLFlBQVk7WUFDdkUsWUFBWSxDQUFDO1FBRWYsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRXBELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVsRSxvQkFBb0IsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELE1BQU0sVUFBVSxHQUFHLG1CQUFtQixTQUFTLElBQUksVUFBVSxFQUFFLENBQUM7UUFDaEUsb0JBQW9CLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxVQUFVLENBQUM7UUFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVPLDhCQUE4QixDQUNwQyxjQUE4RDtRQUU5RCxJQUFJLG9CQUFvRCxDQUFDO1FBRXpELElBQUksY0FBYyxFQUFFO1lBQ2xCLG9CQUFvQixHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDekU7YUFBTSxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ2pELG9CQUFvQixHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN2RDtRQUVELElBQUksQ0FBQyxvQkFBb0IsRUFBRTtZQUN6QixvQkFBb0IsR0FBRztnQkFDckIsZUFBZSxFQUFFLEVBQUU7Z0JBQ25CLGtCQUFrQixFQUFFLEtBQUs7Z0JBQ3pCLE9BQU8sRUFBRSxFQUFFO2dCQUNYLFFBQVEsRUFBRSxJQUFJLENBQUMsNkJBQTZCLENBQzFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQ25DO2FBQ0YsQ0FBQztZQUNGLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztTQUN4RDtRQUNELE9BQU8sb0JBQW9CLENBQUM7SUFDOUIsQ0FBQztJQUVPLGlCQUFpQixDQUFDLElBQXFCO1FBQzdDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRXBDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVqRCxJQUFJLENBQUMsY0FBYyxDQUFDLG1DQUFnQixDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxjQUFjLENBQUMseUJBQXlCLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUNuRSxJQUFJLENBQUMsY0FBYyxDQUNqQixtQ0FBZ0IsQ0FBQyxrQkFBa0IsRUFDbkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQ3JCLENBQUM7UUFDRixJQUFJLENBQUMsY0FBYyxDQUNqQixtQ0FBZ0IsQ0FBQyxnQkFBZ0IsRUFDakMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUNyQixDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRTtZQUN6QixJQUFJLENBQUMsY0FBYyxDQUFDLG1DQUFnQixDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUMxRDtRQUVELElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxZQUFZLFVBQVUsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksWUFBWSxRQUFRLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLFlBQVksVUFBVSxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxZQUFZLFdBQVcsQ0FBQyxDQUFDO1FBRTNELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRU0sZ0JBQWdCLENBQUMsU0FBcUI7UUFDM0MsSUFBSSxZQUFZLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDdkMsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJDLElBQUksWUFBWSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN0QyxZQUFZLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1NBQzdEO1FBQ0QsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVPLFFBQVEsQ0FBQyxRQUFnQjtRQUMvQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUM1QixDQUFDLElBQWdCLEVBQUUsRUFBRSxDQUNuQixJQUFJLFlBQVksR0FBRyxDQUFDLEtBQUssSUFBSyxJQUFrQixDQUFDLFFBQVEsS0FBSyxRQUFRLENBQ3pFLENBQUM7UUFFRixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFTyxjQUFjLENBQUMsWUFBb0I7UUFDekMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FDbEMsQ0FBQyxJQUFnQixFQUFFLEVBQUUsQ0FDbkIsSUFBSSxZQUFZLE1BQU0sQ0FBQyxRQUFRO1lBQzlCLElBQXdCLENBQUMsWUFBWSxLQUFLLFlBQVksQ0FDMUQsQ0FBQztRQUVGLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFTyxXQUFXLENBQ2pCLFVBQXlDLEVBQ3pDLE1BQW1CO1FBRW5CLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDWCxNQUFNLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDekI7UUFFRCxLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ3ZDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNwQixPQUFPLElBQVMsQ0FBQzthQUNsQjtZQUNELElBQUksQ0FBQyxXQUFXLENBQUksVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVPLG9CQUFvQixDQUMxQixJQUFxQixFQUNyQixRQUF5QztRQUV6QyxLQUFLLE1BQU0sRUFBRSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbEMsSUFBSSxFQUFFLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRTtnQkFDeEIsSUFBSSxRQUFRLEVBQUU7b0JBQ1osRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztpQkFDM0M7Z0JBQ0QsT0FBTzthQUNSO1NBQ0Y7UUFFRCxNQUFNLEVBQUUsR0FBZ0I7WUFDdEIsUUFBUSxFQUFFLElBQUk7WUFDZCxPQUFPLEVBQUUsRUFBRTtTQUNaLENBQUM7UUFFRixJQUFJLFFBQVEsRUFBRTtZQUNaLEVBQUUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUM7U0FDM0M7UUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsUUFBZ0I7UUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBRW5ELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUN0QixPQUFPLEdBQUcsQ0FBQztTQUNaO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBRXZELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN2QixPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLEdBQUcsUUFBUSxJQUFJLG1CQUFtQixDQUFDLENBQUM7SUFDbEUsQ0FBQzs7QUF0dUJILHNDQXV1QkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgYXBpR3dWMiBmcm9tICdAYXdzLWNkay9hd3MtYXBpZ2F0ZXdheXYyLWFscGhhJztcbmltcG9ydCAqIGFzIGFwaUd3VjJJbnQgZnJvbSAnQGF3cy1jZGsvYXdzLWFwaWdhdGV3YXl2Mi1pbnRlZ3JhdGlvbnMtYWxwaGEnO1xuaW1wb3J0IHsgQ2ZuT3V0cHV0LCBEdXJhdGlvbiwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBhZ3cgZnJvbSAnYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXl2Mic7XG5pbXBvcnQgKiBhcyBkeW5hbW9EYiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0ICogYXMgZXZlbnRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMnO1xuaW1wb3J0ICogYXMgdGFyZ2V0cyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzLXRhcmdldHMnO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgZHluYW1vRGJTdHJlYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ldmVudC1zb3VyY2VzJztcbmltcG9ydCB7IFNxc0V2ZW50U291cmNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ldmVudC1zb3VyY2VzJztcbmltcG9ydCAqIGFzIGxhbWJkYU5vZGUgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0IHsgTm9kZWpzRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLW5vZGVqcyc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgczNub3RpZiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMtbm90aWZpY2F0aW9ucyc7XG5pbXBvcnQgKiBhcyBzbnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNucyc7XG5pbXBvcnQgKiBhcyBzbnNTdWJzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zbnMtc3Vic2NyaXB0aW9ucyc7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNxcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGVudlZhcmlhYmxlTmFtZXMgfSBmcm9tICcuL2NvbW1vbi9lbnZWYXJpYWJsZU5hbWVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJsZXNzU3B5UHJvcHMge1xuICByZWFkb25seSBnZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgc3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZGVidWdNb2RlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcHlGaWx0ZXIge1xuICByZWFkb25seSBzcHlMYW1iZGE/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTcXM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTbnNUb3BpYz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweVNuc1N1YnNyaXB0aW9uPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5RXZlbnRCcmlkZ2U/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlFdmVudEJyaWRnZVJ1bGU/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTMz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweUR5bmFtb0RCPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIFNlcnZlcmxlc3NTcHkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwcml2YXRlIGV4dGVuc2lvbkxheWVyOiBsYW1iZGEuTGF5ZXJWZXJzaW9uO1xuICBwcml2YXRlIHRhYmxlOiBkeW5hbW9EYi5UYWJsZTtcbiAgcHJpdmF0ZSB3ZWJTb2NrZXRBcGk6IGFwaUd3VjIuV2ViU29ja2V0QXBpO1xuICBwcml2YXRlIGNyZWF0ZWRSZXNvdXJjZXNCeVNTcHk6IElDb25zdHJ1Y3RbXSA9IFtdO1xuICBwcml2YXRlIGxhbWJkYVN1YnNjcmlwdGlvblBvb2w6IExhbWJkYVN1YnNjcmlwdGlvbltdID0gW107XG4gIHByaXZhdGUgbGFtYmRhU3Vic2NyaXB0aW9uTWFpbjogTGFtYmRhU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIGxhbWJkYXNTcGllZDogTGFtYmRhU3BpZWRbXSA9IFtdO1xuICBwcml2YXRlIHdlYlNvY2tldFN0YWdlOiBhcGlHd1YyLldlYlNvY2tldFN0YWdlO1xuICBwdWJsaWMgc2VydmljZUtleXM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgc3BpZWROb2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gIHdzVXJsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByaXZhdGUgcHJvcHM/OiBTZXJ2ZXJsZXNzU3B5UHJvcHNcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuZXh0ZW5zaW9uTGF5ZXIgPSBuZXcgbGFtYmRhLkxheWVyVmVyc2lvbih0aGlzLCAnRXh0ZW5zaW9uJywge1xuICAgICAgY29tcGF0aWJsZVJ1bnRpbWVzOiBbXG4gICAgICAgIGxhbWJkYS5SdW50aW1lLk5PREVKU18xMl9YLFxuICAgICAgICBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTRfWCxcbiAgICAgICAgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE2X1gsXG4gICAgICBdLFxuICAgICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KHRoaXMuZ2V0RXh0ZW5zaW9uQXNzZXRMb2NhdGlvbigpKSxcbiAgICB9KTtcbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaCh0aGlzLmV4dGVuc2lvbkxheWVyKTtcblxuICAgIHRoaXMudGFibGUgPSBuZXcgZHluYW1vRGIuVGFibGUodGhpcywgJ1dlYlNvY2tldCcsIHtcbiAgICAgIHBhcnRpdGlvbktleToge1xuICAgICAgICBuYW1lOiAnY29ubmVjdGlvbklkJyxcbiAgICAgICAgdHlwZTogZHluYW1vRGIuQXR0cmlidXRlVHlwZS5TVFJJTkcsXG4gICAgICB9LFxuICAgICAgYmlsbGluZ01vZGU6IGR5bmFtb0RiLkJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCxcbiAgICB9KTtcbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaCh0aGlzLnRhYmxlKTtcblxuICAgIGNvbnN0IGVudlZhcnMgPSB0aGlzLmdldERhZmF1bHRMYW1iZGFFbnZpcm9ubWVudFZhcmlhYmxlcygpO1xuXG4gICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgZW52VmFyc1tlbnZWYXJpYWJsZU5hbWVzLlNTUFlfREVCVUddID0gJ3RydWUnO1xuICAgIH1cblxuICAgIGNvbnN0IGZ1bmN0aW9uT25Db25uZWN0ID0gbmV3IGxhbWJkYU5vZGUuTm9kZWpzRnVuY3Rpb24odGhpcywgJ09uQ29ubmVjdCcsIHtcbiAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoNSksXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTZfWCxcbiAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgIGVudHJ5OiB0aGlzLmdldEFzc2V0TG9jYXRpb24oJ2Z1bmN0aW9ucy9vbkNvbm5lY3QudHMnKSxcbiAgICAgIGVudmlyb25tZW50OiBlbnZWYXJzLFxuICAgIH0pO1xuICAgIHRoaXMudGFibGUuZ3JhbnRXcml0ZURhdGEoZnVuY3Rpb25PbkNvbm5lY3QpO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGZ1bmN0aW9uT25Db25uZWN0KTtcblxuICAgIGNvbnN0IGZ1bmN0aW9uT25EaXNjb25uZWN0ID0gbmV3IGxhbWJkYU5vZGUuTm9kZWpzRnVuY3Rpb24oXG4gICAgICB0aGlzLFxuICAgICAgJ09uRGlzY29ubmVjdCcsXG4gICAgICB7XG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg1KSxcbiAgICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE2X1gsXG4gICAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgICAgZW50cnk6IHRoaXMuZ2V0QXNzZXRMb2NhdGlvbignZnVuY3Rpb25zL29uRGlzY29ubmVjdC50cycpLFxuICAgICAgICBlbnZpcm9ubWVudDogZW52VmFycyxcbiAgICAgIH1cbiAgICApO1xuICAgIHRoaXMudGFibGUuZ3JhbnRXcml0ZURhdGEoZnVuY3Rpb25PbkRpc2Nvbm5lY3QpO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGZ1bmN0aW9uT25EaXNjb25uZWN0KTtcblxuICAgIHRoaXMud2ViU29ja2V0QXBpID0gbmV3IGFwaUd3VjIuV2ViU29ja2V0QXBpKHRoaXMsICdBcGlHd1dlYlNvY2tldCcpO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHRoaXMud2ViU29ja2V0QXBpKTtcbiAgICB0aGlzLndlYlNvY2tldFN0YWdlID0gbmV3IGFwaUd3VjIuV2ViU29ja2V0U3RhZ2UoXG4gICAgICB0aGlzLFxuICAgICAgJ0FwaUd3V2ViU29ja2V0U3RhZ2UnLFxuICAgICAge1xuICAgICAgICB3ZWJTb2NrZXRBcGk6IHRoaXMud2ViU29ja2V0QXBpLFxuICAgICAgICBzdGFnZU5hbWU6ICdwcm9kJyxcbiAgICAgICAgYXV0b0RlcGxveTogdHJ1ZSxcbiAgICAgIH1cbiAgICApO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHRoaXMud2ViU29ja2V0U3RhZ2UpO1xuICAgIGNvbnN0IHdlYlNvY2tldEFwaVJvdXRlID0gdGhpcy53ZWJTb2NrZXRBcGkuYWRkUm91dGUoJyRjb25uZWN0Jywge1xuICAgICAgaW50ZWdyYXRpb246IG5ldyBhcGlHd1YySW50LldlYlNvY2tldExhbWJkYUludGVncmF0aW9uKFxuICAgICAgICAnJGNvbm5lY3QnLFxuICAgICAgICBmdW5jdGlvbk9uQ29ubmVjdFxuICAgICAgKSxcbiAgICB9KTtcbiAgICAod2ViU29ja2V0QXBpUm91dGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgYWd3LkNmblJvdXRlKS5hdXRob3JpemF0aW9uVHlwZSA9XG4gICAgICAnQVdTX0lBTSc7XG5cbiAgICB0aGlzLndlYlNvY2tldEFwaS5hZGRSb3V0ZSgnJGRpc2Nvbm5lY3QnLCB7XG4gICAgICBpbnRlZ3JhdGlvbjogbmV3IGFwaUd3VjJJbnQuV2ViU29ja2V0TGFtYmRhSW50ZWdyYXRpb24oXG4gICAgICAgICckZGlzY29ubmVjdCcsXG4gICAgICAgIGZ1bmN0aW9uT25EaXNjb25uZWN0XG4gICAgICApLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oKTtcblxuICAgIHRoaXMud2ViU29ja2V0QXBpLmFkZFJvdXRlKCdzZW5kbWVzc2FnZScsIHtcbiAgICAgIGludGVncmF0aW9uOiBuZXcgYXBpR3dWMkludC5XZWJTb2NrZXRMYW1iZGFJbnRlZ3JhdGlvbihcbiAgICAgICAgJ1NlbmRNZXNzYWdlJyxcbiAgICAgICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uXG4gICAgICApLFxuICAgIH0pO1xuXG4gICAgdGhpcy53c1VybCA9IGB3c3M6Ly8ke3RoaXMud2ViU29ja2V0QXBpLmFwaUlkfS5leGVjdXRlLWFwaS4ke1xuICAgICAgU3RhY2sub2YodGhpcykucmVnaW9uXG4gICAgfS5hbWF6b25hd3MuY29tLyR7dGhpcy53ZWJTb2NrZXRTdGFnZS5zdGFnZU5hbWV9YDtcblxuICAgIG5ldyBDZm5PdXRwdXQoU3RhY2sub2YodGhpcyksICdTZXJ2ZXJsZXNzU3B5V3NVcmwnLCB7XG4gICAgICB2YWx1ZTogdGhpcy53c1VybCxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGFmYXVsdExhbWJkYUVudmlyb25tZW50VmFyaWFibGVzKCk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIHJldHVybiB7XG4gICAgICBbZW52VmFyaWFibGVOYW1lcy5TU1BZX1dTX1RBQkxFX05BTUVdOiB0aGlzLnRhYmxlLnRhYmxlTmFtZSxcbiAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRhbGl6ZSBzcHlpbmcgb24gcmVzb3VyY2VzIGdpdmVuIGFzIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIG5vZGVzIFdoaWNoIHJlb3VyY2VzIGFuZCB0aGVpciBjaGlsZHJlbiB0byBzcHkgb24uXG4gICAqL1xuICBwdWJsaWMgc3B5Tm9kZXMobm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgbGV0IG5zID0gdGhpcy5nZXRBbGxOb2Rlcyhub2RlKTtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlOb2Rlcyhucyk7XG4gICAgfVxuXG4gICAgdGhpcy5maW5pYWxpemVTcHkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0YWxpemUgc3B5aW5nIG9uIHJlc291cmNlcy5cbiAgICogQHBhcmFtIGZpbHRlciBMaW1pdCB3aGljaCByZXNvdXJjZXMgdG8gc3B5IG9uLlxuICAgKi9cbiAgcHVibGljIHNweShmaWx0ZXI/OiBTcHlGaWx0ZXIpIHtcbiAgICBsZXQgbm9kZXMgPSB0aGlzLmdldEFsbE5vZGVzKFN0YWNrLm9mKHRoaXMpKTtcblxuICAgIGNvbnN0IGZpbHRlcldpdGhEZWZhdWx0czogUmVxdWlyZWQ8U3B5RmlsdGVyPiA9IHtcbiAgICAgIHNweUxhbWJkYTogdHJ1ZSxcbiAgICAgIHNweVNxczogdHJ1ZSxcbiAgICAgIHNweVNuc1RvcGljOiB0cnVlLFxuICAgICAgc3B5U25zU3Vic3JpcHRpb246IHRydWUsXG4gICAgICBzcHlFdmVudEJyaWRnZTogdHJ1ZSxcbiAgICAgIHNweUV2ZW50QnJpZGdlUnVsZTogdHJ1ZSxcbiAgICAgIHNweVMzOiB0cnVlLFxuICAgICAgc3B5RHluYW1vREI6IHRydWUsXG4gICAgICAuLi5maWx0ZXIsXG4gICAgfTtcblxuICAgIG5vZGVzID0gbm9kZXMuZmlsdGVyKChub2RlKSA9PiB7XG4gICAgICBpZiAoZmlsdGVyV2l0aERlZmF1bHRzLnNweUxhbWJkYSAmJiBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U25zVG9waWMgJiYgbm9kZSBpbnN0YW5jZW9mIHNucy5Ub3BpYykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTbnNTdWJzcmlwdGlvbiAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2Ygc25zLlN1YnNjcmlwdGlvblxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5UzMgJiYgbm9kZSBpbnN0YW5jZW9mIHMzLkJ1Y2tldCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlEeW5hbW9EQiAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZHluYW1vRGIuVGFibGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlFdmVudEJyaWRnZSAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RXZlbnRCcmlkZ2VSdWxlICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBldmVudHMuUnVsZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZ1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICB0aGlzLnByb3BzPy5zcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNxcy5RdWV1ZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG5cbiAgICB0aGlzLmludGVybmFsU3B5Tm9kZXMobm9kZXMpO1xuICAgIHRoaXMuZmluaWFsaXplU3B5KCk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5Tm9kZXMobm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweU5vZGUobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmaW5pYWxpemVTcHkoKSB7XG4gICAgLy9zZXQgbWFwcGluZyBwcm9wZXJ0eSBmb3IgYWxsIGZ1bmN0aW9ucyB3ZSBjcmVhdGVkXG4gICAgZm9yIChjb25zdCBmdW5jIG9mIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbCkge1xuICAgICAgZnVuYy5mdW5jdGlvbi5hZGRFbnZpcm9ubWVudChcbiAgICAgICAgZW52VmFyaWFibGVOYW1lcy5TU1BZX0lORlJBX01BUFBJTkcsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGZ1bmMubWFwcGluZylcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy9zZXQgbWFwcGluZyBwcm9wZXJ0eSBmb3IgYWxsIGZ1bmN0aW9ucyB3ZSBzcHkgb25cbiAgICBmb3IgKGNvbnN0IGZ1bmMgb2YgdGhpcy5sYW1iZGFzU3BpZWQpIHtcbiAgICAgIGZ1bmMuZnVuY3Rpb24uYWRkRW52aXJvbm1lbnQoXG4gICAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9JTkZSQV9NQVBQSU5HLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShmdW5jLm1hcHBpbmcpXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnByb3BzPy5nZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbikge1xuICAgICAgdGhpcy53cml0ZVNweUV2ZW50c0NsYXNzKHRoaXMucHJvcHM/LmdlbmVyYXRlU3B5RXZlbnRzRmlsZUxvY2F0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldEV4dGVuc2lvbkFzc2V0TG9jYXRpb24oKSB7XG4gICAgbGV0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBwYXRoLmpvaW4oXG4gICAgICBfX2Rpcm5hbWUsXG4gICAgICAnLi4vZXh0ZW5zaW9uL2Rpc3QvbGF5ZXInXG4gICAgKTtcblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQgPSBwYXRoLmpvaW4oXG4gICAgICBfX2Rpcm5hbWUsXG4gICAgICAnLi4vbGliL2V4dGVuc2lvbi9kaXN0L2xheWVyJ1xuICAgICk7XG5cbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbikpIHtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZvbGRlciB3aXRoIGFzc2V0cyBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb259IG9yIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdH0gYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbiA9IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBlciA9IHBhdGguam9pbihcbiAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24sXG4gICAgICAnc3B5LXdyYXBwZXInXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFdyYXBlciBzY3JpcHQgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgJHtleHRlbnNpb25Bc3NldExvY2F0aW9ufWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGUgPSBwYXRoLmpvaW4oXG4gICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uLFxuICAgICAgJ25vZGVqcy9ub2RlX21vZHVsZXMvaW50ZXJjZXB0b3IuanMnXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDb2RlIGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGV9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4dGVuc2lvbkFzc2V0TG9jYXRpb247XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgU3B5RXZlbnRzIGNsYXNzLCB3aGljaCBoZWxwcyB3aXRoIHdyaXRpbmcgdGhlIGNvZGUgZm9yIHRlc3RzLlxuICAgKiBAcGFyYW0gZmlsZUxvY2F0aW9uXG4gICAqL1xuICBwcml2YXRlIHdyaXRlU3B5RXZlbnRzQ2xhc3MoZmlsZUxvY2F0aW9uOiBzdHJpbmcpIHtcbiAgICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVMb2NhdGlvbiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuc2VydmljZUtleXNcbiAgICAgIC5tYXAoKHNrKSA9PiBgICAke3NrLnJlcGxhY2UoLyMvZywgJycpfTogJyR7c2t9JyA9ICcke3NrfSc7XFxuYClcbiAgICAgIC5qb2luKCcnKTtcblxuICAgIGNvbnN0IGNvZGUgPSBgLyogZXNsaW50LWRpc2FibGUgKi9cXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc1NweUV2ZW50cyB7XFxuJHtwcm9wZXJ0aWVzfX1cXG5gO1xuXG4gICAgZnMud3JpdGVGaWxlU3luYyhmaWxlTG9jYXRpb24sIGNvZGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2RlcyhwYXJlbnQ6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBub2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gICAgbm9kZXMucHVzaChwYXJlbnQpO1xuICAgIHRoaXMuZ2V0QWxsTm9kZXNSZWN1cnNpdmUocGFyZW50LCBub2Rlcyk7XG4gICAgcmV0dXJuIG5vZGVzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2Rlc1JlY3Vyc2l2ZShwYXJlbnQ6IElDb25zdHJ1Y3QsIG5vZGVzOiBJQ29uc3RydWN0W10pIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcGFyZW50Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIG5vZGVzLnB1c2gobm9kZSk7XG4gICAgICB0aGlzLmdldEFsbE5vZGVzUmVjdXJzaXZlKG5vZGUsIG5vZGVzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5Tm9kZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgaWYgKHRoaXMuc3BpZWROb2Rlcy5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3BpZWROb2Rlcy5wdXNoKG5vZGUpO1xuXG4gICAgaWYgKHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wuZmluZCgocykgPT4gcy5mdW5jdGlvbiA9PT0gbm9kZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBjb25zb2xlLmluZm8oJ1NweSBvbiBub2RlJywgdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKG5vZGUpKTtcbiAgICB9XG5cbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIGxhbWJkYS5GdW5jdGlvbikge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUxhbWJkYShub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTbnNUb3BpYyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzbnMuU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U25zU3Vic2NyaXB0aW9uKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHMzLkJ1Y2tldCkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVMzKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RHluYW1vZGIobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RXZlbnRCdXMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZXZlbnRzLlJ1bGUpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlFdmVudEJ1c1J1bGUobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVNxcyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzcXMuUXVldWUpIHtcbiAgICAgIGlmICh0aGlzLnByb3BzPy5zcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMpIHtcbiAgICAgICAgdGhpcy5pbnRlcm5hbFNweVNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbihub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uKHF1ZXVlOiBzcXMuUXVldWUpIHtcbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLmZpbmRFbGVtZW50PGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmc+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nICYmXG4gICAgICAgIChuIGFzIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcpLmV2ZW50U291cmNlQXJuID09PSBxdWV1ZS5xdWV1ZUFyblxuICAgICk7XG5cbiAgICBpZiAoc3Vic2NyaXB0aW9uKSB7XG4gICAgICByZXR1cm47IC8vYWxyZWFkeSBoYXZlIHN1YnNjcmlwdGlvblxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXVlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShxdWV1ZSk7XG4gICAgY29uc3QgZnVuYyA9IG5ldyBOb2RlanNGdW5jdGlvbihcbiAgICAgIHRoaXMsXG4gICAgICBgJHtxdWV1ZU5hbWV9U3FzU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzYCxcbiAgICAgIHtcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICAgICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTZfWCxcbiAgICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgICBlbnRyeTogdGhpcy5nZXRBc3NldExvY2F0aW9uKFxuICAgICAgICAgICdmdW5jdGlvbnMvc3FzU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzLnRzJ1xuICAgICAgICApLFxuICAgICAgICBlbnZpcm9ubWVudDogdGhpcy5nZXREYWZhdWx0TGFtYmRhRW52aXJvbm1lbnRWYXJpYWJsZXMoKSxcbiAgICAgIH1cbiAgICApO1xuICAgIGZ1bmMuYWRkRXZlbnRTb3VyY2UobmV3IFNxc0V2ZW50U291cmNlKHF1ZXVlKSk7XG5cbiAgICAvL1xuICAgIGZ1bmMuYWRkTGF5ZXJzKHRoaXMuZXh0ZW5zaW9uTGF5ZXIpO1xuXG4gICAgLy9jb25zdCBmdW5jdGlvbk5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoZnVuYyk7XG5cbiAgICAvL2Z1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0ZVTkNUSU9OX05BTUUsIGZ1bmN0aW9uTmFtZSk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudCgnQVdTX0xBTUJEQV9FWEVDX1dSQVBQRVInLCAnL29wdC9zcHktd3JhcHBlcicpO1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoXG4gICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfRU5EUE9JTlQsXG4gICAgICB0aGlzLmdldFdzRW5kcG9pbnQoKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVRywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnRhYmxlLmdyYW50V3JpdGVEYXRhKGZ1bmMpO1xuICAgIHRoaXMudGFibGUuZ3JhbnRSZWFkRGF0YShmdW5jKTtcbiAgICB0aGlzLndlYlNvY2tldEFwaS5ncmFudE1hbmFnZUNvbm5lY3Rpb25zKGZ1bmMpO1xuICAgIC8vXG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChmdW5jKTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU3FzIyR7cXVldWVOYW1lfWA7XG5cbiAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMsIHtcbiAgICAgIGtleTogcXVldWUucXVldWVBcm4sXG4gICAgICB2YWx1ZTogc2VydmljZUtleSxcbiAgICB9KTtcblxuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9TVUJTQ1JJQkVEX1RPX1NRUywgJ3RydWUnKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTcXMobm9kZTogbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykge1xuICAgIGNvbnN0IHF1ZXVlID0gdGhpcy5maW5kRWxlbWVudDxzcXMuUXVldWU+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBzcXMuUXVldWUgJiZcbiAgICAgICAgKG4gYXMgc3FzLlF1ZXVlKS5xdWV1ZUFybiA9PT0gbm9kZS5ldmVudFNvdXJjZUFyblxuICAgICk7XG5cbiAgICBjb25zdCBmdW5jID0gdGhpcy5maW5kRWxlbWVudDxsYW1iZGEuRnVuY3Rpb24+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBsYW1iZGEuRnVuY3Rpb24gJiZcbiAgICAgICAgKG4gYXMgbGFtYmRhLkZ1bmN0aW9uKS5mdW5jdGlvbk5hbWUgPT09IG5vZGUuZnVuY3Rpb25OYW1lXG4gICAgKTtcblxuICAgIGlmIChxdWV1ZSAmJiBmdW5jKSB7XG4gICAgICBjb25zdCBxdWV1ZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUocXVldWUpO1xuXG4gICAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNxcyMke3F1ZXVlTmFtZX1gO1xuXG4gICAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMsIHtcbiAgICAgICAga2V5OiBxdWV1ZS5xdWV1ZUFybixcbiAgICAgICAgdmFsdWU6IHNlcnZpY2VLZXksXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICAgICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfU1VCU0NSSUJFRF9UT19TUVMsICd0cnVlJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgZnVuYyA9IG5ldyBsYW1iZGFOb2RlLk5vZGVqc0Z1bmN0aW9uKHRoaXMsIGBTdWJzY3JpcHRpb24ke2luZGV4fWAsIHtcbiAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoNSksXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTZfWCxcbiAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgIGVudHJ5OiB0aGlzLmdldEFzc2V0TG9jYXRpb24oJ2Z1bmN0aW9ucy9zZW5kTWVzc2FnZS50cycpLFxuICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgW2VudlZhcmlhYmxlTmFtZXMuU1NQWV9XU19UQUJMRV9OQU1FXTogdGhpcy50YWJsZS50YWJsZU5hbWUsXG4gICAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLnRhYmxlLmdyYW50V3JpdGVEYXRhKGZ1bmMpO1xuICAgIHRoaXMudGFibGUuZ3JhbnRSZWFkRGF0YShmdW5jKTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KFxuICAgICAgZW52VmFyaWFibGVOYW1lcy5TU1BZX1dTX0VORFBPSU5ULFxuICAgICAgdGhpcy5nZXRXc0VuZHBvaW50KClcbiAgICApO1xuXG4gICAgdGhpcy53ZWJTb2NrZXRBcGkuZ3JhbnRNYW5hZ2VDb25uZWN0aW9ucyhmdW5jKTtcbiAgICByZXR1cm4gZnVuYztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0V3NFbmRwb2ludCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgaHR0cHM6Ly8ke3RoaXMud2ViU29ja2V0QXBpLmFwaUlkfS5leGVjdXRlLWFwaS4ke1xuICAgICAgU3RhY2sub2YodGhpcykucmVnaW9uXG4gICAgfS5hbWF6b25hd3MuY29tLyR7dGhpcy53ZWJTb2NrZXRTdGFnZS5zdGFnZU5hbWV9YDtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTMyhzM0J1Y2tldDogczMuQnVja2V0KSB7XG4gICAgczNCdWNrZXQuYWRkRXZlbnROb3RpZmljYXRpb24oXG4gICAgICBzMy5FdmVudFR5cGUuT0JKRUNUX0NSRUFURURfUFVULFxuICAgICAgbmV3IHMzbm90aWYuTGFtYmRhRGVzdGluYXRpb24odGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uKVxuICAgICk7XG5cbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHMzQnVja2V0KTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgUzMjJHtuYW1lfWA7XG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLm1hcHBpbmdbczNCdWNrZXQuYnVja2V0QXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUR5bmFtb2RiKHRhYmxlOiBkeW5hbW9EYi5UYWJsZSkge1xuICAgIC8vIGVuYWJsZSBEeW5hbW9EQiBzdHJlYW1zIHdpdGggYSBoYWNrXG4gICAgKHRhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGR5bmFtb0RiLkNmblRhYmxlKS5zdHJlYW1TcGVjaWZpY2F0aW9uID0ge1xuICAgICAgc3RyZWFtVmlld1R5cGU6IGR5bmFtb0RiLlN0cmVhbVZpZXdUeXBlLk5FV19BTkRfT0xEX0lNQUdFUyxcbiAgICB9O1xuICAgICh0YWJsZSBhcyBhbnkpLnRhYmxlU3RyZWFtQXJuID0gKFxuICAgICAgdGFibGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgZHluYW1vRGIuQ2ZuVGFibGVcbiAgICApLmF0dHJTdHJlYW1Bcm47XG5cbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4uZnVuY3Rpb24uYWRkRXZlbnRTb3VyY2UoXG4gICAgICBuZXcgZHluYW1vRGJTdHJlYW0uRHluYW1vRXZlbnRTb3VyY2UodGFibGUsIHtcbiAgICAgICAgc3RhcnRpbmdQb3NpdGlvbjogbGFtYmRhLlN0YXJ0aW5nUG9zaXRpb24uTEFURVNULFxuICAgICAgICBiYXRjaFNpemU6IDEsXG4gICAgICAgIHJldHJ5QXR0ZW1wdHM6IDAsXG4gICAgICB9KVxuICAgICk7XG5cbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRhYmxlKTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRHluYW1vREIjJHtuYW1lfWA7XG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLm1hcHBpbmdbdGFibGUudGFibGVBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5RXZlbnRCdXNSdWxlKHJ1bGU6IGV2ZW50cy5SdWxlKSB7XG4gICAgY29uc3QgeyBldmVudEJ1c05hbWUgfSA9IHJ1bGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgZXZlbnRzLkNmblJ1bGU7XG4gICAgY29uc3QgZXZlbnRCcmlkZ2UgPSB0aGlzLmdldEV2ZW50QnJpZGdlKFxuICAgICAgKHJ1bGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgYW55KS5ldmVudEJ1c05hbWVcbiAgICApO1xuXG4gICAgaWYgKCFldmVudEJyaWRnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGZpbmQgRXZlbnRCcmlkZ2Ugd2l0aCBuYW1lIFwiJHtldmVudEJ1c05hbWV9XCJgKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnVzZWRGb3JFdmVudEJyaWRnZVxuICAgICk7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24udXNlZEZvckV2ZW50QnJpZGdlID0gdHJ1ZTtcblxuICAgIHJ1bGUuYWRkVGFyZ2V0KG5ldyB0YXJnZXRzLkxhbWJkYUZ1bmN0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKSk7XG5cbiAgICBjb25zdCBicmlkZ2VOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGV2ZW50QnJpZGdlKTtcbiAgICBjb25zdCBydWxlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShydWxlKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYEV2ZW50QnJpZGdlUnVsZSMke2JyaWRnZU5hbWV9IyR7cnVsZU5hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nLmV2ZW50QnJpZGdlID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5RXZlbnRCdXMoZXZlbnRCdXM6IGV2ZW50cy5FdmVudEJ1cykge1xuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMudXNlZEZvckV2ZW50QnJpZGdlXG4gICAgKTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi51c2VkRm9yRXZlbnRCcmlkZ2UgPSB0cnVlO1xuXG4gICAgY29uc3QgYnJpZGdlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShldmVudEJ1cyk7XG4gICAgY29uc3QgcnVsZSA9IG5ldyBldmVudHMuUnVsZSh0aGlzLCBgUnVsZUFsbCR7YnJpZGdlTmFtZX1gLCB7XG4gICAgICBldmVudEJ1cyxcbiAgICAgIGV2ZW50UGF0dGVybjogeyB2ZXJzaW9uOiBbJzAnXSB9LFxuICAgICAgdGFyZ2V0czogW25ldyB0YXJnZXRzLkxhbWJkYUZ1bmN0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKV0sXG4gICAgfSk7XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChydWxlKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYEV2ZW50QnJpZGdlIyR7YnJpZGdlTmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmcuZXZlbnRCcmlkZ2UgPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTbnNUb3BpYyh0b3BpYzogc25zLlRvcGljKSB7XG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy5zdWJzcmliZWRUb3BpY3MuaW5jbHVkZXModG9waWMpXG4gICAgKTtcblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRvcGljLmFkZFN1YnNjcmlwdGlvbihcbiAgICAgIG5ldyBzbnNTdWJzLkxhbWJkYVN1YnNjcmlwdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbilcbiAgICApO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHN1YnNjcmlwdGlvbik7XG4gICAgY29uc3QgdG9waWNOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRvcGljKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNuc1RvcGljIyR7dG9waWNOYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZ1t0b3BpYy50b3BpY0Fybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5zdWJzcmliZWRUb3BpY3MucHVzaCh0b3BpYyk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U25zU3Vic2NyaXB0aW9uKHN1YnNjcmlwdGlvbjogc25zLlN1YnNjcmlwdGlvbikge1xuICAgIGlmICghc3Vic2NyaXB0aW9uLm5vZGUuc2NvcGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0b3BpYyA9IHRoaXMuZ2V0VG9waWMoXG4gICAgICAoc3Vic2NyaXB0aW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIHNucy5DZm5TdWJzY3JpcHRpb24pLnRvcGljQXJuXG4gICAgKTtcblxuICAgIGlmICghdG9waWMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBmaW5kIFRvcGljJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy5zdWJzcmliZWRUb3BpY3MuaW5jbHVkZXModG9waWMpXG4gICAgKTtcblxuICAgIGNvbnN0IHsgZmlsdGVyUG9saWN5IH0gPSBzdWJzY3JpcHRpb24ubm9kZVxuICAgICAgLmRlZmF1bHRDaGlsZCBhcyBzbnMuQ2ZuU3Vic2NyaXB0aW9uO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uQ2xvbmUgPSB0b3BpYy5hZGRTdWJzY3JpcHRpb24oXG4gICAgICBuZXcgc25zU3Vicy5MYW1iZGFTdWJzY3JpcHRpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pXG4gICAgKTtcbiAgICAoc3Vic2NyaXB0aW9uQ2xvbmUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgc25zLkNmblN1YnNjcmlwdGlvbikuZmlsdGVyUG9saWN5ID1cbiAgICAgIGZpbHRlclBvbGljeTtcblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHN1YnNjcmlwdGlvbkNsb25lKTtcblxuICAgIGNvbnN0IHRvcGljTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZSh0b3BpYyk7XG4gICAgY29uc3QgdGFyZ2V0TmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShzdWJzY3JpcHRpb24ubm9kZS5zY29wZSk7XG5cbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5zdWJzcmliZWRUb3BpY3MucHVzaCh0b3BpYyk7XG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBTbnNTdWJzY3JpcHRpb24jJHt0b3BpY05hbWV9IyR7dGFyZ2V0TmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmdbdG9waWMudG9waWNBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIHByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICBmaWx0ZXJGdW5jdGlvbj86IChzdWJzY3JpcHRpb246IExhbWJkYVN1YnNjcmlwdGlvbikgPT4gYm9vbGVhblxuICApIHtcbiAgICBsZXQgZnVuY3Rpb25TdWJzY3JpcHRpb246IExhbWJkYVN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChmaWx0ZXJGdW5jdGlvbikge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wuZmluZChmaWx0ZXJGdW5jdGlvbik7XG4gICAgfSBlbHNlIGlmICh0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wubGVuZ3RoID4gMCkge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2xbMF07XG4gICAgfVxuXG4gICAgaWYgKCFmdW5jdGlvblN1YnNjcmlwdGlvbikge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB7XG4gICAgICAgIHN1YnNyaWJlZFRvcGljczogW10sXG4gICAgICAgIHVzZWRGb3JFdmVudEJyaWRnZTogZmFsc2UsXG4gICAgICAgIG1hcHBpbmc6IHt9LFxuICAgICAgICBmdW5jdGlvbjogdGhpcy5jcmVhdGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgICAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wubGVuZ3RoXG4gICAgICAgICksXG4gICAgICB9O1xuICAgICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLnB1c2goZnVuY3Rpb25TdWJzY3JpcHRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb25TdWJzY3JpcHRpb247XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5TGFtYmRhKGZ1bmM6IGxhbWJkYS5GdW5jdGlvbikge1xuICAgIGZ1bmMuYWRkTGF5ZXJzKHRoaXMuZXh0ZW5zaW9uTGF5ZXIpO1xuXG4gICAgY29uc3QgZnVuY3Rpb25OYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGZ1bmMpO1xuXG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfRlVOQ1RJT05fTkFNRSwgZnVuY3Rpb25OYW1lKTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KCdBV1NfTEFNQkRBX0VYRUNfV1JBUFBFUicsICcvb3B0L3NweS13cmFwcGVyJyk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChcbiAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9XU19UQUJMRV9OQU1FLFxuICAgICAgdGhpcy50YWJsZS50YWJsZU5hbWVcbiAgICApO1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoXG4gICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfRU5EUE9JTlQsXG4gICAgICB0aGlzLmdldFdzRW5kcG9pbnQoKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVRywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnRhYmxlLmdyYW50V3JpdGVEYXRhKGZ1bmMpO1xuICAgIHRoaXMudGFibGUuZ3JhbnRSZWFkRGF0YShmdW5jKTtcbiAgICB0aGlzLndlYlNvY2tldEFwaS5ncmFudE1hbmFnZUNvbm5lY3Rpb25zKGZ1bmMpO1xuXG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jUmVxdWVzdGApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I0Vycm9yYCk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jQ29uc29sZWApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I1Jlc3BvbnNlYCk7XG5cbiAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMpO1xuICB9XG5cbiAgcHVibGljIGdldENvbnN0cnVjdE5hbWUoY29uc3RydWN0OiBJQ29uc3RydWN0KSB7XG4gICAgbGV0IGZ1bmN0aW9uTmFtZSA9IGNvbnN0cnVjdC5ub2RlLnBhdGg7XG4gICAgY29uc3QgeyBzdGFja05hbWUgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKGZ1bmN0aW9uTmFtZS5zdGFydHNXaXRoKHN0YWNrTmFtZSkpIHtcbiAgICAgIGZ1bmN0aW9uTmFtZSA9IGZ1bmN0aW9uTmFtZS5zdWJzdHJpbmcoc3RhY2tOYW1lLmxlbmd0aCArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb25OYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUb3BpYyh0b3BpY0Fybjogc3RyaW5nKTogc25zLlRvcGljIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCB0b3BpYyA9IHRoaXMuZmluZEVsZW1lbnQ8c25zLlRvcGljPihcbiAgICAgIChub2RlOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBub2RlIGluc3RhbmNlb2Ygc25zLlRvcGljICYmIChub2RlIGFzIHNucy5Ub3BpYykudG9waWNBcm4gPT09IHRvcGljQXJuXG4gICAgKTtcblxuICAgIHJldHVybiB0b3BpYztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXZlbnRCcmlkZ2UoZXZlbnRCdXNOYW1lOiBzdHJpbmcpOiBldmVudHMuRXZlbnRCdXMgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGV2ZW50QnJpZGdlID0gdGhpcy5maW5kRWxlbWVudDxldmVudHMuRXZlbnRCdXM+KFxuICAgICAgKG5vZGU6IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBldmVudHMuRXZlbnRCdXMgJiZcbiAgICAgICAgKG5vZGUgYXMgZXZlbnRzLkV2ZW50QnVzKS5ldmVudEJ1c05hbWUgPT09IGV2ZW50QnVzTmFtZVxuICAgICk7XG5cbiAgICByZXR1cm4gZXZlbnRCcmlkZ2U7XG4gIH1cblxuICBwcml2YXRlIGZpbmRFbGVtZW50PFQgZXh0ZW5kcyBJQ29uc3RydWN0ID0gSUNvbnN0cnVjdD4oXG4gICAgZmlsdGVyRnVuYzogKG5vZGU6IElDb25zdHJ1Y3QpID0+IGJvb2xlYW4sXG4gICAgcGFyZW50PzogSUNvbnN0cnVjdFxuICApOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXBhcmVudCkge1xuICAgICAgcGFyZW50ID0gU3RhY2sub2YodGhpcyk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHBhcmVudC5ub2RlLmNoaWxkcmVuKSB7XG4gICAgICBpZiAoZmlsdGVyRnVuYyhub2RlKSkge1xuICAgICAgICByZXR1cm4gbm9kZSBhcyBUO1xuICAgICAgfVxuICAgICAgdGhpcy5maW5kRWxlbWVudDxUPihmaWx0ZXJGdW5jLCBub2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRNYXBwaW5nVG9GdW5jdGlvbihcbiAgICBmdW5jOiBsYW1iZGEuRnVuY3Rpb24sXG4gICAga2V5VmFsdWU/OiB7IGtleTogc3RyaW5nOyB2YWx1ZTogc3RyaW5nIH1cbiAgKSB7XG4gICAgZm9yIChjb25zdCBmcyBvZiB0aGlzLmxhbWJkYXNTcGllZCkge1xuICAgICAgaWYgKGZzLmZ1bmN0aW9uID09PSBmdW5jKSB7XG4gICAgICAgIGlmIChrZXlWYWx1ZSkge1xuICAgICAgICAgIGZzLm1hcHBpbmdba2V5VmFsdWUua2V5XSA9IGtleVZhbHVlLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBmczogTGFtYmRhU3BpZWQgPSB7XG4gICAgICBmdW5jdGlvbjogZnVuYyxcbiAgICAgIG1hcHBpbmc6IHt9LFxuICAgIH07XG5cbiAgICBpZiAoa2V5VmFsdWUpIHtcbiAgICAgIGZzLm1hcHBpbmdba2V5VmFsdWUua2V5XSA9IGtleVZhbHVlLnZhbHVlO1xuICAgIH1cblxuICAgIHRoaXMubGFtYmRhc1NwaWVkLnB1c2goZnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBc3NldExvY2F0aW9uKGxvY2F0aW9uOiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2MgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vJyArIGxvY2F0aW9uKTtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKGxvYykpIHtcbiAgICAgIHJldHVybiBsb2M7XG4gICAgfVxuXG4gICAgY29uc3QgbG9jMiA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi8nICsgbG9jYXRpb24pO1xuXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMobG9jMikpIHtcbiAgICAgIHJldHVybiBsb2MyO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgTG9jYXRpb24gJHtsb2N9IGFuZCAke2xvYzJ9IGRvZXMgbm90IGV4aXN0cy5gKTtcbiAgfVxufVxuXG50eXBlIExhbWJkYVN1YnNjcmlwdGlvbiA9IHtcbiAgc3Vic3JpYmVkVG9waWNzOiBzbnMuVG9waWNbXTtcbiAgdXNlZEZvckV2ZW50QnJpZGdlOiBib29sZWFuO1xuICBmdW5jdGlvbjogbGFtYmRhTm9kZS5Ob2RlanNGdW5jdGlvbjtcbiAgbWFwcGluZzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn07XG5cbnR5cGUgTGFtYmRhU3BpZWQgPSB7XG4gIGZ1bmN0aW9uOiBsYW1iZGEuRnVuY3Rpb247XG4gIG1hcHBpbmc6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuIl19
|
|
Binary file
|
package/logo/logo.png
ADDED
|
Binary file
|