@decaf-ts/injectable-decorators 1.5.19 → 1.6.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.
- package/dist/injectable-decorators.cjs +323 -0
- package/dist/injectable-decorators.esm.cjs +310 -0
- package/lib/Injectables.cjs +1 -2
- package/lib/constants.cjs +1 -2
- package/lib/decorators.cjs +1 -2
- package/lib/esm/Injectables.d.ts +43 -0
- package/lib/esm/Injectables.js +1 -2
- package/lib/esm/constants.d.ts +15 -0
- package/lib/esm/constants.js +1 -2
- package/lib/esm/decorators.d.ts +51 -0
- package/lib/esm/decorators.js +1 -2
- package/{dist/types → lib/esm}/index.d.ts +1 -1
- package/lib/esm/index.js +2 -3
- package/lib/esm/registry.js +1 -2
- package/lib/esm/utils.js +1 -2
- package/lib/index.cjs +2 -3
- package/lib/index.d.ts +22 -0
- package/lib/registry.cjs +1 -2
- package/lib/registry.d.ts +61 -0
- package/lib/utils.cjs +1 -2
- package/lib/utils.d.ts +18 -0
- package/package.json +23 -39
- package/dist/esm/injectable-decorators.js +0 -2
- package/dist/esm/injectable-decorators.js.LICENSE.txt +0 -14
- package/dist/injectable-decorators.js +0 -2
- package/dist/injectable-decorators.js.LICENSE.txt +0 -14
- /package/{dist/types → lib}/Injectables.d.ts +0 -0
- /package/{dist/types → lib}/constants.d.ts +0 -0
- /package/{dist/types → lib}/decorators.d.ts +0 -0
- /package/{dist/types → lib/esm}/registry.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils.d.ts +0 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('reflect-metadata')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'reflect-metadata'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["injectable-decorators"] = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @summary Injectables Reflection keys
|
|
9
|
+
* @const InjectablesKeys
|
|
10
|
+
*
|
|
11
|
+
* @property {string} REFLECT Reflection injectables base key
|
|
12
|
+
* @property {string} INJECTABLE Reflection injectable key
|
|
13
|
+
* @property {string} INJECT Reflection inject key
|
|
14
|
+
*
|
|
15
|
+
* @memberOf injectable-decorators
|
|
16
|
+
*/
|
|
17
|
+
const InjectablesKeys = {
|
|
18
|
+
REFLECT: "inject.db.",
|
|
19
|
+
INJECTABLE: "injectable",
|
|
20
|
+
INJECT: "inject",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @summary Holds the vairous {@link Injectable}s
|
|
25
|
+
* @class InjectableRegistryImp
|
|
26
|
+
* @implements InjectablesRegistry
|
|
27
|
+
*/
|
|
28
|
+
class InjectableRegistryImp {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.cache = {};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
get(name, ...args) {
|
|
36
|
+
try {
|
|
37
|
+
const innerCache = this.cache[name];
|
|
38
|
+
const buildDef = { name: name };
|
|
39
|
+
if (!innerCache.singleton && !innerCache.instance)
|
|
40
|
+
return this.build(buildDef, ...args);
|
|
41
|
+
return innerCache.instance || this.build(buildDef, ...args);
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @inheritDoc
|
|
50
|
+
*/
|
|
51
|
+
register(obj, category = undefined, isSingleton = true, force = false) {
|
|
52
|
+
const castObj = obj;
|
|
53
|
+
const constructor = !castObj.name && castObj.constructor;
|
|
54
|
+
if (typeof castObj !== "function" && !constructor)
|
|
55
|
+
throw new Error(`Injectable registering failed. Missing Class name or constructor`);
|
|
56
|
+
const name = category ||
|
|
57
|
+
(constructor && constructor.name && constructor.name !== "Function"
|
|
58
|
+
? constructor.name
|
|
59
|
+
: castObj.name);
|
|
60
|
+
if (!this.cache[name] || force)
|
|
61
|
+
this.cache[name] = {
|
|
62
|
+
instance: constructor ? obj : undefined,
|
|
63
|
+
constructor: !constructor ? obj : undefined,
|
|
64
|
+
singleton: isSingleton,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @inheritDoc
|
|
69
|
+
*/
|
|
70
|
+
build(defs, ...args) {
|
|
71
|
+
const { constructor, singleton } = this.cache[defs.name];
|
|
72
|
+
const instance = new constructor(...args);
|
|
73
|
+
this.cache[defs.name] = {
|
|
74
|
+
instance: instance,
|
|
75
|
+
constructor: constructor,
|
|
76
|
+
singleton: singleton,
|
|
77
|
+
};
|
|
78
|
+
return instance;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @summary Static class Holding the access to the injectables functions
|
|
84
|
+
*
|
|
85
|
+
* @class Injectables
|
|
86
|
+
* @static
|
|
87
|
+
*/
|
|
88
|
+
class Injectables {
|
|
89
|
+
static { this.actingInjectablesRegistry = undefined; }
|
|
90
|
+
constructor() { }
|
|
91
|
+
/**
|
|
92
|
+
* @summary Retrieves the named {@link Injectable} from the registry
|
|
93
|
+
* @param {string} name
|
|
94
|
+
* @param {any[]} args
|
|
95
|
+
*/
|
|
96
|
+
static get(name, ...args) {
|
|
97
|
+
return Injectables.getRegistry().get(name, ...args);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @summary registers an injectable constructor
|
|
101
|
+
* @param {Injectable} constructor
|
|
102
|
+
* @param {any[]} args
|
|
103
|
+
*
|
|
104
|
+
*/
|
|
105
|
+
static register(constructor, ...args) {
|
|
106
|
+
return Injectables.getRegistry().register(constructor, ...args);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* @summary Instantiates an Injectable
|
|
110
|
+
* @param {Record<string, any>} obj
|
|
111
|
+
* @param {any[]} args
|
|
112
|
+
* @return T
|
|
113
|
+
*
|
|
114
|
+
*/
|
|
115
|
+
static build(obj, ...args) {
|
|
116
|
+
return Injectables.getRegistry().build(obj, ...args);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* @summary Sets a new {@link InjectablesRegistry}
|
|
120
|
+
* @param {InjectablesRegistry} operationsRegistry the new implementation of Registry
|
|
121
|
+
*/
|
|
122
|
+
static setRegistry(operationsRegistry) {
|
|
123
|
+
Injectables.actingInjectablesRegistry = operationsRegistry;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* @summary Returns the current {@link InjectablesRegistry}
|
|
127
|
+
*/
|
|
128
|
+
static getRegistry() {
|
|
129
|
+
if (!Injectables.actingInjectablesRegistry)
|
|
130
|
+
Injectables.actingInjectablesRegistry = new InjectableRegistryImp();
|
|
131
|
+
return Injectables.actingInjectablesRegistry;
|
|
132
|
+
}
|
|
133
|
+
static reset() {
|
|
134
|
+
Injectables.setRegistry(new InjectableRegistryImp());
|
|
135
|
+
}
|
|
136
|
+
static selectiveReset(match) {
|
|
137
|
+
const regexp = typeof match === "string" ? new RegExp(match) : match;
|
|
138
|
+
Injectables.actingInjectablesRegistry["cache"] = Object.entries(Injectables.actingInjectablesRegistry["cache"]).reduce((accum, [key, val]) => {
|
|
139
|
+
if (!key.match(regexp))
|
|
140
|
+
accum[key] = val;
|
|
141
|
+
return accum;
|
|
142
|
+
}, {});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @summary holds the key for the design type
|
|
148
|
+
* @const TypeKey
|
|
149
|
+
* @memberOf module:injectable-decorators
|
|
150
|
+
*/
|
|
151
|
+
const TypeKey = "design:type";
|
|
152
|
+
/**
|
|
153
|
+
* @summary Retrieves the type from the decorators
|
|
154
|
+
* @param {any} model
|
|
155
|
+
* @param {string | symbol} propKey
|
|
156
|
+
* @return {string | undefined}
|
|
157
|
+
*
|
|
158
|
+
* @function geTypeFromDecorators
|
|
159
|
+
*
|
|
160
|
+
* @memberOf module:injectable-decorators
|
|
161
|
+
*/
|
|
162
|
+
function getTypeFromDecorator(model, propKey) {
|
|
163
|
+
const typeDef = Reflect.getMetadata(TypeKey, model, propKey);
|
|
164
|
+
return typeDef.name !== "Function" ? typeDef.name : undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @summary Return the reflection key for injectables
|
|
169
|
+
*
|
|
170
|
+
* @param {string} key
|
|
171
|
+
* @function getInjectKey
|
|
172
|
+
*
|
|
173
|
+
* @memberOf module:injectable-decorators
|
|
174
|
+
*/
|
|
175
|
+
const getInjectKey = (key) => InjectablesKeys.REFLECT + key;
|
|
176
|
+
/**
|
|
177
|
+
* @summary Defines a class as an injectable
|
|
178
|
+
*
|
|
179
|
+
* @param {string} [category] defaults to the class Name. (Useful when minification occours and names are changed so we can no longer rely on the class name, or when we want to upcast the Object)
|
|
180
|
+
* @param {boolean} [force] defines if the injectable should override the already existing instance (if any). (only meant for extending decorators
|
|
181
|
+
* @param instanceCallback
|
|
182
|
+
*
|
|
183
|
+
* @function injectable
|
|
184
|
+
*
|
|
185
|
+
* @memberOf module:injectable-decorators.Decorators
|
|
186
|
+
*/
|
|
187
|
+
const injectable = (category = undefined, force = false, instanceCallback) =>
|
|
188
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
189
|
+
(original, propertyKey) => {
|
|
190
|
+
const name = category || original.name;
|
|
191
|
+
// the new constructor behaviour
|
|
192
|
+
const newConstructor = function (...args) {
|
|
193
|
+
let inj = Injectables.get(name, ...args);
|
|
194
|
+
if (!inj) {
|
|
195
|
+
Injectables.register(original, name, true, force);
|
|
196
|
+
inj = Injectables.get(name, ...args);
|
|
197
|
+
if (!inj)
|
|
198
|
+
return undefined;
|
|
199
|
+
if (instanceCallback)
|
|
200
|
+
try {
|
|
201
|
+
instanceCallback(inj);
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
console.error(`Failed to call injectable callback for ${name}: ${e}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const metadata = Object.assign({}, {
|
|
208
|
+
class: name,
|
|
209
|
+
});
|
|
210
|
+
Reflect.defineMetadata(getInjectKey(InjectablesKeys.INJECTABLE), metadata, inj.constructor);
|
|
211
|
+
return inj;
|
|
212
|
+
};
|
|
213
|
+
// copy prototype so instanceof operator still works
|
|
214
|
+
newConstructor.prototype = original.prototype;
|
|
215
|
+
// newConstructor.__proto__ = original.__proto__;
|
|
216
|
+
// Sets the proper constructor name for type verification
|
|
217
|
+
Object.defineProperty(newConstructor, "name", {
|
|
218
|
+
writable: false,
|
|
219
|
+
enumerable: true,
|
|
220
|
+
configurable: false,
|
|
221
|
+
value: original.prototype.constructor.name,
|
|
222
|
+
});
|
|
223
|
+
// return new constructor (will override original)
|
|
224
|
+
return newConstructor;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* @summary Allows for the injection of an {@link injectable} decorated dependency
|
|
228
|
+
* @description the property must be typed for the requested dependency.
|
|
229
|
+
*
|
|
230
|
+
* Only concrete classes. No generics are supported
|
|
231
|
+
*
|
|
232
|
+
* Injected properties should be described like so:
|
|
233
|
+
* <pre>
|
|
234
|
+
* class ClassName {
|
|
235
|
+
* ...
|
|
236
|
+
*
|
|
237
|
+
* @inject()
|
|
238
|
+
* propertyName!: InjectableClass;
|
|
239
|
+
*
|
|
240
|
+
* ...
|
|
241
|
+
* }
|
|
242
|
+
* </pre>
|
|
243
|
+
*
|
|
244
|
+
* where InjectableClass is the class you want to inject.
|
|
245
|
+
* Notice the use of '!:' to ensure the transpiler the property will be set outside the constructor but will always be defined
|
|
246
|
+
* For project where minification occours, you should use the category param to ensure the name is the same throughout
|
|
247
|
+
*
|
|
248
|
+
* @param {string} [category] defaults to the class Name. (Useful when minification occours and names are changed so we can no longer rely on the class name, or when we want to upcast the Object)
|
|
249
|
+
* @param {InstanceTransformer} [transformer]
|
|
250
|
+
*
|
|
251
|
+
* @function inject
|
|
252
|
+
*
|
|
253
|
+
* @memberOf module:injectable-decorators.Decorators
|
|
254
|
+
*/
|
|
255
|
+
const inject = (category, transformer) => (target, propertyKey) => {
|
|
256
|
+
const values = new WeakMap();
|
|
257
|
+
const name = category || getTypeFromDecorator(target, propertyKey);
|
|
258
|
+
if (!name)
|
|
259
|
+
throw new Error(`Could not get Type from decorator`);
|
|
260
|
+
Reflect.defineMetadata(getInjectKey(InjectablesKeys.INJECT), {
|
|
261
|
+
injectable: name,
|
|
262
|
+
}, target, propertyKey);
|
|
263
|
+
Object.defineProperty(target, propertyKey, {
|
|
264
|
+
configurable: true,
|
|
265
|
+
get() {
|
|
266
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
|
|
267
|
+
if (descriptor.configurable) {
|
|
268
|
+
Object.defineProperty(this, propertyKey, {
|
|
269
|
+
enumerable: true,
|
|
270
|
+
configurable: false,
|
|
271
|
+
get() {
|
|
272
|
+
let obj = values.get(this);
|
|
273
|
+
if (!obj) {
|
|
274
|
+
obj = Injectables.get(name);
|
|
275
|
+
if (!obj)
|
|
276
|
+
throw new Error(`Could not get Injectable ${name} to inject in ${target.constructor ? target.constructor.name : target.name}'s ${propertyKey}`);
|
|
277
|
+
if (transformer)
|
|
278
|
+
try {
|
|
279
|
+
obj = transformer(obj, target);
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
console.error(e);
|
|
283
|
+
}
|
|
284
|
+
values.set(this, obj);
|
|
285
|
+
}
|
|
286
|
+
return obj;
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
return this[propertyKey];
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @summary Adds a simple Injectables implementation to create singleton instances of an object
|
|
297
|
+
* and easily inject it into other objects
|
|
298
|
+
*
|
|
299
|
+
* @module injectable-decorators
|
|
300
|
+
*/
|
|
301
|
+
/**
|
|
302
|
+
* @summary functions that decorate classes or class properties
|
|
303
|
+
* @namespace Decorators
|
|
304
|
+
* @memberOf module:injectable-decorators
|
|
305
|
+
*/
|
|
306
|
+
/**
|
|
307
|
+
* @summary Defined on library build. holds the library current version
|
|
308
|
+
* @const VERSION
|
|
309
|
+
* @memberOf module:injectable-decorators
|
|
310
|
+
*/
|
|
311
|
+
const VERSION = "1.6.0";
|
|
312
|
+
|
|
313
|
+
exports.InjectableRegistryImp = InjectableRegistryImp;
|
|
314
|
+
exports.Injectables = Injectables;
|
|
315
|
+
exports.InjectablesKeys = InjectablesKeys;
|
|
316
|
+
exports.TypeKey = TypeKey;
|
|
317
|
+
exports.VERSION = VERSION;
|
|
318
|
+
exports.getTypeFromDecorator = getTypeFromDecorator;
|
|
319
|
+
exports.inject = inject;
|
|
320
|
+
exports.injectable = injectable;
|
|
321
|
+
|
|
322
|
+
}));
|
|
323
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5qZWN0YWJsZS1kZWNvcmF0b3JzLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0YW50cy50cyIsIi4uL3NyYy9yZWdpc3RyeS50cyIsIi4uL3NyYy9JbmplY3RhYmxlcy50cyIsIi4uL3NyYy91dGlscy50cyIsIi4uL3NyYy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHN1bW1hcnkgSW5qZWN0YWJsZXMgUmVmbGVjdGlvbiBrZXlzXG4gKiBAY29uc3QgSW5qZWN0YWJsZXNLZXlzXG4gKlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFRkxFQ1QgUmVmbGVjdGlvbiBpbmplY3RhYmxlcyBiYXNlIGtleVxuICogQHByb3BlcnR5IHtzdHJpbmd9IElOSkVDVEFCTEUgUmVmbGVjdGlvbiBpbmplY3RhYmxlIGtleVxuICogQHByb3BlcnR5IHtzdHJpbmd9IElOSkVDVCBSZWZsZWN0aW9uIGluamVjdCBrZXlcbiAqXG4gKiBAbWVtYmVyT2YgaW5qZWN0YWJsZS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBJbmplY3RhYmxlc0tleXMgPSB7XG4gIFJFRkxFQ1Q6IFwiaW5qZWN0LmRiLlwiLFxuICBJTkpFQ1RBQkxFOiBcImluamVjdGFibGVcIixcbiAgSU5KRUNUOiBcImluamVjdFwiLFxufTtcbiIsIi8qKlxuICogQHN1bW1hcnkgZGVmaW5lcyBhbiBJbmplY3RhYmxlIHR5cGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6aW5qZWN0YWJsZS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCB0eXBlIEluamVjdGFibGU8VD4gPSB7IG5ldyAoLi4uYXJnczogYW55W10pOiBUIH0gfCBUO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEludGVyZmFjZSBmb3IgYW4gaW5qZWN0YWJsZSByZWdpc3RyeVxuICogQGludGVyZmFjZSBJbmplY3RhYmxlUmVnaXN0cnlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmplY3RhYmxlc1JlZ2lzdHJ5IHtcbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHJldHJpZXZlcyBhbiB7QGxpbmsgSW5qZWN0YWJsZX1cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJnc1xuICAgKiBAcmV0dXJuIHtJbmplY3RhYmxlIHwgdW5kZWZpbmVkfVxuICAgKlxuICAgKiBAbWV0aG9kXG4gICAqL1xuICBnZXQ8VD4obmFtZTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSk6IEluamVjdGFibGU8VD4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHJlZ2lzdGVycyBhbiBpbmplY3RhYmxlIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7SW5qZWN0YWJsZX0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHthbnlbXX0gYXJnc1xuICAgKlxuICAgKiBAbWV0aG9kXG4gICAqL1xuICByZWdpc3RlcjxUPihjb25zdHJ1Y3RvcjogSW5qZWN0YWJsZTxUPiwgLi4uYXJnczogYW55W10pOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBJbnN0YW50aWF0ZXMgYW4gSW5qZWN0YWJsZVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9ialxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzXG4gICAqIEByZXR1cm4gVFxuICAgKlxuICAgKiBAbWV0aG9kXG4gICAqL1xuICBidWlsZDxUPihvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4sIC4uLmFyZ3M6IGFueVtdKTogVDtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBIb2xkcyB0aGUgdmFpcm91cyB7QGxpbmsgSW5qZWN0YWJsZX1zXG4gKiBAY2xhc3MgSW5qZWN0YWJsZVJlZ2lzdHJ5SW1wXG4gKiBAaW1wbGVtZW50cyBJbmplY3RhYmxlc1JlZ2lzdHJ5XG4gKi9cbmV4cG9ydCBjbGFzcyBJbmplY3RhYmxlUmVnaXN0cnlJbXAgaW1wbGVtZW50cyBJbmplY3RhYmxlc1JlZ2lzdHJ5IHtcbiAgcHJpdmF0ZSBjYWNoZTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55IH0gPSB7fTtcblxuICAvKipcbiAgICogQGluaGVyaXREb2NcbiAgICovXG4gIGdldDxUPihuYW1lOiBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKTogVCB8IHVuZGVmaW5lZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGlubmVyQ2FjaGUgPSB0aGlzLmNhY2hlW25hbWVdO1xuICAgICAgY29uc3QgYnVpbGREZWYgPSB7IG5hbWU6IG5hbWUgfTtcbiAgICAgIGlmICghaW5uZXJDYWNoZS5zaW5nbGV0b24gJiYgIWlubmVyQ2FjaGUuaW5zdGFuY2UpXG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkPFQ+KGJ1aWxkRGVmLCAuLi5hcmdzKTtcbiAgICAgIHJldHVybiBpbm5lckNhY2hlLmluc3RhbmNlIHx8IHRoaXMuYnVpbGQ8VD4oYnVpbGREZWYsIC4uLmFyZ3MpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBAaW5oZXJpdERvY1xuICAgKi9cbiAgcmVnaXN0ZXI8VD4oXG4gICAgb2JqOiBJbmplY3RhYmxlPFQ+LFxuICAgIGNhdGVnb3J5OiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICAgaXNTaW5nbGV0b246IGJvb2xlYW4gPSB0cnVlLFxuICAgIGZvcmNlOiBib29sZWFuID0gZmFsc2VcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgY2FzdE9iajogUmVjb3JkPHN0cmluZywgYW55PiA9IG9iaiBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG4gICAgY29uc3QgY29uc3RydWN0b3IgPSAhY2FzdE9iai5uYW1lICYmIGNhc3RPYmouY29uc3RydWN0b3I7XG4gICAgaWYgKHR5cGVvZiBjYXN0T2JqICE9PSBcImZ1bmN0aW9uXCIgJiYgIWNvbnN0cnVjdG9yKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW5qZWN0YWJsZSByZWdpc3RlcmluZyBmYWlsZWQuIE1pc3NpbmcgQ2xhc3MgbmFtZSBvciBjb25zdHJ1Y3RvcmBcbiAgICAgICk7XG5cbiAgICBjb25zdCBuYW1lID1cbiAgICAgIGNhdGVnb3J5IHx8XG4gICAgICAoY29uc3RydWN0b3IgJiYgY29uc3RydWN0b3IubmFtZSAmJiBjb25zdHJ1Y3Rvci5uYW1lICE9PSBcIkZ1bmN0aW9uXCJcbiAgICAgICAgPyAoY29uc3RydWN0b3IgYXMgeyBbaW5kZXhlcjogc3RyaW5nXTogYW55IH0pLm5hbWVcbiAgICAgICAgOiBjYXN0T2JqLm5hbWUpO1xuXG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdIHx8IGZvcmNlKVxuICAgICAgdGhpcy5jYWNoZVtuYW1lXSA9IHtcbiAgICAgICAgaW5zdGFuY2U6IGNvbnN0cnVjdG9yID8gb2JqIDogdW5kZWZpbmVkLFxuICAgICAgICBjb25zdHJ1Y3RvcjogIWNvbnN0cnVjdG9yID8gb2JqIDogdW5kZWZpbmVkLFxuICAgICAgICBzaW5nbGV0b246IGlzU2luZ2xldG9uLFxuICAgICAgfTtcbiAgfVxuICAvKipcbiAgICogQGluaGVyaXREb2NcbiAgICovXG4gIGJ1aWxkPFQ+KGRlZnM6IHsgbmFtZTogc3RyaW5nIH0sIC4uLmFyZ3M6IGFueVtdKTogVCB7XG4gICAgY29uc3QgeyBjb25zdHJ1Y3Rvciwgc2luZ2xldG9uIH0gPSB0aGlzLmNhY2hlW2RlZnMubmFtZV07XG4gICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgY29uc3RydWN0b3IoLi4uYXJncyk7XG4gICAgdGhpcy5jYWNoZVtkZWZzLm5hbWVdID0ge1xuICAgICAgaW5zdGFuY2U6IGluc3RhbmNlLFxuICAgICAgY29uc3RydWN0b3I6IGNvbnN0cnVjdG9yLFxuICAgICAgc2luZ2xldG9uOiBzaW5nbGV0b24sXG4gICAgfTtcbiAgICByZXR1cm4gaW5zdGFuY2U7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEluamVjdGFibGUsXG4gIEluamVjdGFibGVSZWdpc3RyeUltcCxcbiAgSW5qZWN0YWJsZXNSZWdpc3RyeSxcbn0gZnJvbSBcIi4vcmVnaXN0cnlcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBTdGF0aWMgY2xhc3MgSG9sZGluZyB0aGUgYWNjZXNzIHRvIHRoZSBpbmplY3RhYmxlcyBmdW5jdGlvbnNcbiAqXG4gKiBAY2xhc3MgSW5qZWN0YWJsZXNcbiAqIEBzdGF0aWNcbiAqL1xuZXhwb3J0IGNsYXNzIEluamVjdGFibGVzIHtcbiAgcHJpdmF0ZSBzdGF0aWMgYWN0aW5nSW5qZWN0YWJsZXNSZWdpc3RyeT86IEluamVjdGFibGVzUmVnaXN0cnkgPSB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgbmFtZWQge0BsaW5rIEluamVjdGFibGV9IGZyb20gdGhlIHJlZ2lzdHJ5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3NcbiAgICovXG4gIHN0YXRpYyBnZXQ8VD4obmFtZTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSk6IEluamVjdGFibGU8VD4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBJbmplY3RhYmxlcy5nZXRSZWdpc3RyeSgpLmdldChuYW1lLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZWdpc3RlcnMgYW4gaW5qZWN0YWJsZSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge0luamVjdGFibGV9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3NcbiAgICpcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlcjxUPihjb25zdHJ1Y3RvcjogSW5qZWN0YWJsZTxUPiwgLi4uYXJnczogYW55W10pOiB2b2lkIHtcbiAgICByZXR1cm4gSW5qZWN0YWJsZXMuZ2V0UmVnaXN0cnkoKS5yZWdpc3Rlcihjb25zdHJ1Y3RvciwgLi4uYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgSW5zdGFudGlhdGVzIGFuIEluamVjdGFibGVcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAgICogQHBhcmFtIHthbnlbXX0gYXJnc1xuICAgKiBAcmV0dXJuIFRcbiAgICpcbiAgICovXG4gIHN0YXRpYyBidWlsZDxUPihvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4sIC4uLmFyZ3M6IGFueVtdKTogVCB7XG4gICAgcmV0dXJuIEluamVjdGFibGVzLmdldFJlZ2lzdHJ5KCkuYnVpbGQob2JqLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBTZXRzIGEgbmV3IHtAbGluayBJbmplY3RhYmxlc1JlZ2lzdHJ5fVxuICAgKiBAcGFyYW0ge0luamVjdGFibGVzUmVnaXN0cnl9IG9wZXJhdGlvbnNSZWdpc3RyeSB0aGUgbmV3IGltcGxlbWVudGF0aW9uIG9mIFJlZ2lzdHJ5XG4gICAqL1xuICBzdGF0aWMgc2V0UmVnaXN0cnkob3BlcmF0aW9uc1JlZ2lzdHJ5OiBJbmplY3RhYmxlc1JlZ2lzdHJ5KSB7XG4gICAgSW5qZWN0YWJsZXMuYWN0aW5nSW5qZWN0YWJsZXNSZWdpc3RyeSA9IG9wZXJhdGlvbnNSZWdpc3RyeTtcbiAgfVxuICAvKipcbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgY3VycmVudCB7QGxpbmsgSW5qZWN0YWJsZXNSZWdpc3RyeX1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldFJlZ2lzdHJ5KCkge1xuICAgIGlmICghSW5qZWN0YWJsZXMuYWN0aW5nSW5qZWN0YWJsZXNSZWdpc3RyeSlcbiAgICAgIEluamVjdGFibGVzLmFjdGluZ0luamVjdGFibGVzUmVnaXN0cnkgPSBuZXcgSW5qZWN0YWJsZVJlZ2lzdHJ5SW1wKCk7XG4gICAgcmV0dXJuIEluamVjdGFibGVzLmFjdGluZ0luamVjdGFibGVzUmVnaXN0cnk7XG4gIH1cblxuICBzdGF0aWMgcmVzZXQoKSB7XG4gICAgSW5qZWN0YWJsZXMuc2V0UmVnaXN0cnkobmV3IEluamVjdGFibGVSZWdpc3RyeUltcCgpKTtcbiAgfVxuXG4gIHN0YXRpYyBzZWxlY3RpdmVSZXNldChtYXRjaDogc3RyaW5nIHwgUmVnRXhwKSB7XG4gICAgY29uc3QgcmVnZXhwID0gdHlwZW9mIG1hdGNoID09PSBcInN0cmluZ1wiID8gbmV3IFJlZ0V4cChtYXRjaCkgOiBtYXRjaDtcbiAgICAoSW5qZWN0YWJsZXMuYWN0aW5nSW5qZWN0YWJsZXNSZWdpc3RyeSBhcyBhbnkpW1wiY2FjaGVcIl0gPSBPYmplY3QuZW50cmllcyhcbiAgICAgIChJbmplY3RhYmxlcy5hY3RpbmdJbmplY3RhYmxlc1JlZ2lzdHJ5IGFzIGFueSlbXCJjYWNoZVwiXVxuICAgICkucmVkdWNlKChhY2N1bTogUmVjb3JkPHN0cmluZywgYW55PiwgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgaWYgKCFrZXkubWF0Y2gocmVnZXhwKSkgYWNjdW1ba2V5XSA9IHZhbDtcbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCB7fSk7XG4gIH1cbn1cbiIsImltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBob2xkcyB0aGUga2V5IGZvciB0aGUgZGVzaWduIHR5cGVcbiAqIEBjb25zdCBUeXBlS2V5XG4gKiBAbWVtYmVyT2YgIG1vZHVsZTppbmplY3RhYmxlLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IFR5cGVLZXkgPSBcImRlc2lnbjp0eXBlXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSB0eXBlIGZyb20gdGhlIGRlY29yYXRvcnNcbiAqIEBwYXJhbSB7YW55fSBtb2RlbFxuICogQHBhcmFtIHtzdHJpbmcgfCBzeW1ib2x9IHByb3BLZXlcbiAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAqXG4gKiBAZnVuY3Rpb24gZ2VUeXBlRnJvbURlY29yYXRvcnNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmluamVjdGFibGUtZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHlwZUZyb21EZWNvcmF0b3IoXG4gIG1vZGVsOiBhbnksXG4gIHByb3BLZXk6IHN0cmluZyB8IHN5bWJvbCxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHR5cGVEZWYgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFR5cGVLZXksIG1vZGVsLCBwcm9wS2V5KTtcbiAgcmV0dXJuIHR5cGVEZWYubmFtZSAhPT0gXCJGdW5jdGlvblwiID8gdHlwZURlZi5uYW1lIDogdW5kZWZpbmVkO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZXNLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJbmplY3RhYmxlcyB9IGZyb20gXCIuL0luamVjdGFibGVzXCI7XG5pbXBvcnQgeyBnZXRUeXBlRnJvbURlY29yYXRvciB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgUmV0dXJuIHRoZSByZWZsZWN0aW9uIGtleSBmb3IgaW5qZWN0YWJsZXNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gKiBAZnVuY3Rpb24gZ2V0SW5qZWN0S2V5XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTppbmplY3RhYmxlLWRlY29yYXRvcnNcbiAqL1xuY29uc3QgZ2V0SW5qZWN0S2V5ID0gKGtleTogc3RyaW5nKSA9PiBJbmplY3RhYmxlc0tleXMuUkVGTEVDVCArIGtleTtcblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgY2xhc3MgYXMgYW4gaW5qZWN0YWJsZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbY2F0ZWdvcnldIGRlZmF1bHRzIHRvIHRoZSBjbGFzcyBOYW1lLiAoVXNlZnVsIHdoZW4gbWluaWZpY2F0aW9uIG9jY291cnMgYW5kIG5hbWVzIGFyZSBjaGFuZ2VkIHNvIHdlIGNhbiBubyBsb25nZXIgcmVseSBvbiB0aGUgY2xhc3MgbmFtZSwgb3Igd2hlbiB3ZSB3YW50IHRvIHVwY2FzdCB0aGUgT2JqZWN0KVxuICogQHBhcmFtIHtib29sZWFufSBbZm9yY2VdIGRlZmluZXMgaWYgdGhlIGluamVjdGFibGUgc2hvdWxkIG92ZXJyaWRlIHRoZSBhbHJlYWR5IGV4aXN0aW5nIGluc3RhbmNlIChpZiBhbnkpLiAob25seSBtZWFudCBmb3IgZXh0ZW5kaW5nIGRlY29yYXRvcnNcbiAqIEBwYXJhbSBpbnN0YW5jZUNhbGxiYWNrXG4gKlxuICogQGZ1bmN0aW9uIGluamVjdGFibGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmluamVjdGFibGUtZGVjb3JhdG9ycy5EZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBpbmplY3RhYmxlID1cbiAgKFxuICAgIGNhdGVnb3J5OiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICAgZm9yY2U6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICBpbnN0YW5jZUNhbGxiYWNrPzogKGluc3RhbmNlOiBhbnksIC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkXG4gICkgPT5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAob3JpZ2luYWw6IGFueSwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCBuYW1lID0gY2F0ZWdvcnkgfHwgb3JpZ2luYWwubmFtZTtcbiAgICAvLyB0aGUgbmV3IGNvbnN0cnVjdG9yIGJlaGF2aW91clxuICAgIGNvbnN0IG5ld0NvbnN0cnVjdG9yOiBhbnkgPSBmdW5jdGlvbiAoLi4uYXJnczogYW55W10pIHtcbiAgICAgIGxldCBpbmo6IGFueSA9IEluamVjdGFibGVzLmdldDxhbnk+KG5hbWUsIC4uLmFyZ3MpO1xuICAgICAgaWYgKCFpbmopIHtcbiAgICAgICAgSW5qZWN0YWJsZXMucmVnaXN0ZXIob3JpZ2luYWwsIG5hbWUsIHRydWUsIGZvcmNlKTtcbiAgICAgICAgaW5qID0gSW5qZWN0YWJsZXMuZ2V0PGFueT4obmFtZSwgLi4uYXJncyk7XG4gICAgICAgIGlmICghaW5qKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChpbnN0YW5jZUNhbGxiYWNrKVxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpbnN0YW5jZUNhbGxiYWNrKGluaik7XG4gICAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIGNhbGwgaW5qZWN0YWJsZSBjYWxsYmFjayBmb3IgJHtuYW1lfTogJHtlfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBtZXRhZGF0YSA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIHt9LFxuICAgICAgICB7XG4gICAgICAgICAgY2xhc3M6IG5hbWUsXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIFJlZmxlY3QuZGVmaW5lTWV0YWRhdGEoXG4gICAgICAgIGdldEluamVjdEtleShJbmplY3RhYmxlc0tleXMuSU5KRUNUQUJMRSksXG4gICAgICAgIG1ldGFkYXRhLFxuICAgICAgICBpbmouY29uc3RydWN0b3JcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBpbmo7XG4gICAgfTtcblxuICAgIC8vIGNvcHkgcHJvdG90eXBlIHNvIGluc3RhbmNlb2Ygb3BlcmF0b3Igc3RpbGwgd29ya3NcbiAgICBuZXdDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBvcmlnaW5hbC5wcm90b3R5cGU7XG4gICAgLy8gbmV3Q29uc3RydWN0b3IuX19wcm90b19fID0gb3JpZ2luYWwuX19wcm90b19fO1xuICAgIC8vIFNldHMgdGhlIHByb3BlciBjb25zdHJ1Y3RvciBuYW1lIGZvciB0eXBlIHZlcmlmaWNhdGlvblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuZXdDb25zdHJ1Y3RvciwgXCJuYW1lXCIsIHtcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgdmFsdWU6IG9yaWdpbmFsLnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgIH0pO1xuICAgIC8vIHJldHVybiBuZXcgY29uc3RydWN0b3IgKHdpbGwgb3ZlcnJpZGUgb3JpZ2luYWwpXG4gICAgcmV0dXJuIG5ld0NvbnN0cnVjdG9yO1xuICB9O1xuXG4vKipcbiAqIEBzdW1tYXJ5IGZ1bmN0aW9uIHdpdGNoIHRyYW5zZm9ybXMgYSBjYWNoZWQge0BsaW5rIGluamVjdGFibGV9XG4gKlxuICogQHBhcmFtIHthbnl9IGluamVjdGFibGVcbiAqIEBwYXJhbSB7YW55fSBvYmogdGhlIG9iaiB0aGUgaW5qZWN0YWJsZSB3aWxsIGJlIGluamVjdGVkIG9uXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTppbmplY3RhYmxlLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IHR5cGUgSW5zdGFuY2VUcmFuc2Zvcm1lciA9IChpbmplY3RhYmxlOiBhbnksIG9iajogYW55KSA9PiBhbnk7XG5cbi8qKlxuICogQHN1bW1hcnkgQWxsb3dzIGZvciB0aGUgaW5qZWN0aW9uIG9mIGFuIHtAbGluayBpbmplY3RhYmxlfSBkZWNvcmF0ZWQgZGVwZW5kZW5jeVxuICogQGRlc2NyaXB0aW9uIHRoZSBwcm9wZXJ0eSBtdXN0IGJlIHR5cGVkIGZvciB0aGUgcmVxdWVzdGVkIGRlcGVuZGVuY3kuXG4gKlxuICogT25seSBjb25jcmV0ZSBjbGFzc2VzLiBObyBnZW5lcmljcyBhcmUgc3VwcG9ydGVkXG4gKlxuICogSW5qZWN0ZWQgcHJvcGVydGllcyBzaG91bGQgYmUgZGVzY3JpYmVkIGxpa2Ugc286XG4gKiA8cHJlPlxuICogICAgIGNsYXNzIENsYXNzTmFtZSB7XG4gKiAgICAgICAgIC4uLlxuICpcbiAqICAgICAgICAgQGluamVjdCgpXG4gKiAgICAgICAgIHByb3BlcnR5TmFtZSE6IEluamVjdGFibGVDbGFzcztcbiAqXG4gKiAgICAgICAgIC4uLlxuICogICAgIH1cbiAqIDwvcHJlPlxuICpcbiAqIHdoZXJlIEluamVjdGFibGVDbGFzcyBpcyB0aGUgY2xhc3MgeW91IHdhbnQgdG8gaW5qZWN0LlxuICogTm90aWNlIHRoZSB1c2Ugb2YgJyE6JyB0byBlbnN1cmUgdGhlIHRyYW5zcGlsZXIgdGhlIHByb3BlcnR5IHdpbGwgYmUgc2V0IG91dHNpZGUgdGhlIGNvbnN0cnVjdG9yIGJ1dCB3aWxsIGFsd2F5cyBiZSBkZWZpbmVkXG4gKiBGb3IgcHJvamVjdCB3aGVyZSBtaW5pZmljYXRpb24gb2Njb3VycywgeW91IHNob3VsZCB1c2UgdGhlIGNhdGVnb3J5IHBhcmFtIHRvIGVuc3VyZSB0aGUgbmFtZSBpcyB0aGUgc2FtZSB0aHJvdWdob3V0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFtjYXRlZ29yeV0gZGVmYXVsdHMgdG8gdGhlIGNsYXNzIE5hbWUuIChVc2VmdWwgd2hlbiBtaW5pZmljYXRpb24gb2Njb3VycyBhbmQgbmFtZXMgYXJlIGNoYW5nZWQgc28gd2UgY2FuIG5vIGxvbmdlciByZWx5IG9uIHRoZSBjbGFzcyBuYW1lLCBvciB3aGVuIHdlIHdhbnQgdG8gdXBjYXN0IHRoZSBPYmplY3QpXG4gKiBAcGFyYW0ge0luc3RhbmNlVHJhbnNmb3JtZXJ9IFt0cmFuc2Zvcm1lcl1cbiAqXG4gKiBAZnVuY3Rpb24gaW5qZWN0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTppbmplY3RhYmxlLWRlY29yYXRvcnMuRGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgaW5qZWN0ID1cbiAgKGNhdGVnb3J5Pzogc3RyaW5nLCB0cmFuc2Zvcm1lcj86IEluc3RhbmNlVHJhbnNmb3JtZXIpID0+XG4gICh0YXJnZXQ6IGFueSwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCB2YWx1ZXMgPSBuZXcgV2Vha01hcCgpO1xuXG4gICAgY29uc3QgbmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkID1cbiAgICAgIGNhdGVnb3J5IHx8IGdldFR5cGVGcm9tRGVjb3JhdG9yKHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICAgIGlmICghbmFtZSkgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZ2V0IFR5cGUgZnJvbSBkZWNvcmF0b3JgKTtcblxuICAgIFJlZmxlY3QuZGVmaW5lTWV0YWRhdGEoXG4gICAgICBnZXRJbmplY3RLZXkoSW5qZWN0YWJsZXNLZXlzLklOSkVDVCksXG4gICAgICB7XG4gICAgICAgIGluamVjdGFibGU6IG5hbWUsXG4gICAgICB9LFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGdldCh0aGlzOiBhbnkpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihcbiAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgcHJvcGVydHlLZXlcbiAgICAgICAgKSBhcyBQcm9wZXJ0eURlc2NyaXB0b3I7XG4gICAgICAgIGlmIChkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSkge1xuICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBwcm9wZXJ0eUtleSwge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBnZXQodGhpczogYW55KSB7XG4gICAgICAgICAgICAgIGxldCBvYmogPSB2YWx1ZXMuZ2V0KHRoaXMpO1xuICAgICAgICAgICAgICBpZiAoIW9iaikge1xuICAgICAgICAgICAgICAgIG9iaiA9IEluamVjdGFibGVzLmdldChuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAoIW9iailcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgYENvdWxkIG5vdCBnZXQgSW5qZWN0YWJsZSAke25hbWV9IHRvIGluamVjdCBpbiAke3RhcmdldC5jb25zdHJ1Y3RvciA/IHRhcmdldC5jb25zdHJ1Y3Rvci5uYW1lIDogdGFyZ2V0Lm5hbWV9J3MgJHtwcm9wZXJ0eUtleX1gXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1lcilcbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIG9iaiA9IHRyYW5zZm9ybWVyKG9iaiwgdGFyZ2V0KTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YWx1ZXMuc2V0KHRoaXMsIG9iaik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHRoaXNbcHJvcGVydHlLZXldO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xuIiwiLyoqXG4gKiBAc3VtbWFyeSBBZGRzIGEgc2ltcGxlIEluamVjdGFibGVzIGltcGxlbWVudGF0aW9uIHRvIGNyZWF0ZSBzaW5nbGV0b24gaW5zdGFuY2VzIG9mIGFuIG9iamVjdFxuICogYW5kIGVhc2lseSBpbmplY3QgaXQgaW50byBvdGhlciBvYmplY3RzXG4gKlxuICogQG1vZHVsZSBpbmplY3RhYmxlLWRlY29yYXRvcnNcbiAqL1xuXG4vKipcbiAqIEBzdW1tYXJ5IGZ1bmN0aW9ucyB0aGF0IGRlY29yYXRlIGNsYXNzZXMgb3IgY2xhc3MgcHJvcGVydGllc1xuICogQG5hbWVzcGFjZSBEZWNvcmF0b3JzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmluamVjdGFibGUtZGVjb3JhdG9yc1xuICovXG5cbmV4cG9ydCAqIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vSW5qZWN0YWJsZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3JlZ2lzdHJ5XCI7XG5leHBvcnQgKiBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZWQgb24gbGlicmFyeSBidWlsZC4gaG9sZHMgdGhlIGxpYnJhcnkgY3VycmVudCB2ZXJzaW9uXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTppbmplY3RhYmxlLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0lBQUE7Ozs7Ozs7OztJQVNHO0FBQ1UsVUFBQSxlQUFlLEdBQUc7SUFDN0IsSUFBQSxPQUFPLEVBQUUsWUFBWTtJQUNyQixJQUFBLFVBQVUsRUFBRSxZQUFZO0lBQ3hCLElBQUEsTUFBTSxFQUFFLFFBQVE7OztJQzRCbEI7Ozs7SUFJRztVQUNVLHFCQUFxQixDQUFBO0lBQWxDLElBQUEsV0FBQSxHQUFBO1lBQ1UsSUFBSyxDQUFBLEtBQUEsR0FBK0IsRUFBRTs7SUFFOUM7O0lBRUc7SUFDSCxJQUFBLEdBQUcsQ0FBSSxJQUFZLEVBQUUsR0FBRyxJQUFXLEVBQUE7SUFDakMsUUFBQSxJQUFJO2dCQUNGLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0lBQ25DLFlBQUEsTUFBTSxRQUFRLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFO2dCQUMvQixJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRO29CQUMvQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUksUUFBUSxFQUFFLEdBQUcsSUFBSSxDQUFDO0lBQ3pDLFlB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
|