projen 0.67.26 → 0.67.28

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.
Files changed (138) hide show
  1. package/.jsii +624 -135
  2. package/docs/api/API.md +155 -0
  3. package/lib/awscdk/auto-discover.js +5 -5
  4. package/lib/awscdk/awscdk-app-java.js +1 -1
  5. package/lib/awscdk/awscdk-app-py.js +1 -1
  6. package/lib/awscdk/awscdk-app-ts.js +1 -1
  7. package/lib/awscdk/awscdk-construct.js +2 -2
  8. package/lib/awscdk/awscdk-deps-java.js +1 -1
  9. package/lib/awscdk/awscdk-deps-js.js +1 -1
  10. package/lib/awscdk/awscdk-deps-py.js +1 -1
  11. package/lib/awscdk/awscdk-deps.js +1 -1
  12. package/lib/awscdk/cdk-config.js +1 -1
  13. package/lib/awscdk/cdk-tasks.js +1 -1
  14. package/lib/awscdk/integration-test.js +1 -1
  15. package/lib/awscdk/lambda-extension.js +1 -1
  16. package/lib/awscdk/lambda-function.js +2 -2
  17. package/lib/build/build-workflow.js +1 -1
  18. package/lib/cdk/auto-discover-base.js +2 -2
  19. package/lib/cdk/construct-lib.js +1 -1
  20. package/lib/cdk/integration-test-base.js +1 -1
  21. package/lib/cdk/jsii-docgen.js +1 -1
  22. package/lib/cdk/jsii-project.js +1 -1
  23. package/lib/cdk8s/auto-discover.js +2 -2
  24. package/lib/cdk8s/cdk8s-app-py.js +1 -1
  25. package/lib/cdk8s/cdk8s-app-ts.js +1 -1
  26. package/lib/cdk8s/cdk8s-construct.js +1 -1
  27. package/lib/cdk8s/cdk8s-deps-py.js +1 -1
  28. package/lib/cdk8s/cdk8s-deps.js +1 -1
  29. package/lib/cdk8s/integration-test.js +1 -1
  30. package/lib/cdktf/cdktf-construct.js +1 -1
  31. package/lib/circleci/circleci.js +1 -1
  32. package/lib/component.js +1 -1
  33. package/lib/dependencies.js +1 -1
  34. package/lib/dev-env.js +1 -1
  35. package/lib/docker-compose/docker-compose-network.d.ts +103 -0
  36. package/lib/docker-compose/docker-compose-network.js +3 -0
  37. package/lib/docker-compose/docker-compose-port.d.ts +44 -0
  38. package/lib/docker-compose/docker-compose-port.js +18 -0
  39. package/lib/docker-compose/docker-compose-render.d.ts +2 -0
  40. package/lib/docker-compose/docker-compose-render.js +129 -0
  41. package/lib/docker-compose/docker-compose-service.d.ts +132 -0
  42. package/lib/docker-compose/docker-compose-service.js +68 -0
  43. package/lib/docker-compose/docker-compose-volume.d.ts +64 -0
  44. package/lib/docker-compose/docker-compose-volume.js +3 -0
  45. package/lib/docker-compose/docker-compose.d.ts +99 -0
  46. package/lib/docker-compose/docker-compose.js +133 -0
  47. package/lib/docker-compose/index.d.ts +5 -0
  48. package/lib/docker-compose/index.js +18 -0
  49. package/lib/file.js +1 -1
  50. package/lib/gitattributes.js +1 -1
  51. package/lib/github/auto-approve.js +1 -1
  52. package/lib/github/auto-merge.js +1 -1
  53. package/lib/github/dependabot.js +1 -1
  54. package/lib/github/github-credentials.js +1 -1
  55. package/lib/github/github-project.js +1 -1
  56. package/lib/github/github.js +1 -1
  57. package/lib/github/mergify.js +1 -1
  58. package/lib/github/pr-template.js +1 -1
  59. package/lib/github/pull-request-lint.js +1 -1
  60. package/lib/github/stale.js +1 -1
  61. package/lib/github/task-workflow.js +1 -1
  62. package/lib/github/workflows.js +1 -1
  63. package/lib/gitlab/configuration.js +1 -1
  64. package/lib/gitlab/gitlab-configuration.js +1 -1
  65. package/lib/gitlab/nested-configuration.js +1 -1
  66. package/lib/gitpod.js +1 -1
  67. package/lib/ignore-file.js +1 -1
  68. package/lib/ini.js +1 -1
  69. package/lib/java/java-project.js +1 -1
  70. package/lib/java/junit.js +1 -1
  71. package/lib/java/maven-compile.js +1 -1
  72. package/lib/java/maven-packaging.js +1 -1
  73. package/lib/java/maven-sample.js +1 -1
  74. package/lib/java/pom.js +1 -1
  75. package/lib/java/projenrc.js +1 -1
  76. package/lib/javascript/bundler.js +1 -1
  77. package/lib/javascript/eslint.js +1 -1
  78. package/lib/javascript/jest.js +1 -1
  79. package/lib/javascript/node-package.js +1 -1
  80. package/lib/javascript/node-project.js +1 -1
  81. package/lib/javascript/npm-config.js +1 -1
  82. package/lib/javascript/prettier.js +1 -1
  83. package/lib/javascript/projenrc.js +1 -1
  84. package/lib/javascript/typescript-config.js +1 -1
  85. package/lib/javascript/upgrade-dependencies.js +2 -2
  86. package/lib/json-patch.js +1 -1
  87. package/lib/json.js +1 -1
  88. package/lib/license.js +1 -1
  89. package/lib/logger.js +1 -1
  90. package/lib/makefile.js +1 -1
  91. package/lib/object-file.js +1 -1
  92. package/lib/project-build.js +1 -1
  93. package/lib/project.js +1 -1
  94. package/lib/projects.js +1 -1
  95. package/lib/projenrc-json.js +1 -1
  96. package/lib/python/pip.js +1 -1
  97. package/lib/python/poetry.js +2 -2
  98. package/lib/python/projenrc.js +1 -1
  99. package/lib/python/pytest-sample.js +1 -1
  100. package/lib/python/pytest.js +1 -1
  101. package/lib/python/python-project.js +1 -1
  102. package/lib/python/python-sample.js +1 -1
  103. package/lib/python/requirements-file.js +1 -1
  104. package/lib/python/setuppy.js +1 -1
  105. package/lib/python/setuptools.js +1 -1
  106. package/lib/python/venv.js +1 -1
  107. package/lib/readme.js +1 -1
  108. package/lib/release/publisher.js +1 -1
  109. package/lib/release/release-trigger.js +1 -1
  110. package/lib/release/release.js +1 -1
  111. package/lib/renovatebot.js +1 -1
  112. package/lib/sample-file.js +2 -2
  113. package/lib/semver.js +1 -1
  114. package/lib/source-code.js +1 -1
  115. package/lib/task-runtime.js +1 -1
  116. package/lib/task.js +1 -1
  117. package/lib/tasks.js +1 -1
  118. package/lib/testing.js +1 -1
  119. package/lib/textfile.js +1 -1
  120. package/lib/toml.js +1 -1
  121. package/lib/typescript/projenrc.js +1 -1
  122. package/lib/typescript/typescript-typedoc.js +1 -1
  123. package/lib/typescript/typescript.js +3 -3
  124. package/lib/version.js +1 -1
  125. package/lib/vscode/devcontainer.js +1 -1
  126. package/lib/vscode/extensions.js +1 -1
  127. package/lib/vscode/launch-config.js +1 -1
  128. package/lib/vscode/settings.js +1 -1
  129. package/lib/vscode/vscode.js +1 -1
  130. package/lib/web/next.js +3 -3
  131. package/lib/web/postcss.js +1 -1
  132. package/lib/web/react.js +4 -4
  133. package/lib/web/tailwind.js +1 -1
  134. package/lib/xmlfile.js +1 -1
  135. package/lib/yaml.js +1 -1
  136. package/package.json +1 -1
  137. package/lib/docker-compose.d.ts +0 -308
  138. package/lib/docker-compose.js +0 -284
