@bluedynamics/cdk8s-plone 0.0.81 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,181 +1,203 @@
1
- # CMS Plone Chart for CDK8S
1
+ # CDK8S Plone
2
2
 
3
- This chart provides a library to bootstrap a Plone deployment on a Kubernetes cluster using the [CDK8S](https://cdk8s.io) framework.
3
+ A CDK8S library for deploying Plone CMS to Kubernetes.
4
4
 
5
- It provides
6
- - Backend (as API with `plone.volto` or as Classic-UI)
7
- - Frontend (Plone-Volto, a ReactJS based user interface)
8
- - Varnish using kube-httpcache. It includes a way to invalidate varnish cluster (optional)
5
+ This library provides constructs to bootstrap a Plone deployment on a Kubernetes cluster using the [CDK8S](https://cdk8s.io) framework.
9
6
 
7
+ ## Features
10
8
 
11
- ### Typescript
9
+ - **Backend**: Plone backend (API with `plone.volto` or Classic-UI)
10
+ - **Frontend**: Plone Volto (modern React-based user interface)
11
+ - **Varnish Caching**: Optional HTTP caching layer using [kube-httpcache](https://github.com/mittwald/kube-httpcache) with cluster-wide cache invalidation
12
+ - **High Availability**: Configurable replicas with PodDisruptionBudgets
13
+ - **Multi-language Support**: Published to npm (TypeScript/JavaScript) and PyPI (Python)
12
14
 
13
- To use this library, create a new CDK8S project (or use an existing one)
15
+
16
+ ## Installation
17
+
18
+ ### TypeScript/JavaScript
19
+
20
+ Create a new CDK8S project (or use an existing one):
14
21
 
15
22
  ```bash
16
23
  cdk8s init typescript-app
17
24
  ```
18
25
 
19
- Then add the following dependency to `package.json`:
26
+ Install the library:
20
27
 
21
- ```json
22
- {
23
- "dependencies": {
24
- "@bluedynamics/cdk8s-plone": "*"
25
- }
26
- }
28
+ ```bash
29
+ npm install @bluedynamics/cdk8s-plone
27
30
  ```
28
- Run `npm install` to install [cdk8s-plone](https://www.npmjs.com/package/@bluedynamics/cdk8s-plone).
31
+
32
+ Package: [@bluedynamics/cdk8s-plone](https://www.npmjs.com/package/@bluedynamics/cdk8s-plone)
29
33
 
30
34
  ### Python
31
35
 
32
- Todo: Document in details how to install.
36
+ Create a new CDK8S project:
33
37
 
34
38
  ```bash
35
39
  cdk8s init python-app
36
40
  ```
37
41
 
38
- Python package name is [cdk8s-plone](https://pypi.org/project/cdk8s-plone/).
42
+ Install the library:
39
43
 
44
+ ```bash
45
+ pip install cdk8s-plone
46
+ ```
40
47
 
41
- ## Usage
48
+ Package: [cdk8s-plone](https://pypi.org/project/cdk8s-plone/)
42
49
 
43
- With `cdk8s-cli` installed, create a new project:
44
50
 
45
- ```bash
46
- cdk8s sythn
51
+ ## Quick Start
52
+
53
+ ### Basic Plone Deployment
54
+
55
+ ```typescript
56
+ import { App, Chart } from 'cdk8s';
57
+ import { Plone, PloneVariant } from '@bluedynamics/cdk8s-plone';
58
+
59
+ const app = new App();
60
+ const chart = new Chart(app, 'PloneDeployment');
61
+
62
+ new Plone(chart, 'my-plone', {
63
+ variant: PloneVariant.VOLTO,
64
+ backend: {
65
+ image: 'plone/plone-backend:6.0.10',
66
+ replicas: 3,
67
+ },
68
+ frontend: {
69
+ image: 'plone/plone-frontend:16.0.0',
70
+ replicas: 2,
71
+ },
72
+ });
73
+
74
+ app.synth();
47
75
  ```
48
76
 
49
- Add the following code to your `main.ts`:
77
+ ### With Varnish HTTP Cache
50
78
 
51
79
  ```typescript
52
- ...
53
- import { Plone } from '@bluedynamics/cdk8s-plone';
54
- ...
55
- super(scope, id, props);
56
-
57
- // define resources here
58
- new Plone(this, 'Plone', {});
59
- ...
80
+ import { PloneHttpcache } from '@bluedynamics/cdk8s-plone';
81
+
82
+ const plone = new Plone(chart, 'my-plone', {
83
+ variant: PloneVariant.VOLTO,
84
+ backend: { image: 'plone/plone-backend:6.0.10' },
85
+ frontend: { image: 'plone/plone-frontend:16.0.0' },
86
+ });
87
+
88
+ new PloneHttpcache(chart, 'cache', {
89
+ plone: plone,
90
+ existingSecret: 'varnish-secret',
91
+ replicas: 2,
92
+ });
93
+ ```
94
+
95
+ ### Generate Kubernetes Manifests
96
+
97
+ ```bash
98
+ cdk8s synth
60
99
  ```
61
100
 
62
- Run `npm run build ` to generate the Kubernetes manifests.
63
- The manifests are stored in the `dist` directory.
64
-
65
- For more have a look at the [example project](https://github.com/bluedynamics/cdk8s-plone-example).
66
-
67
- ### Prerequisites
68
-
69
- For using cdk8s-plone, we assume you already have following tools installed:
70
-
71
- * kubectl A command-line tool for interacting with Kubernetes clusters. For deploying the Kubernetes manifest you will need a tool like this. Take a look at the [Install Tools](https://kubernetes.io/docs/tasks/tools/#kubectl) for kubectl.
72
-
73
- * (optional) Helm – A Kubernetes package manager for managing Plone/Volto deployments. This tool is optional and only needed if you generate helm charts as output with cdk8s synth - instead of pure manifests. There are several ways to install it see the [install section](https://helm.sh/docs/intro/install/) for Helm.
74
-
75
-
76
- ### References
77
- [Kubernetes Documentation](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) relevant for ressource management, readiness and liveness
78
-
79
- #### PloneBaseOptions
80
- *Interface*
81
-
82
-
83
-
84
- - `image`(string):
85
- - The used Plone image
86
- - e.g. `plone/plone-backend:6.1.0`
87
- - `imagePullPolicy`(string):
88
- - default `IfNotPresent`
89
- - `replicas`(numbers)
90
- - `maxUnavailable`(number|string)
91
- - `minAvailable`(number|string)
92
- - `limitCpu`(string)
93
- - `limitMemory`(string)
94
- - `requestCpu`(string)
95
- - `requestMemory`(string)
96
- - `environment`(kplus.Env)
97
- - `readinessEnabled`(boolean)
98
- - `readinessInitialDelaySeconds`(number)
99
- - `readinessIimeoutSeconds`(number)
100
- - `readinessPeriodSeconds`(number)
101
- - `readinessSuccessThreshold`(number)
102
- - `readinessFailureThreshold`(number)
103
- - `livenessEnabled`(boolean)
104
- - should be `true` for `volto`
105
- - should be `false` for `backend/classicui`
106
- - `livenessInitialDelaySeconds`(number)
107
- - `livenessIimeoutSeconds`(number)
108
- - `livenessPeriodSeconds`(number)
109
- - `livenessSuccessThreshold`(number)
110
- - `livenessFailureThreshold`(number)
111
-
112
-
113
- #### PloneOptions
114
- *Interface*
115
-
116
- - `version`(string):
117
- - version of your project
118
- - `siteId`(string):
119
- - default `Plone`
120
- - `variant`(PloneVariant):
121
- - default `PloneVariant.VOLTO`
122
- - `backend` (PloneBaseOptions):
123
- - default `{}`
124
- - needs `image` and `enviroment`
125
- - `frontend` (PloneBaseOptions):
126
- - default `{}`
127
- - needs `image` if `PloneVariant.VOLTO`
128
- - `imagePullSecrets`(string[])
129
-
130
- #### PloneVariants
131
- *Enum*
132
-
133
- - VOLTO = 'volto'
134
- - CLASSICUI = 'classicui'
135
- - no frontend options/image needed
136
-
137
- #### Plone
138
- *class*
139
-
140
- builds the `Plone` Construct
141
-
142
- - `backendServiceName`(string)
143
- - `frontendServiceName`(string)
144
- - `variant`(PloneVariant)
145
- - default `Volto`
146
- - `siteId`(string)
147
- - default `Plone`
148
-
149
- #### PloneHttpcacheOptions
150
- *Interface*
151
-
152
- - `plone`(Plone):
153
- - Plone chart
154
- - `varnishVcl`{string}:
155
- - varnishfile
156
- - per default `varnishVclFile` should be used
157
- - `varnishVclFile`(string):
158
- - File in config folder
159
- - `existingSecret`(string)
160
- - `limitCpu`(string)
161
- - `limitMemory`(string)
162
- - `requestCpu`(string)
163
- - `requestMemory`(string)
164
- - `servicemonitor`(string)
165
- - default `false` used for metrics
166
-
167
- #### PloneHttpcache
168
- *class*
169
-
170
- uses helmchart [kube-httpcache](https://github.com/mittwald/kube-httpcache) and builds the `PloneHttpCache` Construct
171
- - `scope`(Construct)
172
- - `id`(string)
173
- - `options`(PloneHttpcacheOptions)
101
+ The manifests are stored in the `dist/` directory.
102
+
103
+ For a complete example, see the [example project](https://github.com/bluedynamics/cdk8s-plone-example).
104
+
105
+ ## Prerequisites
106
+
107
+ - **kubectl** - Command-line tool for deploying Kubernetes manifests. [Install kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
108
+ - **Helm** (optional) - Only needed if generating Helm charts. [Install Helm](https://helm.sh/docs/intro/install/)
109
+ - **Node.js** - For TypeScript/JavaScript development
110
+ - **Python 3.8+** - For Python development
111
+
112
+
113
+ ## API Documentation
114
+
115
+ For complete API documentation, see [API.md](./API.md).
116
+
117
+ ### Key Constructs
118
+
119
+ #### `Plone`
120
+
121
+ Main construct for deploying Plone CMS. Supports two variants:
122
+ - **VOLTO**: Modern React frontend with REST API backend (default)
123
+ - **CLASSICUI**: Traditional server-side rendered Plone
124
+
125
+ Properties:
126
+ - `backendServiceName` - Name of the backend Kubernetes service
127
+ - `frontendServiceName` - Name of the frontend service (VOLTO only)
128
+ - `variant` - Deployment variant (VOLTO or CLASSICUI)
129
+ - `siteId` - Plone site ID in ZODB (default: 'Plone')
130
+
131
+ #### `PloneHttpcache`
132
+
133
+ Varnish HTTP caching layer using the [kube-httpcache](https://github.com/mittwald/kube-httpcache) Helm chart.
134
+
135
+ Properties:
136
+ - `httpcacheServiceName` - Name of the Varnish service
137
+
138
+ ### Configuration Options
139
+
140
+ #### `PloneOptions`
141
+
142
+ - `version` - Version of your project
143
+ - `siteId` - Plone site ID (default: 'Plone')
144
+ - `variant` - PloneVariant.VOLTO or PloneVariant.CLASSICUI (default: VOLTO)
145
+ - `backend` - Backend configuration (PloneBaseOptions)
146
+ - `frontend` - Frontend configuration (PloneBaseOptions, required for VOLTO)
147
+ - `imagePullSecrets` - Image pull secrets for private registries
148
+
149
+ #### `PloneBaseOptions`
150
+
151
+ Configuration for backend or frontend:
152
+
153
+ **Container:**
154
+ - `image` - Container image (e.g., 'plone/plone-backend:6.0.10')
155
+ - `imagePullPolicy` - Pull policy (default: 'IfNotPresent')
156
+ - `replicas` - Number of replicas (default: 2)
157
+ - `environment` - Environment variables (cdk8s-plus-30.Env)
158
+
159
+ **Resources:**
160
+ - `requestCpu` / `limitCpu` - CPU requests/limits
161
+ - `requestMemory` / `limitMemory` - Memory requests/limits
162
+
163
+ **High Availability:**
164
+ - `minAvailable` - Min pods during updates (for PodDisruptionBudget)
165
+ - `maxUnavailable` - Max unavailable pods during updates
166
+
167
+ **Health Probes:**
168
+ - `readinessEnabled` - Enable readiness probe (default: true)
169
+ - `readinessInitialDelaySeconds` / `readinessTimeoutSeconds` / `readinessPeriodSeconds`
170
+ - `readinessSuccessThreshold` / `readinessFailureThreshold`
171
+ - `livenessEnabled` - Enable liveness probe (default: false, recommended true for frontend)
172
+ - `livenessInitialDelaySeconds` / `livenessTimeoutSeconds` / `livenessPeriodSeconds`
173
+ - `livenessSuccessThreshold` / `livenessFailureThreshold`
174
+
175
+ **Annotations:**
176
+ - `annotations` - Deployment metadata annotations
177
+ - `podAnnotations` - Pod template annotations (e.g., for Prometheus)
178
+ - `serviceAnnotations` - Service annotations (e.g., for external-dns)
179
+
180
+ #### `PloneHttpcacheOptions`
181
+
182
+ - `plone` - Plone construct to attach cache to (required)
183
+ - `varnishVcl` - VCL configuration as string
184
+ - `varnishVclFile` - Path to VCL configuration file
185
+ - `existingSecret` - Kubernetes secret for Varnish admin credentials
186
+ - `replicas` - Number of Varnish replicas (default: 2)
187
+ - `requestCpu` / `limitCpu` - CPU resources
188
+ - `requestMemory` / `limitMemory` - Memory resources
189
+ - `servicemonitor` - Enable Prometheus ServiceMonitor (default: false)
190
+ - `exporterEnabled` - Enable Prometheus exporter sidecar (default: true)
191
+ - `chartVersion` - kube-httpcache Helm chart version (default: latest)
174
192
 
175
193
 
176
194
  ## Development
177
195
 
178
- Clone the repository and install the dependencies:
196
+ This project uses [Projen](https://projen.io/) to manage project configuration. **Do not edit generated files directly.**
197
+
198
+ ### Setup
199
+
200
+ Clone the repository and install dependencies:
179
201
 
180
202
  ```bash
181
203
  nvm use lts/*
@@ -183,11 +205,42 @@ corepack enable
183
205
  npx projen
184
206
  ```
185
207
 
186
- Then run the following command to run the test:
208
+ ### Common Commands
187
209
 
188
210
  ```bash
211
+ # Run tests
189
212
  npx projen test
213
+
214
+ # Run tests in watch mode
215
+ npx projen test:watch
216
+
217
+ # Build (compile TypeScript + generate JSII bindings)
218
+ npx projen build
219
+
220
+ # Lint
221
+ npx projen eslint
222
+
223
+ # Generate API documentation
224
+ npx projen docgen
225
+
226
+ # Package for distribution
227
+ npx projen package-all
190
228
  ```
191
229
 
192
- ## ToDo
193
- - [ ] Option to enable Servicemonitor
230
+ ### Making Changes
231
+
232
+ 1. Edit `.projenrc.ts` for project configuration changes
233
+ 2. Run `npx projen` to regenerate project files
234
+ 3. Make code changes in `src/`
235
+ 4. Run tests and update snapshots if needed: `npx projen test -- -u`
236
+
237
+ ## References
238
+
239
+ - [CDK8S Documentation](https://cdk8s.io/)
240
+ - [Kubernetes Probes Documentation](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/)
241
+ - [kube-httpcache Helm Chart](https://github.com/mittwald/kube-httpcache)
242
+ - [Example Project](https://github.com/bluedynamics/cdk8s-plone-example)
243
+
244
+ ## License
245
+
246
+ See [LICENSE](./LICENSE) file.
@@ -2,97 +2,133 @@ import * as kplus from 'cdk8s-plus-30';
2
2
  import { Construct } from 'constructs';
3
3
  import * as k8s from './imports/k8s';
4
4
  import { PlonePDBOptions } from './pdb';
5
+ /**
6
+ * Container image configuration options.
7
+ */
5
8
  export interface PloneImageOptions {
6
9
  /**
7
- * Specify a custom image for Plone .
8
- * @default ""
10
+ * Container image name and tag.
11
+ * @example 'plone/plone-backend:6.0.10'
12
+ * @default 'plone/plone-backend:latest'
9
13
  */
10
14
  readonly image?: string;
11
15
  /**
12
- * Specify Secret to pull image .
13
- * @default ""
16
+ * Names of Kubernetes secrets for pulling private images.
17
+ * @default []
14
18
  */
15
19
  readonly imagePullSecrets?: string[];
16
20
  /**
17
- * Specify Pull Policy .
18
- * @default ""
21
+ * Image pull policy (Always, IfNotPresent, Never).
22
+ * @default 'IfNotPresent'
19
23
  */
20
24
  readonly imagePullPolicy?: string;
21
25
  }
26
+ /**
27
+ * Configuration options for PloneDeployment.
28
+ */
22
29
  export interface PloneDeploymentOptions {
23
30
  /**
24
- * Specify a custom image for Plone .
25
- * @default "plone/plone-backend:latest"
31
+ * Container image configuration.
32
+ * @default 'plone/plone-backend:latest'
26
33
  */
27
34
  readonly image?: PloneImageOptions;
28
35
  /**
29
- * Specify an environment for Plone .
30
- * @default - none
31
- */
36
+ * Environment variables for the container.
37
+ * Use cdk8s-plus-30 Env to define variables and sources.
38
+ * @default - no additional environment variables
39
+ */
32
40
  readonly environment?: kplus.Env;
33
41
  /**
34
- * Number of replicas.
35
- * @default 2
36
- */
42
+ * Number of pod replicas to run.
43
+ * @default 2
44
+ */
37
45
  readonly replicas?: number;
38
46
  /**
39
- * CPU limit
40
- * @default 1
41
- */
47
+ * CPU limit for the container.
48
+ * @default '1000m'
49
+ */
42
50
  readonly limitCpu?: string;
43
51
  /**
44
- * memory limit
45
- * @default 1
46
- */
52
+ * Memory limit for the container.
53
+ * @default '1Gi'
54
+ */
47
55
  readonly limitMemory?: string;
48
56
  /**
49
- * CPU request
50
- * @default 1
51
- */
57
+ * CPU request for the container.
58
+ * @default '200m'
59
+ */
52
60
  readonly requestCpu?: string;
53
61
  /**
54
- * memory request
55
- * @default 1
56
- */
62
+ * Memory request for the container.
63
+ * @default '300Mi'
64
+ */
57
65
  readonly requestMemory?: string;
58
66
  /**
59
- * Port number.
67
+ * Container port number to expose.
60
68
  */
61
69
  readonly port: number;
62
70
  /**
63
- * Extra labels to associate with resources.
64
- * @default - none
71
+ * Additional Kubernetes labels for the deployment.
72
+ * @default - standard Plone labels only
65
73
  */
66
74
  readonly labels?: {
67
75
  [name: string]: string;
68
76
  };
69
77
  /**
70
- * Extra container spec to use for ploencontainer.
71
- * @default - []
78
+ * Annotations to add to the Deployment metadata.
79
+ * Common annotations include: deployment timestamps, change tracking, etc.
80
+ * @example { 'deployment.kubernetes.io/revision': '1' }
81
+ * @default - no additional annotations
82
+ */
83
+ readonly annotations?: {
84
+ [name: string]: string;
85
+ };
86
+ /**
87
+ * Annotations to add to the Pod template metadata.
88
+ * Common annotations include: Prometheus scraping config, Istio config,
89
+ * backup policies, logging configurations, etc.
90
+ * @example { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '8080' }
91
+ * @default - no additional annotations
92
+ */
93
+ readonly podAnnotations?: {
94
+ [name: string]: string;
95
+ };
96
+ /**
97
+ * Additional container specification overrides.
98
+ * Advanced use only - merges with generated container spec.
99
+ * @default - undefined
72
100
  */
73
101
  readonly ploneContainer?: k8s.Container;
74
102
  /**
75
- * Sidecar container spec to associate with resources.
76
- * @default - []
103
+ * Sidecar containers to run alongside the main container.
104
+ * @example [{ name: 'log-forwarder', image: 'fluentd:latest' }]
105
+ * @default []
77
106
  */
78
107
  readonly sidecars?: k8s.Container[];
79
108
  /**
80
- * Create a PodDisruptionBugdet for the deployment?
81
- * If given
82
- * @default - none
109
+ * PodDisruptionBudget configuration for high availability.
110
+ * If provided, creates a PDB with the specified constraints.
111
+ * @default - no PDB created
83
112
  */
84
113
  readonly pdb?: PlonePDBOptions;
85
114
  /**
86
- * Liveness Probe for the pod.
87
- * @default - generated
115
+ * Liveness probe configuration for the container.
116
+ * @default - undefined (no liveness probe)
88
117
  */
89
118
  livenessProbe?: k8s.Probe;
90
119
  /**
91
- * Readiness Probe for the pod.
92
- * @default - generated
120
+ * Readiness probe configuration for the container.
121
+ * @default - undefined (no readiness probe)
93
122
  */
94
123
  readinessProbe?: k8s.Probe;
95
124
  }
125
+ /**
126
+ * PloneDeployment creates a Kubernetes Deployment for Plone containers.
127
+ *
128
+ * This is an internal construct used by the Plone class.
129
+ * It creates a Deployment with configurable replicas, resources, probes,
130
+ * and an optional PodDisruptionBudget.
131
+ */
96
132
  export declare class PloneDeployment extends Construct {
97
133
  constructor(scope: Construct, id: string, options: PloneDeploymentOptions);
98
134
  }
package/lib/deployment.js CHANGED
@@ -7,6 +7,13 @@ const kplus = require("cdk8s-plus-30");
7
7
  const constructs_1 = require("constructs");
8
8
  const k8s = require("./imports/k8s");
9
9
  const pdb_1 = require("./pdb");
10
+ /**
11
+ * PloneDeployment creates a Kubernetes Deployment for Plone containers.
12
+ *
13
+ * This is an internal construct used by the Plone class.
14
+ * It creates a Deployment with configurable replicas, resources, probes,
15
+ * and an optional PodDisruptionBudget.
16
+ */
10
17
  class PloneDeployment extends constructs_1.Construct {
11
18
  constructor(scope, id, options) {
12
19
  super(scope, id);
@@ -56,6 +63,7 @@ class PloneDeployment extends constructs_1.Construct {
56
63
  const deploymentOptions = {
57
64
  metadata: {
58
65
  labels: deploymentLabels,
66
+ annotations: options.annotations,
59
67
  },
60
68
  spec: {
61
69
  replicas,
@@ -63,7 +71,10 @@ class PloneDeployment extends constructs_1.Construct {
63
71
  matchLabels: label,
64
72
  },
65
73
  template: {
66
- metadata: { labels: template_labels },
74
+ metadata: {
75
+ labels: template_labels,
76
+ annotations: options.podAnnotations,
77
+ },
67
78
  spec: {
68
79
  imagePullSecrets: (image.imagePullSecrets ?? []).map((name) => ({ name: name })),
69
80
  containers: [
@@ -82,4 +93,4 @@ class PloneDeployment extends constructs_1.Construct {
82
93
  }
83
94
  }
84
95
  exports.PloneDeployment = PloneDeployment;
85
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3ltZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUFpQztBQUNqQyxpQ0FBOEI7QUFDOUIsdUNBQXVDO0FBQ3ZDLDJDQUF1QztBQUN2QyxxQ0FBcUM7QUFDckMsK0JBQWtEO0FBNkdsRCxNQUFhLGVBQWdCLFNBQVEsc0JBQVM7SUFFNUMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxPQUErQjtRQUN2RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2xDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFHLEVBQUUsR0FBRyxFQUFFLGFBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNoRCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUMxQyxNQUFNLGdCQUFnQixHQUFHO1lBQ3ZCLHdCQUF3QixFQUFFLFlBQVksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLGFBQWE7WUFDaEYsNkJBQTZCLEVBQUUsWUFBWSxDQUFDLDZCQUE2QixDQUFDLElBQUksRUFBRSxHQUFHLGFBQWE7U0FDakcsQ0FBQztRQUNGLE1BQU0sZUFBZSxHQUFHO1lBQ3RCLEdBQUcsWUFBWTtZQUNmLEdBQUcsS0FBSztZQUNSLDJCQUEyQixFQUFFLE9BQU87WUFDcEMsOEJBQThCLEVBQUUsYUFBYTtTQUM5QyxDQUFDO1FBQ0YsTUFBTSxLQUFLLEdBQWMsT0FBTyxFQUFFLFdBQVcsSUFBSSxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksR0FBRyxHQUFpQixFQUFFLENBQUM7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bnRlbnQiOlsiLy8gaW1wb3J0IHsgbG9nIH0gZnJvbSAnY29uc29sZSc7XG5pbXBvcnQgeyBOYW1lcyB9IGZyb20gJ2NkazhzJztcbmltcG9ydCAqIGFzIGtwbHVzIGZyb20gJ2NkazhzLXBsdXMtMzAnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBrOHMgZnJvbSAnLi9pbXBvcnRzL2s4cyc7XG5pbXBvcnQgeyBQbG9uZVBEQiwgUGxvbmVQREJPcHRpb25zIH0gZnJvbSAnLi9wZGInO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBsb25lSW1hZ2VPcHRpb25zIHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgYSBjdXN0b20gaW1hZ2UgZm9yIFBsb25lIC5cbiAgICogQGRlZmF1bHQgXCJcIlxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgU2VjcmV0IHRvIHB1bGwgaW1hZ2UgLlxuICAgKiBAZGVmYXVsdCBcIlwiXG4gICAqL1xuICByZWFkb25seSBpbWFnZVB1bGxTZWNyZXRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgUHVsbCBQb2xpY3kgLlxuICAgKiBAZGVmYXVsdCBcIlwiXG4gICAqL1xuICByZWFkb25seSBpbWFnZVB1bGxQb2xpY3k/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGxvbmVEZXBsb3ltZW50T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IGEgY3VzdG9tIGltYWdlIGZvciBQbG9uZSAuXG4gICAqIEBkZWZhdWx0IFwicGxvbmUvcGxvbmUtYmFja2VuZDpsYXRlc3RcIlxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2U/OiBQbG9uZUltYWdlT3B0aW9ucztcblxuICAvKipcbiAgICogU3BlY2lmeSBhbiBlbnZpcm9ubWVudCBmb3IgUGxvbmUgLlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgKi9cbiAgcmVhZG9ubHkgZW52aXJvbm1lbnQ/OiBrcGx1cy5FbnY7XG5cbiAgLyoqXG4gKiBOdW1iZXIgb2YgcmVwbGljYXMuXG4gKiBAZGVmYXVsdCAyXG4gKi9cbiAgcmVhZG9ubHkgcmVwbGljYXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gKiBDUFUgbGltaXRcbiAqIEBkZWZhdWx0IDFcbiAqL1xuICByZWFkb25seSBsaW1pdENwdT86IHN0cmluZztcblxuICAvKipcbiAqIG1lbW9yeSBsaW1pdFxuICogQGRlZmF1bHQgMVxuICovXG4gIHJlYWRvbmx5IGxpbWl0TWVtb3J5Pzogc3RyaW5nO1xuXG4gIC8qKlxuICogQ1BVIHJlcXVlc3RcbiAqIEBkZWZhdWx0IDFcbiAqL1xuICByZWFkb25seSByZXF1ZXN0Q3B1Pzogc3RyaW5nO1xuXG4gIC8qKlxuICogbWVtb3J5IHJlcXVlc3RcbiAqIEBkZWZhdWx0IDFcbiAqL1xuICByZWFkb25seSByZXF1ZXN0TWVtb3J5Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBQb3J0IG51bWJlci5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcblxuICAvKipcbiAgICogRXh0cmEgbGFiZWxzIHRvIGFzc29jaWF0ZSB3aXRoIHJlc291cmNlcy5cbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBsYWJlbHM/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogRXh0cmEgY29udGFpbmVyIHNwZWMgdG8gdXNlIGZvciBwbG9lbmNvbnRhaW5lci5cbiAgICogQGRlZmF1bHQgLSBbXVxuICAgKi9cbiAgcmVhZG9ubHkgcGxvbmVDb250YWluZXI/OiBrOHMuQ29udGFpbmVyO1xuXG4gIC8qKlxuICAgKiBTaWRlY2FyIGNvbnRhaW5lciBzcGVjIHRvIGFzc29jaWF0ZSB3aXRoIHJlc291cmNlcy5cbiAgICogQGRlZmF1bHQgLSBbXVxuICAgKi9cbiAgcmVhZG9ubHkgc2lkZWNhcnM/OiBrOHMuQ29udGFpbmVyW107XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIFBvZERpc3J1cHRpb25CdWdkZXQgZm9yIHRoZSBkZXBsb3ltZW50P1xuICAgKiBJZiBnaXZlblxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IHBkYj86IFBsb25lUERCT3B0aW9ucztcblxuICAvKipcbiAgICogTGl2ZW5lc3MgUHJvYmUgZm9yIHRoZSBwb2QuXG4gICAqIEBkZWZhdWx0IC0gZ2VuZXJhdGVkXG4gICAqL1xuICBsaXZlbmVzc1Byb2JlPzogazhzLlByb2JlO1xuXG4gIC8qKlxuICAgKiBSZWFkaW5lc3MgUHJvYmUgZm9yIHRoZSBwb2QuXG4gICAqIEBkZWZhdWx0IC0gZ2VuZXJhdGVkXG4gICAqL1xuICByZWFkaW5lc3NQcm9iZT86IGs4cy5Qcm9iZTtcblxufVxuXG5leHBvcnQgY2xhc3MgUGxvbmVEZXBsb3ltZW50IGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBvcHRpb25zOiBQbG9uZURlcGxveW1lbnRPcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICBjb25zdCBpbWFnZSA9IG9wdGlvbnMuaW1hZ2UgPz8ge307XG4gICAgY29uc3QgcmVwbGljYXMgPSBvcHRpb25zLnJlcGxpY2FzID8/IDI7XG4gICAgY29uc3QgbGFiZWwgPSB7IGFwcDogTmFtZXMudG9MYWJlbFZhbHVlKHRoaXMpIH07XG4gICAgY29uc3Qgb3B0aW9uTGFiZWxzID0gb3B0aW9ucy5sYWJlbHMgPz8ge307XG4gICAgY29uc3QgZGVwbG95bWVudExhYmVscyA9IHtcbiAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogb3B0aW9uTGFiZWxzWydhcHAua3ViZXJuZXRlcy5pby9uYW1lJ10gKyAnLWRlcGxveW1lbnQnLFxuICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL2NvbXBvbmVudCc6IG9wdGlvbkxhYmVsc1snYXBwLmt1YmVybmV0ZXMuaW8vY29tcG9uZW50J10gPz8gJycgKyAnLWRlcGxveW1lbnQnLFxuICAgIH07XG4gICAgY29uc3QgdGVtcGxhdGVfbGFiZWxzID0ge1xuICAgICAgLi4ub3B0aW9uTGFiZWxzLFxuICAgICAgLi4ubGFiZWwsXG4gICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vcGFydC1vZic6ICdwbG9uZScsXG4gICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbWFuYWdlZC1ieSc6ICdjZGs4cy1wbG9uZScsXG4gICAgfTtcbiAgICBjb25zdCBrcEVudjoga3BsdXMuRW52ID0gb3B0aW9ucz8uZW52aXJvbm1lbnQgPz8gbmV3IGtwbHVzLkVudihbXSwge30pO1xuICAgIHZhciBlbnY6IGs4cy5FbnZWYXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgbmFtZSBpbiBrcEVudi52YXJpYWJsZXMpIHtcbiAgICAgIGVudi5wdXNoKHsgbmFtZTogbmFtZSwgdmFsdWU6IGtwRW52LnZhcmlhYmxlc1tuYW1lXS52YWx1ZSwgdmFsdWVGcm9tOiBrcEVudi52YXJpYWJsZXNbbmFtZV0udmFsdWVGcm9tIH0pO1xuICAgIH1cbiAgICB2YXIgZW52RnJvbTogazhzLkVudkZyb21Tb3VyY2VbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaWR4IGluIGtwRW52LnNvdXJjZXMpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGtwRW52LnNvdXJjZXNbaWR4XTtcbiAgICAgIGVudkZyb20ucHVzaChzb3VyY2UuX3RvS3ViZSgpKTtcbiAgICB9XG4gICAgdmFyIHBsb25lQ29udGFpbmVyU3BlYzogazhzLkNvbnRhaW5lciA9IHtcbiAgICAgIG5hbWU6IGlkICsgJy1jb250YWluZXInLCAvLyBoZXJlIHRoZSBuYW1lc3BhY2VkIG5hbWUgc2hvbGQgYmUgdXNlZCwgYnV0IGhvdz9cbiAgICAgIGltYWdlOiBpbWFnZS5pbWFnZSxcbiAgICAgIGltYWdlUHVsbFBvbGljeTogaW1hZ2UuaW1hZ2VQdWxsUG9saWN5LFxuICAgICAgZW52OiBlbnYsXG4gICAgICBlbnZGcm9tOiBlbnZGcm9tLFxuICAgICAgcmVzb3VyY2VzOiB7XG4gICAgICAgIGxpbWl0czoge1xuICAgICAgICAgIGNwdTogazhzLlF1YW50aXR5LmZyb21TdHJpbmcob3B0aW9ucy5saW1pdENwdSA/PyAnMTAwMG0nKSxcbiAgICAgICAgICBtZW1vcnk6IGs4cy5RdWFudGl0eS5mcm9tU3RyaW5nKG9wdGlvbnMubGltaXRNZW1vcnkgPz8gJzFHaScpLFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0czoge1xuICAgICAgICAgIGNwdTogazhzLlF1YW50aXR5LmZyb21TdHJpbmcob3B0aW9ucy5yZXF1ZXN0Q3B1ID8/ICcyMDBtJyksXG4gICAgICAgICAgbWVtb3J5OiBrOHMuUXVhbnRpdHkuZnJvbVN0cmluZyhvcHRpb25zLnJlcXVlc3RNZW1vcnkgPz8gJzMwME1pJyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbGl2ZW5lc3NQcm9iZTogb3B0aW9ucy5saXZlbmVzc1Byb2JlID8/IHVuZGVmaW5lZCxcbiAgICAgIHJlYWRpbmVzc1Byb2JlOiBvcHRpb25zLnJlYWRpbmVzc1Byb2JlID8/IHVuZGVmaW5lZCxcbiAgICB9O1xuICAgIGNvbnN0IGRlcGxveW1lbnRPcHRpb25zOiBrOHMuS3ViZURlcGxveW1lbnRQcm9wcyA9IHtcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIGxhYmVsczogZGVwbG95bWVudExhYmVscyxcbiAgICAgIH0sXG4gICAgICBzcGVjOiB7XG4gICAgICAgIHJlcGxpY2FzLFxuICAgICAgICBzZWxlY3Rvcjoge1xuICAgICAgICAgIG1hdGNoTGFiZWxzOiBsYWJlbCxcbiAgICAgICAgfSxcbiAgICAgICAgdGVtcGxhdGU6IHtcbiAgICAgICAgICBtZXRhZGF0YTogeyBsYWJlbHM6IHRlbXBsYXRlX2xhYmVscyB9LFxuICAgICAgICAgIHNwZWM6IHtcbiAgICAgICAgICAgIGltYWdlUHVsbFNlY3JldHM6IChpbWFnZS5pbWFnZVB1bGxTZWNyZXRzID8/IFtdKS5tYXAoKG5hbWUpID0+ICh7IG5hbWU6IG5hbWUgfSkpLFxuICAgICAgICAgICAgY29udGFpbmVyczogW1xuICAgICAgICAgICAgICBwbG9uZUNvbnRhaW5lclNwZWMsXG4gICAgICAgICAgICAgIC4uLm9wdGlvbnMuc2lkZWNhcnMgPz8gW10sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBuZXcgazhzLkt1YmVEZXBsb3ltZW50KHRoaXMsICdkZXBsb3ltZW50JywgZGVwbG95bWVudE9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnMucGRiID8/IGZhbHNlKSB7XG4gICAgICBjb25zdCBwZGJPcHRpb25zID0gb3B0aW9ucy5wZGIgPz8ge307XG4gICAgICBuZXcgUGxvbmVQREIodGhpcywgJ3BkYicsIGxhYmVsLCBwZGJPcHRpb25zKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
96
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3ltZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUFpQztBQUNqQyxpQ0FBOEI7QUFDOUIsdUNBQXVDO0FBQ3ZDLDJDQUF1QztBQUN2QyxxQ0FBcUM7QUFDckMsK0JBQWtEO0FBdUlsRDs7Ozs7O0dBTUc7QUFDSCxNQUFhLGVBQWdCLFNBQVEsc0JBQVM7SUFFNUMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxPQUErQjtRQUN2RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2xDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFHLEVBQUUsR0FBRyxFQUFFLGFBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNoRCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUMxQyxNQUFNLGdCQUFnQixHQUFHO1lBQ3ZCLHdCQUF3QixFQUFFLFlBQVksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLGFBQWE7WUFDaEYsNkJBQTZCLEVBQUUsWUFBWSxDQUFDLDZCQUE2QixDQUFDLElBQUksRUFBRSxHQUFHLGFBQWE7U0FDakcsQ0FBQztRQUNGLE1BQU0sZUFBZSxHQUFHO1lBQ3RCLEdBQUcsWUFBWTtZQUNmLEdBQUcsS0FBSztZQUNSLDJCQUEyQixFQUFFLE9BQU87WUFDcEMsOEJBQThCLEVBQUUsYUFBYTtTQUM5QyxDQUFDO1FBQ0YsTUFBTSxLQUFLLEdBQWMsT0FBTyxFQUFFLFdBQVcsSUFBSSxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksR0FBRyxH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LEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFoRkQsMENBZ0ZDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IHsgbG9nIH0gZnJvbSAnY29uc29sZSc7XG5pbXBvcnQgeyBOYW1lcyB9IGZyb20gJ2NkazhzJztcbmltcG9ydCAqIGFzIGtwbHVzIGZyb20gJ2NkazhzLXBsdXMtMzAnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBrOHMgZnJvbSAnLi9pbXBvcnRzL2s4cyc7XG5pbXBvcnQgeyBQbG9uZVBEQiwgUGxvbmVQREJPcHRpb25zIH0gZnJvbSAnLi9wZGInO1xuXG4vKipcbiAqIENvbnRhaW5lciBpbWFnZSBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGxvbmVJbWFnZU9wdGlvbnMge1xuICAvKipcbiAgICogQ29udGFpbmVyIGltYWdlIG5hbWUgYW5kIHRhZy5cbiAgICogQGV4YW1wbGUgJ3Bsb25lL3Bsb25lLWJhY2tlbmQ6Ni4wLjEwJ1xuICAgKiBAZGVmYXVsdCAncGxvbmUvcGxvbmUtYmFja2VuZDpsYXRlc3QnXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IHN0cmluZztcblxuICAvKipcbiAgICogTmFtZXMgb2YgS3ViZXJuZXRlcyBzZWNyZXRzIGZvciBwdWxsaW5nIHByaXZhdGUgaW1hZ2VzLlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VQdWxsU2VjcmV0cz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBJbWFnZSBwdWxsIHBvbGljeSAoQWx3YXlzLCBJZk5vdFByZXNlbnQsIE5ldmVyKS5cbiAgICogQGRlZmF1bHQgJ0lmTm90UHJlc2VudCdcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlUHVsbFBvbGljeT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIFBsb25lRGVwbG95bWVudC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbG9uZURlcGxveW1lbnRPcHRpb25zIHtcbiAgLyoqXG4gICAqIENvbnRhaW5lciBpbWFnZSBjb25maWd1cmF0aW9uLlxuICAgKiBAZGVmYXVsdCAncGxvbmUvcGxvbmUtYmFja2VuZDpsYXRlc3QnXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IFBsb25lSW1hZ2VPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgZm9yIHRoZSBjb250YWluZXIuXG4gICAqIFVzZSBjZGs4cy1wbHVzLTMwIEVudiB0byBkZWZpbmUgdmFyaWFibGVzIGFuZCBzb3VyY2VzLlxuICAgKiBAZGVmYXVsdCAtIG5vIGFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IGtwbHVzLkVudjtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHBvZCByZXBsaWNhcyB0byBydW4uXG4gICAqIEBkZWZhdWx0IDJcbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2FzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBDUFUgbGltaXQgZm9yIHRoZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0ICcxMDAwbSdcbiAgICovXG4gIHJlYWRvbmx5IGxpbWl0Q3B1Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBNZW1vcnkgbGltaXQgZm9yIHRoZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0ICcxR2knXG4gICAqL1xuICByZWFkb25seSBsaW1pdE1lbW9yeT86IHN0cmluZztcblxuICAvKipcbiAgICogQ1BVIHJlcXVlc3QgZm9yIHRoZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0ICcyMDBtJ1xuICAgKi9cbiAgcmVhZG9ubHkgcmVxdWVzdENwdT86IHN0cmluZztcblxuICAvKipcbiAgICogTWVtb3J5IHJlcXVlc3QgZm9yIHRoZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0ICczMDBNaSdcbiAgICovXG4gIHJlYWRvbmx5IHJlcXVlc3RNZW1vcnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENvbnRhaW5lciBwb3J0IG51bWJlciB0byBleHBvc2UuXG4gICAqL1xuICByZWFkb25seSBwb3J0OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgS3ViZXJuZXRlcyBsYWJlbHMgZm9yIHRoZSBkZXBsb3ltZW50LlxuICAgKiBAZGVmYXVsdCAtIHN0YW5kYXJkIFBsb25lIGxhYmVscyBvbmx5XG4gICAqL1xuICByZWFkb25seSBsYWJlbHM/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogQW5ub3RhdGlvbnMgdG8gYWRkIHRvIHRoZSBEZXBsb3ltZW50IG1ldGFkYXRhLlxuICAgKiBDb21tb24gYW5ub3RhdGlvbnMgaW5jbHVkZTogZGVwbG95bWVudCB0aW1lc3RhbXBzLCBjaGFuZ2UgdHJhY2tpbmcsIGV0Yy5cbiAgICogQGV4YW1wbGUgeyAnZGVwbG95bWVudC5rdWJlcm5ldGVzLmlvL3JldmlzaW9uJzogJzEnIH1cbiAgICogQGRlZmF1bHQgLSBubyBhZGRpdGlvbmFsIGFubm90YXRpb25zXG4gICAqL1xuICByZWFkb25seSBhbm5vdGF0aW9ucz86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBBbm5vdGF0aW9ucyB0byBhZGQgdG8gdGhlIFBvZCB0ZW1wbGF0ZSBtZXRhZGF0YS5cbiAgICogQ29tbW9uIGFubm90YXRpb25zIGluY2x1ZGU6IFByb21ldGhldXMgc2NyYXBpbmcgY29uZmlnLCBJc3RpbyBjb25maWcsXG4gICAqIGJhY2t1cCBwb2xpY2llcywgbG9nZ2luZyBjb25maWd1cmF0aW9ucywgZXRjLlxuICAgKiBAZXhhbXBsZSB7ICdwcm9tZXRoZXVzLmlvL3NjcmFwZSc6ICd0cnVlJywgJ3Byb21ldGhldXMuaW8vcG9ydCc6ICc4MDgwJyB9XG4gICAqIEBkZWZhdWx0IC0gbm8gYWRkaXRpb25hbCBhbm5vdGF0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgcG9kQW5ub3RhdGlvbnM/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBjb250YWluZXIgc3BlY2lmaWNhdGlvbiBvdmVycmlkZXMuXG4gICAqIEFkdmFuY2VkIHVzZSBvbmx5IC0gbWVyZ2VzIHdpdGggZ2VuZXJhdGVkIGNvbnRhaW5lciBzcGVjLlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcGxvbmVDb250YWluZXI/OiBrOHMuQ29udGFpbmVyO1xuXG4gIC8qKlxuICAgKiBTaWRlY2FyIGNvbnRhaW5lcnMgdG8gcnVuIGFsb25nc2lkZSB0aGUgbWFpbiBjb250YWluZXIuXG4gICAqIEBleGFtcGxlIFt7IG5hbWU6ICdsb2ctZm9yd2FyZGVyJywgaW1hZ2U6ICdmbHVlbnRkOmxhdGVzdCcgfV1cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHJlYWRvbmx5IHNpZGVjYXJzPzogazhzLkNvbnRhaW5lcltdO1xuXG4gIC8qKlxuICAgKiBQb2REaXNydXB0aW9uQnVkZ2V0IGNvbmZpZ3VyYXRpb24gZm9yIGhpZ2ggYXZhaWxhYmlsaXR5LlxuICAgKiBJZiBwcm92aWRlZCwgY3JlYXRlcyBhIFBEQiB3aXRoIHRoZSBzcGVjaWZpZWQgY29uc3RyYWludHMuXG4gICAqIEBkZWZhdWx0IC0gbm8gUERCIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHBkYj86IFBsb25lUERCT3B0aW9ucztcblxuICAvKipcbiAgICogTGl2ZW5lc3MgcHJvYmUgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNvbnRhaW5lci5cbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWQgKG5vIGxpdmVuZXNzIHByb2JlKVxuICAgKi9cbiAgbGl2ZW5lc3NQcm9iZT86IGs4cy5Qcm9iZTtcblxuICAvKipcbiAgICogUmVhZGluZXNzIHByb2JlIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkIChubyByZWFkaW5lc3MgcHJvYmUpXG4gICAqL1xuICByZWFkaW5lc3NQcm9iZT86IGs4cy5Qcm9iZTtcbn1cblxuLyoqXG4gKiBQbG9uZURlcGxveW1lbnQgY3JlYXRlcyBhIEt1YmVybmV0ZXMgRGVwbG95bWVudCBmb3IgUGxvbmUgY29udGFpbmVycy5cbiAqXG4gKiBUaGlzIGlzIGFuIGludGVybmFsIGNvbnN0cnVjdCB1c2VkIGJ5IHRoZSBQbG9uZSBjbGFzcy5cbiAqIEl0IGNyZWF0ZXMgYSBEZXBsb3ltZW50IHdpdGggY29uZmlndXJhYmxlIHJlcGxpY2FzLCByZXNvdXJjZXMsIHByb2JlcyxcbiAqIGFuZCBhbiBvcHRpb25hbCBQb2REaXNydXB0aW9uQnVkZ2V0LlxuICovXG5leHBvcnQgY2xhc3MgUGxvbmVEZXBsb3ltZW50IGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBvcHRpb25zOiBQbG9uZURlcGxveW1lbnRPcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICBjb25zdCBpbWFnZSA9IG9wdGlvbnMuaW1hZ2UgPz8ge307XG4gICAgY29uc3QgcmVwbGljYXMgPSBvcHRpb25zLnJlcGxpY2FzID8/IDI7XG4gICAgY29uc3QgbGFiZWwgPSB7IGFwcDogTmFtZXMudG9MYWJlbFZhbHVlKHRoaXMpIH07XG4gICAgY29uc3Qgb3B0aW9uTGFiZWxzID0gb3B0aW9ucy5sYWJlbHMgPz8ge307XG4gICAgY29uc3QgZGVwbG95bWVudExhYmVscyA9IHtcbiAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogb3B0aW9uTGFiZWxzWydhcHAua3ViZXJuZXRlcy5pby9uYW1lJ10gKyAnLWRlcGxveW1lbnQnLFxuICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL2NvbXBvbmVudCc6IG9wdGlvbkxhYmVsc1snYXBwLmt1YmVybmV0ZXMuaW8vY29tcG9uZW50J10gPz8gJycgKyAnLWRlcGxveW1lbnQnLFxuICAgIH07XG4gICAgY29uc3QgdGVtcGxhdGVfbGFiZWxzID0ge1xuICAgICAgLi4ub3B0aW9uTGFiZWxzLFxuICAgICAgLi4ubGFiZWwsXG4gICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vcGFydC1vZic6ICdwbG9uZScsXG4gICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbWFuYWdlZC1ieSc6ICdjZGs4cy1wbG9uZScsXG4gICAgfTtcbiAgICBjb25zdCBrcEVudjoga3BsdXMuRW52ID0gb3B0aW9ucz8uZW52aXJvbm1lbnQgPz8gbmV3IGtwbHVzLkVudihbXSwge30pO1xuICAgIHZhciBlbnY6IGs4cy5FbnZWYXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgbmFtZSBpbiBrcEVudi52YXJpYWJsZXMpIHtcbiAgICAgIGVudi5wdXNoKHsgbmFtZTogbmFtZSwgdmFsdWU6IGtwRW52LnZhcmlhYmxlc1tuYW1lXS52YWx1ZSwgdmFsdWVGcm9tOiBrcEVudi52YXJpYWJsZXNbbmFtZV0udmFsdWVGcm9tIH0pO1xuICAgIH1cbiAgICB2YXIgZW52RnJvbTogazhzLkVudkZyb21Tb3VyY2VbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaWR4IGluIGtwRW52LnNvdXJjZXMpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGtwRW52LnNvdXJjZXNbaWR4XTtcbiAgICAgIGVudkZyb20ucHVzaChzb3VyY2UuX3RvS3ViZSgpKTtcbiAgICB9XG4gICAgdmFyIHBsb25lQ29udGFpbmVyU3BlYzogazhzLkNvbnRhaW5lciA9IHtcbiAgICAgIG5hbWU6IGlkICsgJy1jb250YWluZXInLCAvLyBoZXJlIHRoZSBuYW1lc3BhY2VkIG5hbWUgc2hvbGQgYmUgdXNlZCwgYnV0IGhvdz9cbiAgICAgIGltYWdlOiBpbWFnZS5pbWFnZSxcbiAgICAgIGltYWdlUHVsbFBvbGljeTogaW1hZ2UuaW1hZ2VQdWxsUG9saWN5LFxuICAgICAgZW52OiBlbnYsXG4gICAgICBlbnZGcm9tOiBlbnZGcm9tLFxuICAgICAgcmVzb3VyY2VzOiB7XG4gICAgICAgIGxpbWl0czoge1xuICAgICAgICAgIGNwdTogazhzLlF1YW50aXR5LmZyb21TdHJpbmcob3B0aW9ucy5saW1pdENwdSA/PyAnMTAwMG0nKSxcbiAgICAgICAgICBtZW1vcnk6IGs4cy5RdWFudGl0eS5mcm9tU3RyaW5nKG9wdGlvbnMubGltaXRNZW1vcnkgPz8gJzFHaScpLFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0czoge1xuICAgICAgICAgIGNwdTogazhzLlF1YW50aXR5LmZyb21TdHJpbmcob3B0aW9ucy5yZXF1ZXN0Q3B1ID8/ICcyMDBtJyksXG4gICAgICAgICAgbWVtb3J5OiBrOHMuUXVhbnRpdHkuZnJvbVN0cmluZyhvcHRpb25zLnJlcXVlc3RNZW1vcnkgPz8gJzMwME1pJyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbGl2ZW5lc3NQcm9iZTogb3B0aW9ucy5saXZlbmVzc1Byb2JlID8/IHVuZGVmaW5lZCxcbiAgICAgIHJlYWRpbmVzc1Byb2JlOiBvcHRpb25zLnJlYWRpbmVzc1Byb2JlID8/IHVuZGVmaW5lZCxcbiAgICB9O1xuICAgIGNvbnN0IGRlcGxveW1lbnRPcHRpb25zOiBrOHMuS3ViZURlcGxveW1lbnRQcm9wcyA9IHtcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIGxhYmVsczogZGVwbG95bWVudExhYmVscyxcbiAgICAgICAgYW5ub3RhdGlvbnM6IG9wdGlvbnMuYW5ub3RhdGlvbnMsXG4gICAgICB9LFxuICAgICAgc3BlYzoge1xuICAgICAgICByZXBsaWNhcyxcbiAgICAgICAgc2VsZWN0b3I6IHtcbiAgICAgICAgICBtYXRjaExhYmVsczogbGFiZWwsXG4gICAgICAgIH0sXG4gICAgICAgIHRlbXBsYXRlOiB7XG4gICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgIGxhYmVsczogdGVtcGxhdGVfbGFiZWxzLFxuICAgICAgICAgICAgYW5ub3RhdGlvbnM6IG9wdGlvbnMucG9kQW5ub3RhdGlvbnMsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzcGVjOiB7XG4gICAgICAgICAgICBpbWFnZVB1bGxTZWNyZXRzOiAoaW1hZ2UuaW1hZ2VQdWxsU2VjcmV0cyA/PyBbXSkubWFwKChuYW1lKSA9PiAoeyBuYW1lOiBuYW1lIH0pKSxcbiAgICAgICAgICAgIGNvbnRhaW5lcnM6IFtcbiAgICAgICAgICAgICAgcGxvbmVDb250YWluZXJTcGVjLFxuICAgICAgICAgICAgICAuLi5vcHRpb25zLnNpZGVjYXJzID8/IFtdLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgbmV3IGs4cy5LdWJlRGVwbG95bWVudCh0aGlzLCAnZGVwbG95bWVudCcsIGRlcGxveW1lbnRPcHRpb25zKTtcblxuICAgIGlmIChvcHRpb25zLnBkYiA/PyBmYWxzZSkge1xuICAgICAgY29uc3QgcGRiT3B0aW9ucyA9IG9wdGlvbnMucGRiID8/IHt9O1xuICAgICAgbmV3IFBsb25lUERCKHRoaXMsICdwZGInLCBsYWJlbCwgcGRiT3B0aW9ucyk7XG4gICAgfVxuICB9XG59XG4iXX0=