@ditojs/server 0.275.0 → 1.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 (216) hide show
  1. package/package.json +25 -43
  2. package/src/app/Application.js +105 -111
  3. package/src/app/Validator.js +6 -3
  4. package/src/app/index.js +2 -2
  5. package/src/cli/db/createMigration.js +1 -1
  6. package/src/cli/db/index.js +7 -7
  7. package/src/cli/db/listAssetConfig.js +1 -1
  8. package/src/cli/db/reset.js +1 -1
  9. package/src/cli/index.js +14 -5
  10. package/src/controllers/AdminController.js +181 -158
  11. package/src/controllers/CollectionController.js +8 -29
  12. package/src/controllers/Controller.js +71 -76
  13. package/src/controllers/ControllerAction.js +39 -17
  14. package/src/controllers/MemberAction.js +2 -2
  15. package/src/controllers/ModelController.js +4 -4
  16. package/src/controllers/RelationController.js +3 -3
  17. package/src/controllers/{UserController.js → UsersController.js} +8 -13
  18. package/src/controllers/index.js +5 -5
  19. package/src/decorators/action.js +3 -3
  20. package/src/decorators/authorize.js +1 -1
  21. package/src/decorators/index.js +6 -6
  22. package/src/decorators/parameters.js +1 -1
  23. package/src/decorators/returns.js +1 -1
  24. package/src/decorators/scope.js +1 -1
  25. package/src/decorators/transacted.js +1 -1
  26. package/src/errors/AssetError.js +1 -1
  27. package/src/errors/AuthenticationError.js +1 -1
  28. package/src/errors/AuthorizationError.js +1 -1
  29. package/src/errors/ControllerError.js +1 -1
  30. package/src/errors/DatabaseError.js +12 -3
  31. package/src/errors/GraphError.js +1 -1
  32. package/src/errors/ModelError.js +1 -1
  33. package/src/errors/NotFoundError.js +1 -1
  34. package/src/errors/NotImplementedError.js +1 -1
  35. package/src/errors/QueryBuilderError.js +1 -1
  36. package/src/errors/RelationError.js +1 -1
  37. package/src/errors/ValidationError.js +1 -1
  38. package/src/errors/WrappedError.js +1 -1
  39. package/src/errors/index.js +14 -14
  40. package/src/graph/DitoGraphProcessor.js +2 -1
  41. package/src/graph/graph.js +1 -1
  42. package/src/graph/index.js +3 -3
  43. package/src/index.js +11 -9
  44. package/src/lib/index.js +2 -2
  45. package/src/middleware/createTransaction.js +1 -1
  46. package/src/middleware/findRoute.js +3 -2
  47. package/src/middleware/handleConnectMiddleware.js +88 -0
  48. package/src/middleware/handleError.js +1 -1
  49. package/src/middleware/handleRoute.js +3 -3
  50. package/src/middleware/index.js +8 -7
  51. package/src/mixins/AssetMixin.js +1 -1
  52. package/src/mixins/UserMixin.js +1 -1
  53. package/src/mixins/index.js +4 -4
  54. package/src/models/AssetModel.js +2 -2
  55. package/src/models/Model.js +16 -12
  56. package/src/models/RelationAccessor.js +1 -1
  57. package/src/models/SessionModel.js +2 -2
  58. package/src/models/TimeStampedModel.js +2 -2
  59. package/src/models/UserModel.js +2 -2
  60. package/src/models/definitions/assets.js +1 -1
  61. package/src/models/definitions/filters.js +57 -44
  62. package/src/models/definitions/hooks.js +1 -1
  63. package/src/models/definitions/index.js +9 -9
  64. package/src/models/definitions/modifiers.js +1 -1
  65. package/src/models/definitions/options.js +1 -1
  66. package/src/models/definitions/properties.js +2 -2
  67. package/src/models/definitions/relations.js +1 -1
  68. package/src/models/definitions/schema.js +1 -1
  69. package/src/models/definitions/scopes.js +2 -2
  70. package/src/models/index.js +5 -5
  71. package/src/query/QueryBuilder.js +5 -5
  72. package/src/query/QueryFilters.js +50 -50
  73. package/src/query/QueryParameters.js +2 -2
  74. package/src/query/index.js +3 -3
  75. package/src/schema/formats/index.js +2 -2
  76. package/src/schema/index.js +4 -4
  77. package/src/schema/keywords/_relate.js +1 -1
  78. package/src/schema/keywords/index.js +12 -12
  79. package/src/schema/properties.test.js +1 -1
  80. package/src/schema/relations.js +1 -1
  81. package/src/schema/relations.test.js +2 -2
  82. package/src/services/index.js +1 -1
  83. package/src/storage/DiskStorage.js +1 -1
  84. package/src/storage/S3Storage.js +4 -4
  85. package/src/storage/Storage.js +1 -1
  86. package/src/storage/index.js +4 -4
  87. package/src/utils/function.test.js +1 -1
  88. package/src/utils/handler.js +17 -0
  89. package/src/utils/index.js +8 -7
  90. package/src/utils/object.test.js +1 -1
  91. package/lib/app/Application.js +0 -961
  92. package/lib/app/SessionStore.js +0 -40
  93. package/lib/app/Validator.js +0 -355
  94. package/lib/app/index.js +0 -26
  95. package/lib/cli/console.js +0 -175
  96. package/lib/cli/db/createMigration.js +0 -237
  97. package/lib/cli/db/index.js +0 -66
  98. package/lib/cli/db/listAssetConfig.js +0 -16
  99. package/lib/cli/db/migrate.js +0 -15
  100. package/lib/cli/db/reset.js +0 -27
  101. package/lib/cli/db/rollback.js +0 -15
  102. package/lib/cli/db/seed.js +0 -104
  103. package/lib/cli/db/unlock.js +0 -15
  104. package/lib/cli/index.js +0 -90
  105. package/lib/controllers/AdminController.js +0 -258
  106. package/lib/controllers/CollectionController.js +0 -263
  107. package/lib/controllers/Controller.js +0 -462
  108. package/lib/controllers/ControllerAction.js +0 -276
  109. package/lib/controllers/MemberAction.js +0 -22
  110. package/lib/controllers/ModelController.js +0 -64
  111. package/lib/controllers/RelationController.js +0 -82
  112. package/lib/controllers/UserController.js +0 -98
  113. package/lib/controllers/index.js +0 -50
  114. package/lib/decorators/action.js +0 -14
  115. package/lib/decorators/authorize.js +0 -13
  116. package/lib/decorators/index.js +0 -58
  117. package/lib/decorators/parameters.js +0 -35
  118. package/lib/decorators/returns.js +0 -26
  119. package/lib/decorators/scope.js +0 -14
  120. package/lib/decorators/transacted.js +0 -12
  121. package/lib/errors/AssetError.js +0 -19
  122. package/lib/errors/AuthenticationError.js +0 -19
  123. package/lib/errors/AuthorizationError.js +0 -19
  124. package/lib/errors/ControllerError.js +0 -24
  125. package/lib/errors/DatabaseError.js +0 -27
  126. package/lib/errors/GraphError.js +0 -19
  127. package/lib/errors/ModelError.js +0 -24
  128. package/lib/errors/NotFoundError.js +0 -19
  129. package/lib/errors/NotImplementedError.js +0 -19
  130. package/lib/errors/QueryBuilderError.js +0 -19
  131. package/lib/errors/RelationError.js +0 -36
  132. package/lib/errors/ResponseError.js +0 -46
  133. package/lib/errors/ValidationError.js +0 -19
  134. package/lib/errors/WrappedError.js +0 -24
  135. package/lib/errors/index.js +0 -122
  136. package/lib/graph/DitoGraphProcessor.js +0 -185
  137. package/lib/graph/expression.js +0 -76
  138. package/lib/graph/graph.js +0 -300
  139. package/lib/graph/index.js +0 -34
  140. package/lib/index.js +0 -82
  141. package/lib/lib/EventEmitter.js +0 -76
  142. package/lib/lib/KnexHelper.js +0 -40
  143. package/lib/lib/index.js +0 -26
  144. package/lib/middleware/attachLogger.js +0 -16
  145. package/lib/middleware/createTransaction.js +0 -36
  146. package/lib/middleware/findRoute.js +0 -35
  147. package/lib/middleware/handleError.js +0 -26
  148. package/lib/middleware/handleRoute.js +0 -29
  149. package/lib/middleware/handleUser.js +0 -36
  150. package/lib/middleware/index.js +0 -66
  151. package/lib/middleware/logRequests.js +0 -122
  152. package/lib/mixins/AssetMixin.js +0 -81
  153. package/lib/mixins/SessionMixin.js +0 -22
  154. package/lib/mixins/TimeStampedMixin.js +0 -47
  155. package/lib/mixins/UserMixin.js +0 -151
  156. package/lib/mixins/index.js +0 -42
  157. package/lib/models/AssetModel.js +0 -12
  158. package/lib/models/Model.js +0 -953
  159. package/lib/models/RelationAccessor.js +0 -41
  160. package/lib/models/SessionModel.js +0 -12
  161. package/lib/models/TimeStampedModel.js +0 -12
  162. package/lib/models/UserModel.js +0 -12
  163. package/lib/models/definitions/assets.js +0 -11
  164. package/lib/models/definitions/filters.js +0 -101
  165. package/lib/models/definitions/hooks.js +0 -11
  166. package/lib/models/definitions/index.js +0 -38
  167. package/lib/models/definitions/modifiers.js +0 -11
  168. package/lib/models/definitions/options.js +0 -11
  169. package/lib/models/definitions/properties.js +0 -87
  170. package/lib/models/definitions/relations.js +0 -11
  171. package/lib/models/definitions/schema.js +0 -11
  172. package/lib/models/definitions/scopes.js +0 -51
  173. package/lib/models/index.js +0 -50
  174. package/lib/query/QueryBuilder.js +0 -745
  175. package/lib/query/QueryFilters.js +0 -82
  176. package/lib/query/QueryParameters.js +0 -77
  177. package/lib/query/Registry.js +0 -40
  178. package/lib/query/index.js +0 -34
  179. package/lib/schema/formats/_empty.js +0 -10
  180. package/lib/schema/formats/_required.js +0 -10
  181. package/lib/schema/formats/index.js +0 -26
  182. package/lib/schema/index.js +0 -49
  183. package/lib/schema/keywords/_computed.js +0 -11
  184. package/lib/schema/keywords/_foreign.js +0 -11
  185. package/lib/schema/keywords/_hidden.js +0 -11
  186. package/lib/schema/keywords/_index.js +0 -11
  187. package/lib/schema/keywords/_instanceof.js +0 -49
  188. package/lib/schema/keywords/_primary.js +0 -11
  189. package/lib/schema/keywords/_range.js +0 -26
  190. package/lib/schema/keywords/_relate.js +0 -19
  191. package/lib/schema/keywords/_specificType.js +0 -11
  192. package/lib/schema/keywords/_unique.js +0 -11
  193. package/lib/schema/keywords/_unsigned.js +0 -11
  194. package/lib/schema/keywords/_validate.js +0 -80
  195. package/lib/schema/keywords/index.js +0 -106
  196. package/lib/schema/properties.js +0 -227
  197. package/lib/schema/properties.test.js +0 -573
  198. package/lib/schema/relations.js +0 -274
  199. package/lib/schema/relations.test.js +0 -155
  200. package/lib/services/Service.js +0 -34
  201. package/lib/services/index.js +0 -18
  202. package/lib/storage/AssetFile.js +0 -97
  203. package/lib/storage/DiskStorage.js +0 -125
  204. package/lib/storage/S3Storage.js +0 -171
  205. package/lib/storage/Storage.js +0 -209
  206. package/lib/storage/index.js +0 -34
  207. package/lib/utils/decorator.js +0 -16
  208. package/lib/utils/deprecate.js +0 -46
  209. package/lib/utils/emitter.js +0 -13
  210. package/lib/utils/function.js +0 -14
  211. package/lib/utils/function.test.js +0 -49
  212. package/lib/utils/index.js +0 -66
  213. package/lib/utils/json.js +0 -9
  214. package/lib/utils/object.js +0 -92
  215. package/lib/utils/object.test.js +0 -65
  216. package/lib/utils/scope.js +0 -14
