@ditojs/server 0.274.0 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/package.json +25 -43
  2. package/src/app/Application.js +110 -112
  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 +164 -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) {
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcHAvQXBwbGljYXRpb24uanMiXSwibmFtZXMiOlsiQXBwbGljYXRpb24iLCJLb2EiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsInZhbGlkYXRvciIsInJvdXRlciIsImV2ZW50cyIsIm1pZGRsZXdhcmUiLCJtb2RlbHMiLCJzZXJ2aWNlcyIsImNvbnRyb2xsZXJzIiwiX3NldHVwRW1pdHRlciIsImFwcCIsImtleXMiLCJsb2ciLCJyZXN0Iiwic2lsZW50IiwicHJvY2VzcyIsImVudiIsIkRJVE9fU0lMRU5UIiwicHJveHkiLCJWYWxpZGF0b3IiLCJSb3V0ZXIiLCJzdG9yYWdlcyIsIk9iamVjdCIsImNyZWF0ZSIsImhhc0NvbnRyb2xsZXJNaWRkbGV3YXJlIiwic2V0dXBMb2dnZXIiLCJzZXR1cEtuZXgiLCJzZXR1cEdsb2JhbE1pZGRsZXdhcmUiLCJ1c2UiLCJhZGRTdG9yYWdlcyIsImFkZE1vZGVscyIsImFkZFNlcnZpY2VzIiwiYWRkQ29udHJvbGxlcnMiLCJhZGRSb3V0ZSIsInZlcmIiLCJwYXRoIiwidHJhbnNhY3RlZCIsImhhbmRsZXJzIiwiY29udHJvbGxlciIsImFjdGlvbiIsImhhbmRsZXIiLCJsZW5ndGgiLCJyb3V0ZSIsIm1vZGVsQ2xhc3MiLCJ2YWx1ZXMiLCJhZGRNb2RlbCIsInNvcnRNb2RlbHMiLCJzb3J0ZWRNb2RlbHMiLCJmaWx0ZXIiLCJuYW1lIiwic2V0dXAiLCJrbmV4IiwiaW5pdGlhbGl6ZSIsImFkZFNjaGVtYSIsImdldEpzb25TY2hlbWEiLCJzY2hlbWEiLCJyZWxhdGlvbnMiLCJzaG91bGRMb2ciLCJvcHRpb24iLCJpbmNsdWRlcyIsImRhdGEiLCJyZWxhdGlvbk1hcHBpbmdzIiwidmFsdWUiLCJNb2RlbCIsImlzUHJvdG90eXBlT2YiLCJjb25zb2xlIiwiaW5mbyIsInBpY28iLCJ5ZWxsb3ciLCJib2xkIiwidXRpbCIsImluc3BlY3QiLCJjb2xvcnMiLCJkZXB0aCIsIm1heEFycmF5TGVuZ3RoIiwiRXJyb3IiLCJzb3J0QnlSZWxhdGlvbnMiLCJsaXN0IiwiY29sbGVjdGVkIiwiZXhjbHVkZWQiLCJyZWxhdGlvbiIsImdldFJlbGF0aW9ucyIsIkJlbG9uZ3NUb09uZVJlbGF0aW9uIiwicmVsYXRlZE1vZGVsQ2xhc3MiLCJqb2luVGFibGVNb2RlbENsYXNzIiwicmVsYXRlZCIsInJldmVyc2UiLCJyZWR1Y2UiLCJnZXRNb2RlbCIsImVuZHNXaXRoIiwiZmluZE1vZGVsIiwiY2FsbGJhY2siLCJmaW5kIiwic2VydmljZSIsImVudHJpZXMiLCJhZGRTZXJ2aWNlIiwiU2VydmljZSIsInVuZGVmaW5lZCIsImdldFNlcnZpY2UiLCJmaW5kU2VydmljZSIsImZvckVhY2hTZXJ2aWNlIiwiUHJvbWlzZSIsImFsbCIsIm1hcCIsIm5hbWVzcGFjZSIsImtleSIsImFkZENvbnRyb2xsZXIiLCJzZXR1cENvbnRyb2xsZXJNaWRkbGV3YXJlIiwiQ29udHJvbGxlciIsInVybCIsImNvbXBvc2UiLCJnZXRDb250cm9sbGVyIiwiZmluZENvbnRyb2xsZXIiLCJnZXRBZG1pbkNvbnRyb2xsZXIiLCJBZG1pbkNvbnRyb2xsZXIiLCJnZXRBZG1pblZ1ZUNvbmZpZyIsImdldFZ1ZUNvbmZpZyIsImdldEFzc2V0Q29uZmlnIiwibm9ybWFsaXplRGJOYW1lcyIsImFzc2V0Q29uZmlnIiwibW9kZWxOYW1lIiwiYXNzZXRzIiwiZGVmaW5pdGlvbiIsIm5vcm1hbGl6ZWRNb2RlbE5hbWUiLCJub3JtYWxpemVJZGVudGlmaWVyIiwiY29udmVydGVkQXNzZXRzIiwiYXNzZXREYXRhUGF0aCIsInByb3BlcnR5IiwibmVzdGVkRGF0YVBhdGgiLCJpbmRleCIsImdldFByb3BlcnR5T3JSZWxhdGlvbkF0RGF0YVBhdGgiLCJub3JtYWxpemVkTmFtZSIsImRhdGFQYXRoIiwiYXNzZXRDb25maWdzIiwiYWRkU3RvcmFnZSIsInN0b3JhZ2UiLCJzdG9yYWdlQ2xhc3MiLCJTdG9yYWdlIiwiZ2V0IiwidHlwZSIsImdldFN0b3JhZ2UiLCJjb21waWxlVmFsaWRhdG9yIiwianNvblNjaGVtYSIsIm9wdGlvbnMiLCJjb21waWxlIiwiY29tcGlsZVBhcmFtZXRlcnNWYWxpZGF0b3IiLCJwYXJhbWV0ZXJzIiwiZGF0YU5hbWUiLCJwcm9wZXJ0aWVzIiwiYWRkUGFyYW1ldGVyIiwicHVzaCIsIm1lbWJlciIsImFzT2JqZWN0IiwidmFsaWRhdGUiLCJjb2VyY2VUeXBlcyIsImN0eCIsImNhbGwiLCJjcmVhdGVWYWxpZGF0aW9uRXJyb3IiLCJtZXNzYWdlIiwiZXJyb3JzIiwianNvbiIsIlZhbGlkYXRpb25FcnJvciIsInBhcnNlRXJyb3JzIiwiY3JlYXRlRGF0YWJhc2VFcnJvciIsImVycm9yIiwic3FsIiwibWF0Y2giLCJEYXRhYmFzZUVycm9yIiwibG9nZ2VyIiwicmVzcG9uc2VUaW1lIiwiZ2V0T3B0aW9ucyIsInJlcXVlc3RzIiwiaGVsbWV0IiwiY29ycyIsImNvbXByZXNzIiwiYnIiLCJwYXJhbXMiLCJ6bGliIiwiY29uc3RhbnRzIiwiQlJPVExJX1BBUkFNX1FVQUxJVFkiLCJldGFnIiwiYm9keVBhcnNlciIsInNlc3Npb24iLCJDb250ZXh0U3RvcmUiLCJwYXNzcG9ydCIsImVyciIsInJlcSIsInJlcyIsInBpbm8iLCJzdGRTZXJpYWxpemVycyIsInVzZXIiLCJpZCIsInNlcmlhbGl6ZXJzIiwibGV2ZWwiLCJwcmV0dHlQcmludCIsImlnbm9yZSIsInRyYW5zbGF0ZVRpbWUiLCJyZWRhY3QiLCJiYXNlIiwiY2hpbGQiLCJjbGllbnQiLCJzbmFrZUNhc2VPcHRpb25zIiwidHlwZVBhcnNlcnMiLCJwYXJzZXIiLCJkcml2ZXIiLCJ0eXBlcyIsInNldFR5cGVQYXJzZXIiLCJzZXR1cEtuZXhMb2dnaW5nIiwic3RhcnRUaW1lcyIsImVuZCIsInF1ZXJ5IiwicmVzcG9uc2UiLCJfX2tuZXhRdWVyeVVpZCIsImRpZmYiLCJocnRpbWUiLCJkdXJhdGlvbiIsImJpbmRpbmdzIiwiZnJvbUVudHJpZXMiLCJzdGFydHNXaXRoIiwib24iLCJpZGVudGlmaWVyIiwid3JhcElkZW50aWZpZXIiLCJyZXBsYWNlIiwiZGVub3JtYWxpemVJZGVudGlmaWVyIiwib2JqIiwicG9zdFByb2Nlc3NSZXNwb25zZSIsIm5vcm1hbGl6ZVBhdGgiLCJub3JtYWxpemVQYXRocyIsImZvcm1hdEVycm9yIiwidG9KU09OIiwic3RyIiwic3RhY2siLCJzcGxpdCIsInNsaWNlIiwiam9pbiIsIm9zIiwiRU9MIiwibG9nRXJyb3IiLCJleHBvc2UiLCJ0ZXh0IiwiUmVzcG9uc2VFcnJvciIsInN0YXR1cyIsImUiLCJzdGFydCIsImVtaXQiLCJzZXJ2ZXIiLCJob3N0IiwicG9ydCIsInJlc29sdmUiLCJyZWplY3QiLCJsaXN0ZW4iLCJhZGRyZXNzIiwic3RvcCIsImNsb3NlIiwic2V0SW1tZWRpYXRlIiwib2ZmIiwic3RhcnRPckV4aXQiLCJleGl0IiwiY3JlYXRlQXNzZXRzIiwiZmlsZXMiLCJjb3VudCIsInRyeCIsIkFzc2V0TW9kZWwiLCJmaWxlIiwiaW5zZXJ0IiwiaGFuZGxlQWRkZGVkQW5kUmVtb3ZlZEFzc2V0cyIsImFkZGVkRmlsZXMiLCJyZW1vdmVkRmlsZXMiLCJjbGVhbnVwVGltZVRocmVzaG9sZCIsInRpbWVUaHJlc2hvbGQiLCJpbXBvcnRlZEZpbGVzIiwiYWRkRm9yZWlnbkFzc2V0cyIsImNoYW5nZUNvdW50IiwiaW5jcmVtZW50Iiwid2hlcmVJbiIsInNldFRpbWVvdXQiLCJyZWxlYXNlVW51c2VkQXNzZXRzIiwiYXNzZXQiLCJmaW5kT25lIiwicmVkIiwiZ3JlZW4iLCJheGlvcyIsInJlcXVlc3QiLCJtZXRob2QiLCJyZXNwb25zZVR5cGUiLCJpbXBvcnRlZEZpbGUiLCJhZGRGaWxlIiwiYXNzaWduIiwiQXNzZXRFcnJvciIsImhhbmRsZU1vZGlmaWVkQXNzZXRzIiwibW9kaWZpZWRGaWxlcyIsImNoYW5nZWRGaWxlIiwidHJhbnNhY3Rpb24iLCJkYXRlIiwiRGF0ZSIsInNldE1pbGxpc2Vjb25kcyIsImdldE1pbGxpc2Vjb25kcyIsIm9ycGhhbmVkQXNzZXRzIiwid2hlcmUiLCJhbmRXaGVyZSIsIm9ycGhhbmVkS2V5cyIsInJlbW92ZUZpbGUiLCJkZWxldGUiLCJFdmVudEVtaXR0ZXIiLCJtaXhpbiIsInByb3RvdHlwZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQU1BOztBQUNBOztBQUNBOztBQVNBOztBQUlBOzs7O0FBT08sTUFBTUEsV0FBTixTQUEwQkMsWUFBMUIsQ0FBOEI7QUFDbkNDLEVBQUFBLFdBQVcsQ0FBQztBQUNWQyxJQUFBQSxNQUFNLEdBQUcsRUFEQztBQUVWQyxJQUFBQSxTQUZVO0FBR1ZDLElBQUFBLE1BSFU7QUFJVkMsSUFBQUEsTUFKVTtBQUtWQyxJQUFBQSxVQUxVO0FBTVZDLElBQUFBLE1BTlU7QUFPVkMsSUFBQUEsUUFQVTtBQVFWQyxJQUFBQTtBQVJVLE1BU1IsRUFUTyxFQVNIO0FBQ047O0FBQ0EsU0FBS0MsYUFBTCxDQUFtQkwsTUFBbkI7O0FBQ0EsVUFBTTtBQUVKTSxNQUFBQSxHQUFHLEVBQUU7QUFBRUMsUUFBQUEsSUFBRjtBQUFRLFdBQUdEO0FBQVgsVUFBbUIsRUFGcEI7QUFHSkUsTUFBQUEsR0FBRyxHQUFHLEVBSEY7QUFJSixTQUFHQztBQUpDLFFBS0ZaLE1BTEo7QUFNQSxTQUFLQSxNQUFMLEdBQWM7QUFDWlMsTUFBQUEsR0FEWTtBQUVaRSxNQUFBQSxHQUFHLEVBQUVBLEdBQUcsQ0FBQ0UsTUFBSixJQUFjQyxPQUFPLENBQUNDLEdBQVIsQ0FBWUMsV0FBMUIsR0FBd0MsRUFBeEMsR0FBNkNMLEdBRnRDO0FBR1osU0FBR0M7QUFIUyxLQUFkO0FBS0EsU0FBS0YsSUFBTCxHQUFZQSxJQUFaO0FBQ0EsU0FBS08s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N0I7O0FBT0EsWUFBSUYsY0FBYyxDQUFDaFEsTUFBZixHQUF3QixDQUE1QixFQUErQjtBQUM3QixnQkFBTW1RLFlBQVksR0FBRyxNQUFNdk0sT0FBTyxDQUFDQyxHQUFSLENBQ3pCbU0sY0FBYyxDQUFDbE0sR0FBZixDQUFtQixNQUFNOEssS0FBTixJQUFlO0FBQ2hDLGdCQUFJO0FBQ0Ysb0JBQU0sS0FBS3pJLFVBQUwsQ0FBZ0J5SSxLQUFLLENBQUM5SSxPQUF0QixFQUErQnNLLFVBQS9CLENBQTBDeEIsS0FBSyxDQUFDZCxJQUFoRCxDQUFOO0FBQ0QsYUFGRCxDQUVFLE9BQU9uRyxLQUFQLEVBQWM7QUFDZCxtQkFBS2dGLElBQUwsQ0FBVSxPQUFWLEVBQW1CaEYsS0FBbkI7QUFDQWlILGNBQUFBLEtBQUssQ0FBQ2pILEtBQU4sR0FBY0EsS0FBZDtBQUNEOztBQUNELG1CQUFPaUgsS0FBSyxDQUFDNUssR0FBYjtBQUNELFdBUkQsQ0FEeUIsQ0FBM0I7QUFXQSxnQkFBTTZKLFVBQVUsQ0FDYnBELEtBREcsQ0FDR21ELEdBREgsRUFFSHlDLE1BRkcsR0FHSDVCLE9BSEcsQ0FHSyxLQUhMLEVBR1kwQixZQUhaLENBQU47QUFJRDs7QUFDRCxlQUFPSCxjQUFQO0FBQ0QsT0E5Qk0sQ0FBUDtBQStCRDtBQUNGOztBQS80QmtDOzs7O0FBbzVCckNNLGtCQUFhQyxLQUFiLENBQW1CbFQsV0FBVyxDQUFDbVQsU0FBL0I7O0FBRUEsU0FBU3ZJLFVBQVQsQ0FBb0IzQixPQUFwQixFQUE2QjtBQUMzQixTQUFPLHNCQUFTQSxPQUFULElBQW9CQSxPQUFwQixHQUE4QixFQUFyQztBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEtvYSBmcm9tICdrb2EnXG5pbXBvcnQgS25leCBmcm9tICdrbmV4J1xuaW1wb3J0IHV0aWwgZnJvbSAndXRpbCdcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcydcbmltcG9ydCBwaWNvIGZyb20gJ3BpY29jb2xvcnMnXG5pbXBvcnQgemxpYiBmcm9tICd6bGliJ1xuaW1wb3J0IHBpbm8gZnJvbSAncGlubydcbmltcG9ydCBvcyBmcm9tICdvcydcbmltcG9ydCBwYXJzZUR1cmF0aW9uIGZyb20gJ3BhcnNlLWR1cmF0aW9uJ1xuaW1wb3J0IGJvZHlQYXJzZXIgZnJvbSAna29hLWJvZHlwYXJzZXInXG5pbXBvcnQgY29ycyBmcm9tICdAa29hL2NvcnMnXG5pbXBvcnQgY29tcG9zZSBmcm9tICdrb2EtY29tcG9zZSdcbmltcG9ydCBjb21wcmVzcyBmcm9tICdrb2EtY29tcHJlc3MnXG5pbXBvcnQgY29uZGl0aW9uYWwgZnJvbSAna29hLWNvbmRpdGlvbmFsLWdldCdcbmltcG9ydCBwYXNzcG9ydCBmcm9tICdrb2EtcGFzc3BvcnQnXG5pbXBvcnQgc2Vzc2lvbiBmcm9tICdrb2Etc2Vzc2lvbidcbmltcG9ydCBldGFnIGZyb20gJ2tvYS1ldGFnJ1xuaW1wb3J0IGhlbG1ldCBmcm9tICdrb2EtaGVsbWV0J1xuaW1wb3J0IHJlc3BvbnNlVGltZSBmcm9tICdrb2EtcmVzcG9uc2UtdGltZSdcbmltcG9ydCBSb3V0ZXIgZnJvbSAnQGRpdG9qcy9yb3V0ZXInXG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdAL2xpYidcbmltcG9ydCB7IENvbnRyb2xsZXIsIEFkbWluQ29udHJvbGxlciB9IGZyb20gJ0AvY29udHJvbGxlcnMnXG5pbXBvcnQgeyBTZXJ2aWNlIH0gZnJvbSAnQC9zZXJ2aWNlcydcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAL3N0b3JhZ2UnXG5pbXBvcnQgeyBjb252ZXJ0U2NoZW1hIH0gZnJvbSAnQC9zY2hlbWEnXG5pbXBvcnQgeyBmb3JtYXRKc29uIH0gZnJvbSAnQC91dGlscydcbmltcG9ydCB7XG4gIFJlc3BvbnNlRXJyb3IsXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgRGF0YWJhc2VFcnJvcixcbiAgQXNzZXRFcnJvclxufSBmcm9tICdAL2Vycm9ycydcbmltcG9ydCBTZXNzaW9uU3RvcmUgZnJvbSAnLi9TZXNzaW9uU3RvcmUnXG5pbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tICcuL1ZhbGlkYXRvcidcbmltcG9ydCB7XG4gIGF0dGFjaExvZ2dlcixcbiAgY3JlYXRlVHJhbnNhY3Rpb24sXG4gIGZpbmRSb3V0ZSxcbiAgaGFuZGxlRXJyb3IsXG4gIGhhbmRsZVJvdXRlLFxuICBoYW5kbGVVc2VyLFxuICBsb2dSZXF1ZXN0c1xufSBmcm9tICdAL21pZGRsZXdhcmUnXG5pbXBvcnQge1xuICBpc0FycmF5LCBpc09iamVjdCwgaXNTdHJpbmcsIGFzQXJyYXksIGlzUGxhaW5PYmplY3QsIGh5cGhlbmF0ZSwgY2xvbmUsIG1lcmdlLFxuICBwYXJzZURhdGFQYXRoLCBub3JtYWxpemVEYXRhUGF0aFxufSBmcm9tICdAZGl0b2pzL3V0aWxzJ1xuaW1wb3J0IHtcbiAgTW9kZWwsXG4gIEJlbG9uZ3NUb09uZVJlbGF0aW9uLFxuICBrbmV4U25ha2VDYXNlTWFwcGVycyxcbiAgcmVmXG59IGZyb20gJ29iamVjdGlvbidcblxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uIGV4dGVuZHMgS29hIHtcbiAgY29uc3RydWN0b3Ioe1xuICAgIGNvbmZpZyA9IHt9LFxuICAgIHZhbGlkYXRvcixcbiAgICByb3V0ZXIsXG4gICAgZXZlbnRzLFxuICAgIG1pZGRsZXdhcmUsXG4gICAgbW9kZWxzLFxuICAgIHNlcnZpY2VzLFxuICAgIGNvbnRyb2xsZXJzXG4gIH0gPSB7fSkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9zZXR1cEVtaXR0ZXIoZXZlbnRzKVxuICAgIGNvbnN0IHtcbiAgICAgIC8vIFBsdWNrIGtleXMgb3V0IG9mIGBjb25maWcuYXBwYCB0byBrZWVwIHRoZW0gc2VjcmV0XG4gICAgICBhcHA6IHsga2V5cywgLi4uYXBwIH0gPSB7fSxcbiAgICAgIGxvZyA9IHt9LFxuICAgICAgLi4ucmVzdFxuICAgIH0gPSBjb25maWdcbiAgICB0aGlzLmNvbmZpZyA9IHtcbiAgICAgIGFwcCxcbiAgICAgIGxvZzogbG9nLnNpbGVudCB8fCBwcm9jZXNzLmVudi5ESVRPX1NJTEVOVCA/IHt9IDogbG9nLFxuICAgICAgLi4ucmVzdFxuICAgIH1cbiAgICB0aGlzLmtleXMgPSBrZXlzXG4gICAgdGhpcy5wcm94eSA9ICEhYXBwLnByb3h5XG4gICAgdGhpcy52YWxpZGF0b3IgPSB2YWxpZGF0b3IgfHwgbmV3IFZhbGlkYXRvcigpXG4gICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXIgfHwgbmV3IFJvdXRlcigpXG4gICAgdGhpcy52YWxpZGF0b3IuYXBwID0gdGhpc1xuICAgIHRoaXMuc3RvcmFnZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgdGhpcy5tb2RlbHMgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgdGhpcy5zZXJ2aWNlcyA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgICB0aGlzLmNvbnRyb2xsZXJzID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuICAgIHRoaXMuaGFzQ29udHJvbGxlck1pZGRsZXdhcmUgPSBmYWxzZVxuICAgIHRoaXMuc2V0dXBMb2dnZXIoKVxuICAgIHRoaXMuc2V0dXBLbmV4KClcbiAgICB0aGlzLnNldHVwR2xvYmFsTWlkZGxld2FyZSgpXG4gICAgaWYgKG1pZGRsZXdhcmUpIHtcbiAgICAgIHRoaXMudXNlKG1pZGRsZXdhcmUpXG4gICAgfVxuICAgIGlmIChjb25maWcuc3RvcmFnZXMpIHtcbiAgICAgIHRoaXMuYWRkU3RvcmFnZXMoY29uZmlnLnN0b3JhZ2VzKVxuICAgIH1cbiAgICBpZiAobW9kZWxzKSB7XG4gICAgICB0aGlzLmFkZE1vZGVscyhtb2RlbHMpXG4gICAgfVxuICAgIGlmIChzZXJ2aWNlcykge1xuICAgICAgdGhpcy5hZGRTZXJ2aWNlcyhzZXJ2aWNlcylcbiAgICB9XG4gICAgaWYgKGNvbnRyb2xsZXJzKSB7XG4gICAgICB0aGlzLmFkZENvbnRyb2xsZXJzKGNvbnRyb2xsZXJzKVxuICAgIH1cbiAgfVxuXG4gIGFkZFJvdXRlKHZlcmIsIHBhdGgsIHRyYW5zYWN0ZWQsIGhhbmRsZXJzLCBjb250cm9sbGVyID0gbnVsbCwgYWN0aW9uID0gbnVsbCkge1xuICAgIGhhbmRsZXJzID0gYXNBcnJheShoYW5kbGVycylcbiAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnMubGVuZ3RoID4gMSA/IGNvbXBvc2UoaGFuZGxlcnMpIDogaGFuZGxlcnNbMF1cbiAgICAvLyBJbnN0ZWFkIG9mIGRpcmVjdGx5IHBhc3NpbmcgYGhhbmRsZXJgLCBwYXNzIGEgYHJvdXRlYCBvYmplY3QgdGhhdCBhbHNvXG4gICAgLy8gd2lsbCBiZSBleHBvc2VkIHRocm91Z2ggYGN0eC5yb3V0ZWAsIHNlZSBgcm91dGVySGFuZGxlcigpYDpcbiAgICBjb25zdCByb3V0ZSA9IHtcbiAgICAgIHZlcmIsXG4gICAgICBwYXRoLFxuICAgICAgdHJhbnNhY3RlZCxcbiAgICAgIGhhbmRsZXIsXG4gICAgICBjb250cm9sbGVyLFxuICAgICAgYWN0aW9uXG4gICAgfVxuICAgIHRoaXMucm91dGVyW3ZlcmJdKHBhdGgsIHJvdXRlKVxuICB9XG5cbiAgYWRkTW9kZWxzKG1vZGVscykge1xuICAgIC8vIEZpcnN0IGFkZCBhbGwgbW9kZWxzIHRoZW4gY2FsbCBpbml0aWFsaXplKCkgZm9yIGVhY2ggaW4gYSBzZWNvbmQgbG9vcCxcbiAgICAvLyBzaW5jZSB0aGV5IG1heSBiZSByZWZlcmVuY2luZyBlYWNoIG90aGVyIGluIHJlbGF0aW9ucy5cbiAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2YgT2JqZWN0LnZhbHVlcyhtb2RlbHMpKSB7XG4gICAgICB0aGlzLmFkZE1vZGVsKG1vZGVsQ2xhc3MpXG4gICAgfVxuICAgIC8vIE5vdyAocmUtKXNvcnQgYWxsIG1vZGVscyBiYXNlZCBvbiB0aGVpciByZWxhdGlvbnMuXG4gICAgdGhpcy5tb2RlbHMgPSB0aGlzLnNvcnRNb2RlbHModGhpcy5tb2RlbHMpXG4gICAgLy8gRmlsdGVyIHRocm91Z2ggYWxsIHNvcnRlZCBtb2RlbHMsIGtlZXBpbmcgb25seSB0aGUgbmV3bHkgYWRkZWQgb25lcy5cbiAgICBjb25zdCBzb3J0ZWRNb2RlbHMgPSBPYmplY3QudmFsdWVzKHRoaXMubW9kZWxzKS5maWx0ZXIoXG4gICAgICBtb2RlbENsYXNzID0+IG1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID09PSBtb2RlbENsYXNzXG4gICAgKVxuICAgIC8vIEluaXRpYWxpemUgdGhlIGFkZGVkIG1vZGVscyBpbiBjb3JyZWN0IHNvcnRlZCBzZXF1ZW5jZSwgc28gdGhhdCBmb3IgZXZlcnlcbiAgICAvLyBtb2RlbCwgZ2V0UmVsYXRlZFJlbGF0aW9ucygpIHJldHVybnMgdGhlIGZ1bGwgbGlzdCBvZiByZWxhdGluZyByZWxhdGlvbnMuXG4gICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIHNvcnRlZE1vZGVscykge1xuICAgICAgaWYgKG1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID09PSBtb2RlbENsYXNzKSB7XG4gICAgICAgIG1vZGVsQ2xhc3Muc2V0dXAodGhpcy5rbmV4KVxuICAgICAgICAvLyBOb3cgdGhhdCB0aGUgbW9kZWxDbGFzcyBpcyBzZXQgdXAsIGNhbGwgYGluaXRpYWxpemUoKWAsIHdoaWNoIGNhbiBiZVxuICAgICAgICAvLyBvdmVycmlkZGVuIGJ5IHN1Yi1jbGFzc2VzLHdpdGhvdXQgaGF2aW5nIHRvIGNhbGwgYHN1cGVyLmluaXRpYWxpemUoKWBcbiAgICAgICAgbW9kZWxDbGFzcy5pbml0aWFsaXplKClcbiAgICAgICAgdGhpcy52YWxpZGF0b3IuYWRkU2NoZW1hKG1vZGVsQ2xhc3MuZ2V0SnNvblNjaGVtYSgpKVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB7IGxvZyB9ID0gdGhpcy5jb25maWdcbiAgICBpZiAobG9nLnNjaGVtYSB8fCBsb2cucmVsYXRpb25zKSB7XG4gICAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2Ygc29ydGVkTW9kZWxzKSB7XG4gICAgICAgIGNvbnN0IHNob3VsZExvZyA9IG9wdGlvbiA9PiAoXG4gICAgICAgICAgb3B0aW9uID09PSB0cnVlIHx8XG4gICAgICAgICAgYXNBcnJheShvcHRpb24pLmluY2x1ZGVzKG1vZGVsQ2xhc3MubmFtZSlcbiAgICAgICAgKVxuICAgICAgICBjb25zdCBkYXRhID0ge31cbiAgICAgICAgaWYgKHNob3VsZExvZyhsb2cuc2NoZW1hKSkge1xuICAgICAgICAgIGRhdGEuc2NoZW1hID0gbW9kZWxDbGFzcy5nZXRKc29uU2NoZW1hKClcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2hvdWxkTG9nKGxvZy5yZWxhdGlvbnMpKSB7XG4gICAgICAgICAgZGF0YS5yZWxhdGlvbnMgPSBjbG9uZShtb2RlbENsYXNzLnJlbGF0aW9uTWFwcGluZ3MsIHZhbHVlID0+XG4gICAgICAgICAgICBNb2RlbC5pc1Byb3RvdHlwZU9mKHZhbHVlKSA/IGBbTW9kZWw6ICR7dmFsdWUubmFtZX1dYCA6IHZhbHVlXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhkYXRhKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgICAgcGljby55ZWxsb3cuYm9sZChgXFxuJHttb2RlbENsYXNzLm5hbWV9OlxcbmApLFxuICAgICAgICAgICAgdXRpbC5pbnNwZWN0KGRhdGEsIHtcbiAgICAgICAgICAgICAgY29sb3JzOiB0cnVlLFxuICAgICAgICAgICAgICBkZXB0aDogbnVsbCxcbiAgICAgICAgICAgICAgbWF4QXJyYXlMZW5ndGg6IG51bGxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYWRkTW9kZWwobW9kZWxDbGFzcykge1xuICAgIGlmIChNb2RlbC5pc1Byb3RvdHlwZU9mKG1vZGVsQ2xhc3MpKSB7XG4gICAgICBtb2RlbENsYXNzLmFwcCA9IHRoaXNcbiAgICAgIHRoaXMubW9kZWxzW21vZGVsQ2xhc3MubmFtZV0gPSBtb2RlbENsYXNzXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBtb2RlbCBjbGFzczogJHttb2RlbENsYXNzfWApXG4gICAgfVxuICB9XG5cbiAgc29ydE1vZGVscyhtb2RlbHMpIHtcbiAgICBjb25zdCBzb3J0QnlSZWxhdGlvbnMgPSAobGlzdCwgY29sbGVjdGVkID0ge30sIGV4Y2x1ZGVkID0ge30pID0+IHtcbiAgICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBsaXN0KSB7XG4gICAgICAgIGNvbnN0IHsgbmFtZSB9ID0gbW9kZWxDbGFzc1xuICAgICAgICBpZiAoIWNvbGxlY3RlZFtuYW1lXSAmJiAhZXhjbHVkZWRbbmFtZV0pIHtcbiAgICAgICAgICBmb3IgKGNvbnN0IHJlbGF0aW9uIG9mIE9iamVjdC52YWx1ZXMobW9kZWxDbGFzcy5nZXRSZWxhdGlvbnMoKSkpIHtcbiAgICAgICAgICAgIGlmICghKHJlbGF0aW9uIGluc3RhbmNlb2YgQmVsb25nc1RvT25lUmVsYXRpb24pKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgcmVsYXRlZE1vZGVsQ2xhc3MsIGpvaW5UYWJsZU1vZGVsQ2xhc3MgfSA9IHJlbGF0aW9uXG4gICAgICAgICAgICAgIGZvciAoY29uc3QgcmVsYXRlZCBvZiBbam9pblRhYmxlTW9kZWxDbGFzcywgcmVsYXRlZE1vZGVsQ2xhc3NdKSB7XG4gICAgICAgICAgICAgICAgLy8gRXhjbHVkZSBzZWxmLXJlZmVyZW5jZXMgYW5kIGdlbmVyYXRlZCBqb2luIG1vZGVsczpcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRlZCAmJiByZWxhdGVkICE9PSBtb2RlbENsYXNzICYmIG1vZGVsc1tyZWxhdGVkLm5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICBzb3J0QnlSZWxhdGlvbnMoW3JlbGF0ZWRdLCBjb2xsZWN0ZWQsIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRXhjbHVkZSBtb2RlbENsYXNzIHRvIHByZXZlbnQgZW5kbGVzcyByZWN1cnNpb25zOlxuICAgICAgICAgICAgICAgICAgICBbbmFtZV06IG1vZGVsQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgIC4uLmV4Y2x1ZGVkXG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb2xsZWN0ZWRbbmFtZV0gPSBtb2RlbENsYXNzXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKGNvbGxlY3RlZClcbiAgICB9XG4gICAgLy8gUmV0dXJuIGEgbmV3IG9iamVjdCB3aXRoIHRoZSBzb3J0ZWQgbW9kZWxzIGFzIGl0cyBrZXkvdmFsdWUgcGFpcnMuXG4gICAgLy8gTk9URTogV2UgbmVlZCB0byByZXZlcnNlIGZvciB0aGUgYWJvdmUgYWxnb3JpdGhtIHRvIHNvcnQgcHJvcGVybHksXG4gICAgLy8gYW5kIHRoZW4gcmV2ZXJzZSB0aGUgcmVzdWx0IGJhY2suXG4gICAgcmV0dXJuIHNvcnRCeVJlbGF0aW9ucyhPYmplY3QudmFsdWVzKG1vZGVscykucmV2ZXJzZSgpKS5yZXZlcnNlKCkucmVkdWNlKFxuICAgICAgKG1vZGVscywgbW9kZWxDbGFzcykgPT4ge1xuICAgICAgICBtb2RlbHNbbW9kZWxDbGFzcy5uYW1lXSA9IG1vZGVsQ2xhc3NcbiAgICAgICAgcmV0dXJuIG1vZGVsc1xuICAgICAgfSxcbiAgICAgIE9iamVjdC5jcmVhdGUobnVsbClcbiAgICApXG4gIH1cblxuICBnZXRNb2RlbChuYW1lKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMubW9kZWxzW25hbWVdIHx8XG4gICAgICAhbmFtZS5lbmRzV2l0aCgnTW9kZWwnKSAmJiB0aGlzLm1vZGVsc1tgJHtuYW1lfU1vZGVsYF0gfHxcbiAgICAgIG51bGxcbiAgICApXG4gIH1cblxuICBmaW5kTW9kZWwoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLm1vZGVscykuZmluZChjYWxsYmFjaylcbiAgfVxuXG4gIGFkZFNlcnZpY2VzKHNlcnZpY2VzKSB7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgc2VydmljZV0gb2YgT2JqZWN0LmVudHJpZXMoc2VydmljZXMpKSB7XG4gICAgICAvLyBIYW5kbGUgRVM2IG1vZHVsZSB3ZWlyZG5lc3MgdGhhdCBjYW4gaGFwcGVuLCBhcHBhcmVudGx5OlxuICAgICAgaWYgKG5hbWUgPT09ICdkZWZhdWx0JyAmJiBpc1BsYWluT2JqZWN0KHNlcnZpY2UpKSB7XG4gICAgICAgIHRoaXMuYWRkU2VydmljZXMoc2VydmljZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWRkU2VydmljZShzZXJ2aWNlLCBuYW1lKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFkZFNlcnZpY2Uoc2VydmljZSwgbmFtZSkge1xuICAgIC8vIEF1dG8taW5zdGFudGlhdGUgY29udHJvbGxlciBjbGFzc2VzOlxuICAgIGlmIChTZXJ2aWNlLmlzUHJvdG90eXBlT2Yoc2VydmljZSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwXG4gICAgICBzZXJ2aWNlID0gbmV3IHNlcnZpY2UodGhpcywgbmFtZSlcbiAgICB9XG4gICAgaWYgKCEoc2VydmljZSBpbnN0YW5jZW9mIFNlcnZpY2UpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc2VydmljZTogJHtzZXJ2aWNlfWApXG4gICAgfVxuICAgIC8vIE9ubHkgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yIGlzIGNhbGxlZCwgYHNlcnZpY2UubmFtZWAgaXMgZ3VhcmFudGVlZCB0byBiZVxuICAgIC8vIHNldCB0byB0aGUgY29ycmVjdCB2YWx1ZSwgZS5nLiB3aXRoIGFuIGFmdGVyLWNvbnN0cnVjdG9yIGNsYXNzIHByb3BlcnR5LlxuICAgICh7IG5hbWUgfSA9IHNlcnZpY2UpXG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWcuc2VydmljZXNbbmFtZV1cbiAgICBpZiAoY29uZmlnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ29uZmlndXJhdGlvbiBtaXNzaW5nIGZvciBzZXJ2aWNlICcke25hbWV9J2ApXG4gICAgfVxuICAgIC8vIEFzIGEgY29udmVudGlvbiwgdGhlIGNvbmZpZ3VyYXRpb24gb2YgYSBzZXJ2aWNlIGNhbiBiZSBzZXQgdG8gYGZhbHNlYFxuICAgIC8vIGluIG9yZGVyIHRvIGVudGlyZWx5IGRlYWN0aXZhdGUgdGhlIHNlcnZpY2UuXG4gICAgaWYgKGNvbmZpZyAhPT0gZmFsc2UpIHtcbiAgICAgIHNlcnZpY2Uuc2V0dXAoY29uZmlnKVxuICAgICAgdGhpcy5zZXJ2aWNlc1tuYW1lXSA9IHNlcnZpY2VcbiAgICAgIC8vIE5vdyB0aGF0IHRoZSBzZXJ2aWNlIGlzIHNldCB1cCwgY2FsbCBgaW5pdGlhbGl6ZSgpYCB3aGljaCBjYW4gYmVcbiAgICAgIC8vIG92ZXJyaWRkZW4gYnkgc2VydmljZXMuXG4gICAgICBzZXJ2aWNlLmluaXRpYWxpemUoKVxuICAgIH1cbiAgfVxuXG4gIGdldFNlcnZpY2UobmFtZSkge1xuICAgIHJldHVybiB0aGlzLnNlcnZpY2VzW25hbWVdIHx8IG51bGxcbiAgfVxuXG4gIGZpbmRTZXJ2aWNlKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5zZXJ2aWNlcykuZmluZChjYWxsYmFjaylcbiAgfVxuXG4gIGZvckVhY2hTZXJ2aWNlKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKE9iamVjdC52YWx1ZXModGhpcy5zZXJ2aWNlcykubWFwKGNhbGxiYWNrKSlcbiAgfVxuXG4gIGFkZENvbnRyb2xsZXJzKGNvbnRyb2xsZXJzLCBuYW1lc3BhY2UpIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhjb250cm9sbGVycykpIHtcbiAgICAgIGlmIChpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICB0aGlzLmFkZENvbnRyb2xsZXJzKHZhbHVlLCBuYW1lc3BhY2UgPyBgJHtuYW1lc3BhY2V9LyR7a2V5fWAgOiBrZXkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZENvbnRyb2xsZXIodmFsdWUsIG5hbWVzcGFjZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhZGRDb250cm9sbGVyKGNvbnRyb2xsZXIsIG5hbWVzcGFjZSkge1xuICAgIC8vIENvbnRyb2xsZXJzIHJlcXVpcmUgYWRkaXRpb25hbCBtaWRkbGV3YXJlIHRvIGJlIGluc3RhbGxlZCBvbmNlLlxuICAgIHRoaXMuc2V0dXBDb250cm9sbGVyTWlkZGxld2FyZSgpXG4gICAgLy8gQXV0by1pbnN0YW50aWF0ZSBjb250cm9sbGVyIGNsYXNzZXM6XG4gICAgaWYgKENvbnRyb2xsZXIuaXNQcm90b3R5cGVPZihjb250cm9sbGVyKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXBcbiAgICAgIGNvbnRyb2xsZXIgPSBuZXcgY29udHJvbGxlcih0aGlzLCBuYW1lc3BhY2UpXG4gICAgfVxuICAgIGlmICghKGNvbnRyb2xsZXIgaW5zdGFuY2VvZiBDb250cm9sbGVyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGNvbnRyb2xsZXI6ICR7Y29udHJvbGxlcn1gKVxuICAgIH1cbiAgICAvLyBJbmhlcml0YW5jZSBvZiBhY3Rpb24gbWV0aG9kcyBjYW5ub3QgaGFwcGVuIGluIHRoZSBjb25zdHJ1Y3RvciBpdHNlbGYsXG4gICAgLy8gc28gY2FsbCBzZXBhcmF0ZSBgc2V0dXAoKWAgbWV0aG9kIGFmdGVyIGluIG9yZGVyIHRvIHRha2UgY2FyZSBvZiBpdC5cbiAgICBjb250cm9sbGVyLnNldHVwKClcbiAgICB0aGlzLmNvbnRyb2xsZXJzW2NvbnRyb2xsZXIudXJsXSA9IGNvbnRyb2xsZXJcbiAgICAvLyBOb3cgdGhhdCB0aGUgY29udHJvbGxlciBpcyBzZXQgdXAsIGNhbGwgYGluaXRpYWxpemUoKWAgd2hpY2ggY2FuIGJlXG4gICAgLy8gb3ZlcnJpZGRlbiBieSBjb250cm9sbGVycy5cbiAgICBjb250cm9sbGVyLmluaXRpYWxpemUoKVxuICAgIC8vIEVhY2ggY29udHJvbGxlciBjYW4gYWxzbyBwcm92aWRlIGZ1cnRoZXIgbWlkZGxld2FyZSwgZS5nLlxuICAgIC8vIGBBZG1pbkNvbnRyb2xsZXJgOlxuICAgIGNvbnN0IG1pZGRsZXdhcmUgPSBjb250cm9sbGVyLmNvbXBvc2UoKVxuICAgIGlmIChtaWRkbGV3YXJlKSB7XG4gICAgICB0aGlzLnVzZShtaWRkbGV3YXJlKVxuICAgIH1cbiAgfVxuXG4gIGdldENvbnRyb2xsZXIodXJsKSB7XG4gICAgcmV0dXJuIHRoaXMuY29udHJvbGxlcnNbdXJsXSB8fCBudWxsXG4gIH1cblxuICBmaW5kQ29udHJvbGxlcihjYWxsYmFjaykge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuY29udHJvbGxlcnMpLmZpbmQoY2FsbGJhY2spXG4gIH1cblxuICBnZXRBZG1pbkNvbnRyb2xsZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluZENvbnRyb2xsZXIoXG4gICAgICBjb250cm9sbGVyID0+IGNvbnRyb2xsZXIgaW5zdGFuY2VvZiBBZG1pbkNvbnRyb2xsZXJcbiAgICApXG4gIH1cblxuICBnZXRBZG1pblZ1ZUNvbmZpZygpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBZG1pbkNvbnRyb2xsZXIoKT8uZ2V0VnVlQ29uZmlnKCkgfHwgbnVsbFxuICB9XG5cbiAgZ2V0QXNzZXRDb25maWcoe1xuICAgIG1vZGVscyA9IE9iamVjdC5rZXlzKHRoaXMubW9kZWxzKSxcbiAgICBub3JtYWxpemVEYk5hbWVzID0gdGhpcy5jb25maWcua25leC5ub3JtYWxpemVEYk5hbWVzXG4gIH0gPSB7fSkge1xuICAgIGNvbnN0IGFzc2V0Q29uZmlnID0ge31cbiAgICBmb3IgKGNvbnN0IG1vZGVsTmFtZSBvZiBtb2RlbHMpIHtcbiAgICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSB0aGlzLm1vZGVsc1ttb2RlbE5hbWVdXG4gICAgICBjb25zdCB7IGFzc2V0cyB9ID0gbW9kZWxDbGFzcy5kZWZpbml0aW9uXG4gICAgICBpZiAoYXNzZXRzKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVEYk5hbWVzXG4gICAgICAgICAgPyB0aGlzLm5vcm1hbGl6ZUlkZW50aWZpZXIobW9kZWxOYW1lKVxuICAgICAgICAgIDogbW9kZWxOYW1lXG4gICAgICAgIGNvbnN0IGNvbnZlcnRlZEFzc2V0cyA9IHt9XG4gICAgICAgIGZvciAoY29uc3QgW2Fzc2V0RGF0YVBhdGgsIGNvbmZpZ10gb2YgT2JqZWN0LmVudHJpZXMoYXNzZXRzKSkge1xuICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIHByb3BlcnR5LFxuICAgICAgICAgICAgbmVzdGVkRGF0YVBhdGgsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICB9ID0gbW9kZWxDbGFzcy5nZXRQcm9wZXJ0eU9yUmVsYXRpb25BdERhdGFQYXRoKGFzc2V0RGF0YVBhdGgpXG4gICAgICAgICAgaWYgKHByb3BlcnR5ICYmIGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICBjb25zdCBub3JtYWxpemVkTmFtZSA9IG5vcm1hbGl6ZURiTmFtZXNcbiAgICAgICAgICAgICAgPyB0aGlzLm5vcm1hbGl6ZUlkZW50aWZpZXIobmFtZSlcbiAgICAgICAgICAgICAgOiBuYW1lXG4gICAgICAgICAgICBjb25zdCBkYXRhUGF0aCA9IG5vcm1hbGl6ZURhdGFQYXRoKFtcbiAgICAgICAgICAgICAgbm9ybWFsaXplZE5hbWUsXG4gICAgICAgICAgICAgIC4uLnBhcnNlRGF0YVBhdGgobmVzdGVkRGF0YVBhdGgpXG4gICAgICAgICAgICBdKVxuICAgICAgICAgICAgY29uc3QgYXNzZXRDb25maWdzID0gY29udmVydGVkQXNzZXRzW25vcm1hbGl6ZWROYW1lXSB8fD0ge31cbiAgICAgICAgICAgIGFzc2V0Q29uZmlnc1tkYXRhUGF0aF0gPSBjb25maWdcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOZXN0ZWQgZ3JhcGggcHJvcGVydGllcyBhcmUgbm90IHN1cHBvcnRlZCB5ZXQnKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhc3NldENvbmZpZ1tub3JtYWxpemVkTW9kZWxOYW1lXSA9IGNvbnZlcnRlZEFzc2V0c1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXNzZXRDb25maWdcbiAgfVxuXG4gIGFkZFN0b3JhZ2VzKHN0b3JhZ2VzKSB7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgY29uZmlnXSBvZiBPYmplY3QuZW50cmllcyhzdG9yYWdlcykpIHtcbiAgICAgIHRoaXMuYWRkU3RvcmFnZShjb25maWcsIG5hbWUpXG4gICAgfVxuICB9XG5cbiAgYWRkU3RvcmFnZShjb25maWcsIG5hbWUpIHtcbiAgICBsZXQgc3RvcmFnZSA9IG51bGxcbiAgICBpZiAoaXNQbGFpbk9iamVjdChjb25maWcpKSB7XG4gICAgICBjb25zdCBzdG9yYWdlQ2xhc3MgPSBTdG9yYWdlLmdldChjb25maWcudHlwZSlcbiAgICAgIGlmICghc3RvcmFnZUNsYXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgc3RvcmFnZTogJHtjb25maWd9YClcbiAgICAgIH1cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwXG4gICAgICBzdG9yYWdlID0gbmV3IHN0b3JhZ2VDbGFzcyh0aGlzLCBjb25maWcpXG4gICAgfSBlbHNlIGlmIChjb25maWcgaW5zdGFuY2VvZiBTdG9yYWdlKSB7XG4gICAgICBzdG9yYWdlID0gY29uZmlnXG4gICAgfVxuICAgIGlmIChzdG9yYWdlKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBzdG9yYWdlLm5hbWUgPSBuYW1lXG4gICAgICB9XG4gICAgICB0aGlzLnN0b3JhZ2VzW3N0b3JhZ2UubmFtZV0gPSBzdG9yYWdlXG4gICAgfVxuICAgIHJldHVybiBzdG9yYWdlXG4gIH1cblxuICBnZXRTdG9yYWdlKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlc1tuYW1lXSB8fCBudWxsXG4gIH1cblxuICBjb21waWxlVmFsaWRhdG9yKGpzb25TY2hlbWEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4ganNvblNjaGVtYVxuICAgICAgPyB0aGlzLnZhbGlkYXRvci5jb21waWxlKGpzb25TY2hlbWEsIG9wdGlvbnMpXG4gICAgICA6IG51bGxcbiAgfVxuXG4gIGNvbXBpbGVQYXJhbWV0ZXJzVmFsaWRhdG9yKHBhcmFtZXRlcnMsIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IGxpc3QgPSBbXVxuICAgIGNvbnN0IHsgZGF0YU5hbWUgPSAnZGF0YScgfSA9IG9wdGlvbnNcblxuICAgIGxldCBwcm9wZXJ0aWVzID0gbnVsbFxuICAgIGNvbnN0IGFkZFBhcmFtZXRlciA9IChuYW1lLCBzY2hlbWEpID0+IHtcbiAgICAgIGxpc3QucHVzaCh7XG4gICAgICAgIG5hbWU6IG5hbWUgPz8gbnVsbCxcbiAgICAgICAgLi4uc2NoZW1hXG4gICAgICB9KVxuICAgICAgaWYgKCFzY2hlbWEubWVtYmVyKSB7XG4gICAgICAgIHByb3BlcnRpZXMgfHw9IHt9XG4gICAgICAgIHByb3BlcnRpZXNbbmFtZSB8fCBkYXRhTmFtZV0gPSBzY2hlbWFcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTdXBwb3J0IHR3byBmb3JtYXRzIG9mIHBhcmFtZXRlcnMgZGVmaW5pdGlvbnM6XG4gICAgLy8gLSBBbiBhcnJheSBvZiBwYXJhbWV0ZXIgc2NoZW1hcywgbmFtZWQgYnkgdGhlaXIgYG5hbWVgIGtleS5cbiAgICAvLyAtIEFuIG9iamVjdCBvZiBwYXJhbWV0ZXIgc2NoZW1hcywgbmFtZWQgYnkgdGhlIGtleSB1bmRlciB3aGljaCBlYWNoXG4gICAgLy8gICBzY2hlbWEgaXMgc3RvcmVkIGluIHRoZSByb290IG9iamVjdC5cbiAgICAvLyBJZiBhbiBhcnJheSBpcyBwYXNzZWQsIHRoZW4gdGhlIGNvbnRyb2xsZXIgYWN0aW9ucyByZWNlaXZlcyB0aGVcbiAgICAvLyBwYXJhbWV0ZXJzIGFzIHNlcGFyYXRlIGFyZ3VtZW50cy4gSWYgYW4gb2JqZWN0IGlzIHBhc3NlZCwgdGhlbiB0aGVcbiAgICAvLyBhY3Rpb25zIHJlY2VpdmVzIG9uZSBwYXJhbWV0ZXIgb2JqZWN0IHdoZXJlIHVuZGVyIHRoZSBzYW1lIGtleXMgdGhlXG4gICAgLy8gc3BlY2lmaWVkIHBhcmFtZXRlciB2YWx1ZXMgYXJlIHN0b3JlZC5cbiAgICBsZXQgYXNPYmplY3QgPSBmYWxzZVxuICAgIGlmIChpc0FycmF5KHBhcmFtZXRlcnMpKSB7XG4gICAgICBmb3IgKGNvbnN0IHsgbmFtZSwgLi4uc2NoZW1hIH0gb2YgcGFyYW1ldGVycykge1xuICAgICAgICBhZGRQYXJhbWV0ZXIobmFtZSwgc2NoZW1hKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocGFyYW1ldGVycykpIHtcbiAgICAgIGFzT2JqZWN0ID0gdHJ1ZVxuICAgICAgZm9yIChjb25zdCBbbmFtZSwgc2NoZW1hXSBvZiBPYmplY3QuZW50cmllcyhwYXJhbWV0ZXJzKSkge1xuICAgICAgICBpZiAoc2NoZW1hKSB7XG4gICAgICAgICAgYWRkUGFyYW1ldGVyKG5hbWUsIHNjaGVtYSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW1ldGVycykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHBhcmFtZXRlcnMgZGVmaW5pdGlvbjogJHtwYXJhbWV0ZXJzfWApXG4gICAgfVxuICAgIC8vIE5PVEU6IElmIHByb3BlcnRpZXMgaXMgbnVsbCwgc2NoZW1hIGFuZCB2YWxpZGF0ZSB3aWxsIGJlY29tZSBudWxsIHRvby5cbiAgICAvLyBOT1RFOiBJZiBpdCBpcyBub3QgbnVsbCwgaXQgd2lsbCBnZXQgZXhwYW5kZWQgdG8gYW4gb2JqZWN0IHNjaGVtYS5cbiAgICBjb25zdCBzY2hlbWEgPSBjb252ZXJ0U2NoZW1hKHByb3BlcnRpZXMsIG9wdGlvbnMpXG4gICAgY29uc3QgdmFsaWRhdGUgPSB0aGlzLmNvbXBpbGVWYWxpZGF0b3Ioc2NoZW1hLCB7XG4gICAgICAvLyBGb3IgcGFyYW1ldGVycywgYWx3YXlzIGNvZXJjZSB0eXBlcywgaW5jbHVkaW5nIGFycmF5cy5cbiAgICAgIGNvZXJjZVR5cGVzOiAnYXJyYXknLFxuICAgICAgLi4ub3B0aW9uc1xuICAgIH0pXG4gICAgY29uc3QgY3R4ID0ge1xuICAgICAgYXBwOiB0aGlzLFxuICAgICAgdmFsaWRhdG9yOiB0aGlzLnZhbGlkYXRvcixcbiAgICAgIG9wdGlvbnNcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGxpc3QsXG4gICAgICBzY2hlbWEsXG4gICAgICBhc09iamVjdCxcbiAgICAgIGRhdGFOYW1lLFxuICAgICAgdmFsaWRhdGU6IHZhbGlkYXRlXG4gICAgICAgIC8vIFVzZSBgY2FsbCgpYCB0byBwYXNzIGN0eCBhcyBjb250ZXh0IHRvIEFqdiwgc2VlIHBhc3NDb250ZXh0OlxuICAgICAgICA/IGRhdGEgPT4gdmFsaWRhdGUuY2FsbChjdHgsIGRhdGEpXG4gICAgICAgIDogbnVsbFxuICAgIH1cbiAgfVxuXG4gIGNyZWF0ZVZhbGlkYXRpb25FcnJvcih7IHR5cGUsIG1lc3NhZ2UsIGVycm9ycywgb3B0aW9ucywganNvbiB9KSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uRXJyb3Ioe1xuICAgICAgdHlwZSxcbiAgICAgIG1lc3NhZ2UsXG4gICAgICBlcnJvcnM6IHRoaXMudmFsaWRhdG9yLnBhcnNlRXJyb3JzKGVycm9ycywgb3B0aW9ucyksXG4gICAgICAvLyBPbmx5IGluY2x1ZGUgdGhlIEpTT04gZGF0YSBpbiB0aGUgZXJyb3IgaWYgYGxvZy5lcnJvcnMuanNvbmBpcyBzZXQuXG4gICAgICBqc29uOiB0aGlzLmNvbmZpZy5sb2cuZXJyb3JzPy5qc29uID8ganNvbiA6IHVuZGVmaW5lZFxuICAgIH0pXG4gIH1cblxuICBjcmVhdGVEYXRhYmFzZUVycm9yKGVycm9yKSB7XG4gICAgLy8gUmVtb3ZlIGtuZXggU1FMIHF1ZXJ5IGFuZCBtb3ZlIHRvIHNlcGFyYXRlIGBzcWxgIHByb3BlcnR5LlxuICAgIC8vIFRPRE86IEZpeCB0aGlzIHByb3Blcmx5IGluIEtuZXggLyBPYmplY3Rpb24gaW5zdGVhZCwgc2VlOlxuICAgIC8vIGh0dHBzOi8vZ2l0dGVyLmltL1ZpbmNpdC9vYmplY3Rpb24uanM/YXQ9NWE2ODcyOGY1YTllYmU0Zjc1Y2E0MGIwXG4gICAgY29uc3QgWywgc3FsLCBtZXNzYWdlXSA9IGVycm9yLm1lc3NhZ2UubWF0Y2goL14oW1xcc1xcU10qKSAtIChbXFxzXFxTXSo/KSQvKSB8fFxuICAgICAgW251bGwsIG51bGwsIGVycm9yLm1lc3NhZ2VdXG4gICAgcmV0dXJuIG5ldyBEYXRhYmFzZUVycm9yKGVycm9yLCB7XG4gICAgICBtZXNzYWdlLFxuICAgICAgLy8gT25seSBpbmNsdWRlIHRoZSBTUUwgcXVlcnkgaW4gdGhlIGVycm9yIGlmIGBsb2cuZXJyb3JzLnNxbGBpcyBzZXQuXG4gICAgICBzcWw6IHRoaXMuY29uZmlnLmxvZy5lcnJvcnM/LnNxbCA/IHNxbCA6IHVuZGVmaW5lZFxuICAgIH0pXG4gIH1cblxuICBzZXR1cEdsb2JhbE1pZGRsZXdhcmUoKSB7XG4gICAgY29uc3QgeyBhcHAsIGxvZyB9ID0gdGhpcy5jb25maWdcblxuICAgIHRoaXMudXNlKGF0dGFjaExvZ2dlcih0aGlzLmxvZ2dlcikpXG5cbiAgICBpZiAoYXBwLnJlc3BvbnNlVGltZSAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMudXNlKHJlc3BvbnNlVGltZShnZXRPcHRpb25zKGFwcC5yZXNwb25zZVRpbWUpKSlcbiAgICB9XG4gICAgaWYgKGxvZy5yZXF1ZXN0cykge1xuICAgICAgdGhpcy51c2UobG9nUmVxdWVzdHMoKSlcbiAgICB9XG4gICAgLy8gTmVlZHMgdG8gYmUgcG9zaXRpb25lZCBhZnRlciB0aGUgcmVxdWVzdCBsb2dnZXIgdG8gbG9nIHRoZSBjb3JyZWN0XG4gICAgLy8gcmVzcG9uc2Ugc3RhdHVzLlxuICAgIHRoaXMudXNlKGhhbmRsZUVycm9yKCkpXG4gICAgaWYgKGFwcC5oZWxtZXQgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnVzZShoZWxtZXQoZ2V0T3B0aW9ucyhhcHAuaGVsbWV0KSkpXG4gICAgfVxuICAgIGlmIChhcHAuY29ycyAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMudXNlKGNvcnMoZ2V0T3B0aW9ucyhhcHAuY29ycykpKVxuICAgIH1cbiAgICBpZiAoYXBwLmNvbXByZXNzICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy51c2UoY29tcHJlc3MobWVyZ2UoXG4gICAgICAgIHtcbiAgICAgICAgICAvLyBVc2UgYSByZWFzb25hYmxlIGRlZmF1bHQgZm9yIEJyb3RsaSBjb21wcmVzc2lvbi5cbiAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2tvYWpzL2NvbXByZXNzL2lzc3Vlcy8xMjZcbiAgICAgICAgICBicjoge1xuICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgIFt6bGliLmNvbnN0YW50cy5CUk9UTElfUEFSQU1fUVVBTElUWV06IDRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGdldE9wdGlvbnMoYXBwLmNvbXByZXNzKVxuICAgICAgKSkpXG4gICAgfVxuICAgIGlmIChhcHAuZXRhZyAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMudXNlKGNvbmRpdGlvbmFsKCkpXG4gICAgICB0aGlzLnVzZShldGFnKCkpXG4gICAgfVxuICB9XG5cbiAgc2V0dXBDb250cm9sbGVyTWlkZGxld2FyZSgpIHtcbiAgICAvLyBOT1RFOiBUaGlzIGlzIG5vdCBwYXJ0IG9mIHRoZSBhdXRvbWF0aWMgYHNldHVwR2xvYmFsTWlkZGxld2FyZSgpYCBzbyB0aGF0XG4gICAgLy8gYXBwcyBjYW4gc2V0IHVwIHRoZSBzdGF0aWMgc2VydmluZyBvZiBhc3NldHMgYmVmb3JlIGluc3RhbGxpbmcgdGhlXG4gICAgLy8gc2Vzc2lvbiBhbmQgcGFzc3BvcnQgbWlkZGxld2FyZS4gSXQgaXMgY2FsbGVkIGZyb20gYGFkZENvbnRyb2xsZXIoKWAuXG4gICAgLy8gVXNlIGEgZmxhZyB0byBvbmx5IGluc3RhbGwgdGhlIG1pZGRsZXdhcmUgb25jZTpcbiAgICBpZiAoIXRoaXMuaGFzQ29udHJvbGxlck1pZGRsZXdhcmUpIHtcbiAgICAgIGNvbnN0IHsgYXBwIH0gPSB0aGlzLmNvbmZpZ1xuICAgICAgLy8gU2VxdWVuY2UgaXMgaW1wb3J0YW50OlxuICAgICAgLy8gMS4gYm9keSBwYXJzZXJcbiAgICAgIHRoaXMudXNlKGJvZHlQYXJzZXIoZ2V0T3B0aW9ucyhhcHAuYm9keVBhcnNlcikpKVxuICAgICAgLy8gMi4gZmluZCByb3V0ZSBmcm9tIHJvdXRlcyBpbnN0YWxsZWQgYnkgY29udHJvbGxlcnMuXG4gICAgICB0aGlzLnVzZShmaW5kUm91dGUodGhpcy5yb3V0ZXIpKVxuICAgICAgLy8gMy4gcmVzcGVjdCB0cmFuc2FjdGVkIHNldHRpbmdzLCBjcmVhdGUgYW5kIGhhbmRsZSB0cmFuc2FjdGlvbnMuXG4gICAgICB0aGlzLnVzZShjcmVhdGVUcmFuc2FjdGlvbigpKVxuICAgICAgLy8gNC4gc2Vzc2lvblxuICAgICAgaWYgKGFwcC5zZXNzaW9uKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBtb2RlbENsYXNzLFxuICAgICAgICAgIC4uLm9wdGlvbnNcbiAgICAgICAgfSA9IGdldE9wdGlvbnMoYXBwLnNlc3Npb24pXG4gICAgICAgIGlmIChtb2RlbENsYXNzKSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgQ29udGV4dFN0b3JlIHRoYXQgcmVzb2x2ZWQgdGhlIHNwZWNpZmllZCBtb2RlbCBjbGFzcyxcbiAgICAgICAgICAvLyB1c2VzIGl0IHRvIHBlcnNpc3QgYW5kIHJldHJpZXZlIHRoZSBzZXNzaW9uLCBhbmQgYXV0b21hdGljYWxseVxuICAgICAgICAgIC8vIGJpbmRzIGFsbCBkYiBvcGVyYXRpb25zIHRvIGBjdHgudHJhbnNhY3Rpb25gLCBpZiBpdCBpcyBzZXQuXG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXBcbiAgICAgICAgICBvcHRpb25zLkNvbnRleHRTdG9yZSA9IFNlc3Npb25TdG9yZShtb2RlbENsYXNzKVxuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlKHNlc3Npb24ob3B0aW9ucywgdGhpcykpXG4gICAgICB9XG4gICAgICAvLyA1LiBwYXNzcG9ydFxuICAgICAgaWYgKGFwcC5wYXNzcG9ydCkge1xuICAgICAgICB0aGlzLnVzZShwYXNzcG9ydC5pbml0aWFsaXplKCkpXG4gICAgICAgIGlmIChhcHAuc2Vzc2lvbikge1xuICAgICAgICAgIHRoaXMudXNlKHBhc3Nwb3J0LnNlc3Npb24oKSlcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVzZShoYW5kbGVVc2VyKCkpXG4gICAgICB9XG5cbiAgICAgIC8vIDYuIGZpbmFsbHkgaGFuZGxlIHRoZSBmb3VuZCByb3V0ZSwgb3Igc2V0IHN0YXR1cyAvIGFsbG93IGFjY29yZGluZ2x5LlxuICAgICAgdGhpcy51c2UoaGFuZGxlUm91dGUoKSlcbiAgICAgIHRoaXMuaGFzQ29udHJvbGxlck1pZGRsZXdhcmUgPSB0cnVlXG4gICAgfVxuICB9XG5cbiAgc2V0dXBMb2dnZXIoKSB7XG4gICAgY29uc3QgeyBlcnIsIHJlcSwgcmVzIH0gPSBwaW5vLnN0ZFNlcmlhbGl6ZXJzXG4gICAgLy8gT25seSBpbmNsdWRlIGBpZGAgZnJvbSB0aGUgdXNlciwgdG8gbm90IGluYWR2ZXJ0ZW50bHkgbG9nIFBJSS5cbiAgICBjb25zdCB1c2VyID0gdXNlciA9PiAoeyBpZDogdXNlci5pZCB9KVxuICAgIGNvbnN0IHNlcmlhbGl6ZXJzID0geyBlcnIsIHJlcSwgcmVzLCB1c2VyIH1cblxuICAgIGNvbnN0IGxvZ2dlciA9IHBpbm8obWVyZ2UoXG4gICAgICB7XG4gICAgICAgIGxldmVsOiAnaW5mbycsXG4gICAgICAgIHNlcmlhbGl6ZXJzLFxuICAgICAgICBwcmV0dHlQcmludDoge1xuICAgICAgICAgIC8vIExpc3Qgb2Yga2V5cyB0byBpZ25vcmUgaW4gcHJldHR5IG1vZGUuXG4gICAgICAgICAgaWdub3JlOiAncmVxLHJlcyxkdXJhdGlvbk1zLHVzZXIscmVxdWVzdElkJyxcbiAgICAgICAgICAvLyBTWVMgdG8gdXNlIHN5c3RlbSB0aW1lIGFuZCBub3QgVVRDLlxuICAgICAgICAgIHRyYW5zbGF0ZVRpbWU6ICdTWVM6SEg6TU06c3MubCdcbiAgICAgICAgfSxcbiAgICAgICAgLy8gUmVkYWN0IGNvbW1vbiBzZW5zaXRpdmUgaGVhZGVycy5cbiAgICAgICAgcmVkYWN0OiBbXG4gICAgICAgICAgJyouaGVhZGVyc1tcImNvb2tpZVwiXScsXG4gICAgICAgICAgJyouaGVhZGVyc1tcInNldC1jb29raWVcIl0nLFxuICAgICAgICAgICcqLmhlYWRlcnNbXCJhdXRob3JpemF0aW9uXCJdJ1xuICAgICAgICBdLFxuICAgICAgICBiYXNlOiBudWxsIC8vIG5vIHBpZCxob3N0bmFtZSxuYW1lXG4gICAgICB9LFxuICAgICAgZ2V0T3B0aW9ucyh0aGlzLmNvbmZpZy5sb2dnZXIpXG4gICAgKSlcblxuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyLmNoaWxkKHsgbmFtZTogJ2FwcCcgfSlcbiAgfVxuXG4gIHNldHVwS25leCgpIHtcbiAgICBsZXQgeyBrbmV4LCBsb2cgfSA9IHRoaXMuY29uZmlnXG4gICAgaWYgKGtuZXg/LmNsaWVudCkge1xuICAgICAgY29uc3Qgc25ha2VDYXNlT3B0aW9ucyA9IGtuZXgubm9ybWFsaXplRGJOYW1lcyA9PT0gdHJ1ZVxuICAgICAgICA/IHt9XG4gICAgICAgIDoga25leC5ub3JtYWxpemVEYk5hbWVzXG4gICAgICBpZiAoc25ha2VDYXNlT3B0aW9ucykge1xuICAgICAgICBrbmV4ID0ge1xuICAgICAgICAgIC4uLmtuZXgsXG4gICAgICAgICAgLi4ua25leFNuYWtlQ2FzZU1hcHBlcnMoc25ha2VDYXNlT3B0aW9ucylcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5rbmV4ID0gS25leChrbmV4KVxuICAgICAgLy8gU3VwcG9ydCBQb3N0Z3JlU1FMIHR5cGUgcGFyc2VyIG1hcHBpbmdzIGluIHRoZSBjb25maWcuXG4gICAgICBpZiAoa25leC5jbGllbnQgPT09ICdwb3N0Z3Jlc3FsJyAmJiBrbmV4LnR5cGVQYXJzZXJzKSB7XG4gICAgICAgIGZvciAoY29uc3QgW3R5cGUsIHBhcnNlcl0gb2YgT2JqZWN0LmVudHJpZXMoa25leC50eXBlUGFyc2VycykpIHtcbiAgICAgICAgICB0aGlzLmtuZXguY2xpZW50LmRyaXZlci50eXBlcy5zZXRUeXBlUGFyc2VyKHR5cGUsIHBhcnNlcilcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGxvZy5zcWwpIHtcbiAgICAgICAgdGhpcy5zZXR1cEtuZXhMb2dnaW5nKClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzZXR1cEtuZXhMb2dnaW5nKCkge1xuICAgIGNvbnN0IHN0YXJ0VGltZXMgPSB7fVxuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMubG9nZ2VyLmNoaWxkKHsgbmFtZTogJ3NxbCcgfSlcbiAgICBmdW5jdGlvbiBlbmQocXVlcnksIHsgcmVzcG9uc2UsIGVycm9yIH0pIHtcbiAgICAgIGNvbnN0IGlkID0gcXVlcnkuX19rbmV4UXVlcnlVaWRcbiAgICAgIGNvbnN0IGRpZmYgPSBwcm9jZXNzLmhydGltZShzdGFydFRpbWVzW2lkXSlcbiAgICAgIGNvbnN0IGR1cmF0aW9uID0gZGlmZlswXSAqIDFlMyArIGRpZmZbMV0gLyAxZTZcbiAgICAgIGRlbGV0ZSBzdGFydFRpbWVzW2lkXVxuICAgICAgY29uc3QgeyBzcWwsIGJpbmRpbmdzIH0gPSBxdWVyeVxuICAgICAgcmVzcG9uc2UgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKHJlc3BvbnNlKS5maWx0ZXIoXG4gICAgICAgICAgKFtrZXldKSA9PiAha2V5LnN0YXJ0c1dpdGgoJ18nKVxuICAgICAgICApXG4gICAgICApXG4gICAgICBsb2dnZXIuaW5mbyh7IGR1cmF0aW9uLCBiaW5kaW5ncywgcmVzcG9uc2UsIGVycm9yIH0sIHNxbClcbiAgICB9XG5cbiAgICB0aGlzLmtuZXhcbiAgICAgIC5vbigncXVlcnknLCBxdWVyeSA9PiB7XG4gICAgICAgIHN0YXJ0VGltZXNbcXVlcnkuX19rbmV4UXVlcnlVaWRdID0gcHJvY2Vzcy5ocnRpbWUoKVxuICAgICAgfSlcbiAgICAgIC5vbigncXVlcnktcmVzcG9uc2UnLCAocmVzcG9uc2UsIHF1ZXJ5KSA9PiB7XG4gICAgICAgIGVuZChxdWVyeSwgeyByZXNwb25zZSB9KVxuICAgICAgfSlcbiAgICAgIC5vbigncXVlcnktZXJyb3InLCAoZXJyb3IsIHF1ZXJ5KSA9PiB7XG4gICAgICAgIGVuZChxdWVyeSwgeyBlcnJvciB9KVxuICAgICAgfSlcbiAgfVxuXG4gIG5vcm1hbGl6ZUlkZW50aWZpZXIoaWRlbnRpZmllcikge1xuICAgIHJldHVybiB0aGlzLmtuZXguY2xpZW50LndyYXBJZGVudGlmaWVyKGlkZW50aWZpZXIpLnJlcGxhY2UoL1snYFwiXS9nLCAnJylcbiAgfVxuXG4gIGRlbm9ybWFsaXplSWRlbnRpZmllcihpZGVudGlmaWVyKSB7XG4gICAgY29uc3Qgb2JqID0gdGhpcy5rbmV4LmNsaWVudC5wb3N0UHJvY2Vzc1Jlc3BvbnNlKHsgW2lkZW50aWZpZXJdOiAxIH0pXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iailbMF1cbiAgfVxuXG4gIG5vcm1hbGl6ZVBhdGgocGF0aCkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5hcHAubm9ybWFsaXplUGF0aHMgPyBoeXBoZW5hdGUocGF0aCkgOiBwYXRoXG4gIH1cblxuICBmb3JtYXRFcnJvcihlcnIpIHtcbiAgICBjb25zdCBtZXNzYWdlID0gZXJyLnRvSlNPTlxuICAgICAgPyBmb3JtYXRKc29uKGVyci50b0pTT04oKSlcbiAgICAgIDogZXJyLm1lc3NhZ2UgfHwgZXJyXG4gICAgY29uc3Qgc3RyID0gYCR7ZXJyLm5hbWV9OiAke21lc3NhZ2V9YFxuICAgIHJldHVybiBlcnIuc3RhY2sgJiYgdGhpcy5jb25maWcubG9nLmVycm9ycz8uc3RhY2sgIT09IGZhbHNlXG4gICAgICA/IGAke3N0cn1cXG4ke2Vyci5zdGFjay5zcGxpdCgvXFxufFxcclxcbnxcXHIvKS5zbGljZSgxKS5qb2luKG9zLkVPTCl9YFxuICAgICAgOiBzdHJcbiAgfVxuXG4gIGxvZ0Vycm9yKGVyciwgY3R4KSB7XG4gICAgaWYgKCFlcnIuZXhwb3NlICYmICF0aGlzLnNpbGVudCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGV4dCA9IHRoaXMuZm9ybWF0RXJyb3IoZXJyKVxuICAgICAgICBjb25zdCBsZXZlbCA9XG4gICAgICAgICAgZXJyIGluc3RhbmNlb2YgUmVzcG9uc2VFcnJvciAmJiBlcnIuc3RhdHVzIDwgNTAwID8gJ2luZm8nIDogJ2Vycm9yJ1xuICAgICAgICBjb25zdCBsb2dnZXIgPSBjdHg/LmxvZ2dlciB8fCB0aGlzLmxvZ2dlclxuICAgICAgICBsb2dnZXJbbGV2ZWxdKHRleHQpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0NvdWxkIG5vdCBsb2cgZXJyb3InLCBlKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHN0YXJ0KCkge1xuICAgIGlmICh0aGlzLmNvbmZpZy5sb2cuZXJyb3JzICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy5vbignZXJyb3InLCB0aGlzLmxvZ0Vycm9yKVxuICAgIH1cbiAgICBhd2FpdCB0aGlzLmVtaXQoJ2JlZm9yZTpzdGFydCcpXG4gICAgYXdhaXQgdGhpcy5mb3JFYWNoU2VydmljZShzZXJ2aWNlID0+IHNlcnZpY2Uuc3RhcnQoKSlcbiAgICBjb25zdCB7XG4gICAgICBzZXJ2ZXI6IHsgaG9zdCwgcG9ydCB9LFxuICAgICAgZW52XG4gICAgfSA9IHRoaXMuY29uZmlnXG4gICAgdGhpcy5zZXJ2ZXIgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLmxpc3Rlbihwb3J0LCBob3N0LCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgcG9ydCB9ID0gc2VydmVyLmFkZHJlc3MoKVxuICAgICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgICAgYCR7ZW52fSBzZXJ2ZXIgc3RhcnRlZCBhdCBodHRwOi8vJHtob3N0fToke3BvcnR9YFxuICAgICAgICApXG4gICAgICAgIHJlc29sdmUoc2VydmVyKVxuICAgICAgfSlcbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYFVuYWJsZSB0byBzdGFydCBzZXJ2ZXIgYXQgaHR0cDovLyR7aG9zdH06JHtwb3J0fWApKVxuICAgICAgfVxuICAgIH0pXG4gICAgYXdhaXQgdGhpcy5lbWl0KCdhZnRlcjpzdGFydCcpXG4gIH1cblxuICBhc3luYyBzdG9wKCkge1xuICAgIGF3YWl0IHRoaXMuZW1pdCgnYmVmb3JlOnN0b3AnKVxuICAgIHRoaXMuc2VydmVyID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgeyBzZXJ2ZXIgfSA9IHRoaXNcbiAgICAgIGlmIChzZXJ2ZXIpIHtcbiAgICAgICAgc2VydmVyLmNsb3NlKGVyciA9PiB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgcmVqZWN0KGVycilcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzb2x2ZShudWxsKVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLy8gSGFjayB0byBtYWtlIHN1cmUgdGhhdCB3ZSBjbG9zZSB0aGUgc2VydmVyLFxuICAgICAgICAvLyAgZXZlbiBpZiBzb2NrZXRzIGFyZSBzdGlsbCBvcGVuLlxuICAgICAgICAvLyAgVGFrZW4gZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzY4MzAwNzIuXG4gICAgICAgIC8vICBBIHByb3BlciBzb2x1dGlvbiB3b3VsZCBiZSB0byB1c2UgYSBsaWJyYXJ5LCBleDogaHR0cHM6Ly9naXRodWIuY29tL2dvZGFkZHkvdGVybWludXNcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHNlcnZlci5lbWl0KCdjbG9zZScpKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignU2VydmVyIGlzIG5vdCBydW5uaW5nJykpXG4gICAgICB9XG4gICAgfSlcbiAgICBhd2FpdCB0aGlzLmZvckVhY2hTZXJ2aWNlKHNlcnZpY2UgPT4gc2VydmljZS5zdG9wKCkpXG4gICAgYXdhaXQgdGhpcy5lbWl0KCdhZnRlcjpzdG9wJylcbiAgICBpZiAodGhpcy5jb25maWcubG9nLmVycm9ycyAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMub2ZmKCdlcnJvcicsIHRoaXMubG9nRXJyb3IpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc3RhcnRPckV4aXQoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnQoKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5sb2dFcnJvcihlcnIpXG4gICAgICBwcm9jZXNzLmV4aXQoLTEpXG4gICAgfVxuICB9XG5cbiAgLy8gQXNzZXRzIGhhbmRsaW5nXG5cbiAgYXN5bmMgY3JlYXRlQXNzZXRzKHN0b3JhZ2UsIGZpbGVzLCBjb3VudCA9IDAsIHRyeCA9IG51bGwpIHtcbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICBjb25zdCBhc3NldHMgPSBmaWxlcy5tYXAoZmlsZSA9PiAoe1xuICAgICAgICBrZXk6IGZpbGUua2V5LFxuICAgICAgICBmaWxlLFxuICAgICAgICBzdG9yYWdlOiBzdG9yYWdlLm5hbWUsXG4gICAgICAgIGNvdW50XG4gICAgICB9KSlcbiAgICAgIHJldHVybiBBc3NldE1vZGVsXG4gICAgICAgIC5xdWVyeSh0cngpXG4gICAgICAgIC5pbnNlcnQoYXNzZXRzKVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgYXN5bmMgaGFuZGxlQWRkZGVkQW5kUmVtb3ZlZEFzc2V0cyhcbiAgICBzdG9yYWdlLFxuICAgIGFkZGVkRmlsZXMsXG4gICAgcmVtb3ZlZEZpbGVzLFxuICAgIHRyeCA9IG51bGxcbiAgKSB7XG4gICAgY29uc3Qge1xuICAgICAgYXNzZXRzOiB7XG4gICAgICAgIGNsZWFudXBUaW1lVGhyZXNob2xkID0gMFxuICAgICAgfSA9IHt9XG4gICAgfSA9IHRoaXMuY29uZmlnXG4gICAgLy8gT25seSByZW1vdmUgdW51c2VkIGFzc2V0cyB0aGF0IGhhdmVuJ3Qgc2VlbiBjaGFuZ2VzIGZvciBnaXZlbiB0aW1lZnJhbWUuXG4gICAgY29uc3QgdGltZVRocmVzaG9sZCA9IGlzU3RyaW5nKGNsZWFudXBUaW1lVGhyZXNob2xkKVxuICAgICAgPyBwYXJzZUR1cmF0aW9uKGNsZWFudXBUaW1lVGhyZXNob2xkKVxuICAgICAgOiBjbGVhbnVwVGltZVRocmVzaG9sZFxuXG4gICAgY29uc3QgaW1wb3J0ZWRGaWxlcyA9IFtdXG4gICAgY29uc3QgQXNzZXRNb2RlbCA9IHRoaXMuZ2V0TW9kZWwoJ0Fzc2V0JylcbiAgICBpZiAoQXNzZXRNb2RlbCkge1xuICAgICAgaW1wb3J0ZWRGaWxlcy5wdXNoKFxuICAgICAgICAuLi5hd2FpdCB0aGlzLmFkZEZvcmVpZ25Bc3NldHMoc3RvcmFnZSwgYWRkZWRGaWxlcywgdHJ4KVxuICAgICAgKVxuICAgICAgaWYgKFxuICAgICAgICBhZGRlZEZpbGVzLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgcmVtb3ZlZEZpbGVzLmxlbmd0aCA+IDBcbiAgICAgICkge1xuICAgICAgICBjb25zdCBjaGFuZ2VDb3VudCA9IChmaWxlcywgaW5jcmVtZW50KSA9PiAoXG4gICAgICAgICAgZmlsZXMubGVuZ3RoID4gMCAmJlxuICAgICAgICAgIEFzc2V0TW9kZWwucXVlcnkodHJ4KVxuICAgICAgICAgICAgLndoZXJlSW4oJ2tleScsIGZpbGVzLm1hcChmaWxlID0+IGZpbGUua2V5KSlcbiAgICAgICAgICAgIC5pbmNyZW1lbnQoJ2NvdW50JywgaW5jcmVtZW50KVxuICAgICAgICApXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICBjaGFuZ2VDb3VudChhZGRlZEZpbGVzLCAxKSxcbiAgICAgICAgICBjaGFuZ2VDb3VudChyZW1vdmVkRmlsZXMsIC0xKVxuICAgICAgICBdKVxuICAgICAgICBpZiAodGltZVRocmVzaG9sZCA+IDApIHtcbiAgICAgICAgICBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgLy8gRG9uJ3QgcGFzcyBgdHJ4YCBoZXJlLCBhcyB3ZSB3YW50IHRoaXMgZGVsYXllZCBleGVjdXRpb24gdG9cbiAgICAgICAgICAgIC8vIGNyZWF0ZSBpdHMgb3duIHRyYW5zYWN0aW9uLlxuICAgICAgICAgICAgKCkgPT4gdGhpcy5yZWxlYXNlVW51c2VkQXNzZXRzKHRpbWVUaHJlc2hvbGQpLFxuICAgICAgICAgICAgdGltZVRocmVzaG9sZFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQWxzbyBleGVjdXRlIHJlbGVhc2VVbnVzZWRBc3NldHMoKSBpbW1lZGlhdGVseSBpbiB0aGUgc2FtZVxuICAgICAgLy8gdHJhbnNhY3Rpb24sIHRvIHBvdGVudGlhbGx5IGNsZWFuIHVwIG90aGVyIHBlbmRpbmcgYXNzZXRzLlxuICAgICAgYXdhaXQgdGhpcy5yZWxlYXNlVW51c2VkQXNzZXRzKHRpbWVUaHJlc2hvbGQsIHRyeClcbiAgICAgIHJldHVybiBpbXBvcnRlZEZpbGVzXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYWRkRm9yZWlnbkFzc2V0cyhzdG9yYWdlLCBmaWxlcywgdHJ4ID0gbnVsbCkge1xuICAgIGNvbnN0IGltcG9ydGVkRmlsZXMgPSBbXVxuICAgIGNvbnN0IEFzc2V0TW9kZWwgPSB0aGlzLmdldE1vZGVsKCdBc3NldCcpXG4gICAgaWYgKEFzc2V0TW9kZWwpIHtcbiAgICAgIC8vIEZpbmQgbWlzc2luZyBhc3NldHMgKGNvcGllZCBmcm9tIGFub3RoZXIgc3lzdGVtKSwgYW5kIGFkZCB0aGVtLlxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGZpbGVzLm1hcChhc3luYyBmaWxlID0+IHtcbiAgICAgICAgICBjb25zdCBhc3NldCA9IGF3YWl0IEFzc2V0TW9kZWwucXVlcnkodHJ4KS5maW5kT25lKCdrZXknLCBmaWxlLmtleSlcbiAgICAgICAgICBpZiAoIWFzc2V0KSB7XG4gICAgICAgICAgICBpZiAoZmlsZS5kYXRhIHx8IGZpbGUudXJsKSB7XG4gICAgICAgICAgICAgIGxldCB7IGRhdGEgfSA9IGZpbGVcbiAgICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgICAgICAgICAgYCR7XG4gICAgICAgICAgICAgICAgICAgIHBpY28ucmVkKCdJTkZPOicpXG4gICAgICAgICAgICAgICAgICB9IEFzc2V0ICR7XG4gICAgICAgICAgICAgICAgICAgIHBpY28uZ3JlZW4oYCcke2ZpbGUubmFtZX0nYClcbiAgICAgICAgICAgICAgICAgIH0gaXMgZnJvbSBhIGZvcmVpZ24gc291cmNlLCBmZXRjaGluZyBmcm9tICR7XG4gICAgICAgICAgICAgICAgICAgIHBpY28uZ3JlZW4oYCcke2ZpbGUudXJsfSdgKVxuICAgICAgICAgICAgICAgICAgfSBhbmQgYWRkaW5nIHRvIHN0b3JhZ2UgJHtcbiAgICAgICAgICAgICAgICAgICAgcGljby5ncmVlbihgJyR7c3RvcmFnZS5uYW1lfSdgKVxuICAgICAgICAgICAgICAgICAgfS4uLmBcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5yZXF1ZXN0KHtcbiAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ2dldCcsXG4gICAgICAgICAgICAgICAgICB1cmw6IGZpbGUudXJsLFxuICAgICAgICAgICAgICAgICAgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICBkYXRhID0gcmVzcG9uc2UuZGF0YVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnN0IGltcG9ydGVkRmlsZSA9IGF3YWl0IHN0b3JhZ2UuYWRkRmlsZShmaWxlLCBkYXRhKVxuICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZUFzc2V0cyhzdG9yYWdlLCBbaW1wb3J0ZWRGaWxlXSwgMCwgdHJ4KVxuICAgICAgICAgICAgICAvLyBNZXJnZSBiYWNrIHRoZSBjaGFuZ2VkIGZpbGUgcHJvcGVydGllcyBpbnRvIHRoZSBhY3R1YWwgZmlsZXNcbiAgICAgICAgICAgICAgLy8gb2JqZWN0LCBzbyB0aGF0IHRoZSBkYXRhIGZyb20gdGhlIHN0YXRpYyBtb2RlbCBob29rIGNhbiBiZSB1c2VkXG4gICAgICAgICAgICAgIC8vIGRpcmVjdGx5IGZvciB0aGUgYWN0dWFsIHJ1bm5pbmcgcXVlcnkuXG4gICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZmlsZSwgaW1wb3J0ZWRGaWxlKVxuICAgICAgICAgICAgICBpbXBvcnRlZEZpbGVzLnB1c2goaW1wb3J0ZWRGaWxlKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2V0RXJyb3IoXG4gICAgICAgICAgICAgICAgYFVuYWJsZSB0byBpbXBvcnQgYXNzZXQgZnJvbSBmb3JlaWduIHNvdXJjZTogJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLm5hbWVcbiAgICAgICAgICAgICAgICB9JyAoJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLmtleVxuICAgICAgICAgICAgICAgIH0nKWBcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBc3NldCBpcyBmcm9tIGEgZm9yZWlnbiBzb3VyY2UsIGJ1dCB3YXMgYWxyZWFkeSBpbXBvcnRlZCBhbmQgY2FuXG4gICAgICAgICAgICAvLyBiZSByZXVzZWQuIFNlZSBhYm92ZSBmb3IgYW4gZXhwbGFuYXRpb24gb2YgdGhpcyBtZXJnZS5cbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZmlsZSwgYXNzZXQuZmlsZSlcbiAgICAgICAgICAgIC8vIE5PVEU6IE5vIG5lZWQgdG8gYWRkIGBmaWxlYCB0byBgaW1wb3J0ZWRGaWxlc2AsIHNpbmNlIGl0J3NcbiAgICAgICAgICAgIC8vIGFscmVhZHkgYmVlbiBpbXBvcnRlZCB0byB0aGUgc3RvcmFnZSBiZWZvcmUuXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKVxuICAgIH1cbiAgICByZXR1cm4gaW1wb3J0ZWRGaWxlc1xuICB9XG5cbiAgYXN5bmMgaGFuZGxlTW9kaWZpZWRBc3NldHMoc3RvcmFnZSwgZmlsZXMsIHRyeCA9IG51bGwpIHtcbiAgICBjb25zdCBtb2RpZmllZEZpbGVzID0gW11cbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZmlsZXMubWFwKGFzeW5jIGZpbGUgPT4ge1xuICAgICAgICAgIGlmIChmaWxlLmRhdGEpIHtcbiAgICAgICAgICAgIGNvbnN0IGFzc2V0ID0gYXdhaXQgQXNzZXRNb2RlbC5xdWVyeSh0cngpLmZpbmRPbmUoJ2tleScsIGZpbGUua2V5KVxuICAgICAgICAgICAgaWYgKGFzc2V0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IGNoYW5nZWRGaWxlID0gYXdhaXQgc3RvcmFnZS5hZGRGaWxlKGZpbGUsIGZpbGUuZGF0YSlcbiAgICAgICAgICAgICAgLy8gTWVyZ2UgYmFjayB0aGUgY2hhbmdlZCBmaWxlIHByb3BlcnRpZXMgaW50byB0aGUgYWN0dWFsIGZpbGVzXG4gICAgICAgICAgICAgIC8vIG9iamVjdCwgc28gdGhhdCB0aGUgZGF0YSBmcm9tIHRoZSBzdGF0aWMgbW9kZWwgaG9vayBjYW4gYmUgdXNlZFxuICAgICAgICAgICAgICAvLyBkaXJlY3RseSBmb3IgdGhlIGFjdHVhbCBydW5uaW5nIHF1ZXJ5LlxuICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKGZpbGUsIGNoYW5nZWRGaWxlKVxuICAgICAgICAgICAgICBtb2RpZmllZEZpbGVzLnB1c2goY2hhbmdlZEZpbGUpXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXRFcnJvcihcbiAgICAgICAgICAgICAgICBgVW5hYmxlIHRvIHVwZGF0ZSBtb2RpZmllZCBhc3NldCBmcm9tIG1lbW9yeSBzb3VyY2U6ICcke1xuICAgICAgICAgICAgICAgICAgZmlsZS5uYW1lXG4gICAgICAgICAgICAgICAgfScgKCcke1xuICAgICAgICAgICAgICAgICAgZmlsZS5rZXlcbiAgICAgICAgICAgICAgICB9JylgXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiBtb2RpZmllZEZpbGVzXG4gIH1cblxuICBhc3luYyByZWxlYXNlVW51c2VkQXNzZXRzKHRpbWVUaHJlc2hvbGQgPSAwLCB0cnggPSBudWxsKSB7XG4gICAgY29uc3QgQXNzZXRNb2RlbCA9IHRoaXMuZ2V0TW9kZWwoJ0Fzc2V0JylcbiAgICBpZiAoQXNzZXRNb2RlbCkge1xuICAgICAgcmV0dXJuIEFzc2V0TW9kZWwudHJhbnNhY3Rpb24odHJ4LCBhc3luYyB0cnggPT4ge1xuICAgICAgICAvLyBEZXRlcm1pbmUgdGhlIHRpbWUgdGhyZXNob2xkIGluIEpTIGluc3RlYWQgb2YgU1FMLCBhcyB0aGVyZSBpcyBub1xuICAgICAgICAvLyBlYXN5IGNyb3NzLVNRTCB3YXkgdG8gZG8gYG5vdygpIC0gaW50ZXJ2YWwgWCBob3Vyc2A6XG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpXG4gICAgICAgIGRhdGUuc2V0TWlsbGlzZWNvbmRzKGRhdGUuZ2V0TWlsbGlzZWNvbmRzKCkgLSB0aW1lVGhyZXNob2xkKVxuICAgICAgICBjb25zdCBvcnBoYW5lZEFzc2V0cyA9IGF3YWl0IEFzc2V0TW9kZWxcbiAgICAgICAgICAucXVlcnkodHJ4KVxuICAgICAgICAgIC53aGVyZSgnY291bnQnLCAwKVxuICAgICAgICAgIC5hbmRXaGVyZSgndXBkYXRlZEF0JywgJzw9JywgZGF0ZSlcbiAgICAgICAgICAvLyBQcm90ZWN0IGZyZXNobHkgY3JlYXRlZCBhc3NldHMgZnJvbSBiZWluZyBkZWxldGVkIGFnYWluIHJpZ2h0IGF3YXksXG4gICAgICAgICAgLy8gLmUuZy4gd2hlbiBgY29uZmlnLmFzc2V0cy5jbGVhbnVwVGltZVRocmVzaG9sZCA9IDBgXG4gICAgICAgICAgLmFuZFdoZXJlKCd1cGRhdGVkQXQnLCAnPicsIHJlZignY3JlYXRlZEF0JykpXG4gICAgICAgIGlmIChvcnBoYW5lZEFzc2V0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3Qgb3JwaGFuZWRLZXlzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICBvcnBoYW5lZEFzc2V0cy5tYXAoYXN5bmMgYXNzZXQgPT4ge1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0U3RvcmFnZShhc3NldC5zdG9yYWdlKS5yZW1vdmVGaWxlKGFzc2V0LmZpbGUpXG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIGVycm9yKVxuICAgICAgICAgICAgICAgIGFzc2V0LmVycm9yID0gZXJyb3JcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gYXNzZXQua2V5XG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICAgICBhd2FpdCBBc3NldE1vZGVsXG4gICAgICAgICAgICAucXVlcnkodHJ4KVxuICAgICAgICAgICAgLmRlbGV0ZSgpXG4gICAgICAgICAgICAud2hlcmVJbigna2V5Jywgb3JwaGFuZWRLZXlzKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvcnBoYW5lZEFzc2V0c1xuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cblxuLy8gT3ZlcnJpZGUgS29hJ3MgZXZlbnRzIHdpdGggb3VyIG93biBFdmVudEVtaXR0ZXIgdGhhdCBhZGRzIHN1cHBvcnQgZm9yXG4vLyBhc3luY2hyb25vdXMgZXZlbnRzLlxuRXZlbnRFbWl0dGVyLm1peGluKEFwcGxpY2F0aW9uLnByb3RvdHlwZSlcblxuZnVuY3Rpb24gZ2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gIHJldHVybiBpc09iamVjdChvcHRpb25zKSA/IG9wdGlvbnMgOiB7fVxufVxuIl19