@decaf-ts/injectable-decorators 1.5.15 → 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/LICENSE.md CHANGED
File without changes
package/README.md CHANGED
@@ -6,18 +6,21 @@ Simple implementation of injectables
6
6
  ![Licence](https://img.shields.io/github/license/decaf-ts/injectable-decorators.svg?style=plastic)
7
7
  ![GitHub language count](https://img.shields.io/github/languages/count/decaf-ts/injectable-decorators?style=plastic)
8
8
  ![GitHub top language](https://img.shields.io/github/languages/top/decaf-ts/injectable-decorators?style=plastic)
9
- [![Tests](https://github.com/decaf-ts/injectable-decorators/actions/workflows/jest-test.yaml/badge.svg)](http://www.pdmfc.com)
10
- [![CodeQL](https://github.com/starnowski/posmulten/workflows/CodeQL/badge.svg)](https://github.com/decaf-ts/injectable-decorators/actions?query=workflow%3ACodeQL)
9
+
10
+ [![Build & Test](https://github.com/decaf-ts/injectable-decorators/actions/workflows/nodejs-build-prod.yaml/badge.svg)](https://github.com/decaf-ts/injectable-decorators/actions/workflows/nodejs-build-prod.yaml)
11
+ [![CodeQL](https://github.com/decaf-ts/injectable-decorators/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/decaf-ts/injectable-decorators/actions/workflows/codeql-analysis.yml)[![Snyk Analysis](https://github.com/decaf-ts/injectable-decorators/actions/workflows/snyk-analysis.yaml/badge.svg)](https://github.com/decaf-ts/injectable-decorators/actions/workflows/snyk-analysis.yaml)
12
+ [![Pages builder](https://github.com/decaf-ts/injectable-decorators/actions/workflows/pages.yaml/badge.svg)](https://github.com/decaf-ts/injectable-decorators/actions/workflows/pages.yaml)
13
+ [![.github/workflows/release-on-tag.yaml](https://github.com/decaf-ts/injectable-decorators/actions/workflows/release-on-tag.yaml/badge.svg?event=release)](https://github.com/decaf-ts/injectable-decorators/actions/workflows/release-on-tag.yaml)
11
14
 
12
15
  ![Open Issues](https://img.shields.io/github/issues/decaf-ts/injectable-decorators.svg)
13
16
  ![Closed Issues](https://img.shields.io/github/issues-closed/decaf-ts/injectable-decorators.svg)
14
17
  ![Pull Requests](https://img.shields.io/github/issues-pr-closed/decaf-ts/injectable-decorators.svg)
15
18
  ![Maintained](https://img.shields.io/badge/Maintained%3F-yes-green.svg)
16
19
 
17
- ![Line Coverage](workdocs/coverage/badge-lines.svg)
18
- ![Function Coverage](workdocs/coverage/badge-functions.svg)
19
- ![Statement Coverage](workdocs/coverage/badge-statements.svg)
20
- ![Branch Coverage](workdocs/coverage/badge-branches.svg)
20
+ ![Line Coverage](workdocs/reports/coverage/badge-lines.svg)
21
+ ![Function Coverage](workdocs/reports/coverage/badge-functions.svg)
22
+ ![Statement Coverage](workdocs/reports/coverage/badge-statements.svg)
23
+ ![Branch Coverage](workdocs/reports/coverage/badge-branches.svg)
21
24
 
22
25
 
23
26
  ![Forks](https://img.shields.io/github/forks/decaf-ts/injectable-decorators.svg)
@@ -27,108 +30,32 @@ Simple implementation of injectables
27
30
  ![Node Version](https://img.shields.io/badge/dynamic/json.svg?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbadges%2Fshields%2Fmaster%2Fpackage.json&label=Node&query=$.engines.node&colorB=blue)
28
31
  ![NPM Version](https://img.shields.io/badge/dynamic/json.svg?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbadges%2Fshields%2Fmaster%2Fpackage.json&label=NPM&query=$.engines.npm&colorB=purple)
29
32
 
30
- ### Decorator based
33
+ Documentation available [here](https://decaf-ts.github.io/injectable-decorators/)
34
+
35
+ ### Description
31
36
 
32
37
  Simple implementation of a Typescript decorator based injectable system.
33
- ## Considerations
34
-
35
- #### Typescript Compilation options
36
-
37
- Even though all code is exported in both CommonJS and ESM format, and the default is ES2022
38
- in order to take advantage to all the latest Typescript and JS features,
39
- when importing these libraries the following flag in `tsconfig.compilerOptions` is mandatory:
40
- ```json
41
- {
42
- "experimentalDecorators": true,
43
- "emitDecoratorMetadata": true,
44
- "useDefineForClassFields": false
45
- }
46
- ```
38
+
39
+ ### How to Use
40
+
41
+ - [Initial Setup](./tutorials/For%20Developers.md#_initial-setup_)
42
+ - [Installation](./tutorials/For%20Developers.md#installation)
43
+
44
+
45
+
46
+
47
47
  ### Related
48
48
 
49
- [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=decaf-ts&repo=decorator-validation)](https://github.com/decaf-ts/decorator-validation)
50
- [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=decaf-ts&repo=db-decorators)](https://github.com/decaf-ts/db-decorators)
49
+ [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=decaf-ts&repo=ts-workspace)](https://github.com/decaf-ts/ts-workspace)
50
+
51
51
  ### Social
52
52
 
53
53
  [![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/decaf-ts/)
54
- ### Scripts
55
-
56
- The following npm scripts are available for development:
57
-
58
- - `preinstall` - will run only on the first install to trigger the dep update. will self delete;
59
- - `do-install` - sets a `TOKEN` environment variable to the contents of `.token` and runs npm install (useful when you
60
- have private dependencies);
61
- - `flash-forward` - updates all dependencies. Take care, This may not be desirable is some cases;
62
- - `reset` - updates all dependencies. Take care, This may not be desirable is some cases;
63
- - `build` - builds the code (via gulp `gulpfile.js`) in development mode (generates `lib` and `dist` folder);
64
- - `build:prod` - builds the code (via gulp `gulpfile.js`) in production mode (generates `lib` and `dist` folder);
65
- - `test` - runs unit tests;
66
- - `test:integration` - runs it tests;
67
- - `test:all` - runs all tests;
68
- - `lint` - runs es lint on the code folder;
69
- - `lint-fix` - tries to auto-fix the code folder;
70
- - `prepare-release` - defines the commands to run prior to a new tag (defaults to linting, building production code,
71
- running tests and documentation generation);
72
- - `release` - triggers a new tag being pushed to master (via `./bin/tag_release.sh`);
73
- - `clean-publish` - cleans the package.json for publishing;
74
- - `coverage` - runs all test, calculates coverage and generates badges for readme;
75
- - `drawings` - compiles all DrawIO `*.drawio` files in the `workdocs/drawings` folder to png and moves them to
76
- the `workdocs/resources` folder;
77
- - `uml` - compiles all PlantUML `*.puml` files in the `workdocs/uml` folder to png and moves them to
78
- the `workdocs/resources` folder;
79
- - `docs` - compiles all the coverage, drawings, uml, jsdocs and md docs into a readable web page under `./docs`;
80
-
81
- ### Repository Structure
82
-
83
- ```
84
- injectable-decorators
85
-
86
- │ .gitignore <-- Defines files ignored to git
87
- │ .npmignore <-- Defines files ignored by npm
88
- │ .nmprc <-- Defines the Npm registry for this package
89
- │ .eslintrc.cjs <-- linting for the project
90
- │ .prettier.config.cjs <-- Code style for the project
91
- │ .gitlab-ci.yml <-- Gillab CI/CD file
92
- │ gulpfile.js <-- Gulp build scripts. used for building na other features (eg docs)
93
- │ jest.config.ts <-- Tests Configuration file
94
- │ mdCompile.json <-- md Documentation generation configuration file
95
- │ jsdocs.json <-- jsdoc Documentation generation configuration file
96
- │ Dockerfile <-- minimal example of a node service Dockerfile
97
- │ LICENCE.md <-- Licence disclamer
98
- │ package.json
99
- │ package-lock.json
100
- │ README.md <-- Readme File dynamically compiled from 'workdocs' via the 'docs' npm script
101
- │ tsconfig.json <-- Typescript config file. Is overriden in 'gulpfile.js'
102
-
103
- └───bin
104
- │ │ tag_release.sh <-- Script to help with releases
105
-
106
- └───docs
107
- │ │ ... <-- Dinamically generated folder, containing the compiled documentation for this repository. generated via the 'docs' npm script
108
-
109
- └───src
110
- │ │ ... <-- Source code for this repository
111
-
112
- └───tests
113
- │ │───unit <-- Unit tests
114
- │ └───integration <-- Integration tests
115
-
116
- └───workdocs <-- Folder with all pre-compiled documentation
117
- │ │───assets <-- Documentation asset folder
118
- │ │───badges <-- Auto generated coverage badges folder
119
- │ │───coverage <-- Auto generated coverage results
120
- │ │───drawings <-- DrawIO folder. Drawings (*.drawio) here will be processed to generate documentation (requires docker)
121
- │ │───uml <-- PlantUML folder. Diagrams (*.puml) here will be processed to generate documentation (requires docker)
122
- │ │───tutorials <-- Tutorial folder
123
- │ │ ... <-- Categorized *.md files that are merged to generate the final readme (via md compile)
124
- │ │ Readme.md <-- Entry point to the README.md
125
-
126
- └───dist
127
- │ │ ... <-- Dinamically generated folder containing the bundles for distribution
128
-
129
- └───lib
130
- | ... <-- Dinamically generated folder containing the compiled code
131
- ```
54
+
55
+
56
+
57
+
58
+ #### Languages
132
59
 
133
60
  ![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
134
61
  ![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)
@@ -137,7 +64,7 @@ injectable-decorators
137
64
 
138
65
  ## Getting help
139
66
 
140
- If you have bug reports, questions or suggestions please [create a new issue](https://github.com/decaf-ts/decorator-validation/issues/new/choose).
67
+ If you have bug reports, questions or suggestions please [create a new issue](https://github.com/decaf-ts/ts-workspace/issues/new/choose).
141
68
 
142
69
  ## Contributing
143
70
 
@@ -147,14 +74,12 @@ I am grateful for any contributions made to this project. Please read [this](./w
147
74
 
148
75
  The first and easiest way you can support it is by [Contributing](./workdocs/98-Contributing.md). Even just finding a typo in the documentation is important.
149
76
 
150
- Financial support is always welcome and helps keep the both me and the project alive and healthy.
77
+ Financial support is always welcome and helps keep both me and the project alive and healthy.
151
78
 
152
79
  So if you can, if this project in any way. either by learning something or simply by helping you save precious time, please consider donating.
153
80
 
154
81
  ## License
155
82
 
156
- This project is released under the [MIT License](LICENSE.md).
157
-
158
- #### Disclaimer:
83
+ This project is released under the [MIT License](./LICENSE.md).
159
84
 
160
- badges found [here](https://dev.to/envoy_/150-badges-for-github-pnk), [here](https://github.com/alexandresanlim/Badges4-README.md-Profile#-social-) and [here](https://github.com/Ileriayo/markdown-badges)
85
+ By developers, for developers...
@@ -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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