build-strap 3.0.0-dev.42 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -34
  3. package/dist/src/ant.d.ts +19 -0
  4. package/dist/src/ant.js +18 -0
  5. package/dist/src/cert.d.ts +12 -0
  6. package/dist/src/cert.js +91 -0
  7. package/dist/src/clean.d.ts +4 -0
  8. package/dist/src/clean.js +11 -0
  9. package/dist/src/copy.d.ts +7 -0
  10. package/dist/src/copy.js +53 -0
  11. package/dist/src/cp.d.ts +17 -0
  12. package/dist/src/cp.js +88 -0
  13. package/dist/src/docker.container.d.ts +73 -0
  14. package/dist/src/docker.container.js +247 -0
  15. package/dist/src/docker.d.ts +68 -0
  16. package/dist/src/docker.js +188 -0
  17. package/dist/src/docker.network.d.ts +42 -0
  18. package/dist/src/docker.network.js +85 -0
  19. package/dist/src/docker.volume.d.ts +26 -0
  20. package/dist/src/docker.volume.js +62 -0
  21. package/dist/src/dockerCleanup.d.ts +38 -0
  22. package/dist/src/dockerCleanup.js +77 -0
  23. package/dist/src/dockerCompose.d.ts +154 -0
  24. package/dist/src/dockerCompose.js +439 -0
  25. package/dist/src/fs.d.ts +5 -0
  26. package/dist/src/fs.js +38 -0
  27. package/dist/src/git.d.ts +9 -0
  28. package/dist/src/git.js +24 -0
  29. package/dist/src/index.d.ts +20 -0
  30. package/dist/src/index.js +20 -0
  31. package/dist/src/maps.d.ts +33 -0
  32. package/dist/src/maps.js +41 -0
  33. package/dist/src/npm.d.ts +35 -0
  34. package/dist/src/npm.js +104 -0
  35. package/dist/src/pkg.d.ts +33 -0
  36. package/dist/src/pkg.js +33 -0
  37. package/dist/src/publish.d.ts +27 -0
  38. package/dist/src/publish.js +57 -0
  39. package/dist/src/run.d.ts +13 -0
  40. package/dist/src/run.js +44 -0
  41. package/dist/src/tgz.d.ts +13 -0
  42. package/dist/src/tgz.js +67 -0
  43. package/dist/src/version.d.ts +34 -0
  44. package/dist/src/version.js +101 -0
  45. package/dist/src/yarn.d.ts +26 -0
  46. package/dist/src/yarn.js +75 -0
  47. package/package.json +74 -20
  48. package/ant.js +0 -43
  49. package/ant.js.flow +0 -42
  50. package/artifactory.js +0 -617
  51. package/artifactory.js.flow +0 -616
  52. package/cert.conf +0 -20
  53. package/cert.js +0 -153
  54. package/cert.js.flow +0 -152
  55. package/clean.js +0 -20
  56. package/clean.js.flow +0 -19
  57. package/copy.js +0 -80
  58. package/copy.js.flow +0 -79
  59. package/cp.js +0 -173
  60. package/cp.js.flow +0 -172
  61. package/docker.container.js +0 -390
  62. package/docker.container.js.flow +0 -389
  63. package/docker.js +0 -368
  64. package/docker.js.flow +0 -367
  65. package/docker.network.js +0 -160
  66. package/docker.network.js.flow +0 -159
  67. package/docker.volume.js +0 -136
  68. package/docker.volume.js.flow +0 -136
  69. package/dockerCleanup.js +0 -152
  70. package/dockerCleanup.js.flow +0 -151
  71. package/dockerCompose.js +0 -766
  72. package/dockerCompose.js.flow +0 -765
  73. package/flow.js +0 -21
  74. package/flow.js.flow +0 -20
  75. package/fs.js +0 -95
  76. package/fs.js.flow +0 -96
  77. package/git.js +0 -35
  78. package/git.js.flow +0 -34
  79. package/hg.js +0 -35
  80. package/hg.js.flow +0 -34
  81. package/index.js +0 -27
  82. package/index.js.flow +0 -26
  83. package/inline-resources.js +0 -158
  84. package/inline-resources.js.flow +0 -157
  85. package/maps.js +0 -112
  86. package/maps.js.flow +0 -111
  87. package/npm.js +0 -145
  88. package/npm.js.flow +0 -144
  89. package/pkg.js +0 -81
  90. package/pkg.js.flow +0 -80
  91. package/publish.js +0 -145
  92. package/publish.js.flow +0 -144
  93. package/run.js +0 -90
  94. package/run.js.flow +0 -89
  95. package/src/ant.js +0 -42
  96. package/src/artifactory.js +0 -616
  97. package/src/cert.conf +0 -20
  98. package/src/cert.js +0 -152
  99. package/src/clean.js +0 -19
  100. package/src/copy.js +0 -79
  101. package/src/cp.js +0 -172
  102. package/src/docker.container.js +0 -389
  103. package/src/docker.js +0 -367
  104. package/src/docker.network.js +0 -159
  105. package/src/docker.volume.js +0 -136
  106. package/src/dockerCleanup.js +0 -151
  107. package/src/dockerCompose.js +0 -765
  108. package/src/flow.js +0 -20
  109. package/src/fs.js +0 -96
  110. package/src/git.js +0 -34
  111. package/src/hg.js +0 -34
  112. package/src/index.js +0 -26
  113. package/src/inline-resources.js +0 -157
  114. package/src/maps.js +0 -111
  115. package/src/npm.js +0 -144
  116. package/src/pkg.js +0 -80
  117. package/src/publish.js +0 -144
  118. package/src/run.js +0 -89
  119. package/src/test.js +0 -55
  120. package/src/tgz.js +0 -101
  121. package/src/version.js +0 -141
  122. package/src/yarn.js +0 -123
  123. package/test.js +0 -56
  124. package/test.js.flow +0 -55
  125. package/tgz.js +0 -102
  126. package/tgz.js.flow +0 -101
  127. package/version.js +0 -142
  128. package/version.js.flow +0 -141
  129. package/yarn.js +0 -124
  130. package/yarn.js.flow +0 -123
