@nlabs/arkhamjs 3.24.0 → 3.26.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/README.md CHANGED
@@ -75,7 +75,3 @@ Try tinkering with a simplified demo in [JSFiddle](https://jsfiddle.net/nitrog7/
75
75
  ### React Typescript Example
76
76
 
77
77
  For a complete example of a React setup using Typescript, feel free to start your project with [arkhamjs-example-ts-react](https://github.com/nitrogenlabs/arkhamjs-example-ts-react).
78
-
79
- ### React Flow Example
80
-
81
- For a complete example of a React setup using Flow, feel free to start your project with [arkhamjs-example-flow-react](https://github.com/nitrogenlabs/arkhamjs-example-flow-react).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nlabs/arkhamjs",
3
- "version": "3.24.0",
3
+ "version": "3.26.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -36,7 +36,11 @@
36
36
  "build": "lex compile -r",
37
37
  "clean": "lex clean",
38
38
  "lint": "eslint ./src --ext .ts,.tsx",
39
- "pretest": "yarn lint",
39
+ "prepublishOnly": "npm run build",
40
+ "pretest": "npm run lint",
41
+ "publish:major": "npm version major && npm publish",
42
+ "publish:minor": "npm version minor && npm publish",
43
+ "publish:patch": "npm version patch && npm publish",
40
44
  "test": "lex test",
41
45
  "update": "lex update -i"
42
46
  },
@@ -47,12 +51,12 @@
47
51
  },
48
52
  "devDependencies": {
49
53
  "@types/events": "^3.0.0",
50
- "@types/jest": "^28.1.4",
51
- "@types/lodash": "^4.14.178",
52
- "@types/node": "^18.0.3",
53
- "eslint": "^8.19.0",
54
- "eslint-config-styleguidejs": "^2.1.2",
55
- "typescript": "^4.5.5"
54
+ "@types/jest": "^29.5.0",
55
+ "@types/lodash": "^4.14.191",
56
+ "@types/node": "^18.15.5",
57
+ "eslint": "^8.36.0",
58
+ "eslint-config-styleguidejs": "^3.2.1",
59
+ "typescript": "^5.0.2"
56
60
  },
57
- "gitHead": "00d9ba3197abda87d27d6505d8002ccb3e622116"
61
+ "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
58
62
  }
