appium 2.0.0-beta.2 → 2.0.0-beta.23

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 (122) hide show
  1. package/README.md +9 -9
  2. package/build/check-npm-pack-files.js +23 -0
  3. package/build/commands-yml/parse.js +319 -0
  4. package/build/commands-yml/validator.js +130 -0
  5. package/build/index.js +19 -0
  6. package/build/lib/appium-config.schema.json +0 -0
  7. package/build/lib/appium.js +160 -53
  8. package/build/lib/cli/args.js +115 -279
  9. package/build/lib/cli/driver-command.js +11 -1
  10. package/build/lib/cli/extension-command.js +60 -8
  11. package/build/lib/cli/extension.js +30 -7
  12. package/build/lib/cli/npm.js +43 -29
  13. package/build/lib/cli/parser.js +156 -89
  14. package/build/lib/cli/plugin-command.js +11 -1
  15. package/build/lib/cli/utils.js +29 -3
  16. package/build/lib/config-file.js +141 -0
  17. package/build/lib/config.js +53 -65
  18. package/build/lib/driver-config.js +42 -19
  19. package/build/lib/drivers.js +8 -4
  20. package/build/lib/ext-config-io.js +165 -0
  21. package/build/lib/extension-config.js +130 -61
  22. package/build/lib/grid-register.js +22 -24
  23. package/build/lib/logger.js +3 -3
  24. package/build/lib/logsink.js +11 -13
  25. package/build/lib/main.js +197 -77
  26. package/build/lib/plugin-config.js +21 -11
  27. package/build/lib/plugins.js +4 -2
  28. package/build/lib/schema/appium-config-schema.js +253 -0
  29. package/build/lib/schema/arg-spec.js +120 -0
  30. package/build/lib/schema/cli-args.js +188 -0
  31. package/build/lib/schema/cli-transformers.js +76 -0
  32. package/build/lib/schema/index.js +36 -0
  33. package/build/lib/schema/keywords.js +72 -0
  34. package/build/lib/schema/schema.js +357 -0
  35. package/build/lib/utils.js +44 -99
  36. package/build/postinstall.js +90 -0
  37. package/build/test/cli/cli-e2e-specs.js +221 -0
  38. package/build/test/cli/cli-helpers.js +86 -0
  39. package/build/test/cli/cli-specs.js +71 -0
  40. package/build/test/cli/fixtures/test-driver/package.json +27 -0
  41. package/build/test/cli/schema-args-specs.js +48 -0
  42. package/build/test/cli/schema-e2e-specs.js +47 -0
  43. package/build/test/config-e2e-specs.js +112 -0
  44. package/build/test/config-file-e2e-specs.js +209 -0
  45. package/build/test/config-file-specs.js +281 -0
  46. package/build/test/config-specs.js +159 -0
  47. package/build/test/driver-e2e-specs.js +435 -0
  48. package/build/test/driver-specs.js +321 -0
  49. package/build/test/ext-config-io-specs.js +181 -0
  50. package/build/test/extension-config-specs.js +365 -0
  51. package/build/test/fixtures/allow-feat.txt +5 -0
  52. package/build/test/fixtures/caps.json +3 -0
  53. package/build/test/fixtures/config/allow-insecure.txt +3 -0
  54. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +5 -0
  55. package/build/test/fixtures/config/appium.config.bad.json +32 -0
  56. package/build/test/fixtures/config/appium.config.ext-good.json +9 -0
  57. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +10 -0
  58. package/build/test/fixtures/config/appium.config.good.js +40 -0
  59. package/build/test/fixtures/config/appium.config.good.json +33 -0
  60. package/build/test/fixtures/config/appium.config.good.yaml +30 -0
  61. package/build/test/fixtures/config/appium.config.invalid.json +31 -0
  62. package/build/test/fixtures/config/appium.config.security-array.json +5 -0
  63. package/build/test/fixtures/config/appium.config.security-delimited.json +5 -0
  64. package/build/test/fixtures/config/appium.config.security-path.json +5 -0
  65. package/build/test/fixtures/config/driver-fake.config.json +8 -0
  66. package/build/test/fixtures/config/nodeconfig.json +3 -0
  67. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  68. package/build/test/fixtures/default-args.js +35 -0
  69. package/build/test/fixtures/deny-feat.txt +5 -0
  70. package/build/test/fixtures/driver.schema.js +20 -0
  71. package/build/test/fixtures/extensions.yaml +27 -0
  72. package/build/test/fixtures/flattened-schema.js +504 -0
  73. package/build/test/fixtures/plugin.schema.js +20 -0
  74. package/build/test/fixtures/schema-with-extensions.js +28 -0
  75. package/build/test/grid-register-specs.js +74 -0
  76. package/build/test/helpers.js +75 -0
  77. package/build/test/logger-specs.js +76 -0
  78. package/build/test/npm-specs.js +20 -0
  79. package/build/test/parser-specs.js +314 -0
  80. package/build/test/plugin-e2e-specs.js +316 -0
  81. package/build/test/schema/arg-spec-specs.js +70 -0
  82. package/build/test/schema/cli-args-specs.js +431 -0
  83. package/build/test/schema/schema-specs.js +389 -0
  84. package/build/test/utils-specs.js +266 -0
  85. package/index.js +11 -0
  86. package/lib/appium-config.schema.json +278 -0
  87. package/lib/appium.js +207 -65
  88. package/lib/cli/args.js +174 -375
  89. package/lib/cli/driver-command.js +4 -0
  90. package/lib/cli/extension-command.js +70 -5
  91. package/lib/cli/extension.js +25 -5
  92. package/lib/cli/npm.js +86 -18
  93. package/lib/cli/parser.js +257 -79
  94. package/lib/cli/plugin-command.js +4 -0
  95. package/lib/cli/utils.js +21 -1
  96. package/lib/config-file.js +227 -0
  97. package/lib/config.js +84 -63
  98. package/lib/driver-config.js +66 -11
  99. package/lib/drivers.js +4 -1
  100. package/lib/ext-config-io.js +287 -0
  101. package/lib/extension-config.js +225 -67
  102. package/lib/grid-register.js +27 -24
  103. package/lib/logger.js +1 -1
  104. package/lib/logsink.js +10 -7
  105. package/lib/main.js +214 -77
  106. package/lib/plugin-config.js +35 -6
  107. package/lib/plugins.js +1 -0
  108. package/lib/schema/appium-config-schema.js +287 -0
  109. package/lib/schema/arg-spec.js +222 -0
  110. package/lib/schema/cli-args.js +285 -0
  111. package/lib/schema/cli-transformers.js +123 -0
  112. package/lib/schema/index.js +2 -0
  113. package/lib/schema/keywords.js +135 -0
  114. package/lib/schema/schema.js +577 -0
  115. package/lib/utils.js +42 -88
  116. package/package.json +55 -84
  117. package/postinstall.js +71 -0
  118. package/types/appium-config.d.ts +197 -0
  119. package/types/types.d.ts +201 -0
  120. package/CHANGELOG.md +0 -3515
  121. package/build/lib/cli/parser-helpers.js +0 -82
  122. package/lib/cli/parser-helpers.js +0 -79