package/docker.js DELETED
@@ -1,368 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.copyFilesFromDockerImage = copyFilesFromDockerImage;exports.dockerBuild = dockerBuild;exports.dockerImages = dockerImages;exports.dockerLogin = dockerLogin;exports.dockerPull = dockerPull;exports.dockerPullAndRunContainer = dockerPullAndRunContainer;exports.dockerPush = dockerPush;exports.dockerRmi = dockerRmi;exports.dockerTag = dockerTag;exports.dockerTagVersion = dockerTagVersion;exports.getDockerConfig = getDockerConfig;exports.getDockerDigest = getDockerDigest;exports.getDockerId = getDockerId;exports.getDockerRepo = getDockerRepo;exports.getDockerTags = getDockerTags;exports.getUntaggedDockerIds = getUntaggedDockerIds;exports.parseDockerDate = void 0;
2
- var _path = _interopRequireDefault(require("path"));
3
- var _bytes = _interopRequireDefault(require("bytes"));
4
- var _isReachable = _interopRequireDefault(require("is-reachable"));
5
- var _moment = _interopRequireDefault(require("moment"));
6
- var _run = require("./run");
7
- var _pkg = require("./pkg");
8
- var _cp = require("./cp");
9
- var _version = require("./version");
10
- var _docker = require("./docker.container");
11
-
12
-
13
-
14
- var _docker2 = require("./docker.network");function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
- function getDockerConfig() {
23
- return (0, _pkg.getCfg)().docker || {};
24
- }
25
-
26
- const parseDockerDate = (date) =>
27
- (0, _moment.default)(date, 'YYYY-MM-DD HH:mm:ss ZZ').toDate();exports.parseDockerDate = parseDockerDate;
28
-
29
- async function dockerBuild(
30
- tags = ['latest'],
31
- buildArgs = [],
32
- target = null,
33
- extraArgs = [],
34
- repo = getDockerRepo(),
35
- dockerFile = './Dockerfile',
36
- workDir = '.')
37
- {
38
- const args = [
39
- 'build',
40
- ...['-f', _path.default.resolve(dockerFile)],
41
- ...(target ? ['--target', target] : []),
42
- ...tags.reduce((ar, t) => [...ar, '-t', `${repo}:${t}`], []),
43
- ...buildArgs.reduce((ar, a) => [...ar, '--build-arg', a], []),
44
- ...(extraArgs || []),
45
- _path.default.resolve(workDir)];
46
-
47
-
48
- return (0, _cp.spawn)('docker', args, { stdio: 'inherit' });
49
- }
50
-
51
- async function dockerTag(
52
- imageId,
53
- tags = ['latest'],
54
- repo = getDockerRepo())
55
- {
56
- await Promise.all(
57
- tags.map(async (t) => {
58
- await (0, _cp.spawn)('docker', ['tag', imageId, `${repo}:${t}`]);
59
- (0, _run.buildLog)(`Tagged image ${imageId} as ${repo}:${t}`);
60
- }));
61
-
62
- }
63
-
64
- /**
65
- * Apply the standard convention for tagging the docker image for the project,
66
- * based on the source control branch being built.
67
- * For releases, applies `latest`, `M.m.p`, `M.m`, `M`
68
- * For release candidates, applies `latest-rc`
69
- * For feature branches, applies `latest-feature`
70
- * For development branch, applies `latest-dev`
71
- * All other branches, no tag is applies
72
- * @param {string} imageId id of the docker image to which to apply the tags
73
- * @param {string} repo optional override of the docker repo url to use (derived from package.json by default)
74
- */
75
- async function dockerTagVersion(
76
- imageId,
77
- repo = getDockerRepo())
78
- {
79
- const { isRelease, major, minor, patch, branch } = await (0, _version.getVersion)();
80
- // determine what tags to apply
81
- if (isRelease) {
82
- await dockerTag(
83
- imageId,
84
- ['latest', `${major}`, `${major}.${minor}`, `${major}.${minor}.${patch}`],
85
- repo);
86
-
87
- } else if (branch === (0, _version.getDevBranch)()) {
88
- await dockerTag(imageId, ['latest-dev'], repo);
89
- } else if (branch.match(/^(release|patch)-/)) {
90
- await dockerTag(imageId, ['latest-rc'], repo);
91
- } else if (branch.match(/^feature-/)) {
92
- await dockerTag(imageId, ['latest-feature'], repo);
93
- }
94
- }
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
- async function dockerImages(
108
- repo = getDockerRepo(),
109
- filter = null)
110
- {
111
- return (
112
- await (0, _cp.spawn)(
113
- 'docker',
114
- ['images', '--format', `{{json .}}`, ...(repo ? [repo] : [])],
115
- { captureOutput: true })).
116
-
117
-
118
- split('\n').
119
- filter((line) => !!line.trim()).
120
- map((l) => {
121
- const {
122
- Repository: repository,
123
- Tag: tag,
124
- ID: id,
125
- Digest: digest,
126
- CreatedAt,
127
- Size } =
128
- JSON.parse(l.trim());
129
- return {
130
- repository,
131
- tag,
132
- id,
133
- digest,
134
- created: parseDockerDate(CreatedAt),
135
- size: _bytes.default.parse(Size) };
136
-
137
- }).
138
- filter(
139
- (m) =>
140
- (m && m.id) != null && (
141
- typeof filter === 'function' ? filter(m) : true));
142
-
143
- }
144
-
145
- async function getDockerId(
146
- tag = 'latest',
147
- repo)
148
- {
149
- return (await dockerImages(repo, (m) => m.tag === tag)).map((m) => m.id)[0];
150
- }
151
-
152
- async function getUntaggedDockerIds(
153
- repo,
154
- filter = null)
155
- {
156
- return (
157
- await dockerImages(
158
- repo,
159
- (m) =>
160
- m.tag === '<none>' && (typeof filter === 'function' ? filter(m) : true))).
161
-
162
- map((m) => m.id);
163
- }
164
-
165
- async function getDockerTags(
166
- id,
167
- repo,
168
- fullName = false,
169
- filter = null)
170
- {
171
- return (
172
- await dockerImages(
173
- repo,
174
- (m) =>
175
- (!id || m.id === id) && (
176
- typeof filter === 'function' ? filter(m) : true))).
177
-
178
- map((m) => fullName ? `${m.repository}:${m.tag}` : m.tag);
179
- }
180
-
181
- async function getDockerDigest(
182
- imageId,
183
- repo)
184
- {
185
- return (await dockerImages(repo, (m) => m.id === imageId)).map(
186
- (m) => m.digest)[
187
- 0];
188
- }
189
-
190
- async function dockerLogin(
191
- user,
192
- password,
193
- registry)
194
- {
195
- const reg = registry || getDockerConfig().registry;
196
- await (0, _cp.spawn)(
197
- 'docker',
198
- [
199
- 'login',
200
- '-u',
201
- user || process.env.ARTIFACTORY_USER || '',
202
- '-p',
203
- password || process.env.ARTIFACTORY_PASSWORD || '',
204
- ...(reg ? [reg] : [])],
205
-
206
- { stdio: 'inherit' });
207
-
208
- }
209
-
210
- async function dockerPush(
211
- tags = ['latest'],
212
- repo = getDockerRepo())
213
- {
214
- // do this sequentially, so you don't push the same image simultaneously
215
- await tags.reduce(async (prev, tag) => {
216
- await prev;
217
- await (0, _cp.spawn)('docker', ['push', `${repo}:${tag}`], { stdio: 'inherit' });
218
- }, Promise.resolve());
219
- }
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
- async function dockerPull({
228
- image,
229
- offline = process.argv.includes('--offline'),
230
- testUrl })
231
- {
232
- if (
233
- offline ||
234
- !(await (0, _isReachable.default)(testUrl || 'https://hub.docker.com')))
235
- {
236
- if (offline === false) {
237
- throw new Error('Offline, cannot docker pull');
238
- }
239
- (0, _run.buildLog)('It looks like you are offline, skipping docker pull');
240
- } else {
241
- // throws on failure
242
- await (0, _cp.spawn)('docker', ['pull', image], { stdio: 'inherit' });
243
- }
244
- }
245
-
246
- async function dockerRmi(
247
- images = [],
248
- ignoreErrors = true)
249
- {
250
- // must do these sequentially, or they will interfere with each other
251
- await images.reduce(async (prev, image) => {
252
- await prev;
253
- await (0, _cp.spawn)('docker', ['rmi', image], { stdio: 'inherit' }).catch((err) => {
254
- if (ignoreErrors) {
255
- (0, _run.buildLog)(
256
- `Warning (ignored Error): Failed to rm image(s): ${err.message}`);
257
-
258
- } else {
259
- throw err;
260
- }
261
- });
262
- }, Promise.resolve());
263
- }
264
-
265
- function getDockerRepo() {
266
- const { registry, repository: dkrRepo, name: dkrName } = getDockerConfig();
267
- const repository = dkrRepo || (0, _pkg.getPkgScope)();
268
- const name = dkrName || (0, _pkg.getPkgName)(false);
269
- if (!repository || !name) {
270
- throw new Error(
271
- 'Docker configuration is missing or incomplete in package.json');
272
-
273
- }
274
- return `${registry ? `${registry}/` : ''}${repository}/${name}`;
275
- }
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
- async function dockerPullAndRunContainer(
286
- image,
287
- options = {})
288
- {
289
- const {
290
- runArgs = [],
291
- cmd = [],
292
- network,
293
- alias,
294
- offline = process.argv.includes('--offline'),
295
- testUrl } =
296
- options;
297
-
298
- try {
299
- await dockerPull({ image, offline, testUrl });
300
- } catch (err) {
301
- (0, _run.buildLog)(`docker pull failed (${err.message}), attempting to continue...`);
302
- }
303
- const { id } = await (0, _docker.dockerContainerRunDaemon)({ image, runArgs, cmd });
304
- if (network) {
305
- await (0, _docker2.dockerNetworkConnect)(network, id, alias);
306
- }
307
- return id;
308
- }
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
- async function copyFilesFromDockerImage({
322
- imageId,
323
- filePaths,
324
- ignoreErrors })
325
- {
326
- const container = await (0, _docker.dockerContainerRunDaemon)({
327
- image: imageId,
328
- runArgs: ['-it', '--rm', '--entrypoint=/bin/bash'],
329
- cmd: ['read', '-p', 'pause'] });
330
-
331
-
332
- (0, _run.buildLog)(`Copying Files from Docker Image - imageId (${imageId})`);
333
-
334
- const spawnOptions = {
335
- stdio: 'inherit',
336
- pipeOutput: true,
337
- captureOutput: false };
338
-
339
- const copyErrors = [];
340
-
341
- try {
342
- filePaths.forEach(async (fp) => {
343
- // Try to copy from the Debug Folder
344
- try {
345
- await (0, _cp.spawn)(
346
- 'docker',
347
- ['cp', `${container.id}:${fp.from}`, fp.to],
348
- spawnOptions);
349
-
350
- (0, _run.buildLog)(`Copied ${fp.from} => ${fp.to}`);
351
- } catch (error) {
352
- copyErrors.push(error);
353
- (0, _run.buildLog)(`Error copying file ${fp.from}`);
354
- }
355
- });
356
- } finally {
357
- try {
358
- await (0, _docker.dockerContainerKill)(container.id);
359
- } catch (error) {
360
- copyErrors.push(error);
361
- }
362
- }
363
-
364
- if (copyErrors.length > 0 && ignoreErrors !== true) {
365
- throw new Error('Some files failed to copy');
366
- }
367
- }
368
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kb2NrZXIuanMiXSwibmFtZXMiOlsiZ2V0RG9ja2VyQ29uZmlnIiwiZG9ja2VyIiwicGFyc2VEb2NrZXJEYXRlIiwiZGF0ZSIsInRvRGF0ZSIsImRvY2tlckJ1aWxkIiwidGFncyIsImJ1aWxkQXJncyIsInRhcmdldCIsImV4dHJhQXJncyIsInJlcG8iLCJnZXREb2NrZXJSZXBvIiwiZG9ja2VyRmlsZSIsIndvcmtEaXIiLCJhcmdzIiwicGF0aCIsInJlc29sdmUiLCJyZWR1Y2UiLCJhciIsInQiLCJhIiwic3RkaW8iLCJkb2NrZXJUYWciLCJpbWFnZUlkIiwiUHJvbWlzZSIsImFsbCIsIm1hcCIsImRvY2tlclRhZ1ZlcnNpb24iLCJpc1JlbGVhc2UiLCJtYWpvciIsIm1pbm9yIiwicGF0Y2giLCJicmFuY2giLCJtYXRjaCIsImRvY2tlckltYWdlcyIsImZpbHRlciIsImNhcHR1cmVPdXRwdXQiLCJzcGxpdCIsImxpbmUiLCJ0cmltIiwibCIsIlJlcG9zaXRvcnkiLCJyZXBvc2l0b3J5IiwiVGFnIiwidGFnIiwiSUQiLCJpZCIsIkRpZ2VzdCIsImRpZ2VzdCIsIkNyZWF0ZWRBdCIsIlNpemUiLCJKU09OIiwicGFyc2UiLCJjcmVhdGVkIiwic2l6ZSIsImJ5dGVzIiwibSIsImdldERvY2tlcklkIiwiZ2V0VW50YWdnZWREb2NrZXJJZHMiLCJnZXREb2NrZXJUYWdzIiwiZnVsbE5hbWUiLCJnZXREb2NrZXJEaWdlc3QiLCJkb2NrZXJMb2dpbiIsInVzZXIiLCJwYXNzd29yZCIsInJlZ2lzdHJ5IiwicmVnIiwicHJvY2VzcyIsImVudiIsIkFSVElGQUNUT1JZX1VTRVIiLCJBUlRJRkFDVE9SWV9QQVNTV09SRCIsImRvY2tlclB1c2giLCJwcmV2IiwiZG9ja2VyUHVsbCIsImltYWdlIiwib2ZmbGluZSIsImFyZ3YiLCJpbmNsdWRlcyIsInRlc3RVcmwiLCJFcnJvciIsImRvY2tlclJtaSIsImltYWdlcyIsImlnbm9yZUVycm9ycyIsImNhdGNoIiwiZXJyIiwibWVzc2FnZSIsImRrclJlcG8iLCJuYW1lIiwiZGtyTmFtZSIsImRvY2tlclB1bGxBbmRSdW5Db250YWluZXIiLCJvcHRpb25zIiwicnVuQXJncyIsImNtZCIsIm5ldHdvcmsiLCJhbGlhcyIsImNvcHlGaWxlc0Zyb21Eb2NrZXJJbWFnZSIsImZpbGVQYXRocyIsImNvbnRhaW5lciIsInNwYXduT3B0aW9ucyIsInBpcGVPdXRwdXQiLCJjb3B5RXJyb3JzIiwiZm9yRWFjaCIsImZwIiwiZnJvbSIsInRvIiwiZXJyb3IiLCJwdXNoIiwibGVuZ3RoIl0sIm1hcHBpbmdzIjoiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUEsMkM7Ozs7Ozs7O0FBUU8sU0FBU0EsZUFBVCxHQUF5QztBQUM5QyxTQUFPLG1CQUFTQyxNQUFULElBQW1CLEVBQTFCO0FBQ0Q7O0FBRU0sTUFBTUMsZUFBZSxHQUFHLENBQUNDLElBQUQ7QUFDN0IscUJBQU9BLElBQVAsRUFBYSx3QkFBYixFQUF1Q0MsTUFBdkMsRUFESyxDOztBQUdBLGVBQWVDLFdBQWY7QUFDTEMsSUFBYyxHQUFHLENBQUMsUUFBRCxDQURaO0FBRUxDLFNBQW1CLEdBQUcsRUFGakI7QUFHTEMsTUFBZSxHQUFHLElBSGI7QUFJTEMsU0FBdUIsR0FBRyxFQUpyQjtBQUtMQyxJQUFZLEdBQUdDLGFBQWEsRUFMdkI7QUFNTEMsVUFBa0IsR0FBRyxjQU5oQjtBQU9MQyxPQUFlLEdBQUcsR0FQYjtBQVFZO0FBQ2pCLFFBQU1DLElBQUksR0FBRztBQUNYLFNBRFc7QUFFWCxLQUFHLENBQUMsSUFBRCxFQUFPQyxjQUFLQyxPQUFMLENBQWFKLFVBQWIsQ0FBUCxDQUZRO0FBR1gsTUFBSUosTUFBTSxHQUFHLENBQUMsVUFBRCxFQUFhQSxNQUFiLENBQUgsR0FBMEIsRUFBcEMsQ0FIVztBQUlYLEtBQUdGLElBQUksQ0FBQ1csTUFBTCxDQUFZLENBQUNDLEVBQUQsRUFBS0MsQ0FBTCxLQUFXLENBQUMsR0FBR0QsRUFBSixF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RCxLQUFQLEVBQWM7QUFDZEwsTUFBQUEsVUFBVSxDQUFDTSxJQUFYLENBQWdCRCxLQUFoQjtBQUNEO0FBQ0Y7O0FBRUQsTUFBSUwsVUFBVSxDQUFDTyxNQUFYLEdBQW9CLENBQXBCLElBQXlCekIsWUFBWSxLQUFLLElBQTlDLEVBQW9EO0FBQ2xELFVBQU0sSUFBSUgsS0FBSixDQUFVLDJCQUFWLENBQU47QUFDRDtBQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGJ5dGVzIGZyb20gJ2J5dGVzJztcbmltcG9ydCBpc1JlYWNoYWJsZSBmcm9tICdpcy1yZWFjaGFibGUnO1xuaW1wb3J0IG1vbWVudCBmcm9tICdtb21lbnQnO1xuaW1wb3J0IHsgYnVpbGRMb2cgfSBmcm9tICcuL3J1bic7XG5pbXBvcnQgeyBnZXRDZmcsIGdldFBrZ05hbWUsIGdldFBrZ1Njb3BlIH0gZnJvbSAnLi9wa2cnO1xuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICcuL2NwJztcbmltcG9ydCB7IGdldFZlcnNpb24sIGdldERldkJyYW5jaCB9IGZyb20gJy4vdmVyc2lvbic7XG5pbXBvcnQge1xuICBkb2NrZXJDb250YWluZXJSdW5EYWVtb24sXG4gIGRvY2tlckNvbnRhaW5lcktpbGwsXG59IGZyb20gJy4vZG9ja2VyLmNvbnRhaW5lcic7XG5pbXBvcnQgeyBkb2NrZXJOZXR3b3JrQ29ubmVjdCB9IGZyb20gJy4vZG9ja2VyLm5ldHdvcmsnO1xuXG5leHBvcnQgdHlwZSBEb2NrZXJDb25maWcgPSB7XG4gIHJlZ2lzdHJ5Pzogc3RyaW5nLFxuICByZXBvc2l0b3J5Pzogc3RyaW5nLFxuICBuYW1lPzogc3RyaW5nLFxufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldERvY2tlckNvbmZpZygpOiBEb2NrZXJDb25maWcge1xuICByZXR1cm4gZ2V0Q2ZnKCkuZG9ja2VyIHx8IHt9O1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VEb2NrZXJEYXRlID0gKGRhdGU6IHN0cmluZyk6IERhdGUgPT5cbiAgbW9tZW50KGRhdGUsICdZWVlZLU1NLUREIEhIOm1tOnNzIFpaJykudG9EYXRlKCk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJCdWlsZChcbiAgdGFnczogc3RyaW5nW10gPSBbJ2xhdGVzdCddLFxuICBidWlsZEFyZ3M6IHN0cmluZ1tdID0gW10sXG4gIHRhcmdldDogP3N0cmluZyA9IG51bGwsXG4gIGV4dHJhQXJncz86ID8oc3RyaW5nW10pID0gW10sXG4gIHJlcG86IHN0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbiAgZG9ja2VyRmlsZTogc3RyaW5nID0gJy4vRG9ja2VyZmlsZScsXG4gIHdvcmtEaXI6IHN0cmluZyA9ICcuJyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGFyZ3MgPSBbXG4gICAgJ2J1aWxkJyxcbiAgICAuLi5bJy1mJywgcGF0aC5yZXNvbHZlKGRvY2tlckZpbGUpXSxcbiAgICAuLi4odGFyZ2V0ID8gWyctLXRhcmdldCcsIHRhcmdldF0gOiBbXSksXG4gICAgLi4udGFncy5yZWR1Y2UoKGFyLCB0KSA9PiBbLi4uYXIsICctdCcsIGAke3JlcG99OiR7dH1gXSwgW10pLFxuICAgIC4uLmJ1aWxkQXJncy5yZWR1Y2UoKGFyLCBhKSA9PiBbLi4uYXIsICctLWJ1aWxkLWFyZycsIGFdLCBbXSksXG4gICAgLi4uKGV4dHJhQXJncyB8fCBbXSksXG4gICAgcGF0aC5yZXNvbHZlKHdvcmtEaXIpLFxuICBdO1xuXG4gIHJldHVybiBzcGF3bignZG9ja2VyJywgYXJncywgeyBzdGRpbzogJ2luaGVyaXQnIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyVGFnKFxuICBpbWFnZUlkOiBzdHJpbmcsXG4gIHRhZ3M6IHN0cmluZ1tdID0gWydsYXRlc3QnXSxcbiAgcmVwbz86IHN0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0YWdzLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgYXdhaXQgc3Bhd24oJ2RvY2tlcicsIFsndGFnJywgaW1hZ2VJZCwgYCR7cmVwb306JHt0fWBdKTtcbiAgICAgIGJ1aWxkTG9nKGBUYWdnZWQgaW1hZ2UgJHtpbWFnZUlkfSBhcyAke3JlcG99OiR7dH1gKTtcbiAgICB9KSxcbiAgKTtcbn1cblxuLyoqXG4gKiBBcHBseSB0aGUgc3RhbmRhcmQgY29udmVudGlvbiBmb3IgdGFnZ2luZyB0aGUgZG9ja2VyIGltYWdlIGZvciB0aGUgcHJvamVjdCxcbiAqIGJhc2VkIG9uIHRoZSBzb3VyY2UgY29udHJvbCBicmFuY2ggYmVpbmcgYnVpbHQuXG4gKiBGb3IgcmVsZWFzZXMsIGFwcGxpZXMgYGxhdGVzdGAsIGBNLm0ucGAsIGBNLm1gLCBgTWBcbiAqIEZvciByZWxlYXNlIGNhbmRpZGF0ZXMsIGFwcGxpZXMgYGxhdGVzdC1yY2BcbiAqIEZvciBmZWF0dXJlIGJyYW5jaGVzLCBhcHBsaWVzIGBsYXRlc3QtZmVhdHVyZWBcbiAqIEZvciBkZXZlbG9wbWVudCBicmFuY2gsIGFwcGxpZXMgYGxhdGVzdC1kZXZgXG4gKiBBbGwgb3RoZXIgYnJhbmNoZXMsIG5vIHRhZyBpcyBhcHBsaWVzXG4gKiBAcGFyYW0ge3N0cmluZ30gaW1hZ2VJZCBpZCBvZiB0aGUgZG9ja2VyIGltYWdlIHRvIHdoaWNoIHRvIGFwcGx5IHRoZSB0YWdzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVwbyBvcHRpb25hbCBvdmVycmlkZSBvZiB0aGUgZG9ja2VyIHJlcG8gdXJsIHRvIHVzZSAoZGVyaXZlZCBmcm9tIHBhY2thZ2UuanNvbiBieSBkZWZhdWx0KVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyVGFnVmVyc2lvbihcbiAgaW1hZ2VJZDogc3RyaW5nLFxuICByZXBvPzogc3RyaW5nID0gZ2V0RG9ja2VyUmVwbygpLFxuKSB7XG4gIGNvbnN0IHsgaXNSZWxlYXNlLCBtYWpvciwgbWlub3IsIHBhdGNoLCBicmFuY2ggfSA9IGF3YWl0IGdldFZlcnNpb24oKTtcbiAgLy8gZGV0ZXJtaW5lIHdoYXQgdGFncyB0byBhcHBseVxuICBpZiAoaXNSZWxlYXNlKSB7XG4gICAgYXdhaXQgZG9ja2VyVGFnKFxuICAgICAgaW1hZ2VJZCxcbiAgICAgIFsnbGF0ZXN0JywgYCR7bWFqb3J9YCwgYCR7bWFqb3J9LiR7bWlub3J9YCwgYCR7bWFqb3J9LiR7bWlub3J9LiR7cGF0Y2h9YF0sXG4gICAgICByZXBvLFxuICAgICk7XG4gIH0gZWxzZSBpZiAoYnJhbmNoID09PSBnZXREZXZCcmFuY2goKSkge1xuICAgIGF3YWl0IGRvY2tlclRhZyhpbWFnZUlkLCBbJ2xhdGVzdC1kZXYnXSwgcmVwbyk7XG4gIH0gZWxzZSBpZiAoYnJhbmNoLm1hdGNoKC9eKHJlbGVhc2V8cGF0Y2gpLS8pKSB7XG4gICAgYXdhaXQgZG9ja2VyVGFnKGltYWdlSWQsIFsnbGF0ZXN0LXJjJ10sIHJlcG8pO1xuICB9IGVsc2UgaWYgKGJyYW5jaC5tYXRjaCgvXmZlYXR1cmUtLykpIHtcbiAgICBhd2FpdCBkb2NrZXJUYWcoaW1hZ2VJZCwgWydsYXRlc3QtZmVhdHVyZSddLCByZXBvKTtcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBEb2NrZXJJbWFnZSA9IHtcbiAgcmVwb3NpdG9yeTogc3RyaW5nLFxuICB0YWc6IHN0cmluZyxcbiAgaWQ6IHN0cmluZyxcbiAgZGlnZXN0OiBzdHJpbmcsXG4gIGNyZWF0ZWQ6IERhdGUsXG4gIHNpemU6IG51bWJlcixcbn07XG5cbmV4cG9ydCB0eXBlIERvY2tlckltYWdlRmlsdGVyID0gKGk6IERvY2tlckltYWdlKSA9PiBib29sZWFuO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VySW1hZ2VzKFxuICByZXBvPzogP3N0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbiAgZmlsdGVyPzogP0RvY2tlckltYWdlRmlsdGVyID0gbnVsbCxcbik6IFByb21pc2U8RG9ja2VySW1hZ2VbXT4ge1xuICByZXR1cm4gKFxuICAgIGF3YWl0IHNwYXduKFxuICAgICAgJ2RvY2tlcicsXG4gICAgICBbJ2ltYWdlcycsICctLWZvcm1hdCcsIGB7e2pzb24gLn19YCwgLi4uKHJlcG8gPyBbcmVwb10gOiBbXSldLFxuICAgICAgeyBjYXB0dXJlT3V0cHV0OiB0cnVlIH0sXG4gICAgKVxuICApXG4gICAgLnNwbGl0KCdcXG4nKVxuICAgIC5maWx0ZXIoKGxpbmUpID0+ICEhbGluZS50cmltKCkpXG4gICAgLm1hcCgobCkgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICBSZXBvc2l0b3J5OiByZXBvc2l0b3J5LFxuICAgICAgICBUYWc6IHRhZyxcbiAgICAgICAgSUQ6IGlkLFxuICAgICAgICBEaWdlc3Q6IGRpZ2VzdCxcbiAgICAgICAgQ3JlYXRlZEF0LFxuICAgICAgICBTaXplLFxuICAgICAgfSA9IEpTT04ucGFyc2UobC50cmltKCkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVwb3NpdG9yeSxcbiAgICAgICAgdGFnLFxuICAgICAgICBpZCxcbiAgICAgICAgZGlnZXN0LFxuICAgICAgICBjcmVhdGVkOiBwYXJzZURvY2tlckRhdGUoQ3JlYXRlZEF0KSxcbiAgICAgICAgc2l6ZTogYnl0ZXMucGFyc2UoU2l6ZSksXG4gICAgICB9O1xuICAgIH0pXG4gICAgLmZpbHRlcihcbiAgICAgIChtKSA9PlxuICAgICAgICAobSAmJiBtLmlkKSAhPSBudWxsICYmXG4gICAgICAgICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nID8gZmlsdGVyKG0pIDogdHJ1ZSksXG4gICAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldERvY2tlcklkKFxuICB0YWc6IHN0cmluZyA9ICdsYXRlc3QnLFxuICByZXBvPzogP3N0cmluZyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiAoYXdhaXQgZG9ja2VySW1hZ2VzKHJlcG8sIChtKSA9PiBtLnRhZyA9PT0gdGFnKSkubWFwKChtKSA9PiBtLmlkKVswXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFVudGFnZ2VkRG9ja2VySWRzKFxuICByZXBvPzogP3N0cmluZyxcbiAgZmlsdGVyPzogP0RvY2tlckltYWdlRmlsdGVyID0gbnVsbCxcbik6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgcmV0dXJuIChcbiAgICBhd2FpdCBkb2NrZXJJbWFnZXMoXG4gICAgICByZXBvLFxuICAgICAgKG0pID0+XG4gICAgICAgIG0udGFnID09PSAnPG5vbmU+JyAmJiAodHlwZW9mIGZpbHRlciA9PT0gJ2Z1bmN0aW9uJyA/IGZpbHRlcihtKSA6IHRydWUpLFxuICAgIClcbiAgKS5tYXAoKG0pID0+IG0uaWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RG9ja2VyVGFncyhcbiAgaWQ/OiA/c3RyaW5nLFxuICByZXBvPzogP3N0cmluZyxcbiAgZnVsbE5hbWU6IGJvb2xlYW4gPSBmYWxzZSxcbiAgZmlsdGVyPzogP0RvY2tlckltYWdlRmlsdGVyID0gbnVsbCxcbik6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgcmV0dXJuIChcbiAgICBhd2FpdCBkb2NrZXJJbWFnZXMoXG4gICAgICByZXBvLFxuICAgICAgKG0pID0+XG4gICAgICAgICghaWQgfHwgbS5pZCA9PT0gaWQpICYmXG4gICAgICAgICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nID8gZmlsdGVyKG0pIDogdHJ1ZSksXG4gICAgKVxuICApLm1hcCgobSkgPT4gKGZ1bGxOYW1lID8gYCR7bS5yZXBvc2l0b3J5fToke20udGFnfWAgOiBtLnRhZykpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RG9ja2VyRGlnZXN0KFxuICBpbWFnZUlkOiBzdHJpbmcsXG4gIHJlcG8/OiBzdHJpbmcsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICByZXR1cm4gKGF3YWl0IGRvY2tlckltYWdlcyhyZXBvLCAobSkgPT4gbS5pZCA9PT0gaW1hZ2VJZCkpLm1hcChcbiAgICAobSkgPT4gbS5kaWdlc3QsXG4gIClbMF07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJMb2dpbihcbiAgdXNlcjogc3RyaW5nLFxuICBwYXNzd29yZDogc3RyaW5nLFxuICByZWdpc3RyeTogc3RyaW5nLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlZyA9IHJlZ2lzdHJ5IHx8IGdldERvY2tlckNvbmZpZygpLnJlZ2lzdHJ5O1xuICBhd2FpdCBzcGF3bihcbiAgICAnZG9ja2VyJyxcbiAgICBbXG4gICAgICAnbG9naW4nLFxuICAgICAgJy11JyxcbiAgICAgIHVzZXIgfHwgcHJvY2Vzcy5lbnYuQVJUSUZBQ1RPUllfVVNFUiB8fCAnJyxcbiAgICAgICctcCcsXG4gICAgICBwYXNzd29yZCB8fCBwcm9jZXNzLmVudi5BUlRJRkFDVE9SWV9QQVNTV09SRCB8fCAnJyxcbiAgICAgIC4uLihyZWcgPyBbcmVnXSA6IFtdKSxcbiAgICBdLFxuICAgIHsgc3RkaW86ICdpbmhlcml0JyB9LFxuICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyUHVzaChcbiAgdGFncz86IHN0cmluZ1tdID0gWydsYXRlc3QnXSxcbiAgcmVwbz86IHN0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbikge1xuICAvLyBkbyB0aGlzIHNlcXVlbnRpYWxseSwgc28geW91IGRvbid0IHB1c2ggdGhlIHNhbWUgaW1hZ2Ugc2ltdWx0YW5lb3VzbHlcbiAgYXdhaXQgdGFncy5yZWR1Y2UoYXN5bmMgKHByZXYsIHRhZykgPT4ge1xuICAgIGF3YWl0IHByZXY7XG4gICAgYXdhaXQgc3Bhd24oJ2RvY2tlcicsIFsncHVzaCcsIGAke3JlcG99OiR7dGFnfWBdLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7XG4gIH0sIFByb21pc2UucmVzb2x2ZSgpKTtcbn1cblxuZXhwb3J0IHR5cGUgRG9ja2VyUHVsbE9wdGlvbnMgPSB7XG4gIGltYWdlOiBzdHJpbmcsXG4gIG9mZmxpbmU/OiBib29sZWFuLFxuICB0ZXN0VXJsPzogP3N0cmluZyxcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJQdWxsKHtcbiAgaW1hZ2UsXG4gIG9mZmxpbmUgPSBwcm9jZXNzLmFyZ3YuaW5jbHVkZXMoJy0tb2ZmbGluZScpLFxuICB0ZXN0VXJsLFxufTogRG9ja2VyUHVsbE9wdGlvbnMpIHtcbiAgaWYgKFxuICAgIG9mZmxpbmUgfHxcbiAgICAhKGF3YWl0IGlzUmVhY2hhYmxlKHRlc3RVcmwgfHwgJ2h0dHBzOi8vaHViLmRvY2tlci5jb20nKSlcbiAgKSB7XG4gICAgaWYgKG9mZmxpbmUgPT09IGZhbHNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09mZmxpbmUsIGNhbm5vdCBkb2NrZXIgcHVsbCcpO1xuICAgIH1cbiAgICBidWlsZExvZygnSXQgbG9va3MgbGlrZSB5b3UgYXJlIG9mZmxpbmUsIHNraXBwaW5nIGRvY2tlciBwdWxsJyk7XG4gIH0gZWxzZSB7XG4gICAgLy8gdGhyb3dzIG9uIGZhaWx1cmVcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWydwdWxsJywgaW1hZ2VdLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvY2tlclJtaShcbiAgaW1hZ2VzOiBzdHJpbmdbXSA9IFtdLFxuICBpZ25vcmVFcnJvcnM6IGJvb2xlYW4gPSB0cnVlLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIG11c3QgZG8gdGhlc2Ugc2VxdWVudGlhbGx5LCBvciB0aGV5IHdpbGwgaW50ZXJmZXJlIHdpdGggZWFjaCBvdGhlclxuICBhd2FpdCBpbWFnZXMucmVkdWNlKGFzeW5jIChwcmV2LCBpbWFnZSkgPT4ge1xuICAgIGF3YWl0IHByZXY7XG4gICAgYXdhaXQgc3Bhd24oJ2RvY2tlcicsIFsncm1pJywgaW1hZ2VdLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgaWYgKGlnbm9yZUVycm9ycykge1xuICAgICAgICBidWlsZExvZyhcbiAgICAgICAgICBgV2FybmluZyAoaWdub3JlZCBFcnJvcik6IEZhaWxlZCB0byBybSBpbWFnZShzKTogJHtlcnIubWVzc2FnZX1gLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH0pO1xuICB9LCBQcm9taXNlLnJlc29sdmUoKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREb2NrZXJSZXBvKCk6IHN0cmluZyB7XG4gIGNvbnN0IHsgcmVnaXN0cnksIHJlcG9zaXRvcnk6IGRrclJlcG8sIG5hbWU6IGRrck5hbWUgfSA9IGdldERvY2tlckNvbmZpZygpO1xuICBjb25zdCByZXBvc2l0b3J5ID0gZGtyUmVwbyB8fCBnZXRQa2dTY29wZSgpO1xuICBjb25zdCBuYW1lID0gZGtyTmFtZSB8fCBnZXRQa2dOYW1lKGZhbHNlKTtcbiAgaWYgKCFyZXBvc2l0b3J5IHx8ICFuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0RvY2tlciBjb25maWd1cmF0aW9uIGlzIG1pc3Npbmcgb3IgaW5jb21wbGV0ZSBpbiBwYWNrYWdlLmpzb24nLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGAke3JlZ2lzdHJ5ID8gYCR7cmVnaXN0cnl9L2AgOiAnJ30ke3JlcG9zaXRvcnl9LyR7bmFtZX1gO1xufVxuXG5leHBvcnQgdHlwZSBQdWxsQW5kUnVuQ29udGFpbmVyT3B0aW9ucyA9IHtcbiAgLi4uRG9ja2VyUHVsbE9wdGlvbnMsXG4gIHJ1bkFyZ3M/OiBzdHJpbmdbXSxcbiAgY21kPzogc3RyaW5nW10sXG4gIG5ldHdvcms/OiA/c3RyaW5nLFxuICBhbGlhcz86ID9zdHJpbmcsXG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyUHVsbEFuZFJ1bkNvbnRhaW5lcihcbiAgaW1hZ2U6IHN0cmluZyxcbiAgb3B0aW9uczogUHVsbEFuZFJ1bkNvbnRhaW5lck9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHtcbiAgICBydW5BcmdzID0gW10sXG4gICAgY21kID0gW10sXG4gICAgbmV0d29yayxcbiAgICBhbGlhcyxcbiAgICBvZmZsaW5lID0gcHJvY2Vzcy5hcmd2LmluY2x1ZGVzKCctLW9mZmxpbmUnKSxcbiAgICB0ZXN0VXJsLFxuICB9ID0gb3B0aW9ucztcblxuICB0cnkge1xuICAgIGF3YWl0IGRvY2tlclB1bGwoeyBpbWFnZSwgb2ZmbGluZSwgdGVzdFVybCB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgYnVpbGRMb2coYGRvY2tlciBwdWxsIGZhaWxlZCAoJHtlcnIubWVzc2FnZX0pLCBhdHRlbXB0aW5nIHRvIGNvbnRpbnVlLi4uYCk7XG4gIH1cbiAgY29uc3QgeyBpZCB9ID0gYXdhaXQgZG9ja2VyQ29udGFpbmVyUnVuRGFlbW9uKHsgaW1hZ2UsIHJ1bkFyZ3MsIGNtZCB9KTtcbiAgaWYgKG5ldHdvcmspIHtcbiAgICBhd2FpdCBkb2NrZXJOZXR3b3JrQ29ubmVjdChuZXR3b3JrLCBpZCwgYWxpYXMpO1xuICB9XG4gIHJldHVybiBpZDtcbn1cblxuZXhwb3J0IHR5cGUgQ29weUZpbGVQYXRoQ29uZmlnID0ge1xuICBmcm9tOiBzdHJpbmcsXG4gIHRvOiBzdHJpbmcsXG59O1xuXG5leHBvcnQgdHlwZSBDb3B5RmlsZXNGcm9tRG9ja2VySW1hZ2VDb25maWcgPSB7XG4gIGltYWdlSWQ6IHN0cmluZyxcbiAgZmlsZVBhdGhzOiBDb3B5RmlsZVBhdGhDb25maWdbXSxcbiAgaWdub3JlRXJyb3JzPzogP2Jvb2xlYW4sXG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29weUZpbGVzRnJvbURvY2tlckltYWdlKHtcbiAgaW1hZ2VJZCxcbiAgZmlsZVBhdGhzLFxuICBpZ25vcmVFcnJvcnMsXG59OiBDb3B5RmlsZXNGcm9tRG9ja2VySW1hZ2VDb25maWcpOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCBjb250YWluZXIgPSBhd2FpdCBkb2NrZXJDb250YWluZXJSdW5EYWVtb24oe1xuICAgIGltYWdlOiBpbWFnZUlkLFxuICAgIHJ1bkFyZ3M6IFsnLWl0JywgJy0tcm0nLCAnLS1lbnRyeXBvaW50PS9iaW4vYmFzaCddLFxuICAgIGNtZDogWydyZWFkJywgJy1wJywgJ3BhdXNlJ10sXG4gIH0pO1xuXG4gIGJ1aWxkTG9nKGBDb3B5aW5nIEZpbGVzIGZyb20gRG9ja2VyIEltYWdlIC0gaW1hZ2VJZCAoJHtpbWFnZUlkfSlgKTtcblxuICBjb25zdCBzcGF3bk9wdGlvbnMgPSB7XG4gICAgc3RkaW86ICdpbmhlcml0JyxcbiAgICBwaXBlT3V0cHV0OiB0cnVlLFxuICAgIGNhcHR1cmVPdXRwdXQ6IGZhbHNlLFxuICB9O1xuICBjb25zdCBjb3B5RXJyb3JzID0gW107XG5cbiAgdHJ5IHtcbiAgICBmaWxlUGF0aHMuZm9yRWFjaChhc3luYyAoZnApID0+IHtcbiAgICAgIC8vIFRyeSB0byBjb3B5IGZyb20gdGhlIERlYnVnIEZvbGRlclxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc3Bhd24oXG4gICAgICAgICAgJ2RvY2tlcicsXG4gICAgICAgICAgWydjcCcsIGAke2NvbnRhaW5lci5pZH06JHtmcC5mcm9tfWAsIGZwLnRvXSxcbiAgICAgICAgICBzcGF3bk9wdGlvbnMsXG4gICAgICAgICk7XG4gICAgICAgIGJ1aWxkTG9nKGBDb3BpZWQgJHtmcC5mcm9tfSA9PiAke2ZwLnRvfWApO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29weUVycm9ycy5wdXNoKGVycm9yKTtcbiAgICAgICAgYnVpbGRMb2coYEVycm9yIGNvcHlpbmcgZmlsZSAke2ZwLmZyb219YCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGRvY2tlckNvbnRhaW5lcktpbGwoY29udGFpbmVyLmlkKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29weUVycm9ycy5wdXNoKGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBpZiAoY29weUVycm9ycy5sZW5ndGggPiAwICYmIGlnbm9yZUVycm9ycyAhPT0gdHJ1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU29tZSBmaWxlcyBmYWlsZWQgdG8gY29weScpO1xuICB9XG59XG4iXX0=