@@ -1,38 +0,0 @@
1
- /// <reference types="node" />
2
- import { EventEmitter } from 'events';
3
- import { FluxAction, FluxMiddlewareType, FluxOptions, FluxStore } from './Flux.types';
4
- export declare class FluxFramework extends EventEmitter {
5
- static initFlux: boolean;
6
- isInit: boolean;
7
- pluginTypes: string[];
8
- private state;
9
- private storeActions;
10
- private defaultOptions;
11
- private middleware;
12
- private options;
13
- constructor();
14
- addMiddleware(middleware: FluxMiddlewareType[]): void;
15
- clearAppData(): Promise<boolean>;
16
- clearMiddleware(): boolean;
17
- removeStores(storeNames: string[]): void;
18
- dispatch(action: FluxAction, silent?: boolean): Promise<FluxAction>;
19
- getOptions(): FluxOptions;
20
- getState(path?: string | string[], defaultValue?: any): any;
21
- getStore(name?: string): FluxStore;
22
- init(options?: FluxOptions, reset?: boolean): Promise<FluxFramework>;
23
- onInit(listener: (...args: any[]) => void): void;
24
- offInit(listener: (...args: any[]) => void): void;
25
- off(eventType: string, listener: (...args: any[]) => void): this;
26
- on(eventType: string, listener: (...args: any[]) => void): this;
27
- addStores(stores: any[]): Promise<object[]>;
28
- removeMiddleware(names: string[]): void;
29
- reset(clearStorage?: boolean): Promise<void>;
30
- setState(path: string | string[], value: any): Promise<boolean>;
31
- private addPlugin;
32
- private deregister;
33
- private register;
34
- private removePlugin;
35
- private updateStorage;
36
- private useStorage;
37
- }
38
- export declare const Flux: FluxFramework;
package/lib/Flux/Flux.js DELETED
@@ -1,349 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
20
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
- var Flux_exports = {};
22
- __export(Flux_exports, {
23
- Flux: () => Flux,
24
- FluxFramework: () => FluxFramework
25
- });
26
- module.exports = __toCommonJS(Flux_exports);
27
- var import_error_stack_parser = __toESM(require("error-stack-parser"));
28
- var import_events = require("events");
29
- var import_debounce = __toESM(require("lodash/debounce"));
30
- var import_cloneDeep = __toESM(require("lodash/fp/cloneDeep"));
31
- var import_get = __toESM(require("lodash/fp/get"));
32
- var import_isEmpty = __toESM(require("lodash/fp/isEmpty"));
33
- var import_merge = __toESM(require("lodash/fp/merge"));
34
- var import_set = __toESM(require("lodash/fp/set"));
35
- var import_ArkhamConstants = require("../constants/ArkhamConstants");
36
- class FluxFramework extends import_events.EventEmitter {
37
- constructor() {
38
- super();
39
- this.isInit = false;
40
- this.pluginTypes = ["preDispatch", "postDispatch"];
41
- this.state = {};
42
- this.storeActions = {};
43
- this.defaultOptions = {
44
- name: "arkhamjs",
45
- routerType: "browser",
46
- scrollToTop: true,
47
- state: null,
48
- storage: null,
49
- storageWait: 300,
50
- stores: [],
51
- title: "ArkhamJS"
52
- };
53
- this.middleware = {};
54
- this.options = this.defaultOptions;
55
- this.updateStorage = () => Promise.resolve(false);
56
- this.addMiddleware = this.addMiddleware.bind(this);
57
- this.addStores = this.addStores.bind(this);
58
- this.clearAppData = this.clearAppData.bind(this);
59
- this.clearMiddleware = this.clearMiddleware.bind(this);
60
- this.deregister = this.deregister.bind(this);
61
- this.dispatch = this.dispatch.bind(this);
62
- this.getOptions = this.getOptions.bind(this);
63
- this.getState = this.getState.bind(this);
64
- this.getStore = this.getStore.bind(this);
65
- this.init = this.init.bind(this);
66
- this.off = this.off.bind(this);
67
- this.register = this.register.bind(this);
68
- this.removeMiddleware = this.removeMiddleware.bind(this);
69
- this.removeStores = this.removeStores.bind(this);
70
- this.reset = this.reset.bind(this);
71
- this.setState = this.setState.bind(this);
72
- this.pluginTypes.forEach((type) => this.middleware[`${type}List`] = []);
73
- }
74
- addMiddleware(middleware) {
75
- middleware.forEach((middleObj) => {
76
- if (!!middleObj && (typeof middleObj === "function" || typeof middleObj === "object")) {
77
- const middleName = middleObj.name || "";
78
- if (!middleName) {
79
- throw Error("Unknown middleware is not configured properly. Requires name property. Cannot add to Flux.");
80
- }
81
- this.pluginTypes.forEach((type) => {
82
- const method = middleObj[type];
83
- const plugin = { method, name: middleName };
84
- this.middleware[`${type}List`] = this.addPlugin(type, plugin);
85
- });
86
- } else {
87
- throw Error("Unknown middleware is not configured properly. Cannot add to Flux.");
88
- }
89
- });
90
- }
91
- clearAppData() {
92
- Object.keys(this.storeActions).forEach((storeName) => {
93
- const storeFn = this.storeActions[storeName];
94
- this.state[storeFn.name] = (0, import_cloneDeep.default)(storeFn.initialState);
95
- });
96
- const { name, storage } = this.options;
97
- if (storage) {
98
- return storage.setStorageData(name, this.state);
99
- }
100
- return Promise.resolve(true);
101
- }
102
- clearMiddleware() {
103
- Object.keys(this.middleware).forEach((pluginType) => {
104
- this.middleware[pluginType] = [];
105
- });
106
- return true;
107
- }
108
- removeStores(storeNames) {
109
- storeNames.forEach((name) => this.deregister(name));
110
- }
111
- async dispatch(action, silent = false) {
112
- if (!action) {
113
- throw new Error("ArkhamJS Error: Flux.dispatch requires an action.");
114
- }
115
- let clonedAction = (0, import_cloneDeep.default)(action);
116
- const startTime = Date.now();
117
- let stack = [];
118
- try {
119
- const stackProperty = "stackTraceLimit";
120
- const { stackTraceLimit } = Error;
121
- Error[stackProperty] = Infinity;
122
- stack = import_error_stack_parser.default.parse(new Error());
123
- Error[stackProperty] = stackTraceLimit;
124
- } catch (error) {
125
- }
126
- const options = (0, import_cloneDeep.default)(this.options);
127
- const appInfo = { duration: 0, options, stack };
128
- const { postDispatchList = [], preDispatchList = [] } = this.middleware;
129
- if (preDispatchList.length) {
130
- clonedAction = await Promise.all(preDispatchList.map((plugin) => plugin.method((0, import_cloneDeep.default)(clonedAction), (0, import_cloneDeep.default)(this.state), appInfo))).then((actions) => actions.reduce((updatedAction, action2) => (0, import_merge.default)(updatedAction, action2), clonedAction)).catch((error) => {
131
- throw error;
132
- });
133
- }
134
- const { type, ...data } = clonedAction;
135
- if (!type || type === "") {
136
- console.warn("ArkhamJS Warning: Flux.dispatch is missing an action type for the payload:", data);
137
- return Promise.resolve(clonedAction);
138
- }
139
- Object.keys(this.storeActions).forEach((storeName) => {
140
- const storeFn = this.storeActions[storeName];
141
- const state = (0, import_cloneDeep.default)(this.state[storeName]) || (0, import_cloneDeep.default)(storeFn.initialState) || {};
142
- this.state[storeName] = (0, import_cloneDeep.default)(storeFn.action(type, data, state)) || state;
143
- });
144
- const { storage } = this.options;
145
- if (storage) {
146
- try {
147
- await this.updateStorage();
148
- } catch (error) {
149
- }
150
- }
151
- const endTime = +new Date();
152
- const duration = endTime - startTime;
153
- appInfo.duration = duration;
154
- if (postDispatchList.length) {
155
- clonedAction = await Promise.all(postDispatchList.map(async (plugin) => plugin.method((0, import_cloneDeep.default)(clonedAction), (0, import_cloneDeep.default)(this.state), appInfo))).then((actions) => actions.reduce((updatedAction, action2) => (0, import_merge.default)(updatedAction, action2), clonedAction)).catch((error) => {
156
- throw error;
157
- });
158
- }
159
- if (!silent) {
160
- this.emit(type, clonedAction);
161
- this.emit("arkhamjs", this.state);
162
- }
163
- return Promise.resolve(clonedAction);
164
- }
165
- getOptions() {
166
- return this.options;
167
- }
168
- getState(path = "", defaultValue) {
169
- let storeValue;
170
- if (!path) {
171
- storeValue = this.state || {};
172
- } else {
173
- storeValue = (0, import_get.default)(path, this.state);
174
- }
175
- const value = storeValue ? (0, import_cloneDeep.default)(storeValue) : storeValue;
176
- return value === void 0 ? defaultValue : value;
177
- }
178
- getStore(name = "") {
179
- return this.storeActions[name];
180
- }
181
- async init(options = {}, reset = false) {
182
- if (reset) {
183
- this.isInit = false;
184
- this.reset(false);
185
- }
186
- const updatedOptions = { ...options };
187
- if (this.isInit) {
188
- updatedOptions.name = this.options.name;
189
- }
190
- this.options = { ...this.defaultOptions, ...updatedOptions };
191
- const { debug, middleware, name, stores } = this.options;
192
- try {
193
- await this.useStorage(name);
194
- } catch (error) {
195
- console.error("Arkham Error: There was an error while using storage.", name);
196
- throw error;
197
- }
198
- if (!!stores && stores.length) {
199
- try {
200
- await this.addStores(stores);
201
- } catch (error) {
202
- console.error("Arkham Error: There was an error while adding stores.", stores);
203
- throw error;
204
- }
205
- }
206
- if (!!middleware && middleware.length) {
207
- this.addMiddleware(middleware);
208
- }
209
- const windowProperty = "arkhamjs";
210
- if (debug) {
211
- window[windowProperty] = this;
212
- } else {
213
- delete window[windowProperty];
214
- }
215
- this.isInit = true;
216
- this.emit(import_ArkhamConstants.ArkhamConstants.INIT);
217
- return this;
218
- }
219
- onInit(listener) {
220
- this.on(import_ArkhamConstants.ArkhamConstants.INIT, listener);
221
- if (this.isInit) {
222
- listener();
223
- }
224
- }
225
- offInit(listener) {
226
- this.off(import_ArkhamConstants.ArkhamConstants.INIT, listener);
227
- }
228
- off(eventType, listener) {
229
- return this.removeListener(eventType, listener);
230
- }
231
- on(eventType, listener) {
232
- return this.addListener(eventType, listener);
233
- }
234
- async addStores(stores) {
235
- const registeredStores = stores.map((store) => this.register(store));
236
- const { name, storage } = this.options;
237
- if (storage) {
238
- try {
239
- await storage.setStorageData(name, this.state);
240
- } catch (error) {
241
- throw error;
242
- }
243
- }
244
- return registeredStores;
245
- }
246
- removeMiddleware(names) {
247
- names.forEach((name) => {
248
- this.pluginTypes.forEach((type) => {
249
- this.middleware[`${type}List`] = this.removePlugin(type, name);
250
- });
251
- });
252
- }
253
- async reset(clearStorage = true) {
254
- const { name, storage } = this.options;
255
- if (storage && clearStorage) {
256
- try {
257
- await storage.setStorageData(name, {});
258
- } catch (error) {
259
- throw error;
260
- }
261
- }
262
- this.middleware = {};
263
- this.options = { ...this.defaultOptions };
264
- this.state = {};
265
- this.storeActions = {};
266
- this.isInit = false;
267
- }
268
- setState(path = "", value) {
269
- if (!!path) {
270
- this.state = (0, import_set.default)(path, (0, import_cloneDeep.default)(value), this.state);
271
- }
272
- const { storage } = this.options;
273
- if (storage) {
274
- return this.updateStorage();
275
- }
276
- return Promise.resolve(false);
277
- }
278
- addPlugin(type, plugin) {
279
- const list = this.middleware[`${type}List`] || [];
280
- const { method, name } = plugin;
281
- if (method && typeof method === "function") {
282
- const exists = !!list.filter((obj) => obj.name === name).length;
283
- if (!exists) {
284
- list.push({ method, name });
285
- }
286
- } else if (method !== void 0) {
287
- throw Error(`${plugin.name} middleware is not configured properly. Method is not a function.`);
288
- }
289
- return list;
290
- }
291
- deregister(name = "") {
292
- delete this.storeActions[name];
293
- delete this.state[name];
294
- }
295
- register(storeFn) {
296
- if (!storeFn) {
297
- throw Error("Store is undefined. Cannot register with Flux.");
298
- }
299
- const isFnc = typeof storeFn === "function";
300
- if (!isFnc) {
301
- throw Error(`${storeFn} is not a store function. Cannot register with Flux.`);
302
- }
303
- const { name } = storeFn;
304
- const initialState = storeFn();
305
- const storeAction = {
306
- action: storeFn,
307
- initialState: storeFn(),
308
- name
309
- };
310
- if (!(0, import_isEmpty.default)(name) && !this.storeActions[name]) {
311
- this.storeActions[name] = storeAction;
312
- if (!this.state[name]) {
313
- if (initialState) {
314
- this.state[name] = (0, import_cloneDeep.default)(initialState);
315
- } else {
316
- this.state[name] = {};
317
- }
318
- }
319
- }
320
- return this.storeActions[name];
321
- }
322
- removePlugin(type, name) {
323
- const list = this.middleware[`${type}List`] || [];
324
- return list.filter((obj) => obj.name !== name);
325
- }
326
- async useStorage(name) {
327
- const { storage, state, storageWait } = this.options;
328
- if (storage) {
329
- try {
330
- this.state = state || await storage.getStorageData(name) || {};
331
- this.updateStorage = (0, import_debounce.default)(() => storage.setStorageData(name, this.state), storageWait, { leading: true, trailing: true });
332
- } catch (error) {
333
- console.error(`ArkhamJS Error: Using storage, "${name}".`);
334
- throw error;
335
- }
336
- } else {
337
- this.state = state || {};
338
- }
339
- return null;
340
- }
341
- }
342
- FluxFramework.initFlux = false;
343
- const Flux = new FluxFramework();
344
- // Annotate the CommonJS export names for ESM import in node:
345
- 0 && (module.exports = {
346
- Flux,
347
- FluxFramework
348
- });
349
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL0ZsdXgvRmx1eC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCBFcnJvclN0YWNrUGFyc2VyIGZyb20gJ2Vycm9yLXN0YWNrLXBhcnNlcic7XG5pbXBvcnQge0V2ZW50RW1pdHRlcn0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBkZWJvdW5jZSBmcm9tICdsb2Rhc2gvZGVib3VuY2UnO1xuaW1wb3J0IGNsb25lRGVlcCBmcm9tICdsb2Rhc2gvZnAvY2xvbmVEZWVwJztcbmltcG9ydCBnZXQgZnJvbSAnbG9kYXNoL2ZwL2dldCc7XG5pbXBvcnQgaXNFbXB0eSBmcm9tICdsb2Rhc2gvZnAvaXNFbXB0eSc7XG5pbXBvcnQgbWVyZ2UgZnJvbSAnbG9kYXNoL2ZwL21lcmdlJztcbmltcG9ydCBzZXQgZnJvbSAnbG9kYXNoL2ZwL3NldCc7XG5cbmltcG9ydCB7QXJraGFtQ29uc3RhbnRzfSBmcm9tICcuLi9jb25zdGFudHMvQXJraGFtQ29uc3RhbnRzJztcbmltcG9ydCB7Rmx1eEFjdGlvbiwgRmx1eE1pZGRsZXdhcmVUeXBlLCBGbHV4T3B0aW9ucywgRmx1eFBsdWdpblR5cGUsIEZsdXhTdG9yZX0gZnJvbSAnLi9GbHV4LnR5cGVzJztcblxuLyoqXG4gKiBGbHV4RnJhbWV3b3JrXG4gKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuICovXG5leHBvcnQgY2xhc3MgRmx1eEZyYW1ld29yayBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIHN0YXRpYyBpbml0Rmx1eDogYm9vbGVhbiA9IGZhbHNlO1xuICBpc0luaXQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgLy8gUHVibGljIHByb3BlcnRpZXNcbiAgcGx1Z2luVHlwZXM6IHN0cmluZ1tdID0gWydwcmVEaXNwYXRjaCcsICdwb3N0RGlzcGF0Y2gnXTtcbiAgLy8gUHJpdmF0ZSBwcm9wZXJ0aWVzXG4gIHByaXZhdGUgc3RhdGU6IGFueSA9IHt9O1xuICBwcml2YXRlIHN0b3JlQWN0aW9uczogYW55ID0ge307XG4gIHByaXZhdGUgZGVmYXVsdE9wdGlvbnM6IEZsdXhPcHRpb25zID0ge1xuICAgIG5hbWU6ICdhcmtoYW1qcycsXG4gICAgcm91dGVyVHlwZTogJ2Jyb3dzZXInLFxuICAgIHNjcm9sbFRvVG9wOiB0cnVlLFxuICAgIHN0YXRlOiBudWxsLFxuICAgIHN0b3JhZ2U6IG51bGwsXG4gICAgc3RvcmFnZVdhaXQ6IDMwMCxcbiAgICBzdG9yZXM6IFtdLFxuICAgIHRpdGxlOiAnQXJraGFtSlMnXG4gIH07XG4gIHByaXZhdGUgbWlkZGxld2FyZTogYW55ID0ge307XG4gIHByaXZhdGUgb3B0aW9uczogRmx1eE9wdGlvbnMgPSB0aGlzLmRlZmF1bHRPcHRpb25zO1xuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIEZsdXguICBOb3RlIHRoYXQgdGhlIEZsdXggb2JqZWN0XG4gICAqIGlzIGEgU2luZ2xldG9uIHBhdHRlcm4sIHNvIG9ubHkgb25lIHNob3VsZCBldmVyIGV4aXN0LlxuICAgKlxuICAgKiBAY29uc3RydWN0b3JcbiAgICogQHRoaXMge0ZsdXhGcmFtZXdvcmt9XG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgLy8gTWV0aG9kc1xuICAgIHRoaXMuYWRkTWlkZGxld2FyZSA9IHRoaXMuYWRkTWlkZGxld2FyZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuYWRkU3RvcmVzID0gdGhpcy5hZGRTdG9yZXMuYmluZCh0aGlzKTtcbiAgICB0aGlzLmNsZWFyQXBwRGF0YSA9IHRoaXMuY2xlYXJBcHBEYXRhLmJpbmQodGhpcyk7XG4gICAgdGhpcy5jbGVhck1pZGRsZXdhcmUgPSB0aGlzLmNsZWFyTWlkZGxld2FyZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZGVyZWdpc3RlciA9IHRoaXMuZGVyZWdpc3Rlci5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZGlzcGF0Y2ggPSB0aGlzLmRpc3BhdGNoLmJpbmQodGhpcyk7XG4gICAgdGhpcy5nZXRPcHRpb25zID0gdGhpcy5nZXRPcHRpb25zLmJpbmQodGhpcyk7XG4gICAgdGhpcy5nZXRTdGF0ZSA9IHRoaXMuZ2V0U3RhdGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLmdldFN0b3JlID0gdGhpcy5nZXRTdG9yZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaW5pdCA9IHRoaXMuaW5pdC5iaW5kKHRoaXMpO1xuICAgIHRoaXMub2ZmID0gdGhpcy5vZmYuYmluZCh0aGlzKTtcbiAgICB0aGlzLnJlZ2lzdGVyID0gdGhpcy5yZWdpc3Rlci5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVtb3ZlTWlkZGxld2FyZSA9IHRoaXMucmVtb3ZlTWlkZGxld2FyZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVtb3ZlU3RvcmVzID0gdGhpcy5yZW1vdmVTdG9yZXMuYmluZCh0aGlzKTtcbiAgICB0aGlzLnJlc2V0ID0gdGhpcy5yZXNldC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuc2V0U3RhdGUgPSB0aGlzLnNldFN0YXRlLmJpbmQodGhpcyk7XG5cbiAgICAvLyBBZGQgbWlkZGxld2FyZSBwbHVnaW4gdHlwZXNcbiAgICB0aGlzLnBsdWdpblR5cGVzLmZvckVhY2goKHR5cGU6IHN0cmluZykgPT4gdGhpcy5taWRkbGV3YXJlW2Ake3R5cGV9TGlzdGBdID0gW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBtaWRkbGV3YXJlIHRvIGZyYW1ld29yay5cbiAgICpcbiAgICogQHBhcmFtIHthcnJheX0gbWlkZGxld2FyZSBBbiBhcnJheSBvZiBtaWRkbGV3YXJlIHRvIGFkZCB0byB0aGUgZnJhbWV3b3JrLlxuICAgKi9cbiAgYWRkTWlkZGxld2FyZShtaWRkbGV3YXJlOiBGbHV4TWlkZGxld2FyZVR5cGVbXSk6IHZvaWQge1xuICAgIG1pZGRsZXdhcmUuZm9yRWFjaCgobWlkZGxlT2JqOiBGbHV4TWlkZGxld2FyZVR5cGUpID0+IHtcbiAgICAgIC8vIE1ha2Ugc3VyZSBtaWRkbGV3YXJlIGlzIGVpdGhlciBhIGNsYXNzIG9yIG9iamVjdC5cbiAgICAgIGlmKCEhbWlkZGxlT2JqICYmICgodHlwZW9mIG1pZGRsZU9iaiA9PT0gJ2Z1bmN0aW9uJykgfHwgKHR5cGVvZiBtaWRkbGVPYmogPT09ICdvYmplY3QnKSkpIHtcbiAgICAgICAgY29uc3QgbWlkZGxlTmFtZTogc3RyaW5nID0gbWlkZGxlT2JqLm5hbWUgfHwgJyc7XG5cbiAgICAgICAgaWYoIW1pZGRsZU5hbWUpIHtcbiAgICAgICAgICB0aHJvdyBFcnJvcignVW5rbm93biBtaWRkbGV3YXJlIGlzIG5vdCBjb25maWd1cmVkIHByb3Blcmx5LiBSZXF1aXJlcyBuYW1lIHByb3BlcnR5LiBDYW5ub3QgYWRkIHRvIEZsdXguJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTb3J0IG1pZGRsZXdhcmUgcGx1Z2lucyBmb3IgZWZmaWNpZW5jeVxuICAgICAgICB0aGlzLnBsdWdpblR5cGVzLmZvckVhY2goKHR5cGU6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGNvbnN0IG1ldGhvZCA9IG1pZGRsZU9ialt0eXBlXTtcbiAgICAgICAgICBjb25zdCBwbHVnaW46IEZsdXhQbHVnaW5UeXBlID0ge21ldGhvZCwgbmFtZTogbWlkZGxlTmFtZX07XG4gICAgICAgICAgdGhpcy5taWRkbGV3YXJlW2Ake3R5cGV9TGlzdGBdID0gdGhpcy5hZGRQbHVnaW4odHlwZSwgcGx1Z2luKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcignVW5rbm93biBtaWRkbGV3YXJlIGlzIG5vdCBjb25maWd1cmVkIHByb3Blcmx5LiBDYW5ub3QgYWRkIHRvIEZsdXguJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFsbCBhcHAgZGF0YSBmcm9tIHN0b3JhZ2UuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBXaGV0aGVyIGFwcCBkYXRhIHdhcyBzdWNjZXNzZnVsbHkgcmVtb3ZlZC5cbiAgICovXG4gIGNsZWFyQXBwRGF0YSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBTZXQgYWxsIHN0b3JlIGRhdGEgdG8gaW5pdGlhbCBzdGF0ZVxuICAgIE9iamVjdFxuICAgICAgLmtleXModGhpcy5zdG9yZUFjdGlvbnMpXG4gICAgICAuZm9yRWFjaCgoc3RvcmVOYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3Qgc3RvcmVGbiA9IHRoaXMuc3RvcmVBY3Rpb25zW3N0b3JlTmFtZV07XG4gICAgICAgIHRoaXMuc3RhdGVbc3RvcmVGbi5uYW1lXSA9IGNsb25lRGVlcChzdG9yZUZuLmluaXRpYWxTdGF0ZSk7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHtuYW1lLCBzdG9yYWdlfSA9IHRoaXMub3B0aW9ucztcblxuICAgIGlmKHN0b3JhZ2UpIHtcbiAgICAgIHJldHVybiBzdG9yYWdlLnNldFN0b3JhZ2VEYXRhKG5hbWUsIHRoaXMuc3RhdGUpO1xuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFsbCBtaWRkbGV3YXJlLlxuICAgKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciBtaWRkbGV3YXJlIHdhcyBzdWNjZXNzZnVsbHkgcmVtb3ZlZC5cbiAgICovXG4gIGNsZWFyTWlkZGxld2FyZSgpOiBib29sZWFuIHtcbiAgICAvLyBTZXQgYWxsIHN0b3JlIGRhdGEgdG8gaW5pdGlhbCBzdGF0ZVxuICAgIE9iamVjdFxuICAgICAgLmtleXModGhpcy5taWRkbGV3YXJlKVxuICAgICAgLmZvckVhY2goKHBsdWdpblR5cGU6IHN0cmluZykgPT4ge1xuICAgICAgICB0aGlzLm1pZGRsZXdhcmVbcGx1Z2luVHlwZV0gPSBbXTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRGUtcmVnaXN0ZXJzIG5hbWVkIHN0b3Jlcy5cbiAgICpcbiAgICogQHBhcmFtIHthcnJheX0gc3RvcmVOYW1lcyBBbiBhcnJheSBvZiBzdG9yZSBuYW1lcyB0byByZW1vdmUgZnJvbSB0aGUgZnJhbWV3b3JrLlxuICAgKi9cbiAgcmVtb3ZlU3RvcmVzKHN0b3JlTmFtZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgc3RvcmVOYW1lcy5mb3JFYWNoKChuYW1lOiBzdHJpbmcpID0+IHRoaXMuZGVyZWdpc3RlcihuYW1lKSk7XG4gIH1cblxuICAvKipcbiAgICogRGlzcGF0Y2hlcyBhbiBhY3Rpb24gdG8gYWxsIHN0b3Jlcy5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IGFjdGlvbiB0byBkaXNwYXRjaCB0byBhbGwgdGhlIHN0b3Jlcy5cbiAgICogQHBhcmFtIHtib29sZWFufSBzaWxlbnQgVG8gc2lsZW5jZSBhbnkgZXZlbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gVGhlIHByb21pc2UgaXMgcmVzb2x2ZWQgd2hlbiBhbmQgaWYgdGhlIGFwcCBzYXZlcyBkYXRhIHRvIHN0b3JhZ2UsIHJldHVybmluZ1xuICAgKiB0aGUgYWN0aW9uLlxuICAgKi9cbiAgYXN5bmMgZGlzcGF0Y2goYWN0aW9uOiBGbHV4QWN0aW9uLCBzaWxlbnQ6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8Rmx1eEFjdGlvbj4ge1xuICAgIGlmKCFhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXJraGFtSlMgRXJyb3I6IEZsdXguZGlzcGF0Y2ggcmVxdWlyZXMgYW4gYWN0aW9uLicpO1xuICAgIH1cblxuICAgIGxldCBjbG9uZWRBY3Rpb246IEZsdXhBY3Rpb24gPSBjbG9uZURlZXAoYWN0aW9uKTtcblxuICAgIC8vIExvZyBkdXJhdGlvbiBvZiBkaXNwYXRjaFxuICAgIGNvbnN0IHN0YXJ0VGltZTogbnVtYmVyID0gRGF0ZS5ub3coKTtcblxuICAgIC8vIEdldCBzdGFja1xuICAgIGxldCBzdGFjayA9IFtdO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YWNrUHJvcGVydHk6IHN0cmluZyA9ICdzdGFja1RyYWNlTGltaXQnO1xuICAgICAgY29uc3Qge3N0YWNrVHJhY2VMaW1pdH06IGFueSA9IEVycm9yO1xuICAgICAgRXJyb3Jbc3RhY2tQcm9wZXJ0eV0gPSBJbmZpbml0eTtcbiAgICAgIHN0YWNrID0gRXJyb3JTdGFja1BhcnNlci5wYXJzZShuZXcgRXJyb3IoKSk7XG4gICAgICBFcnJvcltzdGFja1Byb3BlcnR5XSA9IHN0YWNrVHJhY2VMaW1pdDtcbiAgICB9IGNhdGNoKGVycm9yKSB7fVxuXG4gICAgLy8gR2V0IG9wdGlvbnNcbiAgICBjb25zdCBvcHRpb25zID0gY2xvbmVEZWVwKHRoaXMub3B0aW9ucyk7XG5cbiAgICAvLyBBcHAgaW5mb1xuICAgIGNvbnN0IGFwcEluZm8gPSB7ZHVyYXRpb246IDAsIG9wdGlvbnMsIHN0YWNrfTtcblxuICAgIC8vIEFwcGx5IG1pZGRsZXdhcmUgYmVmb3JlIHRoZSBhY3Rpb24gaXMgcHJvY2Vzc2VkXG4gICAgY29uc3Qge3Bvc3REaXNwYXRjaExpc3QgPSBbXSwgcHJlRGlzcGF0Y2hMaXN0ID0gW119ID0gdGhpcy5taWRkbGV3YXJlO1xuXG4gICAgaWYocHJlRGlzcGF0Y2hMaXN0Lmxlbmd0aCkge1xuICAgICAgY2xvbmVkQWN0aW9uID0gYXdhaXQgUHJvbWlzZVxuICAgICAgICAuYWxsKFxuICAgICAgICAgIHByZURpc3BhdGNoTGlzdC5tYXAoKHBsdWdpbjogRmx1eFBsdWdpblR5cGUpID0+IHBsdWdpbi5tZXRob2QoXG4gICAgICAgICAgICBjbG9uZURlZXAoY2xvbmVkQWN0aW9uKSwgY2xvbmVEZWVwKHRoaXMuc3RhdGUpLCBhcHBJbmZvKVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgICAudGhlbihcbiAgICAgICAgICAoYWN0aW9ucykgPT4gYWN0aW9ucy5yZWR1Y2UoKHVwZGF0ZWRBY3Rpb24sIGFjdGlvbikgPT5cbiAgICAgICAgICAgIG1lcmdlKHVwZGF0ZWRBY3Rpb24sIGFjdGlvbiksIGNsb25lZEFjdGlvbikgYXMgRmx1eEFjdGlvblxuICAgICAgICApXG4gICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3Qge3R5cGUsIC4uLmRhdGF9ID0gY2xvbmVkQWN0aW9uO1xuXG4gICAgLy8gUmVxdWlyZSBhIHR5cGVcbiAgICBpZighdHlwZSB8fCB0eXBlID09PSAnJykge1xuICAgICAgY29uc29sZS53YXJuKCdBcmtoYW1KUyBXYXJuaW5nOiBGbHV4LmRpc3BhdGNoIGlzIG1pc3NpbmcgYW4gYWN0aW9uIHR5cGUgZm9yIHRoZSBwYXlsb2FkOicsIGRhdGEpO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjbG9uZWRBY3Rpb24pO1xuICAgIH1cblxuICAgIC8vIFdoZW4gYW4gYWN0aW9uIGNvbWVzIGluLCBpdCBtdXN0IGJlIGNvbXBsZXRlbHkgaGFuZGxlZCBieSBhbGwgc3RvcmVzXG4gICAgT2JqZWN0XG4gICAgICAua2V5cyh0aGlzLnN0b3JlQWN0aW9ucylcbiAgICAgIC5mb3JFYWNoKChzdG9yZU5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBzdG9yZUZuID0gdGhpcy5zdG9yZUFjdGlvbnNbc3RvcmVOYW1lXTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBjbG9uZURlZXAodGhpcy5zdGF0ZVtzdG9yZU5hbWVdKSB8fCBjbG9uZURlZXAoc3RvcmVGbi5pbml0aWFsU3RhdGUpIHx8IHt9O1xuICAgICAgICB0aGlzLnN0YXRlW3N0b3JlTmFtZV0gPSBjbG9uZURlZXAoc3RvcmVGbi5hY3Rpb24odHlwZSwgZGF0YSwgc3RhdGUpKSB8fCBzdGF0ZTtcbiAgICAgIH0pO1xuXG4gICAgLy8gU2F2ZSBjYWNoZSBpbiBzdG9yYWdlXG4gICAgY29uc3Qge3N0b3JhZ2V9ID0gdGhpcy5vcHRpb25zO1xuXG4gICAgaWYoc3RvcmFnZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVTdG9yYWdlKCk7XG4gICAgICB9IGNhdGNoKGVycm9yKSB7fVxuICAgIH1cblxuICAgIGNvbnN0IGVuZFRpbWU6IG51bWJlciA9ICsobmV3IERhdGUoKSk7XG4gICAgY29uc3QgZHVyYXRpb246IG51bWJlciA9IGVuZFRpbWUgLSBzdGFydFRpbWU7XG4gICAgYXBwSW5mby5kdXJhdGlvbiA9IGR1cmF0aW9uO1xuXG4gICAgaWYocG9zdERpc3BhdGNoTGlzdC5sZW5ndGgpIHtcbiAgICAgIGNsb25lZEFjdGlvbiA9IGF3YWl0IFByb21pc2VcbiAgICAgICAgLmFsbChcbiAgICAgICAgICBwb3N0RGlzcGF0Y2hMaXN0Lm1hcChcbiAgICAgICAgICAgIGFzeW5jIChwbHVnaW46IEZsdXhQbHVnaW5UeXBlKSA9PiBwbHVnaW4ubWV0aG9kKGNsb25lRGVlcChjbG9uZWRBY3Rpb24pLCBjbG9uZURlZXAodGhpcy5zdGF0ZSksIGFwcEluZm8pXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICAgIC50aGVuKFxuICAgICAgICAgIChhY3Rpb25zKSA9PiBhY3Rpb25zLnJlZHVjZSgodXBkYXRlZEFjdGlvbiwgYWN0aW9uKSA9PlxuICAgICAgICAgICAgbWVyZ2UodXBkYXRlZEFjdGlvbiwgYWN0aW9uKSwgY2xvbmVkQWN0aW9uKSBhcyBGbHV4QWN0aW9uXG4gICAgICAgIClcbiAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZighc2lsZW50KSB7XG4gICAgICB0aGlzLmVtaXQodHlwZSwgY2xvbmVkQWN0aW9uKTtcbiAgICAgIHRoaXMuZW1pdCgnYXJraGFtanMnLCB0aGlzLnN0YXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNsb25lZEFjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IEZsdXggb3B0aW9ucy5cbiAgICpcbiAgICogQHJldHVybnMge0ZsdXhPcHRpb25zfSB0aGUgRmx1eCBvcHRpb25zIG9iamVjdC5cbiAgICovXG4gIGdldE9wdGlvbnMoKTogRmx1eE9wdGlvbnMge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IHN0YXRlIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd8YXJyYXl9IFtuYW1lXSAob3B0aW9uYWwpIFRoZSBuYW1lIG9mIHRoZSBzdG9yZSBmb3IgYW4gb2JqZWN0LCBvdGhlcndpc2UgaXQgd2lsbCByZXR1cm4gYWxsIHN0b3JlXG4gICAqICAgb2JqZWN0cy4gWW91IGNhbiBhbHNvIHVzZSBhbiBhcnJheSB0byBzcGVjaWZ5IGEgcHJvcGVydHkgcGF0aCB3aXRoaW4gdGhlIG9iamVjdC5cbiAgICogQHBhcmFtIHthbnl9IFtkZWZhdWx0VmFsdWVdIChvcHRpb25hbCkgQSBkZWZhdWx0IHZhbHVlIHRvIHJldHVybiBpZiBudWxsLlxuICAgKiBAcmV0dXJucyB7YW55fSB0aGUgc3RhdGUgb2JqZWN0IG9yIGEgcHJvcGVydHkgdmFsdWUgd2l0aGluLlxuICAgKi9cbiAgZ2V0U3RhdGUocGF0aDogc3RyaW5nIHwgc3RyaW5nW10gPSAnJywgZGVmYXVsdFZhbHVlPyk6IGFueSB7XG4gICAgbGV0IHN0b3JlVmFsdWU7XG5cbiAgICBpZighcGF0aCkge1xuICAgICAgc3RvcmVWYWx1ZSA9IHRoaXMuc3RhdGUgfHwge307XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0b3JlVmFsdWUgPSBnZXQocGF0aCwgdGhpcy5zdGF0ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgdmFsdWUgPSBzdG9yZVZhbHVlID8gY2xvbmVEZWVwKHN0b3JlVmFsdWUpIDogc3RvcmVWYWx1ZTtcbiAgICByZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/IGRlZmF1bHRWYWx1ZSA6IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHN0b3JlIG9iamVjdCByZWdpc3RlcmVkIHdpdGggRmx1eC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHN0b3JlLlxuICAgKiBAcmV0dXJucyB7Rmx1eFN0b3JlfSB0aGUgc3RvcmUgb2JqZWN0LlxuICAgKi9cbiAgZ2V0U3RvcmUobmFtZTogc3RyaW5nID0gJycpOiBGbHV4U3RvcmUge1xuICAgIHJldHVybiB0aGlzLnN0b3JlQWN0aW9uc1tuYW1lXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGFuZCBzZXQgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyBDb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gICAqL1xuICBhc3luYyBpbml0KG9wdGlvbnM6IEZsdXhPcHRpb25zID0ge30sIHJlc2V0OiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPEZsdXhGcmFtZXdvcms+IHtcbiAgICAvLyBTaG91bGQgcmVzZXQgcHJldmlvdXMgcGFyYW1zXG4gICAgaWYocmVzZXQpIHtcbiAgICAgIHRoaXMuaXNJbml0ID0gZmFsc2U7XG4gICAgICB0aGlzLnJlc2V0KGZhbHNlKTtcbiAgICB9XG5cbiAgICAvLyBTZXQgb3B0aW9uc1xuICAgIGNvbnN0IHVwZGF0ZWRPcHRpb25zID0gey4uLm9wdGlvbnN9O1xuXG4gICAgaWYodGhpcy5pc0luaXQpIHtcbiAgICAgIC8vIFJlbW92ZSB0aGUgbmFtZSBmcm9tIG9wdGlvbnMgaWYgYWxyZWFkeSBpbml0aWFsaXplZCwgb3RoZXJ3aXNlIHRoZSByb290IGFwcCB3aWxsIG5vdCBiZSBhYmxlIHRvIGFjY2Vzc1xuICAgICAgLy8gdGhlIHN0YXRlIHRyZWVcbiAgICAgIHVwZGF0ZWRPcHRpb25zLm5hbWUgPSB0aGlzLm9wdGlvbnMubmFtZTtcbiAgICB9XG5cbiAgICB0aGlzLm9wdGlvbnMgPSB7Li4udGhpcy5kZWZhdWx0T3B0aW9ucywgLi4udXBkYXRlZE9wdGlvbnN9O1xuICAgIGNvbnN0IHtkZWJ1ZywgbWlkZGxld2FyZSwgbmFtZSwgc3RvcmVzfSA9IHRoaXMub3B0aW9ucztcblxuICAgIC8vIFVwZGF0ZSBkZWZhdWx0IHN0b3JlXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXNlU3RvcmFnZShuYW1lKTtcbiAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdBcmtoYW0gRXJyb3I6IFRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSB1c2luZyBzdG9yYWdlLicsIG5hbWUpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgaWYoISFzdG9yZXMgJiYgc3RvcmVzLmxlbmd0aCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5hZGRTdG9yZXMoc3RvcmVzKTtcbiAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQXJraGFtIEVycm9yOiBUaGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgYWRkaW5nIHN0b3Jlcy4nLCBzdG9yZXMpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZighIW1pZGRsZXdhcmUgJiYgbWlkZGxld2FyZS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuYWRkTWlkZGxld2FyZShtaWRkbGV3YXJlKTtcbiAgICB9XG5cbiAgICBjb25zdCB3aW5kb3dQcm9wZXJ0eTogc3RyaW5nID0gJ2Fya2hhbWpzJztcblxuICAgIGlmKGRlYnVnKSB7XG4gICAgICB3aW5kb3dbd2luZG93UHJvcGVydHldID0gdGhpcztcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlIHdpbmRvd1t3aW5kb3dQcm9wZXJ0eV07XG4gICAgfVxuXG4gICAgdGhpcy5pc0luaXQgPSB0cnVlO1xuICAgIHRoaXMuZW1pdChBcmtoYW1Db25zdGFudHMuSU5JVCk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGluaXRpYWxpemF0aW9uIGxpc3RlbmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbbGlzdGVuZXJdIFRoZSBjYWxsYmFjayBhc3NvY2lhdGVkIHdpdGggdGhlIHN1YnNjcmliZWQgZXZlbnQuXG4gICAqL1xuICBvbkluaXQobGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub24oQXJraGFtQ29uc3RhbnRzLklOSVQsIGxpc3RlbmVyKTtcblxuICAgIGlmKHRoaXMuaXNJbml0KSB7XG4gICAgICBsaXN0ZW5lcigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBpbml0aWFsaXphdGlvbiBsaXN0ZW5lci5cbiAgICpcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW2xpc3RlbmVyXSBUaGUgY2FsbGJhY2sgYXNzb2NpYXRlZCB3aXRoIHRoZSBzdWJzY3JpYmVkIGV2ZW50LlxuICAgKi9cbiAgb2ZmSW5pdChsaXN0ZW5lcjogKC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vZmYoQXJraGFtQ29uc3RhbnRzLklOSVQsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGFuIGV2ZW50IGxpc3RlbmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2V2ZW50VHlwZV0gRXZlbnQgdG8gdW5zdWJzY3JpYmUuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtsaXN0ZW5lcl0gVGhlIGNhbGxiYWNrIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3Vic2NyaWJlZCBldmVudC5cbiAgICovXG4gIG9mZihldmVudFR5cGU6IHN0cmluZywgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHRoaXMge1xuICAgIHJldHVybiB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZXZlbnQgbGlzdGVuZXIuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZXZlbnRUeXBlXSBFdmVudCB0byBzdWJzY3JpYmUuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtsaXN0ZW5lcl0gVGhlIGNhbGxiYWNrIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3Vic2NyaWJlZCBldmVudC5cbiAgICovXG4gIG9uKGV2ZW50VHlwZTogc3RyaW5nLCBsaXN0ZW5lcjogKC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkKTogdGhpcyB7XG4gICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXJzIG5ldyBTdG9yZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7YXJyYXl9IHN0b3JlcyBTdG9yZSBjbGFzcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8b2JqZWN0W10+fSB0aGUgY2xhc3Mgb2JqZWN0KHMpLlxuICAgKi9cbiAgYXN5bmMgYWRkU3RvcmVzKHN0b3JlczogYW55W10pOiBQcm9taXNlPG9iamVjdFtdPiB7XG4gICAgY29uc3QgcmVnaXN0ZXJlZFN0b3JlczogRmx1eFN0b3JlW10gPSBzdG9yZXMubWFwKChzdG9yZTogRmx1eFN0b3JlKSA9PiB0aGlzLnJlZ2lzdGVyKHN0b3JlKSk7XG5cbiAgICAvLyBTYXZlIGNhY2hlIGluIHNlc3Npb24gc3RvcmFnZVxuICAgIGNvbnN0IHtuYW1lLCBzdG9yYWdlfSA9IHRoaXMub3B0aW9ucztcblxuICAgIGlmKHN0b3JhZ2UpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2V0U3RvcmFnZURhdGEobmFtZSwgdGhpcy5zdGF0ZSk7XG4gICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybiBjbGFzc2VzXG4gICAgcmV0dXJuIHJlZ2lzdGVyZWRTdG9yZXM7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIG1pZGRsZXdhcmUgZnJvbSBmcmFtZXdvcmsuXG4gICAqXG4gICAqIEBwYXJhbSB7YXJyYXl9IHN0cmluZyBtaWRkbGV3YXJlIG5hbWVzIHRvIHJlbW92ZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8b2JqZWN0W10+fSB0aGUgY2xhc3Mgb2JqZWN0KHMpLlxuICAgKi9cbiAgcmVtb3ZlTWlkZGxld2FyZShuYW1lczogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBuYW1lcy5mb3JFYWNoKChuYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgIC8vIFJlbW92ZSBtaWRkbGV3YXJlIHBsdWdpbnNcbiAgICAgIHRoaXMucGx1Z2luVHlwZXMuZm9yRWFjaCgodHlwZTogc3RyaW5nKSA9PiB7XG4gICAgICAgIHRoaXMubWlkZGxld2FyZVtgJHt0eXBlfUxpc3RgXSA9IHRoaXMucmVtb3ZlUGx1Z2luKHR5cGUsIG5hbWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgZnJhbWV3b3JrLlxuICAgKlxuICAgKiBAcGFyYW0ge2FycmF5fSBzdHJpbmcgbWlkZGxld2FyZSBuYW1lcyB0byByZW1vdmUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG9iamVjdFtdPn0gdGhlIGNsYXNzIG9iamVjdChzKS5cbiAgICovXG4gIGFzeW5jIHJlc2V0KGNsZWFyU3RvcmFnZTogYm9vbGVhbiA9IHRydWUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7bmFtZSwgc3RvcmFnZX0gPSB0aGlzLm9wdGlvbnM7XG5cbiAgICAvLyBDbGVhciBwZXJzaXN0ZW50IGNhY2hlXG4gICAgaWYoc3RvcmFnZSAmJiBjbGVhclN0b3JhZ2UpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2V0U3RvcmFnZURhdGEobmFtZSwge30pO1xuICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDbGVhciBhbGwgcHJvcGVydGllc1xuICAgIHRoaXMubWlkZGxld2FyZSA9IHt9O1xuICAgIHRoaXMub3B0aW9ucyA9IHsuLi50aGlzLmRlZmF1bHRPcHRpb25zfTtcbiAgICB0aGlzLnN0YXRlID0ge307XG4gICAgdGhpcy5zdG9yZUFjdGlvbnMgPSB7fTtcbiAgICB0aGlzLmlzSW5pdCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGN1cnJlbnQgc3RhdGUgb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ3xhcnJheX0gW25hbWVdIFRoZSBuYW1lIG9mIHRoZSBzdG9yZSB0byBzZXQuIFlvdSBjYW4gYWxzbyB1c2UgYW4gYXJyYXkgdG8gc3BlY2lmeSBhIHByb3BlcnR5IHBhdGhcbiAgICogd2l0aGluIHRoZSBvYmplY3QuXG4gICAqIEBwYXJhbSB7YW55fSBbdmFsdWVdIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAqL1xuICBzZXRTdGF0ZShwYXRoOiBzdHJpbmcgfCBzdHJpbmdbXSA9ICcnLCB2YWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmKCEhcGF0aCkge1xuICAgICAgdGhpcy5zdGF0ZSA9IHNldChwYXRoLCBjbG9uZURlZXAodmFsdWUpLCB0aGlzLnN0YXRlKTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgcGVyc2lzdGVudCBjYWNoZVxuICAgIGNvbnN0IHtzdG9yYWdlfSA9IHRoaXMub3B0aW9ucztcblxuICAgIGlmKHN0b3JhZ2UpIHtcbiAgICAgIHJldHVybiB0aGlzLnVwZGF0ZVN0b3JhZ2UoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkUGx1Z2luKHR5cGU6IHN0cmluZywgcGx1Z2luOiBGbHV4UGx1Z2luVHlwZSk6IEZsdXhQbHVnaW5UeXBlW10ge1xuICAgIGNvbnN0IGxpc3QgPSB0aGlzLm1pZGRsZXdhcmVbYCR7dHlwZX1MaXN0YF0gfHwgW107XG4gICAgY29uc3Qge21ldGhvZCwgbmFtZX0gPSBwbHVnaW47XG5cbiAgICBpZihtZXRob2QgJiYgdHlwZW9mIG1ldGhvZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQ2hlY2sgaWYgcGx1Z2luIGFscmVhZHkgZXhpc3RzXG4gICAgICBjb25zdCBleGlzdHM6IGJvb2xlYW4gPSAhIWxpc3QuZmlsdGVyKChvYmo6IEZsdXhQbHVnaW5UeXBlKSA9PiBvYmoubmFtZSA9PT0gbmFtZSkubGVuZ3RoO1xuXG4gICAgICAvLyBEbyBub3QgYWRkIGR1cGxpY2F0ZSBwbHVnaW5zXG4gICAgICBpZighZXhpc3RzKSB7XG4gICAgICAgIGxpc3QucHVzaCh7bWV0aG9kLCBuYW1lfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKG1ldGhvZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBFcnJvcihgJHtwbHVnaW4ubmFtZX0gbWlkZGxld2FyZSBpcyBub3QgY29uZmlndXJlZCBwcm9wZXJseS4gTWV0aG9kIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgIH1cblxuICAgIHJldHVybiBsaXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBkZXJlZ2lzdGVyKG5hbWU6IHN0cmluZyA9ICcnKTogdm9pZCB7XG4gICAgZGVsZXRlIHRoaXMuc3RvcmVBY3Rpb25zW25hbWVdO1xuICAgIGRlbGV0ZSB0aGlzLnN0YXRlW25hbWVdO1xuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlcihzdG9yZUZuKTogRmx1eFN0b3JlIHtcbiAgICBpZighc3RvcmVGbikge1xuICAgICAgdGhyb3cgRXJyb3IoJ1N0b3JlIGlzIHVuZGVmaW5lZC4gQ2Fubm90IHJlZ2lzdGVyIHdpdGggRmx1eC4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBpc0ZuYzogYm9vbGVhbiA9IHR5cGVvZiBzdG9yZUZuID09PSAnZnVuY3Rpb24nO1xuXG4gICAgaWYoIWlzRm5jKSB7XG4gICAgICB0aHJvdyBFcnJvcihgJHtzdG9yZUZufSBpcyBub3QgYSBzdG9yZSBmdW5jdGlvbi4gQ2Fubm90IHJlZ2lzdGVyIHdpdGggRmx1eC5gKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgc3RvcmUgb2JqZWN0XG4gICAgY29uc3Qge25hbWV9ID0gc3RvcmVGbjtcbiAgICBjb25zdCBpbml0aWFsU3RhdGU6IGFueSA9IHN0b3JlRm4oKTtcbiAgICBjb25zdCBzdG9yZUFjdGlvbiA9IHtcbiAgICAgIGFjdGlvbjogc3RvcmVGbixcbiAgICAgIGluaXRpYWxTdGF0ZTogc3RvcmVGbigpLFxuICAgICAgbmFtZVxuICAgIH07XG5cbiAgICBpZighaXNFbXB0eShuYW1lKSAmJiAhdGhpcy5zdG9yZUFjdGlvbnNbbmFtZV0pIHtcbiAgICAgIC8vIFNhdmUgc3RvcmUgb2JqZWN0XG4gICAgICB0aGlzLnN0b3JlQWN0aW9uc1tuYW1lXSA9IHN0b3JlQWN0aW9uO1xuXG4gICAgICAvLyBHZXQgZGVmYXVsdCB2YWx1ZXNcbiAgICAgIGlmKCF0aGlzLnN0YXRlW25hbWVdKSB7XG4gICAgICAgIGlmKGluaXRpYWxTdGF0ZSkge1xuICAgICAgICAgIHRoaXMuc3RhdGVbbmFtZV0gPSBjbG9uZURlZXAoaW5pdGlhbFN0YXRlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnN0YXRlW25hbWVdID0ge307XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZXR1cm4gc3RvcmUgY2xhc3NcbiAgICByZXR1cm4gdGhpcy5zdG9yZUFjdGlvbnNbbmFtZV07XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZVBsdWdpbih0eXBlOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IEZsdXhQbHVnaW5UeXBlW10ge1xuICAgIGNvbnN0IGxpc3QgPSB0aGlzLm1pZGRsZXdhcmVbYCR7dHlwZX1MaXN0YF0gfHwgW107XG5cbiAgICAvLyByZW1vdmUgYWxsIG9jY3VycmVuY2VzIG9mIHRoZSBwbHVnaW5cbiAgICByZXR1cm4gbGlzdC5maWx0ZXIoKG9iajogRmx1eFBsdWdpblR5cGUpID0+IG9iai5uYW1lICE9PSBuYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlU3RvcmFnZSA9ICgpID0+IFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG5cbiAgcHJpdmF0ZSBhc3luYyB1c2VTdG9yYWdlKG5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHtzdG9yYWdlLCBzdGF0ZSwgc3RvcmFnZVdhaXR9ID0gdGhpcy5vcHRpb25zO1xuXG4gICAgLy8gQ2FjaGVcbiAgICBpZihzdG9yYWdlKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLnN0YXRlID0gc3RhdGUgfHwgYXdhaXQgc3RvcmFnZS5nZXRTdG9yYWdlRGF0YShuYW1lKSB8fCB7fTtcbiAgICAgICAgdGhpcy51cGRhdGVTdG9yYWdlID0gZGVib3VuY2UoXG4gICAgICAgICAgKCkgPT4gc3RvcmFnZS5zZXRTdG9yYWdlRGF0YShuYW1lLCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICBzdG9yYWdlV2FpdCxcbiAgICAgICAgICB7bGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IHRydWV9XG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEFya2hhbUpTIEVycm9yOiBVc2luZyBzdG9yYWdlLCBcIiR7bmFtZX1cIi5gKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RhdGUgPSBzdGF0ZSB8fCB7fTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgRmx1eDogRmx1eEZyYW1ld29yayA9IG5ldyBGbHV4RnJhbWV3b3JrKCk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7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