@@ -0,0 +1,431 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ require("source-map-support/register");
6
+
7
+ var _lodash = _interopRequireDefault(require("lodash"));
8
+
9
+ var _schema = require("../../lib/schema");
10
+
11
+ var _cliArgs = require("../../lib/schema/cli-args");
12
+
13
+ var _cliTransformers = require("../../lib/schema/cli-transformers");
14
+
15
+ const {
16
+ expect
17
+ } = chai;
18
+ describe('cli-args', function () {
19
+ describe('toParserArgs()', function () {
20
+ function getArgs(opts = {}) {
21
+ let {
22
+ extName,
23
+ extType,
24
+ schema
25
+ } = opts;
26
+
27
+ if (schema && extName && extType) {
28
+ (0, _schema.registerSchema)(extType, extName, schema);
29
+ }
30
+
31
+ (0, _schema.finalizeSchema)();
32
+ return _lodash.default.fromPairs([...(0, _cliArgs.toParserArgs)(opts)]);
33
+ }
34
+
35
+ beforeEach(_schema.resetSchema);
36
+ afterEach(_schema.resetSchema);
37
+ describe('schema contents', function () {
38
+ const extName = 'blob';
39
+ const extType = 'plugin';
40
+ describe('type', function () {
41
+ let result;
42
+ describe('boolean', function () {
43
+ beforeEach(function () {
44
+ const schema = {
45
+ properties: {
46
+ foo: {
47
+ type: 'boolean'
48
+ }
49
+ },
50
+ type: 'object'
51
+ };
52
+ result = getArgs({
53
+ schema,
54
+ extName,
55
+ extType
56
+ });
57
+ });
58
+ it('should return options containing `action` prop of `store_true` and no `type`', function () {
59
+ expect(result['--plugin-blob-foo']).to.have.property('action', 'store_true');
60
+ });
61
+ it('should not contain a `metavar` property', function () {
62
+ expect(result['--plugin-blob-foo']).not.to.have.property('metavar');
63
+ });
64
+ });
65
+ describe('object', function () {
66
+ beforeEach(function () {
67
+ const schema = {
68
+ properties: {
69
+ foo: {
70
+ type: 'object'
71
+ }
72
+ },
73
+ type: 'object'
74
+ };
75
+ result = getArgs({
76
+ schema,
77
+ extName,
78
+ extType
79
+ });
80
+ });
81
+ it('should use the `json` transformer', function () {
82
+ expect(result['--plugin-blob-foo']).to.have.property('type', _cliTransformers.transformers.json);
83
+ });
84
+ it('should contain a SCREAMING_SNAKE_CASE `metavar` prop', function () {
85
+ expect(result['--plugin-blob-foo']).to.have.property('metavar', 'FOO');
86
+ });
87
+ });
88
+ describe('array', function () {
89
+ beforeEach(function () {
90
+ const schema = {
91
+ properties: {
92
+ foo: {
93
+ type: 'array'
94
+ }
95
+ },
96
+ type: 'object'
97
+ };
98
+ result = getArgs({
99
+ schema,
100
+ extName,
101
+ extType
102
+ });
103
+ });
104
+ it('should use the `csv` transformer', function () {
105
+ expect(result['--plugin-blob-foo']).to.have.property('type', _cliTransformers.transformers.csv);
106
+ });
107
+ it('should contain a SCREAMING_SNAKE_CASE `metavar` prop', function () {
108
+ expect(result['--plugin-blob-foo']).to.have.property('metavar', 'FOO');
109
+ });
110
+ });
111
+ describe('number', function () {
112
+ beforeEach(function () {
113
+ const schema = {
114
+ properties: {
115
+ foo: {
116
+ type: 'number'
117
+ }
118
+ },
119
+ type: 'object'
120
+ };
121
+ result = getArgs({
122
+ schema,
123
+ extName,
124
+ extType
125
+ });
126
+ });
127
+ it('should parse the value as a float', function () {
128
+ expect(result['--plugin-blob-foo'].type('10.5')).to.equal(10.5);
129
+ });
130
+ it('should contain a SCREAMING_SNAKE_CASE `metavar` prop', function () {
131
+ expect(result['--plugin-blob-foo']).to.have.property('metavar', 'FOO');
132
+ });
133
+ });
134
+ describe('integer', function () {
135
+ beforeEach(function () {
136
+ const schema = {
137
+ properties: {
138
+ foo: {
139
+ type: 'integer'
140
+ }
141
+ },
142
+ type: 'object'
143
+ };
144
+ result = getArgs({
145
+ schema,
146
+ extName,
147
+ extType
148
+ });
149
+ });
150
+ it('should parse the value as an integer', function () {
151
+ expect(result['--plugin-blob-foo'].type('10.5')).to.equal(10);
152
+ });
153
+ it('should contain a SCREAMING_SNAKE_CASE `metavar` prop', function () {
154
+ expect(result['--plugin-blob-foo']).to.have.property('metavar', 'FOO');
155
+ });
156
+ });
157
+ describe('string', function () {
158
+ beforeEach(function () {
159
+ const schema = {
160
+ properties: {
161
+ foo: {
162
+ type: 'string'
163
+ }
164
+ },
165
+ type: 'object'
166
+ };
167
+ result = getArgs({
168
+ schema,
169
+ extName,
170
+ extType
171
+ });
172
+ });
173
+ it('should parse the value as an integer', function () {
174
+ expect(result['--plugin-blob-foo'].type('10.5')).to.equal('10.5');
175
+ });
176
+ it('should contain a SCREAMING_SNAKE_CASE `metavar` prop', function () {
177
+ expect(result['--plugin-blob-foo']).to.have.property('metavar', 'FOO');
178
+ });
179
+ });
180
+ describe('null', function () {
181
+ it('should throw', function () {
182
+ const schema = {
183
+ properties: {
184
+ foo: {
185
+ type: 'null'
186
+ }
187
+ },
188
+ type: 'object'
189
+ };
190
+ expect(() => getArgs({
191
+ extType,
192
+ extName,
193
+ schema
194
+ })).to.throw(TypeError, /unknown or disallowed/);
195
+ });
196
+ });
197
+ describe('(unknown)', function () {
198
+ it('should throw', function () {
199
+ const schema = {
200
+ properties: {
201
+ foo: {
202
+ type: 'donkey'
203
+ }
204
+ },
205
+ type: 'object'
206
+ };
207
+ expect(() => getArgs({
208
+ extType,
209
+ extName,
210
+ schema
211
+ })).to.throw(Error, /schema is invalid/);
212
+ });
213
+ });
214
+ });
215
+ describe('appiumCliAliases', function () {
216
+ let result;
217
+ it('should not allow short aliases for extensions', function () {
218
+ const schema = {
219
+ properties: {
220
+ foo: {
221
+ type: 'string',
222
+ appiumCliAliases: ['fooooo', 'F']
223
+ }
224
+ },
225
+ type: 'object'
226
+ };
227
+ result = getArgs({
228
+ schema,
229
+ extName,
230
+ extType
231
+ });
232
+ expect(result).to.have.property('--plugin-blob-foo,--plugin-blob-fooooo,--plugin-blob-F');
233
+ });
234
+ });
235
+ describe('appiumCliDescription', function () {
236
+ let result;
237
+ it('should be preferred over `description`', function () {
238
+ const schema = {
239
+ properties: {
240
+ foo: {
241
+ type: 'string',
242
+ appiumCliDescription: 'foo',
243
+ description: 'bar'
244
+ }
245
+ },
246
+ type: 'object'
247
+ };
248
+ result = getArgs({
249
+ schema,
250
+ extName,
251
+ extType
252
+ });
253
+ expect(result['--plugin-blob-foo']).to.have.property('help', 'foo');
254
+ });
255
+ });
256
+ describe('appiumCliTransformer', function () {
257
+ let result;
258
+ it('should use the transformer', function () {
259
+ const schema = {
260
+ properties: {
261
+ foo: {
262
+ type: 'string',
263
+ appiumCliTransformer: 'json'
264
+ }
265
+ },
266
+ type: 'object'
267
+ };
268
+ result = getArgs({
269
+ schema,
270
+ extName,
271
+ extType
272
+ });
273
+ expect(result['--plugin-blob-foo'].type('{"herp": "derp"}')).to.eql({
274
+ herp: 'derp'
275
+ });
276
+ });
277
+ it('should error if the value is not valid for the transformer', function () {
278
+ const schema = {
279
+ properties: {
280
+ foo: {
281
+ type: 'string',
282
+ appiumCliTransformer: 'json'
283
+ }
284
+ },
285
+ type: 'object'
286
+ };
287
+ result = getArgs({
288
+ schema,
289
+ extName,
290
+ extType
291
+ });
292
+ expect(() => result['--plugin-blob-foo'].type('123')).to.throw(/must be a valid json/i);
293
+ });
294
+ describe('when used with `enum`', function () {
295
+ describe('and enum members are invalid as per the transformer', function () {
296
+ describe('when provided an enum member', function () {
297
+ it('should throw', function () {
298
+ const schema = {
299
+ properties: {
300
+ foo: {
301
+ type: 'string',
302
+ appiumCliTransformer: 'json',
303
+ enum: ['herp', 'derp']
304
+ }
305
+ },
306
+ type: 'object'
307
+ };
308
+ result = getArgs({
309
+ schema,
310
+ extName,
311
+ extType
312
+ });
313
+ expect(() => result['--plugin-blob-foo'].type('herp')).to.throw(/must be a valid json/i);
314
+ });
315
+ });
316
+ });
317
+ describe('and enum members are valid as per the transformer', function () {
318
+ describe('when provided an enum member', function () {
319
+ it('should return a transformed value', function () {
320
+ const schema = {
321
+ properties: {
322
+ foo: {
323
+ type: 'string',
324
+ appiumCliTransformer: 'json',
325
+ enum: ['{"herp": "derp"}', '{"derp": "herp"}']
326
+ }
327
+ },
328
+ type: 'object'
329
+ };
330
+ result = getArgs({
331
+ schema,
332
+ extName,
333
+ extType
334
+ });
335
+ expect(result['--plugin-blob-foo'].type('{"herp": "derp"}')).to.eql({
336
+ herp: 'derp'
337
+ });
338
+ });
339
+ });
340
+ describe('when not provided an enum member', function () {
341
+ it('should throw', function () {
342
+ const schema = {
343
+ properties: {
344
+ foo: {
345
+ type: 'string',
346
+ appiumCliTransformer: 'json',
347
+ enum: ['{"herp": "derp"}', '{"derp": "herp"}']
348
+ }
349
+ },
350
+ type: 'object'
351
+ };
352
+ result = getArgs({
353
+ schema,
354
+ extName,
355
+ extType
356
+ });
357
+ expect(() => result['--plugin-blob-foo'].type('{"georgy": "porgy"}')).to.throw(/one of the allowed values/i);
358
+ });
359
+ });
360
+ });
361
+ });
362
+ });
363
+ describe('enum', function () {
364
+ describe('when used with a non-`string` type', function () {
365
+ it('should throw', function () {
366
+ const schema = {
367
+ properties: {
368
+ foo: {
369
+ type: 'number',
370
+ enum: ['herp', 'derp']
371
+ }
372
+ },
373
+ type: 'object'
374
+ };
375
+ expect(() => getArgs({
376
+ schema,
377
+ extName,
378
+ extType
379
+ })).to.throw(TypeError, /`enum` is only supported for `type: 'string'`/i);
380
+ });
381
+ it('should actually throw earlier by failing schema validation, but that would mean overriding the behavior of `enum` which sounds inadvisable');
382
+ });
383
+ describe('when used with a `string` type', function () {
384
+ it('should set `choices` prop', function () {
385
+ const schema = {
386
+ properties: {
387
+ foo: {
388
+ type: 'string',
389
+ enum: ['herp', 'derp']
390
+ }
391
+ },
392
+ type: 'object'
393
+ };
394
+ const result = getArgs({
395
+ schema,
396
+ extName,
397
+ extType
398
+ });
399
+ expect(result['--plugin-blob-foo']).to.have.deep.property('choices', ['herp', 'derp']);
400
+ });
401
+ });
402
+ });
403
+ describe('overrides', function () {
404
+ it('should set them via "dest" key', function () {
405
+ const schema = {
406
+ properties: {
407
+ foo: {
408
+ type: 'string'
409
+ }
410
+ },
411
+ type: 'object'
412
+ };
413
+ const result = getArgs({
414
+ schema,
415
+ extName,
416
+ extType,
417
+ overrides: {
418
+ 'plugin.blob.foo': {
419
+ enum: ['slug', 'snail']
420
+ }
421
+ }
422
+ });
423
+ expect(result['--plugin-blob-foo']).to.have.deep.property('enum', ['slug', 'snail']);
424
+ });
425
+ });
426
+ });
427
+ });
428
+ });require('source-map-support').install();
429
+
430
+
431
+ //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3Qvc2NoZW1hL2NsaS1hcmdzLXNwZWNzLmpzIl0sIm5hbWVzIjpbImV4cGVjdCIsImNoYWkiLCJkZXNjcmliZSIsImdldEFyZ3MiLCJvcHRzIiwiZXh0TmFtZSIsImV4dFR5cGUiLCJzY2hlbWEiLCJfIiwiZnJvbVBhaXJzIiwiYmVmb3JlRWFjaCIsInJlc2V0U2NoZW1hIiwiYWZ0ZXJFYWNoIiwicmVzdWx0IiwicHJvcGVydGllcyIsImZvbyIsInR5cGUiLCJpdCIsInRvIiwiaGF2ZSIsInByb3BlcnR5Iiwibm90IiwidHJhbnNmb3JtZXJzIiwianNvbiIsImNzdiIsImVxdWFsIiwidGhyb3ciLCJUeXBlRXJyb3IiLCJFcnJvciIsImFwcGl1bUNsaUFsaWFzZXMiLCJhcHBpdW1DbGlEZXNjcmlwdGlvbiIsImRlc2NyaXB0aW9uIiwiYXBwaXVtQ2xpVHJhbnNmb3JtZXIiLCJlcWwiLCJoZXJwIiwiZW51bSIsImRlZXAiLCJvdmVycmlkZXMiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUVBLE1BQU07QUFBQ0EsRUFBQUE7QUFBRCxJQUFXQyxJQUFqQjtBQUVBQyxRQUFRLENBQUMsVUFBRCxFQUFhLFlBQVk7QUFDL0JBLEVBQUFBLFFBQVEsQ0FBQyxnQkFBRCxFQUFtQixZQUFZO0FBTXJDLGFBQVNDLE9BQVQsQ0FBa0JDLElBQUksR0FBRyxFQUF6QixFQUE2QjtBQUMzQixVQUFJO0FBQUNDLFFBQUFBLE9BQUQ7QUFBVUMsUUFBQUEsT0FBVjtBQUFtQkMsUUFBQUE7QUFBbkIsVUFBNkJILElBQWpDOztBQUNBLFVBQUlHLE1BQU0sSUFBSUYsT0FBVixJQUFxQkMsT0FBekIsRUFBa0M7QUFDaEMsb0NBQWVBLE9BQWYsRUFBd0JELE9BQXhCLEVBQWlDRSxNQUFqQztBQUNEOztBQUNEO0FBQ0EsYUFBT0MsZ0JBQUVDLFNBQUYsQ0FBWSxDQUFDLEdBQUcsMkJBQWFMLElBQWIsQ0FBSixDQUFaLENBQVA7QUFDRDs7QUFFRE0s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QUF2QyxDQUE0Q2lCLElBQTVDLENBQWlEaEIsUUFBakQsQ0FDRSxTQURGLEVBRUUsQ0FBQyxNQUFELEVBQVMsTUFBVCxDQUZGO0FBSUQsV0FmQyxDQUFGO0FBZ0JELFNBakJPLENBQVI7QUFrQkQsT0F6Q08sQ0FBUjtBQTJDQWxCLE1BQUFBLFFBQVEsQ0FBQyxXQUFELEVBQWMsWUFBWTtBQUdoQ2UsUUFBQUEsRUFBRSxDQUFDLGdDQUFELEVBQW1DLFlBQVk7QUFDL0MsZ0JBQU1WLE1BQU0sR0FBRztBQUNiTyxZQUFBQSxVQUFVLEVBQUU7QUFDVkMsY0FBQUEsR0FBRyxFQUFFO0FBQ0hDLGdCQUFBQSxJQUFJLEVBQUU7QUFESDtBQURLLGFBREM7QUFNYkEsWUFBQUEsSUFBSSxFQUFFO0FBTk8sV0FBZjtBQVNBLGdCQUFNSCxNQUFNLEdBQUdWLE9BQU8sQ0FBQztBQUNyQkksWUFBQUEsTUFEcUI7QUFFckJGLFlBQUFBLE9BRnFCO0FBR3JCQyxZQUFBQSxPQUhxQjtBQUlyQitCLFlBQUFBLFNBQVMsRUFBRTtBQUFDLGlDQUFtQjtBQUFDRixnQkFBQUEsSUFBSSxFQUFFLENBQUMsTUFBRCxFQUFTLE9BQVQ7QUFBUDtBQUFwQjtBQUpVLFdBQUQsQ0FBdEI7QUFNQW5DLFVBQUFBLE1BQU0sQ0FBQ2EsTUFBTSxDQUFDLG1CQUFELENBQVAsQ0FBTixDQUFvQ0ssRUFBcEMsQ0FBdUNDLElBQXZDLENBQTRDaUIsSUFBNUMsQ0FBaURoQixRQUFqRCxDQUEwRCxNQUExRCxFQUFrRSxDQUNoRSxNQURnRSxFQUVoRSxPQUZnRSxDQUFsRTtBQUlELFNBcEJDLENBQUY7QUFxQkQsT0F4Qk8sQ0FBUjtBQXlCRCxLQXRWTyxDQUFSO0FBdVZELEdBMVdPLENBQVI7QUEyV0QsQ0E1V08sQ0FBUiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHtyZXNldFNjaGVtYSwgZmluYWxpemVTY2hlbWEsIHJlZ2lzdGVyU2NoZW1hfSBmcm9tICcuLi8uLi9saWIvc2NoZW1hJztcbmltcG9ydCB7dG9QYXJzZXJBcmdzfSBmcm9tICcuLi8uLi9saWIvc2NoZW1hL2NsaS1hcmdzJztcbmltcG9ydCB7dHJhbnNmb3JtZXJzfSBmcm9tICcuLi8uLi9saWIvc2NoZW1hL2NsaS10cmFuc2Zvcm1lcnMnO1xuXG5jb25zdCB7ZXhwZWN0fSA9IGNoYWk7XG5cbmRlc2NyaWJlKCdjbGktYXJncycsIGZ1bmN0aW9uICgpIHtcbiAgZGVzY3JpYmUoJ3RvUGFyc2VyQXJncygpJywgZnVuY3Rpb24gKCkge1xuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBvcHRzXG4gICAgICogQHJldHVybnNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRBcmdzIChvcHRzID0ge30pIHtcbiAgICAgIGxldCB7ZXh0TmFtZSwgZXh0VHlwZSwgc2NoZW1hfSA9IG9wdHM7XG4gICAgICBpZiAoc2NoZW1hICYmIGV4dE5hbWUgJiYgZXh0VHlwZSkge1xuICAgICAgICByZWdpc3RlclNjaGVtYShleHRUeXBlLCBleHROYW1lLCBzY2hlbWEpO1xuICAgICAgfVxuICAgICAgZmluYWxpemVTY2hlbWEoKTtcbiAgICAgIHJldHVybiBfLmZyb21QYWlycyhbLi4udG9QYXJzZXJBcmdzKG9wdHMpXSk7XG4gICAgfVxuXG4gICAgYmVmb3JlRWFjaChyZXNldFNjaGVtYSk7XG5cbiAgICBhZnRlckVhY2gocmVzZXRTY2hlbWEpO1xuXG4gICAgZGVzY3JpYmUoJ3NjaGVtYSBjb250ZW50cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dE5hbWUgPSAnYmxvYic7XG4gICAgICBjb25zdCBleHRUeXBlID0gJ3BsdWdpbic7XG5cbiAgICAgIGRlc2NyaWJlKCd0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuXG4gICAgICAgIGRlc2NyaWJlKCdib29sZWFuJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge3Byb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnYm9vbGVhbid9fSwgdHlwZTogJ29iamVjdCd9O1xuICAgICAgICAgICAgcmVzdWx0ID0gZ2V0QXJncyh7c2NoZW1hLCBleHROYW1lLCBleHRUeXBlfSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpdCgnc2hvdWxkIHJldHVybiBvcHRpb25zIGNvbnRhaW5pbmcgYGFjdGlvbmAgcHJvcCBvZiBgc3RvcmVfdHJ1ZWAgYW5kIG5vIGB0eXBlYCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10pLnRvLmhhdmUucHJvcGVydHkoXG4gICAgICAgICAgICAgICdhY3Rpb24nLFxuICAgICAgICAgICAgICAnc3RvcmVfdHJ1ZScsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaXQoJ3Nob3VsZCBub3QgY29udGFpbiBhIGBtZXRhdmFyYCBwcm9wZXJ0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10pLm5vdC50by5oYXZlLnByb3BlcnR5KCdtZXRhdmFyJyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCdvYmplY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7cHJvcGVydGllczoge2Zvbzoge3R5cGU6ICdvYmplY3QnfX0sIHR5cGU6ICdvYmplY3QnfTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGdldEFyZ3Moe3NjaGVtYSwgZXh0TmFtZSwgZXh0VHlwZX0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaXQoJ3Nob3VsZCB1c2UgdGhlIGBqc29uYCB0cmFuc2Zvcm1lcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10pLnRvLmhhdmUucHJvcGVydHkoXG4gICAgICAgICAgICAgICd0eXBlJyxcbiAgICAgICAgICAgICAgdHJhbnNmb3JtZXJzLmpzb24sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaXQoJ3Nob3VsZCBjb250YWluIGEgU0NSRUFNSU5HX1NOQUtFX0NBU0UgYG1ldGF2YXJgIHByb3AnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBleHBlY3QocmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddKS50by5oYXZlLnByb3BlcnR5KFxuICAgICAgICAgICAgICAnbWV0YXZhcicsXG4gICAgICAgICAgICAgICdGT08nLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZGVzY3JpYmUoJ2FycmF5JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge3Byb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnYXJyYXknfX0sIHR5cGU6ICdvYmplY3QnfTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGdldEFyZ3Moe3NjaGVtYSwgZXh0TmFtZSwgZXh0VHlwZX0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaXQoJ3Nob3VsZCB1c2UgdGhlIGBjc3ZgIHRyYW5zZm9ybWVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXSkudG8uaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ3R5cGUnLFxuICAgICAgICAgICAgICB0cmFuc2Zvcm1lcnMuY3N2LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGl0KCdzaG91bGQgY29udGFpbiBhIFNDUkVBTUlOR19TTkFLRV9DQVNFIGBtZXRhdmFyYCBwcm9wJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXSkudG8uaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ21ldGF2YXInLFxuICAgICAgICAgICAgICAnRk9PJyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCdudW1iZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7cHJvcGVydGllczoge2Zvbzoge3R5cGU6ICdudW1iZXInfX0sIHR5cGU6ICdvYmplY3QnfTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGdldEFyZ3Moe3NjaGVtYSwgZXh0TmFtZSwgZXh0VHlwZX0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaXQoJ3Nob3VsZCBwYXJzZSB0aGUgdmFsdWUgYXMgYSBmbG9hdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10udHlwZSgnMTAuNScpKS50by5lcXVhbCgxMC41KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGl0KCdzaG91bGQgY29udGFpbiBhIFNDUkVBTUlOR19TTkFLRV9DQVNFIGBtZXRhdmFyYCBwcm9wJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXSkudG8uaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ21ldGF2YXInLFxuICAgICAgICAgICAgICAnRk9PJyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCdpbnRlZ2VyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge3Byb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnaW50ZWdlcid9fSwgdHlwZTogJ29iamVjdCd9O1xuICAgICAgICAgICAgcmVzdWx0ID0gZ2V0QXJncyh7c2NoZW1hLCBleHROYW1lLCBleHRUeXBlfSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpdCgnc2hvdWxkIHBhcnNlIHRoZSB2YWx1ZSBhcyBhbiBpbnRlZ2VyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXS50eXBlKCcxMC41JykpLnRvLmVxdWFsKDEwKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGl0KCdzaG91bGQgY29udGFpbiBhIFNDUkVBTUlOR19TTkFLRV9DQVNFIGBtZXRhdmFyYCBwcm9wJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXSkudG8uaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ21ldGF2YXInLFxuICAgICAgICAgICAgICAnRk9PJyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCdzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnc3RyaW5nJ319LFxuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGl0KCdzaG91bGQgcGFyc2UgdGhlIHZhbHVlIGFzIGFuIGludGVnZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBleHBlY3QocmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJzEwLjUnKSkudG8uZXF1YWwoJzEwLjUnKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGl0KCdzaG91bGQgY29udGFpbiBhIFNDUkVBTUlOR19TTkFLRV9DQVNFIGBtZXRhdmFyYCBwcm9wJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXhwZWN0KHJlc3VsdFsnLS1wbHVnaW4tYmxvYi1mb28nXSkudG8uaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ21ldGF2YXInLFxuICAgICAgICAgICAgICAnRk9PJyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCdudWxsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGl0KCdzaG91bGQgdGhyb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7cHJvcGVydGllczoge2Zvbzoge3R5cGU6ICdudWxsJ319LCB0eXBlOiAnb2JqZWN0J307XG4gICAgICAgICAgICBleHBlY3QoKCkgPT4gZ2V0QXJncyh7ZXh0VHlwZSwgZXh0TmFtZSwgc2NoZW1hfSkpLnRvLnRocm93KFxuICAgICAgICAgICAgICBUeXBlRXJyb3IsXG4gICAgICAgICAgICAgIC91bmtub3duIG9yIGRpc2FsbG93ZWQvLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZGVzY3JpYmUoJyh1bmtub3duKScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpdCgnc2hvdWxkIHRocm93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge1xuICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7Zm9vOiB7dHlwZTogJ2RvbmtleSd9fSxcbiAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZXhwZWN0KCgpID0+IGdldEFyZ3Moe2V4dFR5cGUsIGV4dE5hbWUsIHNjaGVtYX0pKS50by50aHJvdyhcbiAgICAgICAgICAgICAgRXJyb3IsXG4gICAgICAgICAgICAgIC9zY2hlbWEgaXMgaW52YWxpZC8sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnYXBwaXVtQ2xpQWxpYXNlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcblxuICAgICAgICBpdCgnc2hvdWxkIG5vdCBhbGxvdyBzaG9ydCBhbGlhc2VzIGZvciBleHRlbnNpb25zJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgZm9vOiB7dHlwZTogJ3N0cmluZycsIGFwcGl1bUNsaUFsaWFzZXM6IFsnZm9vb29vJywgJ0YnXX0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICBleHBlY3QocmVzdWx0KS50by5oYXZlLnByb3BlcnR5KFxuICAgICAgICAgICAgJy0tcGx1Z2luLWJsb2ItZm9vLC0tcGx1Z2luLWJsb2ItZm9vb29vLC0tcGx1Z2luLWJsb2ItRicsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ2FwcGl1bUNsaURlc2NyaXB0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuXG4gICAgICAgIGl0KCdzaG91bGQgYmUgcHJlZmVycmVkIG92ZXIgYGRlc2NyaXB0aW9uYCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIGZvbzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIGFwcGl1bUNsaURlc2NyaXB0aW9uOiAnZm9vJyxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogJ2JhcicsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICBleHBlY3QocmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddKS50by5oYXZlLnByb3BlcnR5KCdoZWxwJywgJ2ZvbycpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnYXBwaXVtQ2xpVHJhbnNmb3JtZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCB1c2UgdGhlIHRyYW5zZm9ybWVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnc3RyaW5nJywgYXBwaXVtQ2xpVHJhbnNmb3JtZXI6ICdqc29uJ319LFxuICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICBleHBlY3QocmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJ3tcImhlcnBcIjogXCJkZXJwXCJ9JykpLnRvLmVxbCh7XG4gICAgICAgICAgICBoZXJwOiAnZGVycCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgZXJyb3IgaWYgdGhlIHZhbHVlIGlzIG5vdCB2YWxpZCBmb3IgdGhlIHRyYW5zZm9ybWVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtmb286IHt0eXBlOiAnc3RyaW5nJywgYXBwaXVtQ2xpVHJhbnNmb3JtZXI6ICdqc29uJ319LFxuICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICBleHBlY3QoKCkgPT4gcmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJzEyMycpKS50by50aHJvdyhcbiAgICAgICAgICAgIC9tdXN0IGJlIGEgdmFsaWQganNvbi9pLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHRoaXMgaXMgdW5saWtlbHkgdG8gaGFwcGVuLCBidXQgSSB3YW50IHRvIGVzdGFibGlzaCB0aGUgYmVoYXZpb3IgYXMgZGVmaW5lZC5cbiAgICAgICAgZGVzY3JpYmUoJ3doZW4gdXNlZCB3aXRoIGBlbnVtYCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBkZXNjcmliZSgnYW5kIGVudW0gbWVtYmVycyBhcmUgaW52YWxpZCBhcyBwZXIgdGhlIHRyYW5zZm9ybWVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZGVzY3JpYmUoJ3doZW4gcHJvdmlkZWQgYW4gZW51bSBtZW1iZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIGl0KCdzaG91bGQgdGhyb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge1xuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICBhcHBpdW1DbGlUcmFuc2Zvcm1lcjogJ2pzb24nLFxuICAgICAgICAgICAgICAgICAgICAgIGVudW06IFsnaGVycCcsICdkZXJwJ10sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICAgICAgICBleHBlY3QoKCkgPT4gcmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJ2hlcnAnKSkudG8udGhyb3coXG4gICAgICAgICAgICAgICAgICAvbXVzdCBiZSBhIHZhbGlkIGpzb24vaSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgZGVzY3JpYmUoJ2FuZCBlbnVtIG1lbWJlcnMgYXJlIHZhbGlkIGFzIHBlciB0aGUgdHJhbnNmb3JtZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBkZXNjcmliZSgnd2hlbiBwcm92aWRlZCBhbiBlbnVtIG1lbWJlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gYSB0cmFuc2Zvcm1lZCB2YWx1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGZvbzoge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgIGFwcGl1bUNsaVRyYW5zZm9ybWVyOiAnanNvbicsXG4gICAgICAgICAgICAgICAgICAgICAgZW51bTogWyd7XCJoZXJwXCI6IFwiZGVycFwifScsICd7XCJkZXJwXCI6IFwiaGVycFwifSddLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gZ2V0QXJncyh7c2NoZW1hLCBleHROYW1lLCBleHRUeXBlfSk7XG4gICAgICAgICAgICAgICAgZXhwZWN0KFxuICAgICAgICAgICAgICAgICAgcmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJ3tcImhlcnBcIjogXCJkZXJwXCJ9JyksXG4gICAgICAgICAgICAgICAgKS50by5lcWwoe2hlcnA6ICdkZXJwJ30pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBkZXNjcmliZSgnd2hlbiBub3QgcHJvdmlkZWQgYW4gZW51bSBtZW1iZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIGl0KCdzaG91bGQgdGhyb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0ge1xuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICBhcHBpdW1DbGlUcmFuc2Zvcm1lcjogJ2pzb24nLFxuICAgICAgICAgICAgICAgICAgICAgIGVudW06IFsne1wiaGVycFwiOiBcImRlcnBcIn0nLCAne1wiZGVycFwiOiBcImhlcnBcIn0nXSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGdldEFyZ3Moe3NjaGVtYSwgZXh0TmFtZSwgZXh0VHlwZX0pO1xuICAgICAgICAgICAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICAgICAgICAgICAgcmVzdWx0WyctLXBsdWdpbi1ibG9iLWZvbyddLnR5cGUoJ3tcImdlb3JneVwiOiBcInBvcmd5XCJ9JyksXG4gICAgICAgICAgICAgICAgKS50by50aHJvdygvb25lIG9mIHRoZSBhbGxvd2VkIHZhbHVlcy9pKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ2VudW0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGRlc2NyaWJlKCd3aGVuIHVzZWQgd2l0aCBhIG5vbi1gc3RyaW5nYCB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGl0KCdzaG91bGQgdGhyb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgICAgZW51bTogWydoZXJwJywgJ2RlcnAnXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBleHBlY3QoKCkgPT4gZ2V0QXJncyh7c2NoZW1hLCBleHROYW1lLCBleHRUeXBlfSkpLnRvLnRocm93KFxuICAgICAgICAgICAgICBUeXBlRXJyb3IsXG4gICAgICAgICAgICAgIC9gZW51bWAgaXMgb25seSBzdXBwb3J0ZWQgZm9yIGB0eXBlOiAnc3RyaW5nJ2AvaSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpdChcbiAgICAgICAgICAgICdzaG91bGQgYWN0dWFsbHkgdGhyb3cgZWFybGllciBieSBmYWlsaW5nIHNjaGVtYSB2YWxpZGF0aW9uLCBidXQgdGhhdCB3b3VsZCBtZWFuIG92ZXJyaWRpbmcgdGhlIGJlaGF2aW9yIG9mIGBlbnVtYCB3aGljaCBzb3VuZHMgaW5hZHZpc2FibGUnLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlKCd3aGVuIHVzZWQgd2l0aCBhIGBzdHJpbmdgIHR5cGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaXQoJ3Nob3VsZCBzZXQgYGNob2ljZXNgIHByb3AnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgICAgZW51bTogWydoZXJwJywgJ2RlcnAnXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBnZXRBcmdzKHtzY2hlbWEsIGV4dE5hbWUsIGV4dFR5cGV9KTtcbiAgICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10pLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eShcbiAgICAgICAgICAgICAgJ2Nob2ljZXMnLFxuICAgICAgICAgICAgICBbJ2hlcnAnLCAnZGVycCddLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ292ZXJyaWRlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gdGhpcyBtaWdodCBiZSBiZXR0ZXIgc29tZSBvdGhlciB3YXksIElESy4gIEkgc3VzcGVjdCB0aGlzIHdpbGwgYmUgcmFyZWx5IHVzZWQuXG4gICAgICAgIC8vIHNpbmNlIGV4dGVuc2lvbnMgY2FuJ3QgYWN0dWFsbHkgY2FsbCBgdG9QYXJzZXJBcmdzKClgLCB0aGV5IGNhbid0IHNldCBgb3ZlcnJpZGVzYCBhbnl3YXkuXG4gICAgICAgIGl0KCdzaG91bGQgc2V0IHRoZW0gdmlhIFwiZGVzdFwiIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBzY2hlbWEgPSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIGZvbzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBnZXRBcmdzKHtcbiAgICAgICAgICAgIHNjaGVtYSxcbiAgICAgICAgICAgIGV4dE5hbWUsXG4gICAgICAgICAgICBleHRUeXBlLFxuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7J3BsdWdpbi5ibG9iLmZvbyc6IHtlbnVtOiBbJ3NsdWcnLCAnc25haWwnXX19LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGV4cGVjdChyZXN1bHRbJy0tcGx1Z2luLWJsb2ItZm9vJ10pLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnZW51bScsIFtcbiAgICAgICAgICAgICdzbHVnJyxcbiAgICAgICAgICAgICdzbmFpbCcsXG4gICAgICAgICAgXSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXSwiZmlsZSI6InRlc3Qvc2NoZW1hL2NsaS1hcmdzLXNwZWNzLmpzIiwic291cmNlUm9vdCI6Ii4uLy4uLy4uIn0=