@@ -1,308 +0,0 @@
1
- import { Component } from "./component";
2
- import { Project } from "./project";
3
- /**
4
- * Props for DockerCompose.
5
- */
6
- export interface DockerComposeProps {
7
- /**
8
- * A name to add to the docker-compose.yml filename.
9
- * @example 'myname' yields 'docker-compose.myname.yml'
10
- * @default - no name is added
11
- */
12
- readonly nameSuffix?: string;
13
- /**
14
- * Docker Compose schema version do be used
15
- * @default 3.3
16
- */
17
- readonly schemaVersion?: string;
18
- /**
19
- * Service descriptions.
20
- */
21
- readonly services?: Record<string, DockerComposeServiceDescription>;
22
- }
23
- /**
24
- * Options for port mappings.
25
- */
26
- export interface DockerComposePortMappingOptions {
27
- /**
28
- * Port mapping protocol.
29
- * @default DockerComposeProtocol.TCP
30
- */
31
- readonly protocol?: DockerComposeProtocol;
32
- }
33
- /**
34
- * Create a docker-compose YAML file.
35
- */
36
- export declare class DockerCompose extends Component {
37
- /**
38
- * Depends on a service name.
39
- */
40
- static serviceName(serviceName: string): IDockerComposeServiceName;
41
- /**
42
- * Create a port mapping.
43
- * @param publishedPort Published port number
44
- * @param targetPort Container's port number
45
- * @param options Port mapping options
46
- */
47
- static portMapping(publishedPort: number, targetPort: number, options?: DockerComposePortMappingOptions): DockerComposeServicePort;
48
- /**
49
- * Create a bind volume that binds a host path to the target path in the container.
50
- * @param sourcePath Host path name
51
- * @param targetPath Target path name
52
- */
53
- static bindVolume(sourcePath: string, targetPath: string): IDockerComposeVolumeBinding;
54
- /**
55
- * Create a named volume and mount it to the target path. If you use this
56
- * named volume in several services, the volume will be shared. In this
57
- * case, the volume configuration of the first-provided options are used.
58
- *
59
- * @param volumeName Name of the volume
60
- * @param targetPath Target path
61
- * @param options volume configuration (default: docker compose defaults)
62
- */
63
- static namedVolume(volumeName: string, targetPath: string, options?: DockerComposeVolumeConfig): IDockerComposeVolumeBinding;
64
- private readonly services;
65
- private readonly version;
66
- constructor(project: Project, props?: DockerComposeProps);
67
- /**
68
- * Add a service to the docker-compose file.
69
- * @param serviceName name of the service
70
- * @param description a service description
71
- */
72
- addService(serviceName: string, description: DockerComposeServiceDescription): DockerComposeService;
73
- /**
74
- * @internal
75
- */
76
- _synthesizeDockerCompose(): object;
77
- }
78
- /**
79
- * An interface providing the name of a docker compose service.
80
- */
81
- export interface IDockerComposeServiceName {
82
- /**
83
- * The name of the docker compose service.
84
- */
85
- readonly serviceName: string;
86
- }
87
- /**
88
- * Description of a docker-compose.yml service.
89
- */
90
- export interface DockerComposeServiceDescription {
91
- /**
92
- * Use a docker image.
93
- * Note: You must specify either `build` or `image` key.
94
- * @see imageBuild
95
- */
96
- readonly image?: string;
97
- /**
98
- * Build a docker image.
99
- * Note: You must specify either `imageBuild` or `image` key.
100
- * @see image
101
- */
102
- readonly imageBuild?: DockerComposeBuild;
103
- /**
104
- * Provide a command to the docker container.
105
- * @default - use the container's default command
106
- */
107
- readonly command?: string[];
108
- /**
109
- * Names of other services this service depends on.
110
- * @default - no dependencies
111
- */
112
- readonly dependsOn?: IDockerComposeServiceName[];
113
- /**
114
- * Mount some volumes into the service.
115
- * Use one of the following to create volumes:
116
- * @see DockerCompose.bindVolume() to mount a host path
117
- * @see DockerCompose.namedVolume() to create & mount a named volume
118
- */
119
- readonly volumes?: IDockerComposeVolumeBinding[];
120
- /**
121
- * Map some ports.
122
- * @default - no ports are mapped
123
- */
124
- readonly ports?: DockerComposeServicePort[];
125
- /**
126
- * Add environment variables.
127
- * @default - no environment variables are provided
128
- */
129
- readonly environment?: Record<string, string>;
130
- }
131
- /**
132
- * A docker-compose service.
133
- */
134
- export declare class DockerComposeService implements IDockerComposeServiceName {
135
- /**
136
- * Name of the service.
137
- */
138
- readonly serviceName: string;
139
- /**
140
- * Docker image.
141
- */
142
- readonly image?: string;
143
- /**
144
- * Docker image build instructions.
145
- */
146
- readonly imageBuild?: DockerComposeBuild;
147
- /**
148
- * Command to run in the container.
149
- */
150
- readonly command?: string[];
151
- /**
152
- * Other services that this service depends on.
153
- */
154
- readonly dependsOn: IDockerComposeServiceName[];
155
- /**
156
- * Volumes mounted in the container.
157
- */
158
- readonly volumes: IDockerComposeVolumeBinding[];
159
- /**
160
- * Published ports.
161
- */
162
- readonly ports: DockerComposeServicePort[];
163
- /**
164
- * Environment variables.
165
- */
166
- readonly environment: Record<string, string>;
167
- constructor(serviceName: string, serviceDescription: DockerComposeServiceDescription);
168
- /**
169
- * Add a port mapping
170
- * @param publishedPort Published port number
171
- * @param targetPort Container's port number
172
- * @param options Port mapping options
173
- */
174
- addPort(publishedPort: number, targetPort: number, options?: DockerComposePortMappingOptions): void;
175
- /**
176
- * Add an environment variable
177
- * @param name environment variable name
178
- * @param value value of the environment variable
179
- */
180
- addEnvironment(name: string, value: string): void;
181
- /**
182
- * Make the service depend on another service.
183
- * @param serviceName
184
- */
185
- addDependsOn(serviceName: IDockerComposeServiceName): void;
186
- /**
187
- * Add a volume to the service.
188
- * @param volume
189
- */
190
- addVolume(volume: IDockerComposeVolumeBinding): void;
191
- }
192
- /**
193
- * A service port mapping
194
- */
195
- export interface DockerComposeServicePort {
196
- /**
197
- * Published port number
198
- */
199
- readonly published: number;
200
- /**
201
- * Target port number
202
- */
203
- readonly target: number;
204
- /**
205
- * Network protocol
206
- */
207
- readonly protocol: DockerComposeProtocol;
208
- /**
209
- * Port mapping mode.
210
- */
211
- readonly mode: string;
212
- }
213
- /**
214
- * Network protocol for port mapping
215
- */
216
- export declare enum DockerComposeProtocol {
217
- /**
218
- * TCP protocol
219
- */
220
- TCP = "tcp",
221
- /**
222
- * UDP protocol
223
- */
224
- UDP = "udp"
225
- }
226
- /**
227
- * Build arguments for creating a docker image.
228
- */
229
- export interface DockerComposeBuild {
230
- /**
231
- * Docker build context directory.
232
- */
233
- readonly context: string;
234
- /**
235
- * A dockerfile to build from.
236
- * @default "Dockerfile"
237
- */
238
- readonly dockerfile?: string;
239
- /**
240
- * Build args.
241
- * @default - none are provided
242
- */
243
- readonly args?: Record<string, string>;
244
- }
245
- /**
246
- * Volume configuration
247
- */
248
- export interface DockerComposeVolumeConfig {
249
- /**
250
- * Driver to use for the volume
251
- * @default - value is not provided
252
- */
253
- readonly driver?: string;
254
- /**
255
- * Options to provide to the driver.
256
- */
257
- readonly driverOpts?: Record<string, string>;
258
- /**
259
- * Set to true to indicate that the volume is externally created.
260
- * @default - unset, indicating that docker-compose creates the volume
261
- */
262
- readonly external?: boolean;
263
- /**
264
- * Name of the volume for when the volume name isn't going to work in YAML.
265
- * @default - unset, indicating that docker-compose creates volumes as usual
266
- */
267
- readonly name?: string;
268
- }
269
- /**
270
- * Volume binding information.
271
- */
272
- export interface IDockerComposeVolumeBinding {
273
- /**
274
- * Binds the requested volume to the docker-compose volume configuration and
275
- * provide mounting instructions for synthesis.
276
- * @param volumeConfig the volume configuration
277
- * @returns mounting instructions for the service.
278
- */
279
- bind(volumeConfig: IDockerComposeVolumeConfig): DockerComposeVolumeMount;
280
- }
281
- /**
282
- * Storage for volume configuration.
283
- */
284
- export interface IDockerComposeVolumeConfig {
285
- /**
286
- * Add volume configuration to the repository.
287
- * @param volumeName
288
- * @param configuration
289
- */
290
- addVolumeConfiguration(volumeName: string, configuration: DockerComposeVolumeConfig): void;
291
- }
292
- /**
293
- * Service volume mounting information.
294
- */
295
- export interface DockerComposeVolumeMount {
296
- /**
297
- * Type of volume.
298
- */
299
- readonly type: string;
300
- /**
301
- * Volume source
302
- */
303
- readonly source: string;
304
- /**
305
- * Volume target
306
- */
307
- readonly target: string;
308
- }
@@ -1,284 +0,0 @@
1
- "use strict";
2
- var _a, _b;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DockerComposeProtocol = exports.DockerComposeService = exports.DockerCompose = void 0;
5
- const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
- const component_1 = require("./component");
7
- const util_1 = require("./util");
8
- const yaml_1 = require("./yaml");
9
- /**
10
- * Create a docker-compose YAML file.
11
- */
12
- class DockerCompose extends component_1.Component {
13
- constructor(project, props) {
14
- super(project);
15
- const nameSuffix = props?.nameSuffix ? `${props.nameSuffix}.yml` : "yml";
16
- new yaml_1.YamlFile(project, `docker-compose.${nameSuffix}`, {
17
- committed: true,
18
- readonly: true,
19
- obj: () => this._synthesizeDockerCompose(),
20
- });
21
- if (props?.schemaVersion && !parseFloat(props.schemaVersion)) {
22
- throw Error("Version tag needs to be a number");
23
- }
24
- this.version = props?.schemaVersion ? props.schemaVersion : "3.3";
25
- this.services = {};
26
- // Add the services provided via the constructor argument.
27
- const initialServices = props?.services ?? {};
28
- for (const [name, serviceDescription] of Object.entries(initialServices)) {
29
- this.addService(name, serviceDescription);
30
- }
31
- }
32
- /**
33
- * Depends on a service name.
34
- */
35
- static serviceName(serviceName) {
36
- return {
37
- serviceName,
38
- };
39
- }
40
- /**
41
- * Create a port mapping.
42
- * @param publishedPort Published port number
43
- * @param targetPort Container's port number
44
- * @param options Port mapping options
45
- */
46
- static portMapping(publishedPort, targetPort, options) {
47
- const protocol = options?.protocol ?? DockerComposeProtocol.TCP;
48
- return {
49
- target: targetPort,
50
- published: publishedPort,
51
- protocol: protocol,
52
- mode: "host",
53
- };
54
- }
55
- /**
56
- * Create a bind volume that binds a host path to the target path in the container.
57
- * @param sourcePath Host path name
58
- * @param targetPath Target path name
59
- */
60
- static bindVolume(sourcePath, targetPath) {
61
- return {
62
- bind(_volumeInfo) {
63
- return {
64
- type: "bind",
65
- source: sourcePath,
66
- target: targetPath,
67
- };
68
- },
69
- };
70
- }
71
- /**
72
- * Create a named volume and mount it to the target path. If you use this
73
- * named volume in several services, the volume will be shared. In this
74
- * case, the volume configuration of the first-provided options are used.
75
- *
76
- * @param volumeName Name of the volume
77
- * @param targetPath Target path
78
- * @param options volume configuration (default: docker compose defaults)
79
- */
80
- static namedVolume(volumeName, targetPath, options = {}) {
81
- return {
82
- bind(volumeInfo) {
83
- volumeInfo.addVolumeConfiguration(volumeName, options);
84
- return {
85
- type: "volume",
86
- source: volumeName,
87
- target: targetPath,
88
- };
89
- },
90
- };
91
- }
92
- /**
93
- * Add a service to the docker-compose file.
94
- * @param serviceName name of the service
95
- * @param description a service description
96
- */
97
- addService(serviceName, description) {
98
- const service = new DockerComposeService(serviceName, description);
99
- this.services[serviceName] = service;
100
- return service;
101
- }
102
- /**
103
- * @internal
104
- */
105
- _synthesizeDockerCompose() {
106
- if (Object.keys(this.services).length === 0) {
107
- throw new Error("DockerCompose requires at least one service");
108
- }
109
- return renderDockerComposeFile(this.services, this.version);
110
- }
111
- }
112
- exports.DockerCompose = DockerCompose;
113
- _a = JSII_RTTI_SYMBOL_1;
114
- DockerCompose[_a] = { fqn: "projen.DockerCompose", version: "0.67.26" };
115
- /**
116
- * A docker-compose service.
117
- */
118
- class DockerComposeService {
119
- constructor(serviceName, serviceDescription) {
120
- if ((!serviceDescription.imageBuild && !serviceDescription.image) ||
121
- (serviceDescription.imageBuild && serviceDescription.image)) {
122
- throw new Error(`A service ${serviceName} requires exactly one of a \`imageBuild\` or \`image\` key`);
123
- }
124
- this.serviceName = serviceName;
125
- this.command = serviceDescription.command;
126
- this.image = serviceDescription.image;
127
- this.imageBuild = serviceDescription.imageBuild;
128
- this.dependsOn = serviceDescription.dependsOn ?? [];
129
- this.volumes = serviceDescription.volumes ?? [];
130
- this.ports = serviceDescription.ports ?? [];
131
- this.environment = serviceDescription.environment ?? {};
132
- }
133
- /**
134
- * Add a port mapping
135
- * @param publishedPort Published port number
136
- * @param targetPort Container's port number
137
- * @param options Port mapping options
138
- */
139
- addPort(publishedPort, targetPort, options) {
140
- this.ports?.push(DockerCompose.portMapping(publishedPort, targetPort, options));
141
- }
142
- /**
143
- * Add an environment variable
144
- * @param name environment variable name
145
- * @param value value of the environment variable
146
- */
147
- addEnvironment(name, value) {
148
- this.environment[name] = value;
149
- }
150
- /**
151
- * Make the service depend on another service.
152
- * @param serviceName
153
- */
154
- addDependsOn(serviceName) {
155
- this.dependsOn.push(serviceName);
156
- }
157
- /**
158
- * Add a volume to the service.
159
- * @param volume
160
- */
161
- addVolume(volume) {
162
- this.volumes.push(volume);
163
- }
164
- }
165
- exports.DockerComposeService = DockerComposeService;
166
- _b = JSII_RTTI_SYMBOL_1;
167
- DockerComposeService[_b] = { fqn: "projen.DockerComposeService", version: "0.67.26" };
168
- /**
169
- * Network protocol for port mapping
170
- */
171
- var DockerComposeProtocol;
172
- (function (DockerComposeProtocol) {
173
- /**
174
- * TCP protocol
175
- */
176
- DockerComposeProtocol["TCP"] = "tcp";
177
- /**
178
- * UDP protocol
179
- */
180
- DockerComposeProtocol["UDP"] = "udp";
181
- })(DockerComposeProtocol = exports.DockerComposeProtocol || (exports.DockerComposeProtocol = {}));
182
- function renderDockerComposeFile(serviceDescriptions, version) {
183
- // Record volume configuration
184
- const volumeConfig = {};
185
- const volumeInfo = {
186
- addVolumeConfiguration(volumeName, configuration) {
187
- if (!volumeConfig[volumeName]) {
188
- // First volume configuration takes precedence.
189
- volumeConfig[volumeName] = configuration;
190
- }
191
- },
192
- };
193
- // Render service configuration
194
- const services = {};
195
- for (const [serviceName, serviceDescription] of Object.entries(serviceDescriptions ?? {})) {
196
- // Resolve the names of each dependency and check that they exist.
197
- // Note: They may not exist if the user made a mistake when referencing a
198
- // service by name via `DockerCompose.serviceName()`.
199
- // @see DockerCompose.serviceName
200
- const dependsOn = Array();
201
- for (const dependsOnServiceName of serviceDescription.dependsOn ?? []) {
202
- const resolvedServiceName = dependsOnServiceName.serviceName;
203
- if (resolvedServiceName === serviceName) {
204
- throw new Error(`Service ${serviceName} cannot depend on itself`);
205
- }
206
- if (!serviceDescriptions[resolvedServiceName]) {
207
- throw new Error(`Unable to resolve service named ${resolvedServiceName} for ${serviceName}`);
208
- }
209
- dependsOn.push(resolvedServiceName);
210
- }
211
- // Give each volume binding a chance to bind any necessary volume
212
- // configuration and provide volume mount information for the service.
213
- const volumes = [];
214
- for (const volumeBinding of serviceDescription.volumes ?? []) {
215
- volumes.push(volumeBinding.bind(volumeInfo));
216
- }
217
- // Create and store the service configuration, taking care not to create
218
- // object members with undefined values.
219
- services[serviceName] = {
220
- ...getObjectWithKeyAndValueIfValueIsDefined("image", serviceDescription.image),
221
- ...getObjectWithKeyAndValueIfValueIsDefined("build", serviceDescription.imageBuild),
222
- ...getObjectWithKeyAndValueIfValueIsDefined("command", serviceDescription.command),
223
- ...(Object.keys(serviceDescription.environment).length > 0
224
- ? { environment: serviceDescription.environment }
225
- : {}),
226
- ...(serviceDescription.ports.length > 0
227
- ? { ports: serviceDescription.ports }
228
- : {}),
229
- ...(dependsOn.length > 0 ? { dependsOn } : {}),
230
- ...(volumes.length > 0 ? { volumes } : {}),
231
- };
232
- }
233
- // Explicit with the type here because the decamelize step after this wipes
234
- // out types.
235
- const input = {
236
- version,
237
- services,
238
- ...(Object.keys(volumeConfig).length > 0 ? { volumes: volumeConfig } : {}),
239
- };
240
- // Change most keys to snake case.
241
- return util_1.decamelizeKeysRecursively(input, {
242
- shouldDecamelize: shouldDecamelizeDockerComposeKey,
243
- separator: "_",
244
- });
245
- }
246
- /**
247
- * Returns `{ [key]: value }` if `value` is defined, otherwise returns `{}` so
248
- * that object spreading can be used to generate a peculiar interface.
249
- * @param key
250
- * @param value
251
- */
252
- function getObjectWithKeyAndValueIfValueIsDefined(key, value) {
253
- return value !== undefined ? { [key]: value } : {};
254
- }
255
- /**
256
- * Determines whether the key at the given path should be decamelized.
257
- * Largely, all keys should be snake cased. But, there are some
258
- * exceptions for user-provided names for services, volumes, and
259
- * environment variables.
260
- *
261
- * @param path
262
- */
263
- function shouldDecamelizeDockerComposeKey(path) {
264
- const poundPath = path.join("#");
265
- // Does not decamelize user's names.
266
- // services.namehere:
267
- // volumes.namehere:
268
- if (/^(services|volumes)#[^#]+$/.test(poundPath)) {
269
- return false;
270
- }
271
- // Does not decamelize environment variables
272
- // services.namehere.environment.*
273
- if (/^services#[^#]+#environment#/.test(poundPath)) {
274
- return false;
275
- }
276
- // Does not decamelize build arguments
277
- // services.namehere.build.args.*
278
- if (/^services#[^#]+#build#args#/.test(poundPath)) {
279
- return false;
280
- }
281
- // Otherwise, let it all decamelize.
282
- return true;
283
- }
284
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9ja2VyLWNvbXBvc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZG9ja2VyLWNvbXBvc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwyQ0FBd0M7QUFFeEMsaUNBQW1EO0FBQ25ELGlDQUFrQztBQW9DbEM7O0dBRUc7QUFDSCxNQUFhLGFBQWMsU0FBUSxxQkFBUztJQWlGMUMsWUFBWSxPQUFnQixFQUFFLEtBQTBCO1FBQ3RELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBTSxDQUFDLFVBQVUsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFDMUUsSUFBSSxlQUFRLENBQUMsT0FBTyxFQUFFLGtCQUFrQixVQUFVLEVBQUUsRUFBRTtZQUNwRCxTQUFTLEVBQUUsSUFBSTtZQUNmLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRTtTQUMzQyxDQUFDLENBQUM7UUFFSCxJQUFJLEtBQUssRUFBRSxhQUFhLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQzVELE1BQU0sS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7U0FDakQ7UUFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNsRSxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUVuQiwwREFBMEQ7UUFDMUQsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUFFLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDOUMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxl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bmVudFwiO1xuaW1wb3J0IHsgUHJvamVjdCB9IGZyb20gXCIuL3Byb2plY3RcIjtcbmltcG9ydCB7IGRlY2FtZWxpemVLZXlzUmVjdXJzaXZlbHkgfSBmcm9tIFwiLi91dGlsXCI7XG5pbXBvcnQgeyBZYW1sRmlsZSB9IGZyb20gXCIuL3lhbWxcIjtcblxuLyoqXG4gKiBQcm9wcyBmb3IgRG9ja2VyQ29tcG9zZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlUHJvcHMge1xuICAvKipcbiAgICogQSBuYW1lIHRvIGFkZCB0byB0aGUgZG9ja2VyLWNvbXBvc2UueW1sIGZpbGVuYW1lLlxuICAgKiBAZXhhbXBsZSAnbXluYW1lJyB5aWVsZHMgJ2RvY2tlci1jb21wb3NlLm15bmFtZS55bWwnXG4gICAqIEBkZWZhdWx0IC0gbm8gbmFtZSBpcyBhZGRlZFxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZVN1ZmZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogRG9ja2VyIENvbXBvc2Ugc2NoZW1hIHZlcnNpb24gZG8gYmUgdXNlZFxuICAgKiBAZGVmYXVsdCAzLjNcbiAgICovXG4gIHJlYWRvbmx5IHNjaGVtYVZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNlcnZpY2UgZGVzY3JpcHRpb25zLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZXM/OiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uPjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBwb3J0IG1hcHBpbmdzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvY2tlckNvbXBvc2VQb3J0TWFwcGluZ09wdGlvbnMge1xuICAvKipcbiAgICogUG9ydCBtYXBwaW5nIHByb3RvY29sLlxuICAgKiBAZGVmYXVsdCBEb2NrZXJDb21wb3NlUHJvdG9jb2wuVENQXG4gICAqL1xuICByZWFkb25seSBwcm90b2NvbD86IERvY2tlckNvbXBvc2VQcm90b2NvbDtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBkb2NrZXItY29tcG9zZSBZQU1MIGZpbGUuXG4gKi9cbmV4cG9ydCBjbGFzcyBEb2NrZXJDb21wb3NlIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIERlcGVuZHMgb24gYSBzZXJ2aWNlIG5hbWUuXG4gICAqL1xuICBzdGF0aWMgc2VydmljZU5hbWUoc2VydmljZU5hbWU6IHN0cmluZyk6IElEb2NrZXJDb21wb3NlU2VydmljZU5hbWUge1xuICAgIHJldHVybiB7XG4gICAgICBzZXJ2aWNlTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHBvcnQgbWFwcGluZy5cbiAgICogQHBhcmFtIHB1Ymxpc2hlZFBvcnQgUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSB0YXJnZXRQb3J0IENvbnRhaW5lcidzIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSBvcHRpb25zIFBvcnQgbWFwcGluZyBvcHRpb25zXG4gICAqL1xuICBzdGF0aWMgcG9ydE1hcHBpbmcoXG4gICAgcHVibGlzaGVkUG9ydDogbnVtYmVyLFxuICAgIHRhcmdldFBvcnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogRG9ja2VyQ29tcG9zZVBvcnRNYXBwaW5nT3B0aW9uc1xuICApOiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnQge1xuICAgIGNvbnN0IHByb3RvY29sID0gb3B0aW9ucz8ucHJvdG9jb2wgPz8gRG9ja2VyQ29tcG9zZVByb3RvY29sLlRDUDtcblxuICAgIHJldHVybiB7XG4gICAgICB0YXJnZXQ6IHRhcmdldFBvcnQsXG4gICAgICBwdWJsaXNoZWQ6IHB1Ymxpc2hlZFBvcnQsXG4gICAgICBwcm90b2NvbDogcHJvdG9jb2wsXG4gICAgICBtb2RlOiBcImhvc3RcIixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGJpbmQgdm9sdW1lIHRoYXQgYmluZHMgYSBob3N0IHBhdGggdG8gdGhlIHRhcmdldCBwYXRoIGluIHRoZSBjb250YWluZXIuXG4gICAqIEBwYXJhbSBzb3VyY2VQYXRoIEhvc3QgcGF0aCBuYW1lXG4gICAqIEBwYXJhbSB0YXJnZXRQYXRoIFRhcmdldCBwYXRoIG5hbWVcbiAgICovXG4gIHN0YXRpYyBiaW5kVm9sdW1lKFxuICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICB0YXJnZXRQYXRoOiBzdHJpbmdcbiAgKTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmluZChfdm9sdW1lSW5mbzogSURvY2tlckNvbXBvc2VWb2x1bWVDb25maWcpOiBEb2NrZXJDb21wb3NlVm9sdW1lTW91bnQge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiYmluZFwiLFxuICAgICAgICAgIHNvdXJjZTogc291cmNlUGF0aCxcbiAgICAgICAgICB0YXJnZXQ6IHRhcmdldFBhdGgsXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmFtZWQgdm9sdW1lIGFuZCBtb3VudCBpdCB0byB0aGUgdGFyZ2V0IHBhdGguIElmIHlvdSB1c2UgdGhpc1xuICAgKiBuYW1lZCB2b2x1bWUgaW4gc2V2ZXJhbCBzZXJ2aWNlcywgdGhlIHZvbHVtZSB3aWxsIGJlIHNoYXJlZC4gSW4gdGhpc1xuICAgKiBjYXNlLCB0aGUgdm9sdW1lIGNvbmZpZ3VyYXRpb24gb2YgdGhlIGZpcnN0LXByb3ZpZGVkIG9wdGlvbnMgYXJlIHVzZWQuXG4gICAqXG4gICAqIEBwYXJhbSB2b2x1bWVOYW1lIE5hbWUgb2YgdGhlIHZvbHVtZVxuICAgKiBAcGFyYW0gdGFyZ2V0UGF0aCBUYXJnZXQgcGF0aFxuICAgKiBAcGFyYW0gb3B0aW9ucyB2b2x1bWUgY29uZmlndXJhdGlvbiAoZGVmYXVsdDogZG9ja2VyIGNvbXBvc2UgZGVmYXVsdHMpXG4gICAqL1xuICBzdGF0aWMgbmFtZWRWb2x1bWUoXG4gICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgIHRhcmdldFBhdGg6IHN0cmluZyxcbiAgICBvcHRpb25zOiBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnID0ge31cbiAgKTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmluZCh2b2x1bWVJbmZvOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZyk6IERvY2tlckNvbXBvc2VWb2x1bWVNb3VudCB7XG4gICAgICAgIHZvbHVtZUluZm8uYWRkVm9sdW1lQ29uZmlndXJhdGlvbih2b2x1bWVOYW1lLCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwidm9sdW1lXCIsXG4gICAgICAgICAgc291cmNlOiB2b2x1bWVOYW1lLFxuICAgICAgICAgIHRhcmdldDogdGFyZ2V0UGF0aCxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VTZXJ2aWNlPjtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgcHJvcHM/OiBEb2NrZXJDb21wb3NlUHJvcHMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIGNvbnN0IG5hbWVTdWZmaXggPSBwcm9wcz8ubmFtZVN1ZmZpeCA/IGAke3Byb3BzIS5uYW1lU3VmZml4fS55bWxgIDogXCJ5bWxcIjtcbiAgICBuZXcgWWFtbEZpbGUocHJvamVjdCwgYGRvY2tlci1jb21wb3NlLiR7bmFtZVN1ZmZpeH1gLCB7XG4gICAgICBjb21taXR0ZWQ6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICAgIG9iajogKCkgPT4gdGhpcy5fc3ludGhlc2l6ZURvY2tlckNvbXBvc2UoKSxcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcz8uc2NoZW1hVmVyc2lvbiAmJiAhcGFyc2VGbG9hdChwcm9wcy5zY2hlbWFWZXJzaW9uKSkge1xuICAgICAgdGhyb3cgRXJyb3IoXCJWZXJzaW9uIHRhZyBuZWVkcyB0byBiZSBhIG51bWJlclwiKTtcbiAgICB9XG4gICAgdGhpcy52ZXJzaW9uID0gcHJvcHM/LnNjaGVtYVZlcnNpb24gPyBwcm9wcy5zY2hlbWFWZXJzaW9uIDogXCIzLjNcIjtcbiAgICB0aGlzLnNlcnZpY2VzID0ge307XG5cbiAgICAvLyBBZGQgdGhlIHNlcnZpY2VzIHByb3ZpZGVkIHZpYSB0aGUgY29uc3RydWN0b3IgYXJndW1lbnQuXG4gICAgY29uc3QgaW5pdGlhbFNlcnZpY2VzID0gcHJvcHM/LnNlcnZpY2VzID8/IHt9O1xuICAgIGZvciAoY29uc3QgW25hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoaW5pdGlhbFNlcnZpY2VzKSkge1xuICAgICAgdGhpcy5hZGRTZXJ2aWNlKG5hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHNlcnZpY2UgdG8gdGhlIGRvY2tlci1jb21wb3NlIGZpbGUuXG4gICAqIEBwYXJhbSBzZXJ2aWNlTmFtZSBuYW1lIG9mIHRoZSBzZXJ2aWNlXG4gICAqIEBwYXJhbSBkZXNjcmlwdGlvbiBhIHNlcnZpY2UgZGVzY3JpcHRpb25cbiAgICovXG4gIHB1YmxpYyBhZGRTZXJ2aWNlKFxuICAgIHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gICAgZGVzY3JpcHRpb246IERvY2tlckNvbXBvc2VTZXJ2aWNlRGVzY3JpcHRpb25cbiAgKTogRG9ja2VyQ29tcG9zZVNlcnZpY2Uge1xuICAgIGNvbnN0IHNlcnZpY2UgPSBuZXcgRG9ja2VyQ29tcG9zZVNlcnZpY2Uoc2VydmljZU5hbWUsIGRlc2NyaXB0aW9uKTtcbiAgICB0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IHNlcnZpY2U7XG4gICAgcmV0dXJuIHNlcnZpY2U7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfc3ludGhlc2l6ZURvY2tlckNvbXBvc2UoKTogb2JqZWN0IHtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5zZXJ2aWNlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEb2NrZXJDb21wb3NlIHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBzZXJ2aWNlXCIpO1xuICAgIH1cblxuICAgIHJldHVybiByZW5kZXJEb2NrZXJDb21wb3NlRmlsZSh0aGlzLnNlcnZpY2VzLCB0aGlzLnZlcnNpb24pO1xuICB9XG59XG5cbi8qKlxuICogQW4gaW50ZXJmYWNlIHByb3ZpZGluZyB0aGUgbmFtZSBvZiBhIGRvY2tlciBjb21wb3NlIHNlcnZpY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSURvY2tlckNvbXBvc2VTZXJ2aWNlTmFtZSB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZG9ja2VyIGNvbXBvc2Ugc2VydmljZS5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VOYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVzY3JpcHRpb24gb2YgYSBkb2NrZXItY29tcG9zZS55bWwgc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uIHtcbiAgLyoqXG4gICAqIFVzZSBhIGRvY2tlciBpbWFnZS5cbiAgICogTm90ZTogWW91IG11c3Qgc3BlY2lmeSBlaXRoZXIgYGJ1aWxkYCBvciBgaW1hZ2VgIGtleS5cbiAgICogQHNlZSBpbWFnZUJ1aWxkXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgYSBkb2NrZXIgaW1hZ2UuXG4gICAqIE5vdGU6IFlvdSBtdXN0IHNwZWNpZnkgZWl0aGVyIGBpbWFnZUJ1aWxkYCBvciBgaW1hZ2VgIGtleS5cbiAgICogQHNlZSBpbWFnZVxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VCdWlsZD86IERvY2tlckNvbXBvc2VCdWlsZDtcblxuICAvKipcbiAgICogUHJvdmlkZSBhIGNvbW1hbmQgdG8gdGhlIGRvY2tlciBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBjb250YWluZXIncyBkZWZhdWx0IGNvbW1hbmRcbiAgICovXG4gIHJlYWRvbmx5IGNvbW1hbmQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTmFtZXMgb2Ygb3RoZXIgc2VydmljZXMgdGhpcyBzZXJ2aWNlIGRlcGVuZHMgb24uXG4gICAqIEBkZWZhdWx0IC0gbm8gZGVwZW5kZW5jaWVzXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRzT24/OiBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lW107XG5cbiAgLyoqXG4gICAqIE1vdW50IHNvbWUgdm9sdW1lcyBpbnRvIHRoZSBzZXJ2aWNlLlxuICAgKiBVc2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgdG8gY3JlYXRlIHZvbHVtZXM6XG4gICAqIEBzZWUgRG9ja2VyQ29tcG9zZS5iaW5kVm9sdW1lKCkgdG8gbW91bnQgYSBob3N0IHBhdGhcbiAgICogQHNlZSBEb2NrZXJDb21wb3NlLm5hbWVkVm9sdW1lKCkgdG8gY3JlYXRlICYgbW91bnQgYSBuYW1lZCB2b2x1bWVcbiAgICovXG4gIHJlYWRvbmx5IHZvbHVtZXM/OiBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmdbXTtcblxuICAvKipcbiAgICogTWFwIHNvbWUgcG9ydHMuXG4gICAqIEBkZWZhdWx0IC0gbm8gcG9ydHMgYXJlIG1hcHBlZFxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydHM/OiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnRbXTtcblxuICAvKipcbiAgICogQWRkIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogQGRlZmF1bHQgLSBubyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXJlIHByb3ZpZGVkXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbi8qKlxuICogQSBkb2NrZXItY29tcG9zZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgY2xhc3MgRG9ja2VyQ29tcG9zZVNlcnZpY2UgaW1wbGVtZW50cyBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmljZU5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogRG9ja2VyIGltYWdlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGltYWdlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb2NrZXIgaW1hZ2UgYnVpbGQgaW5zdHJ1Y3Rpb25zLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGltYWdlQnVpbGQ/OiBEb2NrZXJDb21wb3NlQnVpbGQ7XG5cbiAgLyoqXG4gICAqIENvbW1hbmQgdG8gcnVuIGluIHRoZSBjb250YWluZXIuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY29tbWFuZD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBPdGhlciBzZXJ2aWNlcyB0aGF0IHRoaXMgc2VydmljZSBkZXBlbmRzIG9uLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlcGVuZHNPbjogSURvY2tlckNvbXBvc2VTZXJ2aWNlTmFtZVtdO1xuXG4gIC8qKlxuICAgKiBWb2x1bWVzIG1vdW50ZWQgaW4gdGhlIGNvbnRhaW5lci5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB2b2x1bWVzOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmdbXTtcblxuICAvKipcbiAgICogUHVibGlzaGVkIHBvcnRzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBvcnRzOiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnRbXTtcblxuICAvKipcbiAgICogRW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGVudmlyb25tZW50OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gICAgc2VydmljZURlc2NyaXB0aW9uOiBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uXG4gICkge1xuICAgIGlmIChcbiAgICAgICghc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGQgJiYgIXNlcnZpY2VEZXNjcmlwdGlvbi5pbWFnZSkgfHxcbiAgICAgIChzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2VCdWlsZCAmJiBzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2UpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBBIHNlcnZpY2UgJHtzZXJ2aWNlTmFtZX0gcmVxdWlyZXMgZXhhY3RseSBvbmUgb2YgYSBcXGBpbWFnZUJ1aWxkXFxgIG9yIFxcYGltYWdlXFxgIGtleWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2aWNlTmFtZSA9IHNlcnZpY2VOYW1lO1xuICAgIHRoaXMuY29tbWFuZCA9IHNlcnZpY2VEZXNjcmlwdGlvbi5jb21tYW5kO1xuICAgIHRoaXMuaW1hZ2UgPSBzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2U7XG4gICAgdGhpcy5pbWFnZUJ1aWxkID0gc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGQ7XG4gICAgdGhpcy5kZXBlbmRzT24gPSBzZXJ2aWNlRGVzY3JpcHRpb24uZGVwZW5kc09uID8/IFtdO1xuICAgIHRoaXMudm9sdW1lcyA9IHNlcnZpY2VEZXNjcmlwdGlvbi52b2x1bWVzID8/IFtdO1xuICAgIHRoaXMucG9ydHMgPSBzZXJ2aWNlRGVzY3JpcHRpb24ucG9ydHMgPz8gW107XG4gICAgdGhpcy5lbnZpcm9ubWVudCA9IHNlcnZpY2VEZXNjcmlwdGlvbi5lbnZpcm9ubWVudCA/PyB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBwb3J0IG1hcHBpbmdcbiAgICogQHBhcmFtIHB1Ymxpc2hlZFBvcnQgUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSB0YXJnZXRQb3J0IENvbnRhaW5lcidzIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSBvcHRpb25zIFBvcnQgbWFwcGluZyBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgYWRkUG9ydChcbiAgICBwdWJsaXNoZWRQb3J0OiBudW1iZXIsXG4gICAgdGFyZ2V0UG9ydDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBEb2NrZXJDb21wb3NlUG9ydE1hcHBpbmdPcHRpb25zXG4gICkge1xuICAgIHRoaXMucG9ydHM/LnB1c2goXG4gICAgICBEb2NrZXJDb21wb3NlLnBvcnRNYXBwaW5nKHB1Ymxpc2hlZFBvcnQsIHRhcmdldFBvcnQsIG9wdGlvbnMpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYW4gZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgICogQHBhcmFtIG5hbWUgZW52aXJvbm1lbnQgdmFyaWFibGUgbmFtZVxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgb2YgdGhlIGVudmlyb25tZW50IHZhcmlhYmxlXG4gICAqL1xuICBwdWJsaWMgYWRkRW52aXJvbm1lbnQobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5lbnZpcm9ubWVudFtuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgdGhlIHNlcnZpY2UgZGVwZW5kIG9uIGFub3RoZXIgc2VydmljZS5cbiAgICogQHBhcmFtIHNlcnZpY2VOYW1lXG4gICAqL1xuICBwdWJsaWMgYWRkRGVwZW5kc09uKHNlcnZpY2VOYW1lOiBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lKSB7XG4gICAgdGhpcy5kZXBlbmRzT24ucHVzaChzZXJ2aWNlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgdm9sdW1lIHRvIHRoZSBzZXJ2aWNlLlxuICAgKiBAcGFyYW0gdm9sdW1lXG4gICAqL1xuICBwdWJsaWMgYWRkVm9sdW1lKHZvbHVtZTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nKSB7XG4gICAgdGhpcy52b2x1bWVzLnB1c2godm9sdW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgc2VydmljZSBwb3J0IG1hcHBpbmdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlU2VydmljZVBvcnQge1xuICAvKipcbiAgICogUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqL1xuICByZWFkb25seSBwdWJsaXNoZWQ6IG51bWJlcjtcblxuICAvKipcbiAgICogVGFyZ2V0IHBvcnQgbnVtYmVyXG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IG51bWJlcjtcblxuICAvKipcbiAgICogTmV0d29yayBwcm90b2NvbFxuICAgKi9cbiAgcmVhZG9ubHkgcHJvdG9jb2w6IERvY2tlckNvbXBvc2VQcm90b2NvbDtcblxuICAvKipcbiAgICogUG9ydCBtYXBwaW5nIG1vZGUuXG4gICAqL1xuICByZWFkb25seSBtb2RlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogTmV0d29yayBwcm90b2NvbCBmb3IgcG9ydCBtYXBwaW5nXG4gKi9cbmV4cG9ydCBlbnVtIERvY2tlckNvbXBvc2VQcm90b2NvbCB7XG4gIC8qKlxuICAgKiBUQ1AgcHJvdG9jb2xcbiAgICovXG4gIFRDUCA9IFwidGNwXCIsXG5cbiAgLyoqXG4gICAqIFVEUCBwcm90b2NvbFxuICAgKi9cbiAgVURQID0gXCJ1ZHBcIixcbn1cblxuLyoqXG4gKiBCdWlsZCBhcmd1bWVudHMgZm9yIGNyZWF0aW5nIGEgZG9ja2VyIGltYWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvY2tlckNvbXBvc2VCdWlsZCB7XG4gIC8qKlxuICAgKiBEb2NrZXIgYnVpbGQgY29udGV4dCBkaXJlY3RvcnkuXG4gICAqL1xuICByZWFkb25seSBjb250ZXh0OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgZG9ja2VyZmlsZSB0byBidWlsZCBmcm9tLlxuICAgKiBAZGVmYXVsdCBcIkRvY2tlcmZpbGVcIlxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VyZmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgYXJncy5cbiAgICogQGRlZmF1bHQgLSBub25lIGFyZSBwcm92aWRlZFxuICAgKi9cbiAgcmVhZG9ubHkgYXJncz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbi8qKlxuICogVm9sdW1lIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnIHtcbiAgLyoqXG4gICAqIERyaXZlciB0byB1c2UgZm9yIHRoZSB2b2x1bWVcbiAgICogQGRlZmF1bHQgLSB2YWx1ZSBpcyBub3QgcHJvdmlkZWRcbiAgICovXG4gIHJlYWRvbmx5IGRyaXZlcj86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9ucyB0byBwcm92aWRlIHRvIHRoZSBkcml2ZXIuXG4gICAqL1xuICByZWFkb25seSBkcml2ZXJPcHRzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKipcbiAgICogU2V0IHRvIHRydWUgdG8gaW5kaWNhdGUgdGhhdCB0aGUgdm9sdW1lIGlzIGV4dGVybmFsbHkgY3JlYXRlZC5cbiAgICogQGRlZmF1bHQgLSB1bnNldCwgaW5kaWNhdGluZyB0aGF0IGRvY2tlci1jb21wb3NlIGNyZWF0ZXMgdGhlIHZvbHVtZVxuICAgKi9cbiAgcmVhZG9ubHkgZXh0ZXJuYWw/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSB2b2x1bWUgZm9yIHdoZW4gdGhlIHZvbHVtZSBuYW1lIGlzbid0IGdvaW5nIHRvIHdvcmsgaW4gWUFNTC5cbiAgICogQGRlZmF1bHQgLSB1bnNldCwgaW5kaWNhdGluZyB0aGF0IGRvY2tlci1jb21wb3NlIGNyZWF0ZXMgdm9sdW1lcyBhcyB1c3VhbFxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBWb2x1bWUgYmluZGluZyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmcge1xuICAvKipcbiAgICogQmluZHMgdGhlIHJlcXVlc3RlZCB2b2x1bWUgdG8gdGhlIGRvY2tlci1jb21wb3NlIHZvbHVtZSBjb25maWd1cmF0aW9uIGFuZFxuICAgKiBwcm92aWRlIG1vdW50aW5nIGluc3RydWN0aW9ucyBmb3Igc3ludGhlc2lzLlxuICAgKiBAcGFyYW0gdm9sdW1lQ29uZmlnIHRoZSB2b2x1bWUgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBtb3VudGluZyBpbnN0cnVjdGlvbnMgZm9yIHRoZSBzZXJ2aWNlLlxuICAgKi9cbiAgYmluZCh2b2x1bWVDb25maWc6IElEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnKTogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50O1xufVxuXG4vKipcbiAqIFN0b3JhZ2UgZm9yIHZvbHVtZSBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnIHtcbiAgLyoqXG4gICAqIEFkZCB2b2x1bWUgY29uZmlndXJhdGlvbiB0byB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHBhcmFtIHZvbHVtZU5hbWVcbiAgICogQHBhcmFtIGNvbmZpZ3VyYXRpb25cbiAgICovXG4gIGFkZFZvbHVtZUNvbmZpZ3VyYXRpb24oXG4gICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgIGNvbmZpZ3VyYXRpb246IERvY2tlckNvbXBvc2VWb2x1bWVDb25maWdcbiAgKTogdm9pZDtcbn1cblxuLyoqXG4gKiBTZXJ2aWNlIHZvbHVtZSBtb3VudGluZyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlVm9sdW1lTW91bnQge1xuICAvKipcbiAgICogVHlwZSBvZiB2b2x1bWUuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFZvbHVtZSBzb3VyY2VcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBWb2x1bWUgdGFyZ2V0XG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmUgb2YgYSBkb2NrZXIgY29tcG9zZSBmaWxlIGJlZm9yZSB3ZSBkZWNhbWVsaXplLlxuICogQGludGVybmFsXG4gKi9cbmludGVyZmFjZSBEb2NrZXJDb21wb3NlRmlsZVNjaGVtYSB7XG4gIHZlcnNpb246IHN0cmluZztcbiAgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VGaWxlU2VydmljZVNjaGVtYT47XG4gIHZvbHVtZXM/OiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnPjtcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmUgb2YgYSBkb2NrZXIgY29tcG9zZSBmaWxlJ3Mgc2VydmljZSBiZWZvcmUgd2UgZGVjYW1lbGl6ZS5cbiAqIEBpbnRlcm5hbFxuICovXG5pbnRlcmZhY2UgRG9ja2VyQ29tcG9zZUZpbGVTZXJ2aWNlU2NoZW1hIHtcbiAgcmVhZG9ubHkgZGVwZW5kc09uPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IGJ1aWxkPzogRG9ja2VyQ29tcG9zZUJ1aWxkO1xuICByZWFkb25seSBpbWFnZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY29tbWFuZD86IHN0cmluZ1tdO1xuICByZWFkb25seSB2b2x1bWVzPzogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50W107XG4gIHJlYWRvbmx5IHBvcnRzPzogRG9ja2VyQ29tcG9zZVNlcnZpY2VQb3J0W107XG4gIHJlYWRvbmx5IGVudmlyb25tZW50PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cblxuZnVuY3Rpb24gcmVuZGVyRG9ja2VyQ29tcG9zZUZpbGUoXG4gIHNlcnZpY2VEZXNjcmlwdGlvbnM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VTZXJ2aWNlPixcbiAgdmVyc2lvbjogc3RyaW5nXG4pOiBvYmplY3Qge1xuICAvLyBSZWNvcmQgdm9sdW1lIGNvbmZpZ3VyYXRpb25cbiAgY29uc3Qgdm9sdW1lQ29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnPiA9IHt9O1xuICBjb25zdCB2b2x1bWVJbmZvOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZyA9IHtcbiAgICBhZGRWb2x1bWVDb25maWd1cmF0aW9uKFxuICAgICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgICAgY29uZmlndXJhdGlvbjogRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZ1xuICAgICkge1xuICAgICAgaWYgKCF2b2x1bWVDb25maWdbdm9sdW1lTmFtZV0pIHtcbiAgICAgICAgLy8gRmlyc3Qgdm9sdW1lIGNvbmZpZ3VyYXRpb24gdGFrZXMgcHJlY2VkZW5jZS5cbiAgICAgICAgdm9sdW1lQ29uZmlnW3ZvbHVtZU5hbWVdID0gY29uZmlndXJhdGlvbjtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xuXG4gIC8vIFJlbmRlciBzZXJ2aWNlIGNvbmZpZ3VyYXRpb25cbiAgY29uc3Qgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VGaWxlU2VydmljZVNjaGVtYT4gPSB7fTtcbiAgZm9yIChjb25zdCBbc2VydmljZU5hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgc2VydmljZURlc2NyaXB0aW9ucyA/PyB7fVxuICApKSB7XG4gICAgLy8gUmVzb2x2ZSB0aGUgbmFtZXMgb2YgZWFjaCBkZXBlbmRlbmN5IGFuZCBjaGVjayB0aGF0IHRoZXkgZXhpc3QuXG4gICAgLy8gTm90ZTogVGhleSBtYXkgbm90IGV4aXN0IGlmIHRoZSB1c2VyIG1hZGUgYSBtaXN0YWtlIHdoZW4gcmVmZXJlbmNpbmcgYVxuICAgIC8vIHNlcnZpY2UgYnkgbmFtZSB2aWEgYERvY2tlckNvbXBvc2Uuc2VydmljZU5hbWUoKWAuXG4gICAgLy8gQHNlZSBEb2NrZXJDb21wb3NlLnNlcnZpY2VOYW1lXG4gICAgY29uc3QgZGVwZW5kc09uID0gQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3QgZGVwZW5kc09uU2VydmljZU5hbWUgb2Ygc2VydmljZURlc2NyaXB0aW9uLmRlcGVuZHNPbiA/PyBbXSkge1xuICAgICAgY29uc3QgcmVzb2x2ZWRTZXJ2aWNlTmFtZSA9IGRlcGVuZHNPblNlcnZpY2VOYW1lLnNlcnZpY2VOYW1lO1xuICAgICAgaWYgKHJlc29sdmVkU2VydmljZU5hbWUgPT09IHNlcnZpY2VOYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU2VydmljZSAke3NlcnZpY2VOYW1lfSBjYW5ub3QgZGVwZW5kIG9uIGl0c2VsZmApO1xuICAgICAgfVxuICAgICAgaWYgKCFzZXJ2aWNlRGVzY3JpcHRpb25zW3Jlc29sdmVkU2VydmljZU5hbWVdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVW5hYmxlIHRvIHJlc29sdmUgc2VydmljZSBuYW1lZCAke3Jlc29sdmVkU2VydmljZU5hbWV9IGZvciAke3NlcnZpY2VOYW1lfWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgZGVwZW5kc09uLnB1c2gocmVzb2x2ZWRTZXJ2aWNlTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gR2l2ZSBlYWNoIHZvbHVtZSBiaW5kaW5nIGEgY2hhbmNlIHRvIGJpbmQgYW55IG5lY2Vzc2FyeSB2b2x1bWVcbiAgICAvLyBjb25maWd1cmF0aW9uIGFuZCBwcm92aWRlIHZvbHVtZSBtb3VudCBpbmZvcm1hdGlvbiBmb3IgdGhlIHNlcnZpY2UuXG4gICAgY29uc3Qgdm9sdW1lczogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHZvbHVtZUJpbmRpbmcgb2Ygc2VydmljZURlc2NyaXB0aW9uLnZvbHVtZXMgPz8gW10pIHtcbiAgICAgIHZvbHVtZXMucHVzaCh2b2x1bWVCaW5kaW5nLmJpbmQodm9sdW1lSW5mbykpO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhbmQgc3RvcmUgdGhlIHNlcnZpY2UgY29uZmlndXJhdGlvbiwgdGFraW5nIGNhcmUgbm90IHRvIGNyZWF0ZVxuICAgIC8vIG9iamVjdCBtZW1iZXJzIHdpdGggdW5kZWZpbmVkIHZhbHVlcy5cbiAgICBzZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSB7XG4gICAgICAuLi5nZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkKFxuICAgICAgICBcImltYWdlXCIsXG4gICAgICAgIHNlcnZpY2VEZXNjcmlwdGlvbi5pbWFnZVxuICAgICAgKSxcbiAgICAgIC4uLmdldE9iamVjdFdpdGhLZXlBbmRWYWx1ZUlmVmFsdWVJc0RlZmluZWQoXG4gICAgICAgIFwiYnVpbGRcIixcbiAgICAgICAgc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGRcbiAgICAgICksXG4gICAgICAuLi5nZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkKFxuICAgICAgICBcImNvbW1hbmRcIixcbiAgICAgICAgc2VydmljZURlc2NyaXB0aW9uLmNvbW1hbmRcbiAgICAgICksXG4gICAgICAuLi4oT2JqZWN0LmtleXMoc2VydmljZURlc2NyaXB0aW9uLmVudmlyb25tZW50KS5sZW5ndGggPiAwXG4gICAgICAgID8geyBlbnZpcm9ubWVudDogc2VydmljZURlc2NyaXB0aW9uLmVudmlyb25tZW50IH1cbiAgICAgICAgOiB7fSksXG4gICAgICAuLi4oc2VydmljZURlc2NyaXB0aW9uLnBvcnRzLmxlbmd0aCA+IDBcbiAgICAgICAgPyB7IHBvcnRzOiBzZXJ2aWNlRGVzY3JpcHRpb24ucG9ydHMgfVxuICAgICAgICA6IHt9KSxcbiAgICAgIC4uLihkZXBlbmRzT24ubGVuZ3RoID4gMCA/IHsgZGVwZW5kc09uIH0gOiB7fSksXG4gICAgICAuLi4odm9sdW1lcy5sZW5ndGggPiAwID8geyB2b2x1bWVzIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIC8vIEV4cGxpY2l0IHdpdGggdGhlIHR5cGUgaGVyZSBiZWNhdXNlIHRoZSBkZWNhbWVsaXplIHN0ZXAgYWZ0ZXIgdGhpcyB3aXBlc1xuICAvLyBvdXQgdHlwZXMuXG4gIGNvbnN0IGlucHV0OiBEb2NrZXJDb21wb3NlRmlsZVNjaGVtYSA9IHtcbiAgICB2ZXJzaW9uLFxuICAgIHNlcnZpY2VzLFxuICAgIC4uLihPYmplY3Qua2V5cyh2b2x1bWVDb25maWcpLmxlbmd0aCA+IDAgPyB7IHZvbHVtZXM6IHZvbHVtZUNvbmZpZyB9IDoge30pLFxuICB9O1xuXG4gIC8vIENoYW5nZSBtb3N0IGtleXMgdG8gc25ha2UgY2FzZS5cbiAgcmV0dXJuIGRlY2FtZWxpemVLZXlzUmVjdXJzaXZlbHkoaW5wdXQsIHtcbiAgICBzaG91bGREZWNhbWVsaXplOiBzaG91bGREZWNhbWVsaXplRG9ja2VyQ29tcG9zZUtleSxcbiAgICBzZXBhcmF0b3I6IFwiX1wiLFxuICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGB7IFtrZXldOiB2YWx1ZSB9YCBpZiBgdmFsdWVgIGlzIGRlZmluZWQsIG90aGVyd2lzZSByZXR1cm5zIGB7fWAgc29cbiAqIHRoYXQgb2JqZWN0IHNwcmVhZGluZyBjYW4gYmUgdXNlZCB0byBnZW5lcmF0ZSBhIHBlY3VsaWFyIGludGVyZmFjZS5cbiAqIEBwYXJhbSBrZXlcbiAqIEBwYXJhbSB2YWx1ZVxuICovXG5mdW5jdGlvbiBnZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkPEsgZXh0ZW5kcyBzdHJpbmcsIFQ+KFxuICBrZXk6IEssXG4gIHZhbHVlOiBUXG4pOiB7IEs6IFQgfSB8IHt9IHtcbiAgcmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgPyB7IFtrZXldOiB2YWx1ZSB9IDoge307XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBrZXkgYXQgdGhlIGdpdmVuIHBhdGggc2hvdWxkIGJlIGRlY2FtZWxpemVkLlxuICogTGFyZ2VseSwgYWxsIGtleXMgc2hvdWxkIGJlIHNuYWtlIGNhc2VkLiBCdXQsIHRoZXJlIGFyZSBzb21lXG4gKiBleGNlcHRpb25zIGZvciB1c2VyLXByb3ZpZGVkIG5hbWVzIGZvciBzZXJ2aWNlcywgdm9sdW1lcywgYW5kXG4gKiBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gKlxuICogQHBhcmFtIHBhdGhcbiAqL1xuZnVuY3Rpb24gc2hvdWxkRGVjYW1lbGl6ZURvY2tlckNvbXBvc2VLZXkocGF0aDogc3RyaW5nW10pIHtcbiAgY29uc3QgcG91bmRQYXRoID0gcGF0aC5qb2luKFwiI1wiKTtcblxuICAvLyBEb2VzIG5vdCBkZWNhbWVsaXplIHVzZXIncyBuYW1lcy5cbiAgLy8gc2VydmljZXMubmFtZWhlcmU6XG4gIC8vIHZvbHVtZXMubmFtZWhlcmU6XG4gIGlmICgvXihzZXJ2aWNlc3x2b2x1bWVzKSNbXiNdKyQvLnRlc3QocG91bmRQYXRoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIERvZXMgbm90IGRlY2FtZWxpemUgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gIC8vIHNlcnZpY2VzLm5hbWVoZXJlLmVudmlyb25tZW50LipcbiAgaWYgKC9ec2VydmljZXMjW14jXSsjZW52aXJvbm1lbnQjLy50ZXN0KHBvdW5kUGF0aCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBEb2VzIG5vdCBkZWNhbWVsaXplIGJ1aWxkIGFyZ3VtZW50c1xuICAvLyBzZXJ2aWNlcy5uYW1laGVyZS5idWlsZC5hcmdzLipcbiAgaWYgKC9ec2VydmljZXMjW14jXSsjYnVpbGQjYXJncyMvLnRlc3QocG91bmRQYXRoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSwgbGV0IGl0IGFsbCBkZWNhbWVsaXplLlxuICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==