@@ -1,961 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.Application = void 0;
5
-
6
- require("core-js/modules/esnext.async-iterator.filter.js");
7
-
8
- require("core-js/modules/esnext.iterator.constructor.js");
9
-
10
- require("core-js/modules/esnext.iterator.filter.js");
11
-
12
- require("core-js/modules/es.error.cause.js");
13
-
14
- require("core-js/modules/esnext.async-iterator.reduce.js");
15
-
16
- require("core-js/modules/esnext.iterator.reduce.js");
17
-
18
- require("core-js/modules/esnext.async-iterator.find.js");
19
-
20
- require("core-js/modules/esnext.iterator.find.js");
21
-
22
- require("core-js/modules/esnext.async-iterator.map.js");
23
-
24
- require("core-js/modules/esnext.iterator.map.js");
25
-
26
- var _koa = _interopRequireDefault(require("koa"));
27
-
28
- var _knex2 = _interopRequireDefault(require("knex"));
29
-
30
- var _util = _interopRequireDefault(require("util"));
31
-
32
- var _axios = _interopRequireDefault(require("axios"));
33
-
34
- var _picocolors = _interopRequireDefault(require("picocolors"));
35
-
36
- var _zlib = _interopRequireDefault(require("zlib"));
37
-
38
- var _pino = _interopRequireDefault(require("pino"));
39
-
40
- var _os = _interopRequireDefault(require("os"));
41
-
42
- var _parseDuration = _interopRequireDefault(require("parse-duration"));
43
-
44
- var _koaBodyparser = _interopRequireDefault(require("koa-bodyparser"));
45
-
46
- var _cors = _interopRequireDefault(require("@koa/cors"));
47
-
48
- var _koaCompose = _interopRequireDefault(require("koa-compose"));
49
-
50
- var _koaCompress = _interopRequireDefault(require("koa-compress"));
51
-
52
- var _koaConditionalGet = _interopRequireDefault(require("koa-conditional-get"));
53
-
54
- var _koaPassport = _interopRequireDefault(require("koa-passport"));
55
-
56
- var _koaSession = _interopRequireDefault(require("koa-session"));
57
-
58
- var _koaEtag = _interopRequireDefault(require("koa-etag"));
59
-
60
- var _koaHelmet = _interopRequireDefault(require("koa-helmet"));
61
-
62
- var _koaResponseTime = _interopRequireDefault(require("koa-response-time"));
63
-
64
- var _router = _interopRequireDefault(require("@ditojs/router"));
65
-
66
- var _lib = require("../lib");
67
-
68
- var _controllers = require("../controllers");
69
-
70
- var _services = require("../services");
71
-
72
- var _storage = require("../storage");
73
-
74
- var _schema = require("../schema");
75
-
76
- var _utils = require("../utils");
77
-
78
- var _errors = require("../errors");
79
-
80
- var _SessionStore = _interopRequireDefault(require("./SessionStore"));
81
-
82
- var _Validator = require("./Validator");
83
-
84
- var _middleware = require("../middleware");
85
-
86
- var _utils2 = require("@ditojs/utils");
87
-
88
- var _objection = require("objection");
89
-
90
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
91
-
92
- class Application extends _koa.default {
93
- constructor({
94
- config = {},
95
- validator,
96
- router,
97
- events,
98
- middleware,
99
- models,
100
- services,
101
- controllers
102
- } = {}) {
103
- super();
104
-
105
- this._setupEmitter(events);
106
-
107
- const {
108
- app: {
109
- keys,
110
- ...app
111
- } = {},
112
- log = {},
113
- ...rest
114
- } = config;
115
- this.config = {
116
- app,
117
- log: log.silent || process.env.DITO_SILENT ? {} : log,
118
- ...rest
119
- };
120
- this.keys = keys;
121
- this.proxy = !!app.proxy;
122
- this.validator = validator || new _Validator.Validator();
123
- this.router = router || new _router.default();
124
- this.validator.app = this;
125
- this.storages = Object.create(null);
126
- this.models = Object.create(null);
127
- this.services = Object.create(null);
128
- this.controllers = Object.create(null);
129
- this.hasControllerMiddleware = false;
130
- this.setupLogger();
131
- this.setupKnex();
132
- this.setupGlobalMiddleware();
133
-
134
- if (middleware) {
135
- this.use(middleware);
136
- }
137
-
138
- if (config.storages) {
139
- this.addStorages(config.storages);
140
- }
141
-
142
- if (models) {
143
- this.addModels(models);
144
- }
145
-
146
- if (services) {
147
- this.addServices(services);
148
- }
149
-
150
- if (controllers) {
151
- this.addControllers(controllers);
152
- }
153
- }
154
-
155
- addRoute(verb, path, transacted, handlers, controller = null, action = null) {
156
- handlers = (0, _utils2.asArray)(handlers);
157
- const handler = handlers.length > 1 ? (0, _koaCompose.default)(handlers) : handlers[0];
158
- const route = {
159
- verb,
160
- path,
161
- transacted,
162
- handler,
163
- controller,
164
- action
165
- };
166
- this.router[verb](path, route);
167
- }
168
-
169
- addModels(models) {
170
- for (const modelClass of Object.values(models)) {
171
- this.addModel(modelClass);
172
- }
173
-
174
- this.models = this.sortModels(this.models);
175
- const sortedModels = Object.values(this.models).filter(modelClass => models[modelClass.name] === modelClass);
176
-
177
- for (const modelClass of sortedModels) {
178
- if (models[modelClass.name] === modelClass) {
179
- modelClass.setup(this.knex);
180
- modelClass.initialize();
181
- this.validator.addSchema(modelClass.getJsonSchema());
182
- }
183
- }
184
-
185
- const {
186
- log
187
- } = this.config;
188
-
189
- if (log.schema || log.relations) {
190
- for (const modelClass of sortedModels) {
191
- const shouldLog = option => option === true || (0, _utils2.asArray)(option).includes(modelClass.name);
192
-
193
- const data = {};
194
-
195
- if (shouldLog(log.schema)) {
196
- data.schema = modelClass.getJsonSchema();
197
- }
198
-
199
- if (shouldLog(log.relations)) {
200
- data.relations = (0, _utils2.clone)(modelClass.relationMappings, value => _objection.Model.isPrototypeOf(value) ? `[Model: ${value.name}]` : value);
201
- }
202
-
203
- if (Object.keys(data).length > 0) {
204
- console.info(_picocolors.default.yellow.bold(`\n${modelClass.name}:\n`), _util.default.inspect(data, {
205
- colors: true,
206
- depth: null,
207
- maxArrayLength: null
208
- }));
209
- }
210
- }
211
- }
212
- }
213
-
214
- addModel(modelClass) {
215
- if (_objection.Model.isPrototypeOf(modelClass)) {
216
- modelClass.app = this;
217
- this.models[modelClass.name] = modelClass;
218
- } else {
219
- throw new Error(`Invalid model class: ${modelClass}`);
220
- }
221
- }
222
-
223
- sortModels(models) {
224
- const sortByRelations = (list, collected = {}, excluded = {}) => {
225
- for (const modelClass of list) {
226
- const {
227
- name
228
- } = modelClass;
229
-
230
- if (!collected[name] && !excluded[name]) {
231
- for (const relation of Object.values(modelClass.getRelations())) {
232
- if (!(relation instanceof _objection.BelongsToOneRelation)) {
233
- const {
234
- relatedModelClass,
235
- joinTableModelClass
236
- } = relation;
237
-
238
- for (const related of [joinTableModelClass, relatedModelClass]) {
239
- if (related && related !== modelClass && models[related.name]) {
240
- sortByRelations([related], collected, {
241
- [name]: modelClass,
242
- ...excluded
243
- });
244
- }
245
- }
246
- }
247
- }
248
-
249
- collected[name] = modelClass;
250
- }
251
- }
252
-
253
- return Object.values(collected);
254
- };
255
-
256
- return sortByRelations(Object.values(models).reverse()).reverse().reduce((models, modelClass) => {
257
- models[modelClass.name] = modelClass;
258
- return models;
259
- }, Object.create(null));
260
- }
261
-
262
- getModel(name) {
263
- return this.models[name] || !name.endsWith('Model') && this.models[`${name}Model`] || null;
264
- }
265
-
266
- findModel(callback) {
267
- return Object.values(this.models).find(callback);
268
- }
269
-
270
- addServices(services) {
271
- for (const [name, service] of Object.entries(services)) {
272
- if (name === 'default' && (0, _utils2.isPlainObject)(service)) {
273
- this.addServices(service);
274
- } else {
275
- this.addService(service, name);
276
- }
277
- }
278
- }
279
-
280
- addService(service, name) {
281
- if (_services.Service.isPrototypeOf(service)) {
282
- service = new service(this, name);
283
- }
284
-
285
- if (!(service instanceof _services.Service)) {
286
- throw new Error(`Invalid service: ${service}`);
287
- }
288
-
289
- ({
290
- name
291
- } = service);
292
- const config = this.config.services[name];
293
-
294
- if (config === undefined) {
295
- throw new Error(`Configuration missing for service '${name}'`);
296
- }
297
-
298
- if (config !== false) {
299
- service.setup(config);
300
- this.services[name] = service;
301
- service.initialize();
302
- }
303
- }
304
-
305
- getService(name) {
306
- return this.services[name] || null;
307
- }
308
-
309
- findService(callback) {
310
- return Object.values(this.services).find(callback);
311
- }
312
-
313
- forEachService(callback) {
314
- return Promise.all(Object.values(this.services).map(callback));
315
- }
316
-
317
- addControllers(controllers, namespace) {
318
- for (const [key, value] of Object.entries(controllers)) {
319
- if ((0, _utils2.isPlainObject)(value)) {
320
- this.addControllers(value, namespace ? `${namespace}/${key}` : key);
321
- } else {
322
- this.addController(value, namespace);
323
- }
324
- }
325
- }
326
-
327
- addController(controller, namespace) {
328
- this.setupControllerMiddleware();
329
-
330
- if (_controllers.Controller.isPrototypeOf(controller)) {
331
- controller = new controller(this, namespace);
332
- }
333
-
334
- if (!(controller instanceof _controllers.Controller)) {
335
- throw new Error(`Invalid controller: ${controller}`);
336
- }
337
-
338
- controller.setup();
339
- this.controllers[controller.url] = controller;
340
- controller.initialize();
341
- const middleware = controller.compose();
342
-
343
- if (middleware) {
344
- this.use(middleware);
345
- }
346
- }
347
-
348
- getController(url) {
349
- return this.controllers[url] || null;
350
- }
351
-
352
- findController(callback) {
353
- return Object.values(this.controllers).find(callback);
354
- }
355
-
356
- getAdminController() {
357
- return this.findController(controller => controller instanceof _controllers.AdminController);
358
- }
359
-
360
- getAdminVueConfig() {
361
- var _this$getAdminControl;
362
-
363
- return ((_this$getAdminControl = this.getAdminController()) == null ? void 0 : _this$getAdminControl.getVueConfig()) || null;
364
- }
365
-
366
- getAssetConfig({
367
- models = Object.keys(this.models),
368
- normalizeDbNames = this.config.knex.normalizeDbNames
369
- } = {}) {
370
- const assetConfig = {};
371
-
372
- for (const modelName of models) {
373
- const modelClass = this.models[modelName];
374
- const {
375
- assets
376
- } = modelClass.definition;
377
-
378
- if (assets) {
379
- const normalizedModelName = normalizeDbNames ? this.normalizeIdentifier(modelName) : modelName;
380
- const convertedAssets = {};
381
-
382
- for (const [assetDataPath, config] of Object.entries(assets)) {
383
- const {
384
- property,
385
- nestedDataPath,
386
- name,
387
- index
388
- } = modelClass.getPropertyOrRelationAtDataPath(assetDataPath);
389
-
390
- if (property && index === 0) {
391
- const normalizedName = normalizeDbNames ? this.normalizeIdentifier(name) : name;
392
- const dataPath = (0, _utils2.normalizeDataPath)([normalizedName, ...(0, _utils2.parseDataPath)(nestedDataPath)]);
393
- const assetConfigs = convertedAssets[normalizedName] || (convertedAssets[normalizedName] = {});
394
- assetConfigs[dataPath] = config;
395
- } else {
396
- throw new Error('Nested graph properties are not supported yet');
397
- }
398
- }
399
-
400
- assetConfig[normalizedModelName] = convertedAssets;
401
- }
402
- }
403
-
404
- return assetConfig;
405
- }
406
-
407
- addStorages(storages) {
408
- for (const [name, config] of Object.entries(storages)) {
409
- this.addStorage(config, name);
410
- }
411
- }
412
-
413
- addStorage(config, name) {
414
- let storage = null;
415
-
416
- if ((0, _utils2.isPlainObject)(config)) {
417
- const storageClass = _storage.Storage.get(config.type);
418
-
419
- if (!storageClass) {
420
- throw new Error(`Unsupported storage: ${config}`);
421
- }
422
-
423
- storage = new storageClass(this, config);
424
- } else if (config instanceof _storage.Storage) {
425
- storage = config;
426
- }
427
-
428
- if (storage) {
429
- if (name) {
430
- storage.name = name;
431
- }
432
-
433
- this.storages[storage.name] = storage;
434
- }
435
-
436
- return storage;
437
- }
438
-
439
- getStorage(name) {
440
- return this.storages[name] || null;
441
- }
442
-
443
- compileValidator(jsonSchema, options) {
444
- return jsonSchema ? this.validator.compile(jsonSchema, options) : null;
445
- }
446
-
447
- compileParametersValidator(parameters, options = {}) {
448
- const list = [];
449
- const {
450
- dataName = 'data'
451
- } = options;
452
- let properties = null;
453
-
454
- const addParameter = (name, schema) => {
455
- list.push({
456
- name: name != null ? name : null,
457
- ...schema
458
- });
459
-
460
- if (!schema.member) {
461
- properties || (properties = {});
462
- properties[name || dataName] = schema;
463
- }
464
- };
465
-
466
- let asObject = false;
467
-
468
- if ((0, _utils2.isArray)(parameters)) {
469
- for (const {
470
- name,
471
- ...schema
472
- } of parameters) {
473
- addParameter(name, schema);
474
- }
475
- } else if ((0, _utils2.isObject)(parameters)) {
476
- asObject = true;
477
-
478
- for (const [name, schema] of Object.entries(parameters)) {
479
- if (schema) {
480
- addParameter(name, schema);
481
- }
482
- }
483
- } else if (parameters) {
484
- throw new Error(`Invalid parameters definition: ${parameters}`);
485
- }
486
-
487
- const schema = (0, _schema.convertSchema)(properties, options);
488
- const validate = this.compileValidator(schema, {
489
- coerceTypes: 'array',
490
- ...options
491
- });
492
- const ctx = {
493
- app: this,
494
- validator: this.validator,
495
- options
496
- };
497
- return {
498
- list,
499
- schema,
500
- asObject,
501
- dataName,
502
- validate: validate ? data => validate.call(ctx, data) : null
503
- };
504
- }
505
-
506
- createValidationError({
507
- type,
508
- message,
509
- errors,
510
- options,
511
- json
512
- }) {
513
- var _this$config$log$erro;
514
-
515
- return new _errors.ValidationError({
516
- type,
517
- message,
518
- errors: this.validator.parseErrors(errors, options),
519
- json: (_this$config$log$erro = this.config.log.errors) != null && _this$config$log$erro.json ? json : undefined
520
- });
521
- }
522
-
523
- createDatabaseError(error) {
524
- var _this$config$log$erro2;
525
-
526
- const [, sql, message] = error.message.match(/^([\s\S]*) - ([\s\S]*?)$/) || [null, null, error.message];
527
- return new _errors.DatabaseError(error, {
528
- message,
529
- sql: (_this$config$log$erro2 = this.config.log.errors) != null && _this$config$log$erro2.sql ? sql : undefined
530
- });
531
- }
532
-
533
- setupGlobalMiddleware() {
534
- const {
535
- app,
536
- log
537
- } = this.config;
538
- this.use((0, _middleware.attachLogger)(this.logger));
539
-
540
- if (app.responseTime !== false) {
541
- this.use((0, _koaResponseTime.default)(getOptions(app.responseTime)));
542
- }
543
-
544
- if (log.requests) {
545
- this.use((0, _middleware.logRequests)());
546
- }
547
-
548
- this.use((0, _middleware.handleError)());
549
-
550
- if (app.helmet !== false) {
551
- this.use((0, _koaHelmet.default)(getOptions(app.helmet)));
552
- }
553
-
554
- if (app.cors !== false) {
555
- this.use((0, _cors.default)(getOptions(app.cors)));
556
- }
557
-
558
- if (app.compress !== false) {
559
- this.use((0, _koaCompress.default)((0, _utils2.merge)({
560
- br: {
561
- params: {
562
- [_zlib.default.constants.BROTLI_PARAM_QUALITY]: 4
563
- }
564
- }
565
- }, getOptions(app.compress))));
566
- }
567
-
568
- if (app.etag !== false) {
569
- this.use((0, _koaConditionalGet.default)());
570
- this.use((0, _koaEtag.default)());
571
- }
572
- }
573
-
574
- setupControllerMiddleware() {
575
- if (!this.hasControllerMiddleware) {
576
- const {
577
- app
578
- } = this.config;
579
- this.use((0, _koaBodyparser.default)(getOptions(app.bodyParser)));
580
- this.use((0, _middleware.findRoute)(this.router));
581
- this.use((0, _middleware.createTransaction)());
582
-
583
- if (app.session) {
584
- const {
585
- modelClass,
586
- ...options
587
- } = getOptions(app.session);
588
-
589
- if (modelClass) {
590
- options.ContextStore = (0, _SessionStore.default)(modelClass);
591
- }
592
-
593
- this.use((0, _koaSession.default)(options, this));
594
- }
595
-
596
- if (app.passport) {
597
- this.use(_koaPassport.default.initialize());
598
-
599
- if (app.session) {
600
- this.use(_koaPassport.default.session());
601
- }
602
-
603
- this.use((0, _middleware.handleUser)());
604
- }
605
-
606
- this.use((0, _middleware.handleRoute)());
607
- this.hasControllerMiddleware = true;
608
- }
609
- }
610
-
611
- setupLogger() {
612
- const {
613
- err,
614
- req,
615
- res
616
- } = _pino.default.stdSerializers;
617
-
618
- const user = user => ({
619
- id: user.id
620
- });
621
-
622
- const serializers = {
623
- err,
624
- req,
625
- res,
626
- user
627
- };
628
- const logger = (0, _pino.default)((0, _utils2.merge)({
629
- level: 'info',
630
- serializers,
631
- prettyPrint: {
632
- ignore: 'req,res,durationMs,user,requestId',
633
- translateTime: 'SYS:HH:MM:ss.l'
634
- },
635
- redact: ['*.headers["cookie"]', '*.headers["set-cookie"]', '*.headers["authorization"]'],
636
- base: null
637
- }, getOptions(this.config.logger)));
638
- this.logger = logger.child({
639
- name: 'app'
640
- });
641
- }
642
-
643
- setupKnex() {
644
- var _knex;
645
-
646
- let {
647
- knex,
648
- log
649
- } = this.config;
650
-
651
- if ((_knex = knex) != null && _knex.client) {
652
- const snakeCaseOptions = knex.normalizeDbNames === true ? {} : knex.normalizeDbNames;
653
-
654
- if (snakeCaseOptions) {
655
- knex = { ...knex,
656
- ...(0, _objection.knexSnakeCaseMappers)(snakeCaseOptions)
657
- };
658
- }
659
-
660
- this.knex = (0, _knex2.default)(knex);
661
-
662
- if (knex.client === 'postgresql' && knex.typeParsers && this.knex.client.driver) {
663
- for (const [type, parser] of Object.entries(knex.typeParsers)) {
664
- this.knex.client.driver.types.setTypeParser(type, parser);
665
- }
666
- }
667
-
668
- if (log.sql) {
669
- this.setupKnexLogging();
670
- }
671
- }
672
- }
673
-
674
- setupKnexLogging() {
675
- const startTimes = {};
676
- const logger = this.logger.child({
677
- name: 'sql'
678
- });
679
-
680
- function end(query, {
681
- response,
682
- error
683
- }) {
684
- const id = query.__knexQueryUid;
685
- const diff = process.hrtime(startTimes[id]);
686
- const duration = diff[0] * 1e3 + diff[1] / 1e6;
687
- delete startTimes[id];
688
- const {
689
- sql,
690
- bindings
691
- } = query;
692
- response = Object.fromEntries(Object.entries(response).filter(([key]) => !key.startsWith('_')));
693
- logger.info({
694
- duration,
695
- bindings,
696
- response,
697
- error
698
- }, sql);
699
- }
700
-
701
- this.knex.on('query', query => {
702
- startTimes[query.__knexQueryUid] = process.hrtime();
703
- }).on('query-response', (response, query) => {
704
- end(query, {
705
- response
706
- });
707
- }).on('query-error', (error, query) => {
708
- end(query, {
709
- error
710
- });
711
- });
712
- }
713
-
714
- normalizeIdentifier(identifier) {
715
- return this.knex.client.wrapIdentifier(identifier).replace(/['`"]/g, '');
716
- }
717
-
718
- denormalizeIdentifier(identifier) {
719
- const obj = this.knex.client.postProcessResponse({
720
- [identifier]: 1
721
- });
722
- return Object.keys(obj)[0];
723
- }
724
-
725
- normalizePath(path) {
726
- return this.config.app.normalizePaths ? (0, _utils2.hyphenate)(path) : path;
727
- }
728
-
729
- formatError(err) {
730
- var _this$config$log$erro3;
731
-
732
- const message = err.toJSON ? (0, _utils.formatJson)(err.toJSON()) : err.message || err;
733
- const str = `${err.name}: ${message}`;
734
- return err.stack && ((_this$config$log$erro3 = this.config.log.errors) == null ? void 0 : _this$config$log$erro3.stack) !== false ? `${str}\n${err.stack.split(/\n|\r\n|\r/).slice(1).join(_os.default.EOL)}` : str;
735
- }
736
-
737
- logError(err, ctx) {
738
- if (!err.expose && !this.silent) {
739
- try {
740
- const text = this.formatError(err);
741
- const level = err instanceof _errors.ResponseError && err.status < 500 ? 'info' : 'error';
742
- const logger = (ctx == null ? void 0 : ctx.logger) || this.logger;
743
- logger[level](text);
744
- } catch (e) {
745
- console.error('Could not log error', e);
746
- }
747
- }
748
- }
749
-
750
- async start() {
751
- if (this.config.log.errors !== false) {
752
- this.on('error', this.logError);
753
- }
754
-
755
- await this.emit('before:start');
756
- await this.forEachService(service => service.start());
757
- const {
758
- server: {
759
- host,
760
- port
761
- },
762
- env
763
- } = this.config;
764
- this.server = await new Promise((resolve, reject) => {
765
- const server = this.listen(port, host, () => {
766
- const {
767
- port
768
- } = server.address();
769
- console.info(`${env} server started at http://${host}:${port}`);
770
- resolve(server);
771
- });
772
-
773
- if (!server) {
774
- reject(new Error(`Unable to start server at http://${host}:${port}`));
775
- }
776
- });
777
- await this.emit('after:start');
778
- }
779
-
780
- async stop() {
781
- await this.emit('before:stop');
782
- this.server = await new Promise((resolve, reject) => {
783
- const {
784
- server
785
- } = this;
786
-
787
- if (server) {
788
- server.close(err => {
789
- if (err) {
790
- reject(err);
791
- } else {
792
- resolve(null);
793
- }
794
- });
795
- setImmediate(() => server.emit('close'));
796
- } else {
797
- reject(new Error('Server is not running'));
798
- }
799
- });
800
- await this.forEachService(service => service.stop());
801
- await this.emit('after:stop');
802
-
803
- if (this.config.log.errors !== false) {
804
- this.off('error', this.logError);
805
- }
806
- }
807
-
808
- async startOrExit() {
809
- try {
810
- await this.start();
811
- } catch (err) {
812
- this.logError(err);
813
- process.exit(-1);
814
- }
815
- }
816
-
817
- async createAssets(storage, files, count = 0, trx = null) {
818
- const AssetModel = this.getModel('Asset');
819
-
820
- if (AssetModel) {
821
- const assets = files.map(file => ({
822
- key: file.key,
823
- file,
824
- storage: storage.name,
825
- count
826
- }));
827
- return AssetModel.query(trx).insert(assets);
828
- }
829
-
830
- return null;
831
- }
832
-
833
- async handleAdddedAndRemovedAssets(storage, addedFiles, removedFiles, trx = null) {
834
- const {
835
- assets: {
836
- cleanupTimeThreshold = 0
837
- } = {}
838
- } = this.config;
839
- const timeThreshold = (0, _utils2.isString)(cleanupTimeThreshold) ? (0, _parseDuration.default)(cleanupTimeThreshold) : cleanupTimeThreshold;
840
- const importedFiles = [];
841
- const AssetModel = this.getModel('Asset');
842
-
843
- if (AssetModel) {
844
- importedFiles.push(...(await this.addForeignAssets(storage, addedFiles, trx)));
845
-
846
- if (addedFiles.length > 0 || removedFiles.length > 0) {
847
- const changeCount = (files, increment) => files.length > 0 && AssetModel.query(trx).whereIn('key', files.map(file => file.key)).increment('count', increment);
848
-
849
- await Promise.all([changeCount(addedFiles, 1), changeCount(removedFiles, -1)]);
850
-
851
- if (timeThreshold > 0) {
852
- setTimeout(() => this.releaseUnusedAssets(timeThreshold), timeThreshold);
853
- }
854
- }
855
-
856
- await this.releaseUnusedAssets(timeThreshold, trx);
857
- return importedFiles;
858
- }
859
- }
860
-
861
- async addForeignAssets(storage, files, trx = null) {
862
- const importedFiles = [];
863
- const AssetModel = this.getModel('Asset');
864
-
865
- if (AssetModel) {
866
- await Promise.all(files.map(async file => {
867
- const asset = await AssetModel.query(trx).findOne('key', file.key);
868
-
869
- if (!asset) {
870
- if (file.data || file.url) {
871
- let {
872
- data
873
- } = file;
874
-
875
- if (!data) {
876
- console.info(`${_picocolors.default.red('INFO:')} Asset ${_picocolors.default.green(`'${file.name}'`)} is from a foreign source, fetching from ${_picocolors.default.green(`'${file.url}'`)} and adding to storage ${_picocolors.default.green(`'${storage.name}'`)}...`);
877
- const response = await _axios.default.request({
878
- method: 'get',
879
- url: file.url,
880
- responseType: 'arraybuffer'
881
- });
882
- data = response.data;
883
- }
884
-
885
- const importedFile = await storage.addFile(file, data);
886
- await this.createAssets(storage, [importedFile], 0, trx);
887
- Object.assign(file, importedFile);
888
- importedFiles.push(importedFile);
889
- } else {
890
- throw new _errors.AssetError(`Unable to import asset from foreign source: '${file.name}' ('${file.key}')`);
891
- }
892
- } else {
893
- Object.assign(file, asset.file);
894
- }
895
- }));
896
- }
897
-
898
- return importedFiles;
899
- }
900
-
901
- async handleModifiedAssets(storage, files, trx = null) {
902
- const modifiedFiles = [];
903
- const AssetModel = this.getModel('Asset');
904
-
905
- if (AssetModel) {
906
- await Promise.all(files.map(async file => {
907
- if (file.data) {
908
- const asset = await AssetModel.query(trx).findOne('key', file.key);
909
-
910
- if (asset) {
911
- const changedFile = await storage.addFile(file, file.data);
912
- Object.assign(file, changedFile);
913
- modifiedFiles.push(changedFile);
914
- } else {
915
- throw new _errors.AssetError(`Unable to update modified asset from memory source: '${file.name}' ('${file.key}')`);
916
- }
917
- }
918
- }));
919
- }
920
-
921
- return modifiedFiles;
922
- }
923
-
924
- async releaseUnusedAssets(timeThreshold = 0, trx = null) {
925
- const AssetModel = this.getModel('Asset');
926
-
927
- if (AssetModel) {
928
- return AssetModel.transaction(trx, async trx => {
929
- const date = new Date();
930
- date.setMilliseconds(date.getMilliseconds() - timeThreshold);
931
- const orphanedAssets = await AssetModel.query(trx).where('count', 0).andWhere('updatedAt', '<=', date).andWhere('updatedAt', '>', (0, _objection.ref)('createdAt'));
932
-
933
- if (orphanedAssets.length > 0) {
934
- const orphanedKeys = await Promise.all(orphanedAssets.map(async asset => {
935
- try {
936
- await this.getStorage(asset.storage).removeFile(asset.file);
937
- } catch (error) {
938
- this.emit('error', error);
939
- asset.error = error;
940
- }
941
-
942
- return asset.key;
943
- }));
944
- await AssetModel.query(trx).delete().whereIn('key', orphanedKeys);
945
- }
946
-
947
- return orphanedAssets;
948
- });
949
- }
950
- }
951
-
952
- }
953
-
954
- exports.Application = Application;
955
-
956
- _lib.EventEmitter.mixin(Application.prototype);
957
-
958
- function getOptions(options) {
959
- return (0, _utils2.isObject)(options) ? options : {};
960
- }
961
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcHAvQXBwbGljYXRpb24uanMiXSwibmFtZXMiOlsiQXBwbGljYXRpb24iLCJLb2EiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsInZhbGlkYXRvciIsInJvdXRlciIsImV2ZW50cyIsIm1pZGRsZXdhcmUiLCJtb2RlbHMiLCJzZXJ2aWNlcyIsImNvbnRyb2xsZXJzIiwiX3NldHVwRW1pdHRlciIsImFwcCIsImtleXMiLCJsb2ciLCJyZXN0Iiwic2lsZW50IiwicHJvY2VzcyIsImVudiIsIkRJVE9fU0lMRU5UIiwicHJveHkiLCJWYWxpZGF0b3IiLCJSb3V0ZXIiLCJzdG9yYWdlcyIsIk9iamVjdCIsImNyZWF0ZSIsImhhc0NvbnRyb2xsZXJNaWRkbGV3YXJlIiwic2V0dXBMb2dnZXIiLCJzZXR1cEtuZXgiLCJzZXR1cEdsb2JhbE1pZGRsZXdhcmUiLCJ1c2UiLCJhZGRTdG9yYWdlcyIsImFkZE1vZGVscyIsImFkZFNlcnZpY2VzIiwiYWRkQ29udHJvbGxlcnMiLCJhZGRSb3V0ZSIsInZlcmIiLCJwYXRoIiwidHJhbnNhY3RlZCIsImhhbmRsZXJzIiwiY29udHJvbGxlciIsImFjdGlvbiIsImhhbmRsZXIiLCJsZW5ndGgiLCJyb3V0ZSIsIm1vZGVsQ2xhc3MiLCJ2YWx1ZXMiLCJhZGRNb2RlbCIsInNvcnRNb2RlbHMiLCJzb3J0ZWRNb2RlbHMiLCJmaWx0ZXIiLCJuYW1lIiwic2V0dXAiLCJrbmV4IiwiaW5pdGlhbGl6ZSIsImFkZFNjaGVtYSIsImdldEpzb25TY2hlbWEiLCJzY2hlbWEiLCJyZWxhdGlvbnMiLCJzaG91bGRMb2ciLCJvcHRpb24iLCJpbmNsdWRlcyIsImRhdGEiLCJyZWxhdGlvbk1hcHBpbmdzIiwidmFsdWUiLCJNb2RlbCIsImlzUHJvdG90eXBlT2YiLCJjb25zb2xlIiwiaW5mbyIsInBpY28iLCJ5ZWxsb3ciLCJib2xkIiwidXRpbCIsImluc3BlY3QiLCJjb2xvcnMiLCJkZXB0aCIsIm1heEFycmF5TGVuZ3RoIiwiRXJyb3IiLCJzb3J0QnlSZWxhdGlvbnMiLCJsaXN0IiwiY29sbGVjdGVkIiwiZXhjbHVkZWQiLCJyZWxhdGlvbiIsImdldFJlbGF0aW9ucyIsIkJlbG9uZ3NUb09uZVJlbGF0aW9uIiwicmVsYXRlZE1vZGVsQ2xhc3MiLCJqb2luVGFibGVNb2RlbENsYXNzIiwicmVsYXRlZCIsInJldmVyc2UiLCJyZWR1Y2UiLCJnZXRNb2RlbCIsImVuZHNXaXRoIiwiZmluZE1vZGVsIiwiY2FsbGJhY2siLCJmaW5kIiwic2VydmljZSIsImVudHJpZXMiLCJhZGRTZXJ2aWNlIiwiU2VydmljZSIsInVuZGVmaW5lZCIsImdldFNlcnZpY2UiLCJmaW5kU2VydmljZSIsImZvckVhY2hTZXJ2aWNlIiwiUHJvbWlzZSIsImFsbCIsIm1hcCIsIm5hbWVzcGFjZSIsImtleSIsImFkZENvbnRyb2xsZXIiLCJzZXR1cENvbnRyb2xsZXJNaWRkbGV3YXJlIiwiQ29udHJvbGxlciIsInVybCIsImNvbXBvc2UiLCJnZXRDb250cm9sbGVyIiwiZmluZENvbnRyb2xsZXIiLCJnZXRBZG1pbkNvbnRyb2xsZXIiLCJBZG1pbkNvbnRyb2xsZXIiLCJnZXRBZG1pblZ1ZUNvbmZpZyIsImdldFZ1ZUNvbmZpZyIsImdldEFzc2V0Q29uZmlnIiwibm9ybWFsaXplRGJOYW1lcyIsImFzc2V0Q29uZmlnIiwibW9kZWxOYW1lIiwiYXNzZXRzIiwiZGVmaW5pdGlvbiIsIm5vcm1hbGl6ZWRNb2RlbE5hbWUiLCJub3JtYWxpemVJZGVudGlmaWVyIiwiY29udmVydGVkQXNzZXRzIiwiYXNzZXREYXRhUGF0aCIsInByb3BlcnR5IiwibmVzdGVkRGF0YVBhdGgiLCJpbmRleCIsImdldFByb3BlcnR5T3JSZWxhdGlvbkF0RGF0YVBhdGgiLCJub3JtYWxpemVkTmFtZSIsImRhdGFQYXRoIiwiYXNzZXRDb25maWdzIiwiYWRkU3RvcmFnZSIsInN0b3JhZ2UiLCJzdG9yYWdlQ2xhc3MiLCJTdG9yYWdlIiwiZ2V0IiwidHlwZSIsImdldFN0b3JhZ2UiLCJjb21waWxlVmFsaWRhdG9yIiwianNvblNjaGVtYSIsIm9wdGlvbnMiLCJjb21waWxlIiwiY29tcGlsZVBhcmFtZXRlcnNWYWxpZGF0b3IiLCJwYXJhbWV0ZXJzIiwiZGF0YU5hbWUiLCJwcm9wZXJ0aWVzIiwiYWRkUGFyYW1ldGVyIiwicHVzaCIsIm1lbWJlciIsImFzT2JqZWN0IiwidmFsaWRhdGUiLCJjb2VyY2VUeXBlcyIsImN0eCIsImNhbGwiLCJjcmVhdGVWYWxpZGF0aW9uRXJyb3IiLCJtZXNzYWdlIiwiZXJyb3JzIiwianNvbiIsIlZhbGlkYXRpb25FcnJvciIsInBhcnNlRXJyb3JzIiwiY3JlYXRlRGF0YWJhc2VFcnJvciIsImVycm9yIiwic3FsIiwibWF0Y2giLCJEYXRhYmFzZUVycm9yIiwibG9nZ2VyIiwicmVzcG9uc2VUaW1lIiwiZ2V0T3B0aW9ucyIsInJlcXVlc3RzIiwiaGVsbWV0IiwiY29ycyIsImNvbXByZXNzIiwiYnIiLCJwYXJhbXMiLCJ6bGliIiwiY29uc3RhbnRzIiwiQlJPVExJX1BBUkFNX1FVQUxJVFkiLCJldGFnIiwiYm9keVBhcnNlciIsInNlc3Npb24iLCJDb250ZXh0U3RvcmUiLCJwYXNzcG9ydCIsImVyciIsInJlcSIsInJlcyIsInBpbm8iLCJzdGRTZXJpYWxpemVycyIsInVzZXIiLCJpZCIsInNlcmlhbGl6ZXJzIiwibGV2ZWwiLCJwcmV0dHlQcmludCIsImlnbm9yZSIsInRyYW5zbGF0ZVRpbWUiLCJyZWRhY3QiLCJiYXNlIiwiY2hpbGQiLCJjbGllbnQiLCJzbmFrZUNhc2VPcHRpb25zIiwidHlwZVBhcnNlcnMiLCJkcml2ZXIiLCJwYXJzZXIiLCJ0eXBlcyIsInNldFR5cGVQYXJzZXIiLCJzZXR1cEtuZXhMb2dnaW5nIiwic3RhcnRUaW1lcyIsImVuZCIsInF1ZXJ5IiwicmVzcG9uc2UiLCJfX2tuZXhRdWVyeVVpZCIsImRpZmYiLCJocnRpbWUiLCJkdXJhdGlvbiIsImJpbmRpbmdzIiwiZnJvbUVudHJpZXMiLCJzdGFydHNXaXRoIiwib24iLCJpZGVudGlmaWVyIiwid3JhcElkZW50aWZpZXIiLCJyZXBsYWNlIiwiZGVub3JtYWxpemVJZGVudGlmaWVyIiwib2JqIiwicG9zdFByb2Nlc3NSZXNwb25zZSIsIm5vcm1hbGl6ZVBhdGgiLCJub3JtYWxpemVQYXRocyIsImZvcm1hdEVycm9yIiwidG9KU09OIiwic3RyIiwic3RhY2siLCJzcGxpdCIsInNsaWNlIiwiam9pbiIsIm9zIiwiRU9MIiwibG9nRXJyb3IiLCJleHBvc2UiLCJ0ZXh0IiwiUmVzcG9uc2VFcnJvciIsInN0YXR1cyIsImUiLCJzdGFydCIsImVtaXQiLCJzZXJ2ZXIiLCJob3N0IiwicG9ydCIsInJlc29sdmUiLCJyZWplY3QiLCJsaXN0ZW4iLCJhZGRyZXNzIiwic3RvcCIsImNsb3NlIiwic2V0SW1tZWRpYXRlIiwib2ZmIiwic3RhcnRPckV4aXQiLCJleGl0IiwiY3JlYXRlQXNzZXRzIiwiZmlsZXMiLCJjb3VudCIsInRyeCIsIkFzc2V0TW9kZWwiLCJmaWxlIiwiaW5zZXJ0IiwiaGFuZGxlQWRkZGVkQW5kUmVtb3ZlZEFzc2V0cyIsImFkZGVkRmlsZXMiLCJyZW1vdmVkRmlsZXMiLCJjbGVhbnVwVGltZVRocmVzaG9sZCIsInRpbWVUaHJlc2hvbGQiLCJpbXBvcnRlZEZpbGVzIiwiYWRkRm9yZWlnbkFzc2V0cyIsImNoYW5nZUNvdW50IiwiaW5jcmVtZW50Iiwid2hlcmVJbiIsInNldFRpbWVvdXQiLCJyZWxlYXNlVW51c2VkQXNzZXRzIiwiYXNzZXQiLCJmaW5kT25lIiwicmVkIiwiZ3JlZW4iLCJheGlvcyIsInJlcXVlc3QiLCJtZXRob2QiLCJyZXNwb25zZVR5cGUiLCJpbXBvcnRlZEZpbGUiLCJhZGRGaWxlIiwiYXNzaWduIiwiQXNzZXRFcnJvciIsImhhbmRsZU1vZGlmaWVkQXNzZXRzIiwibW9kaWZpZWRGaWxlcyIsImNoYW5nZWRGaWxlIiwidHJhbnNhY3Rpb24iLCJkYXRlIiwiRGF0ZSIsInNldE1pbGxpc2Vjb25kcyIsImdldE1pbGxpc2Vjb25kcyIsIm9ycGhhbmVkQXNzZXRzIiwid2hlcmUiLCJhbmRXaGVyZSIsIm9ycGhhbmVkS2V5cyIsInJlbW92ZUZpbGUiLCJkZWxldGUiLCJFdmVudEVtaXR0ZXIiLCJtaXhpbiIsInByb3RvdHlwZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQU1BOztBQUNBOztBQUNBOztBQVNBOztBQUlBOzs7O0FBT08sTUFBTUEsV0FBTixTQUEwQkMsWUFBMUIsQ0FBOEI7QUFDbkNDLEVBQUFBLFdBQVcsQ0FBQztBQUNWQyxJQUFBQSxNQUFNLEdBQUcsRUFEQztBQUVWQyxJQUFBQSxTQUZVO0FBR1ZDLElBQUFBLE1BSFU7QUFJVkMsSUFBQUEsTUFKVTtBQUtWQyxJQUFBQSxVQUxVO0FBTVZDLElBQUFBLE1BTlU7QUFPVkMsSUFBQUEsUUFQVTtBQVFWQyxJQUFBQTtBQVJVLE1BU1IsRUFUTyxFQVNIO0FBQ047O0FBQ0EsU0FBS0MsYUFBTCxDQUFtQkwsTUFBbkI7O0FBQ0EsVUFBTTtBQUVKTSxNQUFBQSxHQUFHLEVBQUU7QUFBRUMsUUFBQUEsSUFBRjtBQUFRLFdBQUdEO0FBQVgsVUFBbUIsRUFGcEI7QUFHSkUsTUFBQUEsR0FBRyxHQUFHLEVBSEY7QUFJSixTQUFHQztBQUpDLFFBS0ZaLE1BTEo7QUFNQSxTQUFLQSxNQUFMLEdBQWM7QUFDWlMsTUFBQUEsR0FEWTtBQUVaRSxNQUFBQSxHQUFHLEVBQUVBLEdBQUcsQ0FBQ0UsTUFBSixJQUFjQyxPQUFPLENBQUNDLEdBQVIsQ0FBWUMsV0FBMUIsR0FBd0MsRUFBeEMsR0FBNkNMLEdBRnRDO0FBR1osU0FBR0M7QUFIUyxLQUFkO0FBS0EsU0FBS0YsSUFBTCxHQUFZQSxJQUFaO0FBQ0EsU0FBS08s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TmlCLEVBTUosR0FOSSxFQU1DLG9CQUFJLFdBQUosQ0FORCxDQUE3Qjs7QUFPQSxZQUFJRixjQUFjLENBQUNoUSxNQUFmLEdBQXdCLENBQTVCLEVBQStCO0FBQzdCLGdCQUFNbVEsWUFBWSxHQUFHLE1BQU12TSxPQUFPLENBQUNDLEdBQVIsQ0FDekJtTSxjQUFjLENBQUNsTSxHQUFmLENBQW1CLE1BQU04SyxLQUFOLElBQWU7QUFDaEMsZ0JBQUk7QUFDRixvQkFBTSxLQUFLekksVUFBTCxDQUFnQnlJLEtBQUssQ0FBQzlJLE9BQXRCLEVBQStCc0ssVUFBL0IsQ0FBMEN4QixLQUFLLENBQUNkLElBQWhELENBQU47QUFDRCxhQUZELENBRUUsT0FBT25HLEtBQVAsRUFBYztBQUNkLG1CQUFLZ0YsSUFBTCxDQUFVLE9BQVYsRUFBbUJoRixLQUFuQjtBQUNBaUgsY0FBQUEsS0FBSyxDQUFDakgsS0FBTixHQUFjQSxLQUFkO0FBQ0Q7O0FBQ0QsbUJBQU9pSCxLQUFLLENBQUM1SyxHQUFiO0FBQ0QsV0FSRCxDQUR5QixDQUEzQjtBQVdBLGdCQUFNNkosVUFBVSxDQUNicEQsS0FERyxDQUNHbUQsR0FESCxFQUVIeUMsTUFGRyxHQUdINUIsT0FIRyxDQUdLLEtBSEwsRUFHWTBCLFlBSFosQ0FBTjtBQUlEOztBQUNELGVBQU9ILGNBQVA7QUFDRCxPQTlCTSxDQUFQO0FBK0JEO0FBQ0Y7O0FBbjVCa0M7Ozs7QUF3NUJyQ00sa0JBQWFDLEtBQWIsQ0FBbUJsVCxXQUFXLENBQUNtVCxTQUEvQjs7QUFFQSxTQUFTdkksVUFBVCxDQUFvQjNCLE9BQXBCLEVBQTZCO0FBQzNCLFNBQU8sc0JBQVNBLE9BQVQsSUFBb0JBLE9BQXBCLEdBQThCLEVBQXJDO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgS29hIGZyb20gJ2tvYSdcbmltcG9ydCBLbmV4IGZyb20gJ2tuZXgnXG5pbXBvcnQgdXRpbCBmcm9tICd1dGlsJ1xuaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJ1xuaW1wb3J0IHBpY28gZnJvbSAncGljb2NvbG9ycydcbmltcG9ydCB6bGliIGZyb20gJ3psaWInXG5pbXBvcnQgcGlubyBmcm9tICdwaW5vJ1xuaW1wb3J0IG9zIGZyb20gJ29zJ1xuaW1wb3J0IHBhcnNlRHVyYXRpb24gZnJvbSAncGFyc2UtZHVyYXRpb24nXG5pbXBvcnQgYm9keVBhcnNlciBmcm9tICdrb2EtYm9keXBhcnNlcidcbmltcG9ydCBjb3JzIGZyb20gJ0Brb2EvY29ycydcbmltcG9ydCBjb21wb3NlIGZyb20gJ2tvYS1jb21wb3NlJ1xuaW1wb3J0IGNvbXByZXNzIGZyb20gJ2tvYS1jb21wcmVzcydcbmltcG9ydCBjb25kaXRpb25hbCBmcm9tICdrb2EtY29uZGl0aW9uYWwtZ2V0J1xuaW1wb3J0IHBhc3Nwb3J0IGZyb20gJ2tvYS1wYXNzcG9ydCdcbmltcG9ydCBzZXNzaW9uIGZyb20gJ2tvYS1zZXNzaW9uJ1xuaW1wb3J0IGV0YWcgZnJvbSAna29hLWV0YWcnXG5pbXBvcnQgaGVsbWV0IGZyb20gJ2tvYS1oZWxtZXQnXG5pbXBvcnQgcmVzcG9uc2VUaW1lIGZyb20gJ2tvYS1yZXNwb25zZS10aW1lJ1xuaW1wb3J0IFJvdXRlciBmcm9tICdAZGl0b2pzL3JvdXRlcidcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ0AvbGliJ1xuaW1wb3J0IHsgQ29udHJvbGxlciwgQWRtaW5Db250cm9sbGVyIH0gZnJvbSAnQC9jb250cm9sbGVycydcbmltcG9ydCB7IFNlcnZpY2UgfSBmcm9tICdAL3NlcnZpY2VzJ1xuaW1wb3J0IHsgU3RvcmFnZSB9IGZyb20gJ0Avc3RvcmFnZSdcbmltcG9ydCB7IGNvbnZlcnRTY2hlbWEgfSBmcm9tICdAL3NjaGVtYSdcbmltcG9ydCB7IGZvcm1hdEpzb24gfSBmcm9tICdAL3V0aWxzJ1xuaW1wb3J0IHtcbiAgUmVzcG9uc2VFcnJvcixcbiAgVmFsaWRhdGlvbkVycm9yLFxuICBEYXRhYmFzZUVycm9yLFxuICBBc3NldEVycm9yXG59IGZyb20gJ0AvZXJyb3JzJ1xuaW1wb3J0IFNlc3Npb25TdG9yZSBmcm9tICcuL1Nlc3Npb25TdG9yZSdcbmltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gJy4vVmFsaWRhdG9yJ1xuaW1wb3J0IHtcbiAgYXR0YWNoTG9nZ2VyLFxuICBjcmVhdGVUcmFuc2FjdGlvbixcbiAgZmluZFJvdXRlLFxuICBoYW5kbGVFcnJvcixcbiAgaGFuZGxlUm91dGUsXG4gIGhhbmRsZVVzZXIsXG4gIGxvZ1JlcXVlc3RzXG59IGZyb20gJ0AvbWlkZGxld2FyZSdcbmltcG9ydCB7XG4gIGlzQXJyYXksIGlzT2JqZWN0LCBpc1N0cmluZywgYXNBcnJheSwgaXNQbGFpbk9iamVjdCwgaHlwaGVuYXRlLCBjbG9uZSwgbWVyZ2UsXG4gIHBhcnNlRGF0YVBhdGgsIG5vcm1hbGl6ZURhdGFQYXRoXG59IGZyb20gJ0BkaXRvanMvdXRpbHMnXG5pbXBvcnQge1xuICBNb2RlbCxcbiAgQmVsb25nc1RvT25lUmVsYXRpb24sXG4gIGtuZXhTbmFrZUNhc2VNYXBwZXJzLFxuICByZWZcbn0gZnJvbSAnb2JqZWN0aW9uJ1xuXG5leHBvcnQgY2xhc3MgQXBwbGljYXRpb24gZXh0ZW5kcyBLb2Ege1xuICBjb25zdHJ1Y3Rvcih7XG4gICAgY29uZmlnID0ge30sXG4gICAgdmFsaWRhdG9yLFxuICAgIHJvdXRlcixcbiAgICBldmVudHMsXG4gICAgbWlkZGxld2FyZSxcbiAgICBtb2RlbHMsXG4gICAgc2VydmljZXMsXG4gICAgY29udHJvbGxlcnNcbiAgfSA9IHt9KSB7XG4gICAgc3VwZXIoKVxuICAgIHRoaXMuX3NldHVwRW1pdHRlcihldmVudHMpXG4gICAgY29uc3Qge1xuICAgICAgLy8gUGx1Y2sga2V5cyBvdXQgb2YgYGNvbmZpZy5hcHBgIHRvIGtlZXAgdGhlbSBzZWNyZXRcbiAgICAgIGFwcDogeyBrZXlzLCAuLi5hcHAgfSA9IHt9LFxuICAgICAgbG9nID0ge30sXG4gICAgICAuLi5yZXN0XG4gICAgfSA9IGNvbmZpZ1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgYXBwLFxuICAgICAgbG9nOiBsb2cuc2lsZW50IHx8IHByb2Nlc3MuZW52LkRJVE9fU0lMRU5UID8ge30gOiBsb2csXG4gICAgICAuLi5yZXN0XG4gICAgfVxuICAgIHRoaXMua2V5cyA9IGtleXNcbiAgICB0aGlzLnByb3h5ID0gISFhcHAucHJveHlcbiAgICB0aGlzLnZhbGlkYXRvciA9IHZhbGlkYXRvciB8fCBuZXcgVmFsaWRhdG9yKClcbiAgICB0aGlzLnJvdXRlciA9IHJvdXRlciB8fCBuZXcgUm91dGVyKClcbiAgICB0aGlzLnZhbGlkYXRvci5hcHAgPSB0aGlzXG4gICAgdGhpcy5zdG9yYWdlcyA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgICB0aGlzLm1vZGVscyA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgICB0aGlzLnNlcnZpY2VzID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuICAgIHRoaXMuY29udHJvbGxlcnMgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgdGhpcy5oYXNDb250cm9sbGVyTWlkZGxld2FyZSA9IGZhbHNlXG4gICAgdGhpcy5zZXR1cExvZ2dlcigpXG4gICAgdGhpcy5zZXR1cEtuZXgoKVxuICAgIHRoaXMuc2V0dXBHbG9iYWxNaWRkbGV3YXJlKClcbiAgICBpZiAobWlkZGxld2FyZSkge1xuICAgICAgdGhpcy51c2UobWlkZGxld2FyZSlcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5zdG9yYWdlcykge1xuICAgICAgdGhpcy5hZGRTdG9yYWdlcyhjb25maWcuc3RvcmFnZXMpXG4gICAgfVxuICAgIGlmIChtb2RlbHMpIHtcbiAgICAgIHRoaXMuYWRkTW9kZWxzKG1vZGVscylcbiAgICB9XG4gICAgaWYgKHNlcnZpY2VzKSB7XG4gICAgICB0aGlzLmFkZFNlcnZpY2VzKHNlcnZpY2VzKVxuICAgIH1cbiAgICBpZiAoY29udHJvbGxlcnMpIHtcbiAgICAgIHRoaXMuYWRkQ29udHJvbGxlcnMoY29udHJvbGxlcnMpXG4gICAgfVxuICB9XG5cbiAgYWRkUm91dGUodmVyYiwgcGF0aCwgdHJhbnNhY3RlZCwgaGFuZGxlcnMsIGNvbnRyb2xsZXIgPSBudWxsLCBhY3Rpb24gPSBudWxsKSB7XG4gICAgaGFuZGxlcnMgPSBhc0FycmF5KGhhbmRsZXJzKVxuICAgIGNvbnN0IGhhbmRsZXIgPSBoYW5kbGVycy5sZW5ndGggPiAxID8gY29tcG9zZShoYW5kbGVycykgOiBoYW5kbGVyc1swXVxuICAgIC8vIEluc3RlYWQgb2YgZGlyZWN0bHkgcGFzc2luZyBgaGFuZGxlcmAsIHBhc3MgYSBgcm91dGVgIG9iamVjdCB0aGF0IGFsc29cbiAgICAvLyB3aWxsIGJlIGV4cG9zZWQgdGhyb3VnaCBgY3R4LnJvdXRlYCwgc2VlIGByb3V0ZXJIYW5kbGVyKClgOlxuICAgIGNvbnN0IHJvdXRlID0ge1xuICAgICAgdmVyYixcbiAgICAgIHBhdGgsXG4gICAgICB0cmFuc2FjdGVkLFxuICAgICAgaGFuZGxlcixcbiAgICAgIGNvbnRyb2xsZXIsXG4gICAgICBhY3Rpb25cbiAgICB9XG4gICAgdGhpcy5yb3V0ZXJbdmVyYl0ocGF0aCwgcm91dGUpXG4gIH1cblxuICBhZGRNb2RlbHMobW9kZWxzKSB7XG4gICAgLy8gRmlyc3QgYWRkIGFsbCBtb2RlbHMgdGhlbiBjYWxsIGluaXRpYWxpemUoKSBmb3IgZWFjaCBpbiBhIHNlY29uZCBsb29wLFxuICAgIC8vIHNpbmNlIHRoZXkgbWF5IGJlIHJlZmVyZW5jaW5nIGVhY2ggb3RoZXIgaW4gcmVsYXRpb25zLlxuICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBPYmplY3QudmFsdWVzKG1vZGVscykpIHtcbiAgICAgIHRoaXMuYWRkTW9kZWwobW9kZWxDbGFzcylcbiAgICB9XG4gICAgLy8gTm93IChyZS0pc29ydCBhbGwgbW9kZWxzIGJhc2VkIG9uIHRoZWlyIHJlbGF0aW9ucy5cbiAgICB0aGlzLm1vZGVscyA9IHRoaXMuc29ydE1vZGVscyh0aGlzLm1vZGVscylcbiAgICAvLyBGaWx0ZXIgdGhyb3VnaCBhbGwgc29ydGVkIG1vZGVscywga2VlcGluZyBvbmx5IHRoZSBuZXdseSBhZGRlZCBvbmVzLlxuICAgIGNvbnN0IHNvcnRlZE1vZGVscyA9IE9iamVjdC52YWx1ZXModGhpcy5tb2RlbHMpLmZpbHRlcihcbiAgICAgIG1vZGVsQ2xhc3MgPT4gbW9kZWxzW21vZGVsQ2xhc3MubmFtZV0gPT09IG1vZGVsQ2xhc3NcbiAgICApXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgYWRkZWQgbW9kZWxzIGluIGNvcnJlY3Qgc29ydGVkIHNlcXVlbmNlLCBzbyB0aGF0IGZvciBldmVyeVxuICAgIC8vIG1vZGVsLCBnZXRSZWxhdGVkUmVsYXRpb25zKCkgcmV0dXJucyB0aGUgZnVsbCBsaXN0IG9mIHJlbGF0aW5nIHJlbGF0aW9ucy5cbiAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2Ygc29ydGVkTW9kZWxzKSB7XG4gICAgICBpZiAobW9kZWxzW21vZGVsQ2xhc3MubmFtZV0gPT09IG1vZGVsQ2xhc3MpIHtcbiAgICAgICAgbW9kZWxDbGFzcy5zZXR1cCh0aGlzLmtuZXgpXG4gICAgICAgIC8vIE5vdyB0aGF0IHRoZSBtb2RlbENsYXNzIGlzIHNldCB1cCwgY2FsbCBgaW5pdGlhbGl6ZSgpYCwgd2hpY2ggY2FuIGJlXG4gICAgICAgIC8vIG92ZXJyaWRkZW4gYnkgc3ViLWNsYXNzZXMsd2l0aG91dCBoYXZpbmcgdG8gY2FsbCBgc3VwZXIuaW5pdGlhbGl6ZSgpYFxuICAgICAgICBtb2RlbENsYXNzLmluaXRpYWxpemUoKVxuICAgICAgICB0aGlzLnZhbGlkYXRvci5hZGRTY2hlbWEobW9kZWxDbGFzcy5nZXRKc29uU2NoZW1hKCkpXG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmNvbmZpZ1xuICAgIGlmIChsb2cuc2NoZW1hIHx8IGxvZy5yZWxhdGlvbnMpIHtcbiAgICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBzb3J0ZWRNb2RlbHMpIHtcbiAgICAgICAgY29uc3Qgc2hvdWxkTG9nID0gb3B0aW9uID0+IChcbiAgICAgICAgICBvcHRpb24gPT09IHRydWUgfHxcbiAgICAgICAgICBhc0FycmF5KG9wdGlvbikuaW5jbHVkZXMobW9kZWxDbGFzcy5uYW1lKVxuICAgICAgICApXG4gICAgICAgIGNvbnN0IGRhdGEgPSB7fVxuICAgICAgICBpZiAoc2hvdWxkTG9nKGxvZy5zY2hlbWEpKSB7XG4gICAgICAgICAgZGF0YS5zY2hlbWEgPSBtb2RlbENsYXNzLmdldEpzb25TY2hlbWEoKVxuICAgICAgICB9XG4gICAgICAgIGlmIChzaG91bGRMb2cobG9nLnJlbGF0aW9ucykpIHtcbiAgICAgICAgICBkYXRhLnJlbGF0aW9ucyA9IGNsb25lKG1vZGVsQ2xhc3MucmVsYXRpb25NYXBwaW5ncywgdmFsdWUgPT5cbiAgICAgICAgICAgIE1vZGVsLmlzUHJvdG90eXBlT2YodmFsdWUpID8gYFtNb2RlbDogJHt2YWx1ZS5uYW1lfV1gIDogdmFsdWVcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgICAgICBwaWNvLnllbGxvdy5ib2xkKGBcXG4ke21vZGVsQ2xhc3MubmFtZX06XFxuYCksXG4gICAgICAgICAgICB1dGlsLmluc3BlY3QoZGF0YSwge1xuICAgICAgICAgICAgICBjb2xvcnM6IHRydWUsXG4gICAgICAgICAgICAgIGRlcHRoOiBudWxsLFxuICAgICAgICAgICAgICBtYXhBcnJheUxlbmd0aDogbnVsbFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhZGRNb2RlbChtb2RlbENsYXNzKSB7XG4gICAgaWYgKE1vZGVsLmlzUHJvdG90eXBlT2YobW9kZWxDbGFzcykpIHtcbiAgICAgIG1vZGVsQ2xhc3MuYXBwID0gdGhpc1xuICAgICAgdGhpcy5tb2RlbHNbbW9kZWxDbGFzcy5uYW1lXSA9IG1vZGVsQ2xhc3NcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG1vZGVsIGNsYXNzOiAke21vZGVsQ2xhc3N9YClcbiAgICB9XG4gIH1cblxuICBzb3J0TW9kZWxzKG1vZGVscykge1xuICAgIGNvbnN0IHNvcnRCeVJlbGF0aW9ucyA9IChsaXN0LCBjb2xsZWN0ZWQgPSB7fSwgZXhjbHVkZWQgPSB7fSkgPT4ge1xuICAgICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIGxpc3QpIHtcbiAgICAgICAgY29uc3QgeyBuYW1lIH0gPSBtb2RlbENsYXNzXG4gICAgICAgIGlmICghY29sbGVjdGVkW25hbWVdICYmICFleGNsdWRlZFtuYW1lXSkge1xuICAgICAgICAgIGZvciAoY29uc3QgcmVsYXRpb24gb2YgT2JqZWN0LnZhbHVlcyhtb2RlbENsYXNzLmdldFJlbGF0aW9ucygpKSkge1xuICAgICAgICAgICAgaWYgKCEocmVsYXRpb24gaW5zdGFuY2VvZiBCZWxvbmdzVG9PbmVSZWxhdGlvbikpIHtcbiAgICAgICAgICAgICAgY29uc3QgeyByZWxhdGVkTW9kZWxDbGFzcywgam9pblRhYmxlTW9kZWxDbGFzcyB9ID0gcmVsYXRpb25cbiAgICAgICAgICAgICAgZm9yIChjb25zdCByZWxhdGVkIG9mIFtqb2luVGFibGVNb2RlbENsYXNzLCByZWxhdGVkTW9kZWxDbGFzc10pIHtcbiAgICAgICAgICAgICAgICAvLyBFeGNsdWRlIHNlbGYtcmVmZXJlbmNlcyBhbmQgZ2VuZXJhdGVkIGpvaW4gbW9kZWxzOlxuICAgICAgICAgICAgICAgIGlmIChyZWxhdGVkICYmIHJlbGF0ZWQgIT09IG1vZGVsQ2xhc3MgJiYgbW9kZWxzW3JlbGF0ZWQubmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgIHNvcnRCeVJlbGF0aW9ucyhbcmVsYXRlZF0sIGNvbGxlY3RlZCwge1xuICAgICAgICAgICAgICAgICAgICAvLyBFeGNsdWRlIG1vZGVsQ2xhc3MgdG8gcHJldmVudCBlbmRsZXNzIHJlY3Vyc2lvbnM6XG4gICAgICAgICAgICAgICAgICAgIFtuYW1lXTogbW9kZWxDbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgLi4uZXhjbHVkZWRcbiAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbGxlY3RlZFtuYW1lXSA9IG1vZGVsQ2xhc3NcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoY29sbGVjdGVkKVxuICAgIH1cbiAgICAvLyBSZXR1cm4gYSBuZXcgb2JqZWN0IHdpdGggdGhlIHNvcnRlZCBtb2RlbHMgYXMgaXRzIGtleS92YWx1ZSBwYWlycy5cbiAgICAvLyBOT1RFOiBXZSBuZWVkIHRvIHJldmVyc2UgZm9yIHRoZSBhYm92ZSBhbGdvcml0aG0gdG8gc29ydCBwcm9wZXJseSxcbiAgICAvLyBhbmQgdGhlbiByZXZlcnNlIHRoZSByZXN1bHQgYmFjay5cbiAgICByZXR1cm4gc29ydEJ5UmVsYXRpb25zKE9iamVjdC52YWx1ZXMobW9kZWxzKS5yZXZlcnNlKCkpLnJldmVyc2UoKS5yZWR1Y2UoXG4gICAgICAobW9kZWxzLCBtb2RlbENsYXNzKSA9PiB7XG4gICAgICAgIG1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID0gbW9kZWxDbGFzc1xuICAgICAgICByZXR1cm4gbW9kZWxzXG4gICAgICB9LFxuICAgICAgT2JqZWN0LmNyZWF0ZShudWxsKVxuICAgIClcbiAgfVxuXG4gIGdldE1vZGVsKG5hbWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5tb2RlbHNbbmFtZV0gfHxcbiAgICAgICFuYW1lLmVuZHNXaXRoKCdNb2RlbCcpICYmIHRoaXMubW9kZWxzW2Ake25hbWV9TW9kZWxgXSB8fFxuICAgICAgbnVsbFxuICAgIClcbiAgfVxuXG4gIGZpbmRNb2RlbChjYWxsYmFjaykge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMubW9kZWxzKS5maW5kKGNhbGxiYWNrKVxuICB9XG5cbiAgYWRkU2VydmljZXMoc2VydmljZXMpIHtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBzZXJ2aWNlXSBvZiBPYmplY3QuZW50cmllcyhzZXJ2aWNlcykpIHtcbiAgICAgIC8vIEhhbmRsZSBFUzYgbW9kdWxlIHdlaXJkbmVzcyB0aGF0IGNhbiBoYXBwZW4sIGFwcGFyZW50bHk6XG4gICAgICBpZiAobmFtZSA9PT0gJ2RlZmF1bHQnICYmIGlzUGxhaW5PYmplY3Qoc2VydmljZSkpIHtcbiAgICAgICAgdGhpcy5hZGRTZXJ2aWNlcyhzZXJ2aWNlKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGRTZXJ2aWNlKHNlcnZpY2UsIG5hbWUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYWRkU2VydmljZShzZXJ2aWNlLCBuYW1lKSB7XG4gICAgLy8gQXV0by1pbnN0YW50aWF0ZSBjb250cm9sbGVyIGNsYXNzZXM6XG4gICAgaWYgKFNlcnZpY2UuaXNQcm90b3R5cGVPZihzZXJ2aWNlKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXBcbiAgICAgIHNlcnZpY2UgPSBuZXcgc2VydmljZSh0aGlzLCBuYW1lKVxuICAgIH1cbiAgICBpZiAoIShzZXJ2aWNlIGluc3RhbmNlb2YgU2VydmljZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBzZXJ2aWNlOiAke3NlcnZpY2V9YClcbiAgICB9XG4gICAgLy8gT25seSBhZnRlciB0aGUgY29uc3RydWN0b3IgaXMgY2FsbGVkLCBgc2VydmljZS5uYW1lYCBpcyBndWFyYW50ZWVkIHRvIGJlXG4gICAgLy8gc2V0IHRvIHRoZSBjb3JyZWN0IHZhbHVlLCBlLmcuIHdpdGggYW4gYWZ0ZXItY29uc3RydWN0b3IgY2xhc3MgcHJvcGVydHkuXG4gICAgKHsgbmFtZSB9ID0gc2VydmljZSlcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZy5zZXJ2aWNlc1tuYW1lXVxuICAgIGlmIChjb25maWcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb25maWd1cmF0aW9uIG1pc3NpbmcgZm9yIHNlcnZpY2UgJyR7bmFtZX0nYClcbiAgICB9XG4gICAgLy8gQXMgYSBjb252ZW50aW9uLCB0aGUgY29uZmlndXJhdGlvbiBvZiBhIHNlcnZpY2UgY2FuIGJlIHNldCB0byBgZmFsc2VgXG4gICAgLy8gaW4gb3JkZXIgdG8gZW50aXJlbHkgZGVhY3RpdmF0ZSB0aGUgc2VydmljZS5cbiAgICBpZiAoY29uZmlnICE9PSBmYWxzZSkge1xuICAgICAgc2VydmljZS5zZXR1cChjb25maWcpXG4gICAgICB0aGlzLnNlcnZpY2VzW25hbWVdID0gc2VydmljZVxuICAgICAgLy8gTm93IHRoYXQgdGhlIHNlcnZpY2UgaXMgc2V0IHVwLCBjYWxsIGBpbml0aWFsaXplKClgIHdoaWNoIGNhbiBiZVxuICAgICAgLy8gb3ZlcnJpZGRlbiBieSBzZXJ2aWNlcy5cbiAgICAgIHNlcnZpY2UuaW5pdGlhbGl6ZSgpXG4gICAgfVxuICB9XG5cbiAgZ2V0U2VydmljZShuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmljZXNbbmFtZV0gfHwgbnVsbFxuICB9XG5cbiAgZmluZFNlcnZpY2UoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnNlcnZpY2VzKS5maW5kKGNhbGxiYWNrKVxuICB9XG5cbiAgZm9yRWFjaFNlcnZpY2UoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoT2JqZWN0LnZhbHVlcyh0aGlzLnNlcnZpY2VzKS5tYXAoY2FsbGJhY2spKVxuICB9XG5cbiAgYWRkQ29udHJvbGxlcnMoY29udHJvbGxlcnMsIG5hbWVzcGFjZSkge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbnRyb2xsZXJzKSkge1xuICAgICAgaWYgKGlzUGxhaW5PYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHRoaXMuYWRkQ29udHJvbGxlcnModmFsdWUsIG5hbWVzcGFjZSA/IGAke25hbWVzcGFjZX0vJHtrZXl9YCA6IGtleSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWRkQ29udHJvbGxlcih2YWx1ZSwgbmFtZXNwYWNlKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFkZENvbnRyb2xsZXIoY29udHJvbGxlciwgbmFtZXNwYWNlKSB7XG4gICAgLy8gQ29udHJvbGxlcnMgcmVxdWlyZSBhZGRpdGlvbmFsIG1pZGRsZXdhcmUgdG8gYmUgaW5zdGFsbGVkIG9uY2UuXG4gICAgdGhpcy5zZXR1cENvbnRyb2xsZXJNaWRkbGV3YXJlKClcbiAgICAvLyBBdXRvLWluc3RhbnRpYXRlIGNvbnRyb2xsZXIgY2xhc3NlczpcbiAgICBpZiAoQ29udHJvbGxlci5pc1Byb3RvdHlwZU9mKGNvbnRyb2xsZXIpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcFxuICAgICAgY29udHJvbGxlciA9IG5ldyBjb250cm9sbGVyKHRoaXMsIG5hbWVzcGFjZSlcbiAgICB9XG4gICAgaWYgKCEoY29udHJvbGxlciBpbnN0YW5jZW9mIENvbnRyb2xsZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY29udHJvbGxlcjogJHtjb250cm9sbGVyfWApXG4gICAgfVxuICAgIC8vIEluaGVyaXRhbmNlIG9mIGFjdGlvbiBtZXRob2RzIGNhbm5vdCBoYXBwZW4gaW4gdGhlIGNvbnN0cnVjdG9yIGl0c2VsZixcbiAgICAvLyBzbyBjYWxsIHNlcGFyYXRlIGBzZXR1cCgpYCBtZXRob2QgYWZ0ZXIgaW4gb3JkZXIgdG8gdGFrZSBjYXJlIG9mIGl0LlxuICAgIGNvbnRyb2xsZXIuc2V0dXAoKVxuICAgIHRoaXMuY29udHJvbGxlcnNbY29udHJvbGxlci51cmxdID0gY29udHJvbGxlclxuICAgIC8vIE5vdyB0aGF0IHRoZSBjb250cm9sbGVyIGlzIHNldCB1cCwgY2FsbCBgaW5pdGlhbGl6ZSgpYCB3aGljaCBjYW4gYmVcbiAgICAvLyBvdmVycmlkZGVuIGJ5IGNvbnRyb2xsZXJzLlxuICAgIGNvbnRyb2xsZXIuaW5pdGlhbGl6ZSgpXG4gICAgLy8gRWFjaCBjb250cm9sbGVyIGNhbiBhbHNvIHByb3ZpZGUgZnVydGhlciBtaWRkbGV3YXJlLCBlLmcuXG4gICAgLy8gYEFkbWluQ29udHJvbGxlcmA6XG4gICAgY29uc3QgbWlkZGxld2FyZSA9IGNvbnRyb2xsZXIuY29tcG9zZSgpXG4gICAgaWYgKG1pZGRsZXdhcmUpIHtcbiAgICAgIHRoaXMudXNlKG1pZGRsZXdhcmUpXG4gICAgfVxuICB9XG5cbiAgZ2V0Q29udHJvbGxlcih1cmwpIHtcbiAgICByZXR1cm4gdGhpcy5jb250cm9sbGVyc1t1cmxdIHx8IG51bGxcbiAgfVxuXG4gIGZpbmRDb250cm9sbGVyKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5jb250cm9sbGVycykuZmluZChjYWxsYmFjaylcbiAgfVxuXG4gIGdldEFkbWluQ29udHJvbGxlcigpIHtcbiAgICByZXR1cm4gdGhpcy5maW5kQ29udHJvbGxlcihcbiAgICAgIGNvbnRyb2xsZXIgPT4gY29udHJvbGxlciBpbnN0YW5jZW9mIEFkbWluQ29udHJvbGxlclxuICAgIClcbiAgfVxuXG4gIGdldEFkbWluVnVlQ29uZmlnKCkge1xuICAgIHJldHVybiB0aGlzLmdldEFkbWluQ29udHJvbGxlcigpPy5nZXRWdWVDb25maWcoKSB8fCBudWxsXG4gIH1cblxuICBnZXRBc3NldENvbmZpZyh7XG4gICAgbW9kZWxzID0gT2JqZWN0LmtleXModGhpcy5tb2RlbHMpLFxuICAgIG5vcm1hbGl6ZURiTmFtZXMgPSB0aGlzLmNvbmZpZy5rbmV4Lm5vcm1hbGl6ZURiTmFtZXNcbiAgfSA9IHt9KSB7XG4gICAgY29uc3QgYXNzZXRDb25maWcgPSB7fVxuICAgIGZvciAoY29uc3QgbW9kZWxOYW1lIG9mIG1vZGVscykge1xuICAgICAgY29uc3QgbW9kZWxDbGFzcyA9IHRoaXMubW9kZWxzW21vZGVsTmFtZV1cbiAgICAgIGNvbnN0IHsgYXNzZXRzIH0gPSBtb2RlbENsYXNzLmRlZmluaXRpb25cbiAgICAgIGlmIChhc3NldHMpIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZURiTmFtZXNcbiAgICAgICAgICA/IHRoaXMubm9ybWFsaXplSWRlbnRpZmllcihtb2RlbE5hbWUpXG4gICAgICAgICAgOiBtb2RlbE5hbWVcbiAgICAgICAgY29uc3QgY29udmVydGVkQXNzZXRzID0ge31cbiAgICAgICAgZm9yIChjb25zdCBbYXNzZXREYXRhUGF0aCwgY29uZmlnXSBvZiBPYmplY3QuZW50cmllcyhhc3NldHMpKSB7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICBuZXN0ZWREYXRhUGF0aCxcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBpbmRleFxuICAgICAgICAgIH0gPSBtb2RlbENsYXNzLmdldFByb3BlcnR5T3JSZWxhdGlvbkF0RGF0YVBhdGgoYXNzZXREYXRhUGF0aClcbiAgICAgICAgICBpZiAocHJvcGVydHkgJiYgaW5kZXggPT09IDApIHtcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWROYW1lID0gbm9ybWFsaXplRGJOYW1lc1xuICAgICAgICAgICAgICA/IHRoaXMubm9ybWFsaXplSWRlbnRpZmllcihuYW1lKVxuICAgICAgICAgICAgICA6IG5hbWVcbiAgICAgICAgICAgIGNvbnN0IGRhdGFQYXRoID0gbm9ybWFsaXplRGF0YVBhdGgoW1xuICAgICAgICAgICAgICBub3JtYWxpemVkTmFtZSxcbiAgICAgICAgICAgICAgLi4ucGFyc2VEYXRhUGF0aChuZXN0ZWREYXRhUGF0aClcbiAgICAgICAgICAgIF0pXG4gICAgICAgICAgICBjb25zdCBhc3NldENvbmZpZ3MgPSBjb252ZXJ0ZWRBc3NldHNbbm9ybWFsaXplZE5hbWVdIHx8PSB7fVxuICAgICAgICAgICAgYXNzZXRDb25maWdzW2RhdGFQYXRoXSA9IGNvbmZpZ1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05lc3RlZCBncmFwaCBwcm9wZXJ0aWVzIGFyZSBub3Qgc3VwcG9ydGVkIHlldCcpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFzc2V0Q29uZmlnW25vcm1hbGl6ZWRNb2RlbE5hbWVdID0gY29udmVydGVkQXNzZXRzXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhc3NldENvbmZpZ1xuICB9XG5cbiAgYWRkU3RvcmFnZXMoc3RvcmFnZXMpIHtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBjb25maWddIG9mIE9iamVjdC5lbnRyaWVzKHN0b3JhZ2VzKSkge1xuICAgICAgdGhpcy5hZGRTdG9yYWdlKGNvbmZpZywgbmFtZSlcbiAgICB9XG4gIH1cblxuICBhZGRTdG9yYWdlKGNvbmZpZywgbmFtZSkge1xuICAgIGxldCBzdG9yYWdlID0gbnVsbFxuICAgIGlmIChpc1BsYWluT2JqZWN0KGNvbmZpZykpIHtcbiAgICAgIGNvbnN0IHN0b3JhZ2VDbGFzcyA9IFN0b3JhZ2UuZ2V0KGNvbmZpZy50eXBlKVxuICAgICAgaWYgKCFzdG9yYWdlQ2xhc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBzdG9yYWdlOiAke2NvbmZpZ31gKVxuICAgICAgfVxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXBcbiAgICAgIHN0b3JhZ2UgPSBuZXcgc3RvcmFnZUNsYXNzKHRoaXMsIGNvbmZpZylcbiAgICB9IGVsc2UgaWYgKGNvbmZpZyBpbnN0YW5jZW9mIFN0b3JhZ2UpIHtcbiAgICAgIHN0b3JhZ2UgPSBjb25maWdcbiAgICB9XG4gICAgaWYgKHN0b3JhZ2UpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIHN0b3JhZ2UubmFtZSA9IG5hbWVcbiAgICAgIH1cbiAgICAgIHRoaXMuc3RvcmFnZXNbc3RvcmFnZS5uYW1lXSA9IHN0b3JhZ2VcbiAgICB9XG4gICAgcmV0dXJuIHN0b3JhZ2VcbiAgfVxuXG4gIGdldFN0b3JhZ2UobmFtZSkge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2VzW25hbWVdIHx8IG51bGxcbiAgfVxuXG4gIGNvbXBpbGVWYWxpZGF0b3IoanNvblNjaGVtYSwgb3B0aW9ucykge1xuICAgIHJldHVybiBqc29uU2NoZW1hXG4gICAgICA/IHRoaXMudmFsaWRhdG9yLmNvbXBpbGUoanNvblNjaGVtYSwgb3B0aW9ucylcbiAgICAgIDogbnVsbFxuICB9XG5cbiAgY29tcGlsZVBhcmFtZXRlcnNWYWxpZGF0b3IocGFyYW1ldGVycywgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgbGlzdCA9IFtdXG4gICAgY29uc3QgeyBkYXRhTmFtZSA9ICdkYXRhJyB9ID0gb3B0aW9uc1xuXG4gICAgbGV0IHByb3BlcnRpZXMgPSBudWxsXG4gICAgY29uc3QgYWRkUGFyYW1ldGVyID0gKG5hbWUsIHNjaGVtYSkgPT4ge1xuICAgICAgbGlzdC5wdXNoKHtcbiAgICAgICAgbmFtZTogbmFtZSA/PyBudWxsLFxuICAgICAgICAuLi5zY2hlbWFcbiAgICAgIH0pXG4gICAgICBpZiAoIXNjaGVtYS5tZW1iZXIpIHtcbiAgICAgICAgcHJvcGVydGllcyB8fD0ge31cbiAgICAgICAgcHJvcGVydGllc1tuYW1lIHx8IGRhdGFOYW1lXSA9IHNjaGVtYVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFN1cHBvcnQgdHdvIGZvcm1hdHMgb2YgcGFyYW1ldGVycyBkZWZpbml0aW9uczpcbiAgICAvLyAtIEFuIGFycmF5IG9mIHBhcmFtZXRlciBzY2hlbWFzLCBuYW1lZCBieSB0aGVpciBgbmFtZWAga2V5LlxuICAgIC8vIC0gQW4gb2JqZWN0IG9mIHBhcmFtZXRlciBzY2hlbWFzLCBuYW1lZCBieSB0aGUga2V5IHVuZGVyIHdoaWNoIGVhY2hcbiAgICAvLyAgIHNjaGVtYSBpcyBzdG9yZWQgaW4gdGhlIHJvb3Qgb2JqZWN0LlxuICAgIC8vIElmIGFuIGFycmF5IGlzIHBhc3NlZCwgdGhlbiB0aGUgY29udHJvbGxlciBhY3Rpb25zIHJlY2VpdmVzIHRoZVxuICAgIC8vIHBhcmFtZXRlcnMgYXMgc2VwYXJhdGUgYXJndW1lbnRzLiBJZiBhbiBvYmplY3QgaXMgcGFzc2VkLCB0aGVuIHRoZVxuICAgIC8vIGFjdGlvbnMgcmVjZWl2ZXMgb25lIHBhcmFtZXRlciBvYmplY3Qgd2hlcmUgdW5kZXIgdGhlIHNhbWUga2V5cyB0aGVcbiAgICAvLyBzcGVjaWZpZWQgcGFyYW1ldGVyIHZhbHVlcyBhcmUgc3RvcmVkLlxuICAgIGxldCBhc09iamVjdCA9IGZhbHNlXG4gICAgaWYgKGlzQXJyYXkocGFyYW1ldGVycykpIHtcbiAgICAgIGZvciAoY29uc3QgeyBuYW1lLCAuLi5zY2hlbWEgfSBvZiBwYXJhbWV0ZXJzKSB7XG4gICAgICAgIGFkZFBhcmFtZXRlcihuYW1lLCBzY2hlbWEpXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChpc09iamVjdChwYXJhbWV0ZXJzKSkge1xuICAgICAgYXNPYmplY3QgPSB0cnVlXG4gICAgICBmb3IgKGNvbnN0IFtuYW1lLCBzY2hlbWFdIG9mIE9iamVjdC5lbnRyaWVzKHBhcmFtZXRlcnMpKSB7XG4gICAgICAgIGlmIChzY2hlbWEpIHtcbiAgICAgICAgICBhZGRQYXJhbWV0ZXIobmFtZSwgc2NoZW1hKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwYXJhbWV0ZXJzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGFyYW1ldGVycyBkZWZpbml0aW9uOiAke3BhcmFtZXRlcnN9YClcbiAgICB9XG4gICAgLy8gTk9URTogSWYgcHJvcGVydGllcyBpcyBudWxsLCBzY2hlbWEgYW5kIHZhbGlkYXRlIHdpbGwgYmVjb21lIG51bGwgdG9vLlxuICAgIC8vIE5PVEU6IElmIGl0IGlzIG5vdCBudWxsLCBpdCB3aWxsIGdldCBleHBhbmRlZCB0byBhbiBvYmplY3Qgc2NoZW1hLlxuICAgIGNvbnN0IHNjaGVtYSA9IGNvbnZlcnRTY2hlbWEocHJvcGVydGllcywgb3B0aW9ucylcbiAgICBjb25zdCB2YWxpZGF0ZSA9IHRoaXMuY29tcGlsZVZhbGlkYXRvcihzY2hlbWEsIHtcbiAgICAgIC8vIEZvciBwYXJhbWV0ZXJzLCBhbHdheXMgY29lcmNlIHR5cGVzLCBpbmNsdWRpbmcgYXJyYXlzLlxuICAgICAgY29lcmNlVHlwZXM6ICdhcnJheScsXG4gICAgICAuLi5vcHRpb25zXG4gICAgfSlcbiAgICBjb25zdCBjdHggPSB7XG4gICAgICBhcHA6IHRoaXMsXG4gICAgICB2YWxpZGF0b3I6IHRoaXMudmFsaWRhdG9yLFxuICAgICAgb3B0aW9uc1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgbGlzdCxcbiAgICAgIHNjaGVtYSxcbiAgICAgIGFzT2JqZWN0LFxuICAgICAgZGF0YU5hbWUsXG4gICAgICB2YWxpZGF0ZTogdmFsaWRhdGVcbiAgICAgICAgLy8gVXNlIGBjYWxsKClgIHRvIHBhc3MgY3R4IGFzIGNvbnRleHQgdG8gQWp2LCBzZWUgcGFzc0NvbnRleHQ6XG4gICAgICAgID8gZGF0YSA9PiB2YWxpZGF0ZS5jYWxsKGN0eCwgZGF0YSlcbiAgICAgICAgOiBudWxsXG4gICAgfVxuICB9XG5cbiAgY3JlYXRlVmFsaWRhdGlvbkVycm9yKHsgdHlwZSwgbWVzc2FnZSwgZXJyb3JzLCBvcHRpb25zLCBqc29uIH0pIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25FcnJvcih7XG4gICAgICB0eXBlLFxuICAgICAgbWVzc2FnZSxcbiAgICAgIGVycm9yczogdGhpcy52YWxpZGF0b3IucGFyc2VFcnJvcnMoZXJyb3JzLCBvcHRpb25zKSxcbiAgICAgIC8vIE9ubHkgaW5jbHVkZSB0aGUgSlNPTiBkYXRhIGluIHRoZSBlcnJvciBpZiBgbG9nLmVycm9ycy5qc29uYGlzIHNldC5cbiAgICAgIGpzb246IHRoaXMuY29uZmlnLmxvZy5lcnJvcnM/Lmpzb24gPyBqc29uIDogdW5kZWZpbmVkXG4gICAgfSlcbiAgfVxuXG4gIGNyZWF0ZURhdGFiYXNlRXJyb3IoZXJyb3IpIHtcbiAgICAvLyBSZW1vdmUga25leCBTUUwgcXVlcnkgYW5kIG1vdmUgdG8gc2VwYXJhdGUgYHNxbGAgcHJvcGVydHkuXG4gICAgLy8gVE9ETzogRml4IHRoaXMgcHJvcGVybHkgaW4gS25leCAvIE9iamVjdGlvbiBpbnN0ZWFkLCBzZWU6XG4gICAgLy8gaHR0cHM6Ly9naXR0ZXIuaW0vVmluY2l0L29iamVjdGlvbi5qcz9hdD01YTY4NzI4ZjVhOWViZTRmNzVjYTQwYjBcbiAgICBjb25zdCBbLCBzcWwsIG1lc3NhZ2VdID0gZXJyb3IubWVzc2FnZS5tYXRjaCgvXihbXFxzXFxTXSopIC0gKFtcXHNcXFNdKj8pJC8pIHx8XG4gICAgICBbbnVsbCwgbnVsbCwgZXJyb3IubWVzc2FnZV1cbiAgICByZXR1cm4gbmV3IERhdGFiYXNlRXJyb3IoZXJyb3IsIHtcbiAgICAgIG1lc3NhZ2UsXG4gICAgICAvLyBPbmx5IGluY2x1ZGUgdGhlIFNRTCBxdWVyeSBpbiB0aGUgZXJyb3IgaWYgYGxvZy5lcnJvcnMuc3FsYGlzIHNldC5cbiAgICAgIHNxbDogdGhpcy5jb25maWcubG9nLmVycm9ycz8uc3FsID8gc3FsIDogdW5kZWZpbmVkXG4gICAgfSlcbiAgfVxuXG4gIHNldHVwR2xvYmFsTWlkZGxld2FyZSgpIHtcbiAgICBjb25zdCB7IGFwcCwgbG9nIH0gPSB0aGlzLmNvbmZpZ1xuXG4gICAgdGhpcy51c2UoYXR0YWNoTG9nZ2VyKHRoaXMubG9nZ2VyKSlcblxuICAgIGlmIChhcHAucmVzcG9uc2VUaW1lICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy51c2UocmVzcG9uc2VUaW1lKGdldE9wdGlvbnMoYXBwLnJlc3BvbnNlVGltZSkpKVxuICAgIH1cbiAgICBpZiAobG9nLnJlcXVlc3RzKSB7XG4gICAgICB0aGlzLnVzZShsb2dSZXF1ZXN0cygpKVxuICAgIH1cbiAgICAvLyBOZWVkcyB0byBiZSBwb3NpdGlvbmVkIGFmdGVyIHRoZSByZXF1ZXN0IGxvZ2dlciB0byBsb2cgdGhlIGNvcnJlY3RcbiAgICAvLyByZXNwb25zZSBzdGF0dXMuXG4gICAgdGhpcy51c2UoaGFuZGxlRXJyb3IoKSlcbiAgICBpZiAoYXBwLmhlbG1ldCAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMudXNlKGhlbG1ldChnZXRPcHRpb25zKGFwcC5oZWxtZXQpKSlcbiAgICB9XG4gICAgaWYgKGFwcC5jb3JzICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy51c2UoY29ycyhnZXRPcHRpb25zKGFwcC5jb3JzKSkpXG4gICAgfVxuICAgIGlmIChhcHAuY29tcHJlc3MgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnVzZShjb21wcmVzcyhtZXJnZShcbiAgICAgICAge1xuICAgICAgICAgIC8vIFVzZSBhIHJlYXNvbmFibGUgZGVmYXVsdCBmb3IgQnJvdGxpIGNvbXByZXNzaW9uLlxuICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20va29hanMvY29tcHJlc3MvaXNzdWVzLzEyNlxuICAgICAgICAgIGJyOiB7XG4gICAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgICAgW3psaWIuY29uc3RhbnRzLkJST1RMSV9QQVJBTV9RVUFMSVRZXTogNFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZ2V0T3B0aW9ucyhhcHAuY29tcHJlc3MpXG4gICAgICApKSlcbiAgICB9XG4gICAgaWYgKGFwcC5ldGFnICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy51c2UoY29uZGl0aW9uYWwoKSlcbiAgICAgIHRoaXMudXNlKGV0YWcoKSlcbiAgICB9XG4gIH1cblxuICBzZXR1cENvbnRyb2xsZXJNaWRkbGV3YXJlKCkge1xuICAgIC8vIE5PVEU6IFRoaXMgaXMgbm90IHBhcnQgb2YgdGhlIGF1dG9tYXRpYyBgc2V0dXBHbG9iYWxNaWRkbGV3YXJlKClgIHNvIHRoYXRcbiAgICAvLyBhcHBzIGNhbiBzZXQgdXAgdGhlIHN0YXRpYyBzZXJ2aW5nIG9mIGFzc2V0cyBiZWZvcmUgaW5zdGFsbGluZyB0aGVcbiAgICAvLyBzZXNzaW9uIGFuZCBwYXNzcG9ydCBtaWRkbGV3YXJlLiBJdCBpcyBjYWxsZWQgZnJvbSBgYWRkQ29udHJvbGxlcigpYC5cbiAgICAvLyBVc2UgYSBmbGFnIHRvIG9ubHkgaW5zdGFsbCB0aGUgbWlkZGxld2FyZSBvbmNlOlxuICAgIGlmICghdGhpcy5oYXNDb250cm9sbGVyTWlkZGxld2FyZSkge1xuICAgICAgY29uc3QgeyBhcHAgfSA9IHRoaXMuY29uZmlnXG4gICAgICAvLyBTZXF1ZW5jZSBpcyBpbXBvcnRhbnQ6XG4gICAgICAvLyAxLiBib2R5IHBhcnNlclxuICAgICAgdGhpcy51c2UoYm9keVBhcnNlcihnZXRPcHRpb25zKGFwcC5ib2R5UGFyc2VyKSkpXG4gICAgICAvLyAyLiBmaW5kIHJvdXRlIGZyb20gcm91dGVzIGluc3RhbGxlZCBieSBjb250cm9sbGVycy5cbiAgICAgIHRoaXMudXNlKGZpbmRSb3V0ZSh0aGlzLnJvdXRlcikpXG4gICAgICAvLyAzLiByZXNwZWN0IHRyYW5zYWN0ZWQgc2V0dGluZ3MsIGNyZWF0ZSBhbmQgaGFuZGxlIHRyYW5zYWN0aW9ucy5cbiAgICAgIHRoaXMudXNlKGNyZWF0ZVRyYW5zYWN0aW9uKCkpXG4gICAgICAvLyA0LiBzZXNzaW9uXG4gICAgICBpZiAoYXBwLnNlc3Npb24pIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIG1vZGVsQ2xhc3MsXG4gICAgICAgICAgLi4ub3B0aW9uc1xuICAgICAgICB9ID0gZ2V0T3B0aW9ucyhhcHAuc2Vzc2lvbilcbiAgICAgICAgaWYgKG1vZGVsQ2xhc3MpIHtcbiAgICAgICAgICAvLyBDcmVhdGUgYSBDb250ZXh0U3RvcmUgdGhhdCByZXNvbHZlZCB0aGUgc3BlY2lmaWVkIG1vZGVsIGNsYXNzLFxuICAgICAgICAgIC8vIHVzZXMgaXQgdG8gcGVyc2lzdCBhbmQgcmV0cmlldmUgdGhlIHNlc3Npb24sIGFuZCBhdXRvbWF0aWNhbGx5XG4gICAgICAgICAgLy8gYmluZHMgYWxsIGRiIG9wZXJhdGlvbnMgdG8gYGN0eC50cmFuc2FjdGlvbmAsIGlmIGl0IGlzIHNldC5cbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcFxuICAgICAgICAgIG9wdGlvbnMuQ29udGV4dFN0b3JlID0gU2Vzc2lvblN0b3JlKG1vZGVsQ2xhc3MpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51c2Uoc2Vzc2lvbihvcHRpb25zLCB0aGlzKSlcbiAgICAgIH1cbiAgICAgIC8vIDUuIHBhc3Nwb3J0XG4gICAgICBpZiAoYXBwLnBhc3Nwb3J0KSB7XG4gICAgICAgIHRoaXMudXNlKHBhc3Nwb3J0LmluaXRpYWxpemUoKSlcbiAgICAgICAgaWYgKGFwcC5zZXNzaW9uKSB7XG4gICAgICAgICAgdGhpcy51c2UocGFzc3BvcnQuc2Vzc2lvbigpKVxuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlKGhhbmRsZVVzZXIoKSlcbiAgICAgIH1cblxuICAgICAgLy8gNi4gZmluYWxseSBoYW5kbGUgdGhlIGZvdW5kIHJvdXRlLCBvciBzZXQgc3RhdHVzIC8gYWxsb3cgYWNjb3JkaW5nbHkuXG4gICAgICB0aGlzLnVzZShoYW5kbGVSb3V0ZSgpKVxuICAgICAgdGhpcy5oYXNDb250cm9sbGVyTWlkZGxld2FyZSA9IHRydWVcbiAgICB9XG4gIH1cblxuICBzZXR1cExvZ2dlcigpIHtcbiAgICBjb25zdCB7IGVyciwgcmVxLCByZXMgfSA9IHBpbm8uc3RkU2VyaWFsaXplcnNcbiAgICAvLyBPbmx5IGluY2x1ZGUgYGlkYCBmcm9tIHRoZSB1c2VyLCB0byBub3QgaW5hZHZlcnRlbnRseSBsb2cgUElJLlxuICAgIGNvbnN0IHVzZXIgPSB1c2VyID0+ICh7IGlkOiB1c2VyLmlkIH0pXG4gICAgY29uc3Qgc2VyaWFsaXplcnMgPSB7IGVyciwgcmVxLCByZXMsIHVzZXIgfVxuXG4gICAgY29uc3QgbG9nZ2VyID0gcGlubyhtZXJnZShcbiAgICAgIHtcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgc2VyaWFsaXplcnMsXG4gICAgICAgIHByZXR0eVByaW50OiB7XG4gICAgICAgICAgLy8gTGlzdCBvZiBrZXlzIHRvIGlnbm9yZSBpbiBwcmV0dHkgbW9kZS5cbiAgICAgICAgICBpZ25vcmU6ICdyZXEscmVzLGR1cmF0aW9uTXMsdXNlcixyZXF1ZXN0SWQnLFxuICAgICAgICAgIC8vIFNZUyB0byB1c2Ugc3lzdGVtIHRpbWUgYW5kIG5vdCBVVEMuXG4gICAgICAgICAgdHJhbnNsYXRlVGltZTogJ1NZUzpISDpNTTpzcy5sJ1xuICAgICAgICB9LFxuICAgICAgICAvLyBSZWRhY3QgY29tbW9uIHNlbnNpdGl2ZSBoZWFkZXJzLlxuICAgICAgICByZWRhY3Q6IFtcbiAgICAgICAgICAnKi5oZWFkZXJzW1wiY29va2llXCJdJyxcbiAgICAgICAgICAnKi5oZWFkZXJzW1wic2V0LWNvb2tpZVwiXScsXG4gICAgICAgICAgJyouaGVhZGVyc1tcImF1dGhvcml6YXRpb25cIl0nXG4gICAgICAgIF0sXG4gICAgICAgIGJhc2U6IG51bGwgLy8gbm8gcGlkLGhvc3RuYW1lLG5hbWVcbiAgICAgIH0sXG4gICAgICBnZXRPcHRpb25zKHRoaXMuY29uZmlnLmxvZ2dlcilcbiAgICApKVxuXG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXIuY2hpbGQoeyBuYW1lOiAnYXBwJyB9KVxuICB9XG5cbiAgc2V0dXBLbmV4KCkge1xuICAgIGxldCB7IGtuZXgsIGxvZyB9ID0gdGhpcy5jb25maWdcbiAgICBpZiAoa25leD8uY2xpZW50KSB7XG4gICAgICBjb25zdCBzbmFrZUNhc2VPcHRpb25zID0ga25leC5ub3JtYWxpemVEYk5hbWVzID09PSB0cnVlXG4gICAgICAgID8ge31cbiAgICAgICAgOiBrbmV4Lm5vcm1hbGl6ZURiTmFtZXNcbiAgICAgIGlmIChzbmFrZUNhc2VPcHRpb25zKSB7XG4gICAgICAgIGtuZXggPSB7XG4gICAgICAgICAgLi4ua25leCxcbiAgICAgICAgICAuLi5rbmV4U25ha2VDYXNlTWFwcGVycyhzbmFrZUNhc2VPcHRpb25zKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmtuZXggPSBLbmV4KGtuZXgpXG4gICAgICAvLyBTdXBwb3J0IFBvc3RncmVTUUwgdHlwZSBwYXJzZXIgbWFwcGluZ3MgaW4gdGhlIGNvbmZpZy5cbiAgICAgIGlmIChcbiAgICAgICAga25leC5jbGllbnQgPT09ICdwb3N0Z3Jlc3FsJyAmJlxuICAgICAgICBrbmV4LnR5cGVQYXJzZXJzICYmXG4gICAgICAgIHRoaXMua25leC5jbGllbnQuZHJpdmVyXG4gICAgICApIHtcbiAgICAgICAgZm9yIChjb25zdCBbdHlwZSwgcGFyc2VyXSBvZiBPYmplY3QuZW50cmllcyhrbmV4LnR5cGVQYXJzZXJzKSkge1xuICAgICAgICAgIHRoaXMua25leC5jbGllbnQuZHJpdmVyLnR5cGVzLnNldFR5cGVQYXJzZXIodHlwZSwgcGFyc2VyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG9nLnNxbCkge1xuICAgICAgICB0aGlzLnNldHVwS25leExvZ2dpbmcoKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldHVwS25leExvZ2dpbmcoKSB7XG4gICAgY29uc3Qgc3RhcnRUaW1lcyA9IHt9XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5sb2dnZXIuY2hpbGQoeyBuYW1lOiAnc3FsJyB9KVxuICAgIGZ1bmN0aW9uIGVuZChxdWVyeSwgeyByZXNwb25zZSwgZXJyb3IgfSkge1xuICAgICAgY29uc3QgaWQgPSBxdWVyeS5fX2tuZXhRdWVyeVVpZFxuICAgICAgY29uc3QgZGlmZiA9IHByb2Nlc3MuaHJ0aW1lKHN0YXJ0VGltZXNbaWRdKVxuICAgICAgY29uc3QgZHVyYXRpb24gPSBkaWZmWzBdICogMWUzICsgZGlmZlsxXSAvIDFlNlxuICAgICAgZGVsZXRlIHN0YXJ0VGltZXNbaWRdXG4gICAgICBjb25zdCB7IHNxbCwgYmluZGluZ3MgfSA9IHF1ZXJ5XG4gICAgICByZXNwb25zZSA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgT2JqZWN0LmVudHJpZXMocmVzcG9uc2UpLmZpbHRlcihcbiAgICAgICAgICAoW2tleV0pID0+ICFrZXkuc3RhcnRzV2l0aCgnXycpXG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIGxvZ2dlci5pbmZvKHsgZHVyYXRpb24sIGJpbmRpbmdzLCByZXNwb25zZSwgZXJyb3IgfSwgc3FsKVxuICAgIH1cblxuICAgIHRoaXMua25leFxuICAgICAgLm9uKCdxdWVyeScsIHF1ZXJ5ID0+IHtcbiAgICAgICAgc3RhcnRUaW1lc1txdWVyeS5fX2tuZXhRdWVyeVVpZF0gPSBwcm9jZXNzLmhydGltZSgpXG4gICAgICB9KVxuICAgICAgLm9uKCdxdWVyeS1yZXNwb25zZScsIChyZXNwb25zZSwgcXVlcnkpID0+IHtcbiAgICAgICAgZW5kKHF1ZXJ5LCB7IHJlc3BvbnNlIH0pXG4gICAgICB9KVxuICAgICAgLm9uKCdxdWVyeS1lcnJvcicsIChlcnJvciwgcXVlcnkpID0+IHtcbiAgICAgICAgZW5kKHF1ZXJ5LCB7IGVycm9yIH0pXG4gICAgICB9KVxuICB9XG5cbiAgbm9ybWFsaXplSWRlbnRpZmllcihpZGVudGlmaWVyKSB7XG4gICAgcmV0dXJuIHRoaXMua25leC5jbGllbnQud3JhcElkZW50aWZpZXIoaWRlbnRpZmllcikucmVwbGFjZSgvWydgXCJdL2csICcnKVxuICB9XG5cbiAgZGVub3JtYWxpemVJZGVudGlmaWVyKGlkZW50aWZpZXIpIHtcbiAgICBjb25zdCBvYmogPSB0aGlzLmtuZXguY2xpZW50LnBvc3RQcm9jZXNzUmVzcG9uc2UoeyBbaWRlbnRpZmllcl06IDEgfSlcbiAgICByZXR1cm4gT2JqZWN0LmtleXMob2JqKVswXVxuICB9XG5cbiAgbm9ybWFsaXplUGF0aChwYXRoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmFwcC5ub3JtYWxpemVQYXRocyA/IGh5cGhlbmF0ZShwYXRoKSA6IHBhdGhcbiAgfVxuXG4gIGZvcm1hdEVycm9yKGVycikge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnIudG9KU09OXG4gICAgICA/IGZvcm1hdEpzb24oZXJyLnRvSlNPTigpKVxuICAgICAgOiBlcnIubWVzc2FnZSB8fCBlcnJcbiAgICBjb25zdCBzdHIgPSBgJHtlcnIubmFtZX06ICR7bWVzc2FnZX1gXG4gICAgcmV0dXJuIGVyci5zdGFjayAmJiB0aGlzLmNvbmZpZy5sb2cuZXJyb3JzPy5zdGFjayAhPT0gZmFsc2VcbiAgICAgID8gYCR7c3RyfVxcbiR7ZXJyLnN0YWNrLnNwbGl0KC9cXG58XFxyXFxufFxcci8pLnNsaWNlKDEpLmpvaW4ob3MuRU9MKX1gXG4gICAgICA6IHN0clxuICB9XG5cbiAgbG9nRXJyb3IoZXJyLCBjdHgpIHtcbiAgICBpZiAoIWVyci5leHBvc2UgJiYgIXRoaXMuc2lsZW50KSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB0ZXh0ID0gdGhpcy5mb3JtYXRFcnJvcihlcnIpXG4gICAgICAgIGNvbnN0IGxldmVsID1cbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBSZXNwb25zZUVycm9yICYmIGVyci5zdGF0dXMgPCA1MDAgPyAnaW5mbycgOiAnZXJyb3InXG4gICAgICAgIGNvbnN0IGxvZ2dlciA9IGN0eD8ubG9nZ2VyIHx8IHRoaXMubG9nZ2VyXG4gICAgICAgIGxvZ2dlcltsZXZlbF0odGV4dClcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQ291bGQgbm90IGxvZyBlcnJvcicsIGUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmxvZy5lcnJvcnMgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLm9uKCdlcnJvcicsIHRoaXMubG9nRXJyb3IpXG4gICAgfVxuICAgIGF3YWl0IHRoaXMuZW1pdCgnYmVmb3JlOnN0YXJ0JylcbiAgICBhd2FpdCB0aGlzLmZvckVhY2hTZXJ2aWNlKHNlcnZpY2UgPT4gc2VydmljZS5zdGFydCgpKVxuICAgIGNvbnN0IHtcbiAgICAgIHNlcnZlcjogeyBob3N0LCBwb3J0IH0sXG4gICAgICBlbnZcbiAgICB9ID0gdGhpcy5jb25maWdcbiAgICB0aGlzLnNlcnZlciA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMubGlzdGVuKHBvcnQsIGhvc3QsICgpID0+IHtcbiAgICAgICAgY29uc3QgeyBwb3J0IH0gPSBzZXJ2ZXIuYWRkcmVzcygpXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgICAgICBgJHtlbnZ9IHNlcnZlciBzdGFydGVkIGF0IGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH1gXG4gICAgICAgIClcbiAgICAgICAgcmVzb2x2ZShzZXJ2ZXIpXG4gICAgICB9KVxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgVW5hYmxlIHRvIHN0YXJ0IHNlcnZlciBhdCBodHRwOi8vJHtob3N0fToke3BvcnR9YCkpXG4gICAgICB9XG4gICAgfSlcbiAgICBhd2FpdCB0aGlzLmVtaXQoJ2FmdGVyOnN0YXJ0JylcbiAgfVxuXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgYXdhaXQgdGhpcy5lbWl0KCdiZWZvcmU6c3RvcCcpXG4gICAgdGhpcy5zZXJ2ZXIgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCB7IHNlcnZlciB9ID0gdGhpc1xuICAgICAgaWYgKHNlcnZlcikge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoZXJyID0+IHtcbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZWplY3QoZXJyKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKG51bGwpXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAvLyBIYWNrIHRvIG1ha2Ugc3VyZSB0aGF0IHdlIGNsb3NlIHRoZSBzZXJ2ZXIsXG4gICAgICAgIC8vICBldmVuIGlmIHNvY2tldHMgYXJlIHN0aWxsIG9wZW4uXG4gICAgICAgIC8vICBUYWtlbiBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zNjgzMDA3Mi5cbiAgICAgICAgLy8gIEEgcHJvcGVyIHNvbHV0aW9uIHdvdWxkIGJlIHRvIHVzZSBhIGxpYnJhcnksIGV4OiBodHRwczovL2dpdGh1Yi5jb20vZ29kYWRkeS90ZXJtaW51c1xuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gc2VydmVyLmVtaXQoJ2Nsb3NlJykpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKCdTZXJ2ZXIgaXMgbm90IHJ1bm5pbmcnKSlcbiAgICAgIH1cbiAgICB9KVxuICAgIGF3YWl0IHRoaXMuZm9yRWFjaFNlcnZpY2Uoc2VydmljZSA9PiBzZXJ2aWNlLnN0b3AoKSlcbiAgICBhd2FpdCB0aGlzLmVtaXQoJ2FmdGVyOnN0b3AnKVxuICAgIGlmICh0aGlzLmNvbmZpZy5sb2cuZXJyb3JzICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy5vZmYoJ2Vycm9yJywgdGhpcy5sb2dFcnJvcilcbiAgICB9XG4gIH1cblxuICBhc3luYyBzdGFydE9yRXhpdCgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zdGFydCgpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmxvZ0Vycm9yKGVycilcbiAgICAgIHByb2Nlc3MuZXhpdCgtMSlcbiAgICB9XG4gIH1cblxuICAvLyBBc3NldHMgaGFuZGxpbmdcblxuICBhc3luYyBjcmVhdGVBc3NldHMoc3RvcmFnZSwgZmlsZXMsIGNvdW50ID0gMCwgdHJ4ID0gbnVsbCkge1xuICAgIGNvbnN0IEFzc2V0TW9kZWwgPSB0aGlzLmdldE1vZGVsKCdBc3NldCcpXG4gICAgaWYgKEFzc2V0TW9kZWwpIHtcbiAgICAgIGNvbnN0IGFzc2V0cyA9IGZpbGVzLm1hcChmaWxlID0+ICh7XG4gICAgICAgIGtleTogZmlsZS5rZXksXG4gICAgICAgIGZpbGUsXG4gICAgICAgIHN0b3JhZ2U6IHN0b3JhZ2UubmFtZSxcbiAgICAgICAgY291bnRcbiAgICAgIH0pKVxuICAgICAgcmV0dXJuIEFzc2V0TW9kZWxcbiAgICAgICAgLnF1ZXJ5KHRyeClcbiAgICAgICAgLmluc2VydChhc3NldHMpXG4gICAgfVxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICBhc3luYyBoYW5kbGVBZGRkZWRBbmRSZW1vdmVkQXNzZXRzKFxuICAgIHN0b3JhZ2UsXG4gICAgYWRkZWRGaWxlcyxcbiAgICByZW1vdmVkRmlsZXMsXG4gICAgdHJ4ID0gbnVsbFxuICApIHtcbiAgICBjb25zdCB7XG4gICAgICBhc3NldHM6IHtcbiAgICAgICAgY2xlYW51cFRpbWVUaHJlc2hvbGQgPSAwXG4gICAgICB9ID0ge31cbiAgICB9ID0gdGhpcy5jb25maWdcbiAgICAvLyBPbmx5IHJlbW92ZSB1bnVzZWQgYXNzZXRzIHRoYXQgaGF2ZW4ndCBzZWVuIGNoYW5nZXMgZm9yIGdpdmVuIHRpbWVmcmFtZS5cbiAgICBjb25zdCB0aW1lVGhyZXNob2xkID0gaXNTdHJpbmcoY2xlYW51cFRpbWVUaHJlc2hvbGQpXG4gICAgICA/IHBhcnNlRHVyYXRpb24oY2xlYW51cFRpbWVUaHJlc2hvbGQpXG4gICAgICA6IGNsZWFudXBUaW1lVGhyZXNob2xkXG5cbiAgICBjb25zdCBpbXBvcnRlZEZpbGVzID0gW11cbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICBpbXBvcnRlZEZpbGVzLnB1c2goXG4gICAgICAgIC4uLmF3YWl0IHRoaXMuYWRkRm9yZWlnbkFzc2V0cyhzdG9yYWdlLCBhZGRlZEZpbGVzLCB0cngpXG4gICAgICApXG4gICAgICBpZiAoXG4gICAgICAgIGFkZGVkRmlsZXMubGVuZ3RoID4gMCB8fFxuICAgICAgICByZW1vdmVkRmlsZXMubGVuZ3RoID4gMFxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGNoYW5nZUNvdW50ID0gKGZpbGVzLCBpbmNyZW1lbnQpID0+IChcbiAgICAgICAgICBmaWxlcy5sZW5ndGggPiAwICYmXG4gICAgICAgICAgQXNzZXRNb2RlbC5xdWVyeSh0cngpXG4gICAgICAgICAgICAud2hlcmVJbigna2V5JywgZmlsZXMubWFwKGZpbGUgPT4gZmlsZS5rZXkpKVxuICAgICAgICAgICAgLmluY3JlbWVudCgnY291bnQnLCBpbmNyZW1lbnQpXG4gICAgICAgIClcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIGNoYW5nZUNvdW50KGFkZGVkRmlsZXMsIDEpLFxuICAgICAgICAgIGNoYW5nZUNvdW50KHJlbW92ZWRGaWxlcywgLTEpXG4gICAgICAgIF0pXG4gICAgICAgIGlmICh0aW1lVGhyZXNob2xkID4gMCkge1xuICAgICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgICAvLyBEb24ndCBwYXNzIGB0cnhgIGhlcmUsIGFzIHdlIHdhbnQgdGhpcyBkZWxheWVkIGV4ZWN1dGlvbiB0b1xuICAgICAgICAgICAgLy8gY3JlYXRlIGl0cyBvd24gdHJhbnNhY3Rpb24uXG4gICAgICAgICAgICAoKSA9PiB0aGlzLnJlbGVhc2VVbnVzZWRBc3NldHModGltZVRocmVzaG9sZCksXG4gICAgICAgICAgICB0aW1lVGhyZXNob2xkXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBBbHNvIGV4ZWN1dGUgcmVsZWFzZVVudXNlZEFzc2V0cygpIGltbWVkaWF0ZWx5IGluIHRoZSBzYW1lXG4gICAgICAvLyB0cmFuc2FjdGlvbiwgdG8gcG90ZW50aWFsbHkgY2xlYW4gdXAgb3RoZXIgcGVuZGluZyBhc3NldHMuXG4gICAgICBhd2FpdCB0aGlzLnJlbGVhc2VVbnVzZWRBc3NldHModGltZVRocmVzaG9sZCwgdHJ4KVxuICAgICAgcmV0dXJuIGltcG9ydGVkRmlsZXNcbiAgICB9XG4gIH1cblxuICBhc3luYyBhZGRGb3JlaWduQXNzZXRzKHN0b3JhZ2UsIGZpbGVzLCB0cnggPSBudWxsKSB7XG4gICAgY29uc3QgaW1wb3J0ZWRGaWxlcyA9IFtdXG4gICAgY29uc3QgQXNzZXRNb2RlbCA9IHRoaXMuZ2V0TW9kZWwoJ0Fzc2V0JylcbiAgICBpZiAoQXNzZXRNb2RlbCkge1xuICAgICAgLy8gRmluZCBtaXNzaW5nIGFzc2V0cyAoY29waWVkIGZyb20gYW5vdGhlciBzeXN0ZW0pLCBhbmQgYWRkIHRoZW0uXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZmlsZXMubWFwKGFzeW5jIGZpbGUgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzc2V0ID0gYXdhaXQgQXNzZXRNb2RlbC5xdWVyeSh0cngpLmZpbmRPbmUoJ2tleScsIGZpbGUua2V5KVxuICAgICAgICAgIGlmICghYXNzZXQpIHtcbiAgICAgICAgICAgIGlmIChmaWxlLmRhdGEgfHwgZmlsZS51cmwpIHtcbiAgICAgICAgICAgICAgbGV0IHsgZGF0YSB9ID0gZmlsZVxuICAgICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgICAgICAgICAgICBgJHtcbiAgICAgICAgICAgICAgICAgICAgcGljby5yZWQoJ0lORk86JylcbiAgICAgICAgICAgICAgICAgIH0gQXNzZXQgJHtcbiAgICAgICAgICAgICAgICAgICAgcGljby5ncmVlbihgJyR7ZmlsZS5uYW1lfSdgKVxuICAgICAgICAgICAgICAgICAgfSBpcyBmcm9tIGEgZm9yZWlnbiBzb3VyY2UsIGZldGNoaW5nIGZyb20gJHtcbiAgICAgICAgICAgICAgICAgICAgcGljby5ncmVlbihgJyR7ZmlsZS51cmx9J2ApXG4gICAgICAgICAgICAgICAgICB9IGFuZCBhZGRpbmcgdG8gc3RvcmFnZSAke1xuICAgICAgICAgICAgICAgICAgICBwaWNvLmdyZWVuKGAnJHtzdG9yYWdlLm5hbWV9J2ApXG4gICAgICAgICAgICAgICAgICB9Li4uYFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnZ2V0JyxcbiAgICAgICAgICAgICAgICAgIHVybDogZmlsZS51cmwsXG4gICAgICAgICAgICAgICAgICByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcidcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIGRhdGEgPSByZXNwb25zZS5kYXRhXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgaW1wb3J0ZWRGaWxlID0gYXdhaXQgc3RvcmFnZS5hZGRGaWxlKGZpbGUsIGRhdGEpXG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQXNzZXRzKHN0b3JhZ2UsIFtpbXBvcnRlZEZpbGVdLCAwLCB0cngpXG4gICAgICAgICAgICAgIC8vIE1lcmdlIGJhY2sgdGhlIGNoYW5nZWQgZmlsZSBwcm9wZXJ0aWVzIGludG8gdGhlIGFjdHVhbCBmaWxlc1xuICAgICAgICAgICAgICAvLyBvYmplY3QsIHNvIHRoYXQgdGhlIGRhdGEgZnJvbSB0aGUgc3RhdGljIG1vZGVsIGhvb2sgY2FuIGJlIHVzZWRcbiAgICAgICAgICAgICAgLy8gZGlyZWN0bHkgZm9yIHRoZSBhY3R1YWwgcnVubmluZyBxdWVyeS5cbiAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihmaWxlLCBpbXBvcnRlZEZpbGUpXG4gICAgICAgICAgICAgIGltcG9ydGVkRmlsZXMucHVzaChpbXBvcnRlZEZpbGUpXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXRFcnJvcihcbiAgICAgICAgICAgICAgICBgVW5hYmxlIHRvIGltcG9ydCBhc3NldCBmcm9tIGZvcmVpZ24gc291cmNlOiAnJHtcbiAgICAgICAgICAgICAgICAgIGZpbGUubmFtZVxuICAgICAgICAgICAgICAgIH0nICgnJHtcbiAgICAgICAgICAgICAgICAgIGZpbGUua2V5XG4gICAgICAgICAgICAgICAgfScpYFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFzc2V0IGlzIGZyb20gYSBmb3JlaWduIHNvdXJjZSwgYnV0IHdhcyBhbHJlYWR5IGltcG9ydGVkIGFuZCBjYW5cbiAgICAgICAgICAgIC8vIGJlIHJldXNlZC4gU2VlIGFib3ZlIGZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGlzIG1lcmdlLlxuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihmaWxlLCBhc3NldC5maWxlKVxuICAgICAgICAgICAgLy8gTk9URTogTm8gbmVlZCB0byBhZGQgYGZpbGVgIHRvIGBpbXBvcnRlZEZpbGVzYCwgc2luY2UgaXQnc1xuICAgICAgICAgICAgLy8gYWxyZWFkeSBiZWVuIGltcG9ydGVkIHRvIHRoZSBzdG9yYWdlIGJlZm9yZS5cbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiBpbXBvcnRlZEZpbGVzXG4gIH1cblxuICBhc3luYyBoYW5kbGVNb2RpZmllZEFzc2V0cyhzdG9yYWdlLCBmaWxlcywgdHJ4ID0gbnVsbCkge1xuICAgIGNvbnN0IG1vZGlmaWVkRmlsZXMgPSBbXVxuICAgIGNvbnN0IEFzc2V0TW9kZWwgPSB0aGlzLmdldE1vZGVsKCdBc3NldCcpXG4gICAgaWYgKEFzc2V0TW9kZWwpIHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWxlcy5tYXAoYXN5bmMgZmlsZSA9PiB7XG4gICAgICAgICAgaWYgKGZpbGUuZGF0YSkge1xuICAgICAgICAgICAgY29uc3QgYXNzZXQgPSBhd2FpdCBBc3NldE1vZGVsLnF1ZXJ5KHRyeCkuZmluZE9uZSgna2V5JywgZmlsZS5rZXkpXG4gICAgICAgICAgICBpZiAoYXNzZXQpIHtcbiAgICAgICAgICAgICAgY29uc3QgY2hhbmdlZEZpbGUgPSBhd2FpdCBzdG9yYWdlLmFkZEZpbGUoZmlsZSwgZmlsZS5kYXRhKVxuICAgICAgICAgICAgICAvLyBNZXJnZSBiYWNrIHRoZSBjaGFuZ2VkIGZpbGUgcHJvcGVydGllcyBpbnRvIHRoZSBhY3R1YWwgZmlsZXNcbiAgICAgICAgICAgICAgLy8gb2JqZWN0LCBzbyB0aGF0IHRoZSBkYXRhIGZyb20gdGhlIHN0YXRpYyBtb2RlbCBob29rIGNhbiBiZSB1c2VkXG4gICAgICAgICAgICAgIC8vIGRpcmVjdGx5IGZvciB0aGUgYWN0dWFsIHJ1bm5pbmcgcXVlcnkuXG4gICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZmlsZSwgY2hhbmdlZEZpbGUpXG4gICAgICAgICAgICAgIG1vZGlmaWVkRmlsZXMucHVzaChjaGFuZ2VkRmlsZSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBBc3NldEVycm9yKFxuICAgICAgICAgICAgICAgIGBVbmFibGUgdG8gdXBkYXRlIG1vZGlmaWVkIGFzc2V0IGZyb20gbWVtb3J5IHNvdXJjZTogJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLm5hbWVcbiAgICAgICAgICAgICAgICB9JyAoJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLmtleVxuICAgICAgICAgICAgICAgIH0nKWBcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIG1vZGlmaWVkRmlsZXNcbiAgfVxuXG4gIGFzeW5jIHJlbGVhc2VVbnVzZWRBc3NldHModGltZVRocmVzaG9sZCA9IDAsIHRyeCA9IG51bGwpIHtcbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICByZXR1cm4gQXNzZXRNb2RlbC50cmFuc2FjdGlvbih0cngsIGFzeW5jIHRyeCA9PiB7XG4gICAgICAgIC8vIERldGVybWluZSB0aGUgdGltZSB0aHJlc2hvbGQgaW4gSlMgaW5zdGVhZCBvZiBTUUwsIGFzIHRoZXJlIGlzIG5vXG4gICAgICAgIC8vIGVhc3kgY3Jvc3MtU1FMIHdheSB0byBkbyBgbm93KCkgLSBpbnRlcnZhbCBYIGhvdXJzYDpcbiAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKClcbiAgICAgICAgZGF0ZS5zZXRNaWxsaXNlY29uZHMoZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSAtIHRpbWVUaHJlc2hvbGQpXG4gICAgICAgIGNvbnN0IG9ycGhhbmVkQXNzZXRzID0gYXdhaXQgQXNzZXRNb2RlbFxuICAgICAgICAgIC5xdWVyeSh0cngpXG4gICAgICAgICAgLndoZXJlKCdjb3VudCcsIDApXG4gICAgICAgICAgLmFuZFdoZXJlKCd1cGRhdGVkQXQnLCAnPD0nLCBkYXRlKVxuICAgICAgICAgIC8vIFByb3RlY3QgZnJlc2hseSBjcmVhdGVkIGFzc2V0cyBmcm9tIGJlaW5nIGRlbGV0ZWQgYWdhaW4gcmlnaHQgYXdheSxcbiAgICAgICAgICAvLyAuZS5nLiB3aGVuIGBjb25maWcuYXNzZXRzLmNsZWFudXBUaW1lVGhyZXNob2xkID0gMGBcbiAgICAgICAgICAuYW5kV2hlcmUoJ3VwZGF0ZWRBdCcsICc+JywgcmVmKCdjcmVhdGVkQXQnKSlcbiAgICAgICAgaWYgKG9ycGhhbmVkQXNzZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBvcnBoYW5lZEtleXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIG9ycGhhbmVkQXNzZXRzLm1hcChhc3luYyBhc3NldCA9PiB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRTdG9yYWdlKGFzc2V0LnN0b3JhZ2UpLnJlbW92ZUZpbGUoYXNzZXQuZmlsZSlcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpXG4gICAgICAgICAgICAgICAgYXNzZXQuZXJyb3IgPSBlcnJvclxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBhc3NldC5rZXlcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKVxuICAgICAgICAgIGF3YWl0IEFzc2V0TW9kZWxcbiAgICAgICAgICAgIC5xdWVyeSh0cngpXG4gICAgICAgICAgICAuZGVsZXRlKClcbiAgICAgICAgICAgIC53aGVyZUluKCdrZXknLCBvcnBoYW5lZEtleXMpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9ycGhhbmVkQXNzZXRzXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vLyBPdmVycmlkZSBLb2EncyBldmVudHMgd2l0aCBvdXIgb3duIEV2ZW50RW1pdHRlciB0aGF0IGFkZHMgc3VwcG9ydCBmb3Jcbi8vIGFzeW5jaHJvbm91cyBldmVudHMuXG5FdmVudEVtaXR0ZXIubWl4aW4oQXBwbGljYXRpb24ucHJvdG90eXBlKVxuXG5mdW5jdGlvbiBnZXRPcHRpb25zKG9wdGlvbnMpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KG9wdGlvbnMpID8gb3B0aW9ucyA6IHt9XG59XG4iXX0=