@decaf-ts/transactional-decorators 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE.md +3 -2
  2. package/README.md +242 -17
  3. package/dist/transactional-decorators.cjs +2 -643
  4. package/dist/transactional-decorators.cjs.map +1 -0
  5. package/dist/transactional-decorators.js +2 -0
  6. package/dist/transactional-decorators.js.map +1 -0
  7. package/lib/Transaction.cjs +1 -1
  8. package/lib/Transaction.js.map +1 -0
  9. package/lib/constants.cjs +1 -1
  10. package/lib/constants.js.map +1 -0
  11. package/lib/decorators.cjs +1 -1
  12. package/lib/decorators.js.map +1 -0
  13. package/lib/esm/Transaction.js +1 -1
  14. package/lib/esm/Transaction.js.map +1 -0
  15. package/lib/esm/constants.js +1 -1
  16. package/lib/esm/constants.js.map +1 -0
  17. package/lib/esm/decorators.js +1 -1
  18. package/lib/esm/decorators.js.map +1 -0
  19. package/lib/esm/index.js +1 -1
  20. package/lib/esm/index.js.map +1 -0
  21. package/lib/esm/interfaces/TransactionLock.js +1 -1
  22. package/lib/esm/interfaces/TransactionLock.js.map +1 -0
  23. package/lib/esm/interfaces/index.js +1 -1
  24. package/lib/esm/interfaces/index.js.map +1 -0
  25. package/lib/esm/locks/Lock.js +1 -1
  26. package/lib/esm/locks/Lock.js.map +1 -0
  27. package/lib/esm/locks/SyncronousLock.js +1 -1
  28. package/lib/esm/locks/SyncronousLock.js.map +1 -0
  29. package/lib/esm/locks/index.js +1 -1
  30. package/lib/esm/locks/index.js.map +1 -0
  31. package/lib/esm/types.js +1 -1
  32. package/lib/esm/types.js.map +1 -0
  33. package/lib/esm/utils.js +1 -1
  34. package/lib/esm/utils.js.map +1 -0
  35. package/lib/index.cjs +1 -1
  36. package/lib/index.js.map +1 -0
  37. package/lib/interfaces/TransactionLock.cjs +1 -1
  38. package/lib/interfaces/TransactionLock.js.map +1 -0
  39. package/lib/interfaces/index.cjs +1 -1
  40. package/lib/interfaces/index.js.map +1 -0
  41. package/lib/locks/Lock.cjs +1 -1
  42. package/lib/locks/Lock.js.map +1 -0
  43. package/lib/locks/SyncronousLock.cjs +1 -1
  44. package/lib/locks/SyncronousLock.js.map +1 -0
  45. package/lib/locks/index.cjs +1 -1
  46. package/lib/locks/index.js.map +1 -0
  47. package/lib/types.cjs +1 -1
  48. package/lib/types.js.map +1 -0
  49. package/lib/utils.cjs +1 -1
  50. package/lib/utils.js.map +1 -0
  51. package/package.json +23 -24
  52. package/dist/transactional-decorators.esm.cjs +0 -632
@@ -1,632 +0,0 @@
1
- import { Reflection, metadata } from '@decaf-ts/reflection';
2
- import { getAllPropertyDecoratorsRecursive, DBKeys, InternalError } from '@decaf-ts/db-decorators';
3
-
4
- /**
5
- * @description Base lock implementation for concurrency control
6
- * @summary Provides a basic lock mechanism for controlling access to shared resources, with support for queuing and executing functions when the lock is available
7
- * @class Lock
8
- * @example
9
- * // Using the Lock class to execute a function with exclusive access
10
- * const lock = new Lock();
11
- * const result = await lock.execute(async () => {
12
- * // This code will run with exclusive access
13
- * return await performCriticalOperation();
14
- * });
15
- */
16
- class Lock {
17
- constructor() {
18
- this.queue = [];
19
- this.locked = false;
20
- }
21
- /**
22
- * @description Executes a function with exclusive lock access
23
- * @summary Acquires the lock, executes the provided function, and releases the lock afterward, ensuring proper cleanup even if the function throws an error
24
- * @param {Function} func - The function to execute when the lock is acquired
25
- * @return {Promise<any>} A promise that resolves with the result of the executed function
26
- */
27
- async execute(func) {
28
- await this.acquire();
29
- let result;
30
- try {
31
- result = await Promise.resolve(func());
32
- }
33
- catch (e) {
34
- this.release();
35
- throw e;
36
- }
37
- this.release();
38
- return result;
39
- }
40
- /**
41
- * @summary waits to acquire the lock
42
- * @param {string} [issuer]
43
- */
44
- async acquire() {
45
- // eslint-disable-next-line @typescript-eslint/no-this-alias
46
- const self = this;
47
- if (self.locked) {
48
- return new Promise((resolve) => self.queue.push(resolve));
49
- }
50
- else {
51
- self.locked = true;
52
- return Promise.resolve();
53
- }
54
- }
55
- /**
56
- * @summary releases the lock
57
- */
58
- release() {
59
- // eslint-disable-next-line @typescript-eslint/no-this-alias
60
- const self = this;
61
- const next = self.queue.shift();
62
- if (next) {
63
- if (typeof globalThis.window === "undefined")
64
- globalThis.process.nextTick(next); // if you are on node
65
- else
66
- setTimeout(next, 0); // if you are in the browser
67
- }
68
- else {
69
- self.locked = false;
70
- }
71
- }
72
- }
73
-
74
- /**
75
- * @summary Simple Synchronous Lock implementation
76
- * @description for transaction management
77
- * adapted from {@link https://www.talkinghightech.com/en/creating-a-js-lock-for-a-resource/}
78
- *
79
- * @param {number} [counter] the number of simultaneous transactions allowed. defaults to 1
80
- * @param {Function} [onBegin] to be called at the start of the transaction
81
- * @param {Function} [onEnd] to be called at the conclusion of the transaction
82
- *
83
- * @class SyncronousLock
84
- * @implements TransactionLock
85
- */
86
- class SyncronousLock {
87
- constructor(counter = 1, onBegin, onEnd) {
88
- this.currentTransaction = undefined;
89
- this.lock = new Lock();
90
- this.counter = counter;
91
- this.pendingTransactions = [];
92
- this.onBegin = onBegin;
93
- this.onEnd = onEnd;
94
- }
95
- /**
96
- * @summary Submits a transaction to be processed
97
- * @param {Transaction} transaction
98
- */
99
- submit(transaction) {
100
- // eslint-disable-next-line @typescript-eslint/no-this-alias
101
- const self = this;
102
- self.lock.acquire().then(() => {
103
- if (self.currentTransaction &&
104
- self.currentTransaction.id === transaction.id) {
105
- self.lock.release();
106
- return transaction.fire();
107
- }
108
- if (self.counter > 0) {
109
- self.counter--;
110
- self.lock.release();
111
- return self.fireTransaction(transaction);
112
- }
113
- else {
114
- self.pendingTransactions.push(transaction);
115
- self.lock.release();
116
- }
117
- });
118
- }
119
- /**
120
- * @summary Executes a transaction
121
- *
122
- * @param {Transaction} transaction
123
- * @private
124
- */
125
- fireTransaction(transaction) {
126
- // eslint-disable-next-line @typescript-eslint/no-this-alias
127
- const self = this;
128
- self.lock.acquire().then(() => {
129
- self.currentTransaction = transaction;
130
- self.lock.release();
131
- if (self.onBegin)
132
- self.onBegin().then(() => {
133
- // all.call(
134
- // self,
135
- // `Firing transaction {0}. {1} remaining...`,
136
- // transaction.id,
137
- // this.pendingTransactions.length,
138
- // );
139
- transaction.fire();
140
- });
141
- else {
142
- // all.call(
143
- // self,
144
- // `Firing transaction {0}. {1} remaining...`,
145
- // transaction.id,
146
- // this.pendingTransactions.length,
147
- // );
148
- transaction.fire();
149
- }
150
- });
151
- }
152
- /**
153
- * @summary Releases The lock after the conclusion of a transaction
154
- */
155
- async release(err) {
156
- // eslint-disable-next-line @typescript-eslint/no-this-alias
157
- const self = this;
158
- return new Promise((resolve) => {
159
- self.lock.acquire().then(() => {
160
- if (!self.currentTransaction)
161
- console.warn("Trying to release an unexisting transaction. should never happen...");
162
- // debug.call(
163
- // self,
164
- // "Releasing transaction: {0}",
165
- // self.currentTransaction?.toString(true, true),
166
- // );
167
- self.currentTransaction = undefined;
168
- self.lock.release();
169
- const afterConclusionCB = () => {
170
- self.lock.acquire().then(() => {
171
- if (self.pendingTransactions.length > 0) {
172
- const transaction = self.pendingTransactions.shift();
173
- const cb = () => self.fireTransaction(transaction);
174
- //
175
- // all(
176
- // `Releasing Transaction Lock on transaction {0}`,
177
- // transaction.id,
178
- // );
179
- if (typeof globalThis.window ===
180
- "undefined")
181
- globalThis.process.nextTick(cb); // if you are on node
182
- else
183
- setTimeout(cb, 0); // if you are in the browser
184
- }
185
- else {
186
- self.counter++;
187
- }
188
- self.lock.release();
189
- resolve();
190
- });
191
- };
192
- if (self.onEnd)
193
- self.onEnd(err).then(() => afterConclusionCB());
194
- else
195
- afterConclusionCB();
196
- });
197
- });
198
- }
199
- }
200
-
201
- /**
202
- * @typedef {Object} TransactionalKeysType
203
- * @property {string} REFLECT - Key used for reflection metadata related to transactional models
204
- * @property {string} TRANSACTIONAL - Key used to identify transactional properties
205
- * @memberOf module:transactions
206
- */
207
- /**
208
- * @description Keys used for transactional operations
209
- * @summary Constant object containing string keys used throughout the transactional system for reflection and identification
210
- * @type {TransactionalKeysType}
211
- * @const TransactionalKeys
212
- * @memberOf module:transactions
213
- */
214
- const TransactionalKeys = {
215
- REFLECT: "model.transactional.",
216
- TRANSACTIONAL: "transactional",
217
- };
218
-
219
- function getObjectName(obj) {
220
- if (!obj)
221
- return;
222
- if (typeof obj === "string")
223
- return obj;
224
- if (obj.constructor &&
225
- obj.constructor.name &&
226
- ["Function", "Object"].indexOf(obj.constructor.name) === -1)
227
- return obj.constructor.name;
228
- if (typeof obj === "function" && obj.name)
229
- return obj.name;
230
- return obj.toString();
231
- }
232
-
233
- /**
234
- * @description Core transaction management class
235
- * @summary Manages transaction lifecycle, including creation, execution, and cleanup. Provides mechanisms for binding transactions to objects and methods, ensuring proper transaction context propagation.
236
- * @param {string} source - The source/origin of the transaction (typically a class name)
237
- * @param {string} [method] - The method name associated with the transaction
238
- * @param {function(): any} [action] - The function to execute within the transaction
239
- * @param {any[]} [metadata] - Additional metadata to associate with the transaction
240
- * @class Transaction
241
- * @example
242
- * // Creating and submitting a transaction
243
- * const transaction = new Transaction(
244
- * 'UserService',
245
- * 'createUser',
246
- * async () => {
247
- * // Transaction logic here
248
- * await db.insert('users', { name: 'John' });
249
- * }
250
- * );
251
- * Transaction.submit(transaction);
252
- *
253
- * // Using the transactional decorator
254
- * class UserService {
255
- * @transactional()
256
- * async createUser(data) {
257
- * // Method will be executed within a transaction
258
- * return await db.insert('users', data);
259
- * }
260
- * }
261
- * @mermaid
262
- * sequenceDiagram
263
- * participant C as Client Code
264
- * participant T as Transaction
265
- * participant L as TransactionLock
266
- * participant O as Original Method
267
- *
268
- * C->>T: new Transaction(source, method, action)
269
- * C->>T: Transaction.submit(transaction)
270
- * T->>L: submit(transaction)
271
- * L->>T: fire()
272
- * T->>O: Execute action()
273
- * O-->>T: Return result/error
274
- * T->>L: release(error?)
275
- * L-->>C: Return result/error
276
- */
277
- class Transaction {
278
- constructor(source, method, action, metadata) {
279
- this.id = Date.now();
280
- this.action = action;
281
- this.method = method;
282
- this.log = [[this.id, source, method].join(" | ")];
283
- this.source = source;
284
- this.metadata = metadata;
285
- }
286
- /**
287
- * @description Queues a transaction for execution
288
- * @summary Pushes a transaction to the queue and waits for its resolution. Creates a new transaction with the provided issuer and callback method, then submits it to the transaction lock.
289
- * @param {any} issuer - Any class instance that will be used as 'this' when calling the callbackMethod
290
- * @param {Function} callbackMethod - Callback function containing the transaction logic, will be called with the issuer as 'this'
291
- * @param {any[]} args - Arguments to pass to the method. Last one must be the callback function
292
- * @return {void}
293
- */
294
- static push(issuer, callbackMethod, ...args) {
295
- const callback = args.pop();
296
- if (!callback || typeof callback !== "function")
297
- throw new Error("Missing callback");
298
- const cb = (err, ...args) => {
299
- Transaction.getLock()
300
- .release(err)
301
- .then(() => callback(err, ...args));
302
- };
303
- const transaction = new Transaction(issuer.constructor.name, callbackMethod.name ? getObjectName(callbackMethod) : "Anonymous", () => {
304
- return callbackMethod.call(transaction.bindToTransaction(issuer), ...args, cb);
305
- });
306
- Transaction.getLock().submit(transaction);
307
- }
308
- /**
309
- * @description Configures the transaction lock implementation
310
- * @summary Sets the lock implementation to be used for transaction management, allowing customization of the transaction behavior
311
- * @param {TransactionLock} lock - The lock implementation to use for managing transactions
312
- * @return {void}
313
- */
314
- static setLock(lock) {
315
- this.lock = lock;
316
- }
317
- /**
318
- * @description Retrieves the current transaction lock
319
- * @summary Gets the current transaction lock instance, creating a default SyncronousLock if none exists
320
- * @return {TransactionLock} The current transaction lock implementation
321
- */
322
- static getLock() {
323
- if (!this.lock)
324
- this.lock = new SyncronousLock();
325
- return this.lock;
326
- }
327
- /**
328
- * @description Submits a transaction for processing
329
- * @summary Submits a transaction to the current transaction lock for processing and execution
330
- * @param {Transaction} transaction - The transaction to submit for processing
331
- * @return {void}
332
- */
333
- static submit(transaction) {
334
- Transaction.getLock().submit(transaction);
335
- }
336
- /**
337
- * @description Releases the transaction lock
338
- * @summary Releases the current transaction lock, optionally with an error, allowing the next transaction to proceed
339
- * @param {Error} [err] - Optional error that occurred during transaction execution
340
- * @return {Promise<void>} A promise that resolves when the lock has been released
341
- */
342
- static async release(err) {
343
- return Transaction.getLock().release(err);
344
- }
345
- /**
346
- * @description Retrieves transaction metadata
347
- * @summary Returns a copy of the metadata associated with this transaction, ensuring the original metadata remains unmodified
348
- * @return {any[] | undefined} A copy of the transaction metadata or undefined if no metadata exists
349
- */
350
- getMetadata() {
351
- return this.metadata ? [...this.metadata] : undefined;
352
- }
353
- /**
354
- * @description Links a new transaction to the current one
355
- * @summary Binds a new transaction operation to the current transaction, transferring logs and binding methods to maintain transaction context
356
- * @param {Transaction} nextTransaction - The new transaction to bind to the current one
357
- * @return {void}
358
- */
359
- bindTransaction(nextTransaction) {
360
- // all(`Binding the {0} to {1}`, nextTransaction, this);
361
- this.log.push(...nextTransaction.log);
362
- nextTransaction.bindTransaction = this.bindToTransaction.bind(this);
363
- nextTransaction.bindToTransaction = this.bindToTransaction.bind(this);
364
- this.action = nextTransaction.action;
365
- }
366
- /**
367
- * @description Binds an object to the current transaction context
368
- * @summary Binds a transactional decorated object to the transaction by ensuring all transactional methods automatically receive the current transaction as their first argument
369
- * @param {any} obj - The object to bind to the transaction
370
- * @return {any} The bound object with transaction-aware method wrappers
371
- */
372
- bindToTransaction(obj) {
373
- const transactionalMethods = getAllPropertyDecoratorsRecursive(obj, undefined, TransactionalKeys.REFLECT);
374
- if (!transactionalMethods)
375
- return obj;
376
- // eslint-disable-next-line @typescript-eslint/no-this-alias
377
- const self = this;
378
- const boundObj = Reflection.getAllProperties(obj).reduce((accum, k) => {
379
- if (Object.keys(transactionalMethods).indexOf(k) !== -1 &&
380
- transactionalMethods[k].find((o) => o.key === TransactionalKeys.TRANSACTIONAL))
381
- accum[k] = (...args) => obj[k].call(obj.__originalObj || obj, self, ...args);
382
- else if (k === "clazz" || k === "constructor")
383
- accum[k] = obj[k];
384
- else if (typeof obj[k] === "function")
385
- accum[k] = obj[k].bind(obj.__originalObj || obj);
386
- else if (typeof obj[k] === "object" && obj[k].constructor) {
387
- const decs = Reflection.getClassDecorators(TransactionalKeys.REFLECT, obj[k]);
388
- if (decs.find((e) => e.key === TransactionalKeys.TRANSACTIONAL))
389
- accum[k] = self.bindToTransaction(obj[k]);
390
- else
391
- accum[k] = obj[k];
392
- }
393
- else
394
- accum[k] = obj[k];
395
- return accum;
396
- }, {});
397
- boundObj[DBKeys.ORIGINAL] = obj[DBKeys.ORIGINAL] || obj;
398
- boundObj.toString = () => getObjectName(boundObj[DBKeys.ORIGINAL]) +
399
- " proxy for transaction " +
400
- this.id;
401
- return boundObj;
402
- }
403
- /**
404
- * @description Executes the transaction action
405
- * @summary Fires the transaction by executing its associated action function, throwing an error if no action is defined
406
- * @return {any} The result of the transaction action
407
- */
408
- fire() {
409
- if (!this.action)
410
- throw new Error(`Missing the method`);
411
- return this.action();
412
- }
413
- /**
414
- * @description Provides a string representation of the transaction
415
- * @summary Overrides the default toString method to provide a formatted string representation of the transaction, optionally including the transaction ID and log
416
- * @param {boolean} [withId=true] - Whether to include the transaction ID in the output
417
- * @param {boolean} [withLog=false] - Whether to include the transaction log in the output
418
- * @return {string} A string representation of the transaction
419
- */
420
- toString(withId = true, withLog = false) {
421
- return `${withId ? `[${this.id}]` : ""}[Transaction][${this.source}.${this.method}${withLog ? `]\nTransaction Log:\n${this.log.join("\n")}` : "]"}`;
422
- }
423
- /**
424
- * @description Generates a reflection metadata key for transactions
425
- * @summary Creates a prefixed reflection key for transaction-related metadata, ensuring proper namespacing
426
- * @param {string} key - The base key to prefix with the transaction reflection namespace
427
- * @return {string} The complete reflection key for transaction metadata
428
- * @function key
429
- */
430
- static key(key) {
431
- return TransactionalKeys.REFLECT + key;
432
- }
433
- }
434
-
435
- /**
436
- * @description Method decorator that enables transactional behavior
437
- * @summary Sets a class async method as transactional, wrapping it in a transaction context that can be managed by the transaction system. This decorator handles transaction creation, binding, and error handling.
438
- * @param {any[]} [data] - Optional metadata available to the {@link TransactionLock} implementation
439
- * @return {Function} A decorator function that wraps the original method with transactional behavior
440
- * @function transactional
441
- * @category Method Decorators
442
- * @mermaid
443
- * sequenceDiagram
444
- * participant C as Client Code
445
- * participant D as Decorator
446
- * participant T as Transaction
447
- * participant O as Original Method
448
- *
449
- * C->>D: Call decorated method
450
- * D->>D: Check if transaction exists in args
451
- *
452
- * alt Transaction exists in args
453
- * D->>T: Create updated transaction
454
- * T->>T: Bind to original transaction
455
- * T->>T: Fire transaction
456
- * else No transaction
457
- * D->>T: Create new transaction
458
- * T->>T: Submit transaction
459
- * end
460
- *
461
- * T->>O: Execute original method
462
- * O-->>T: Return result/error
463
- * T->>T: Release transaction
464
- * T-->>C: Return result/error
465
- * @category Decorators
466
- */
467
- function transactional(...data) {
468
- return function (target, propertyKey, descriptor) {
469
- if (!descriptor)
470
- throw new InternalError("Missing descriptor. Should be impossible");
471
- metadata(Transaction.key(TransactionalKeys.TRANSACTIONAL), data)(target, propertyKey);
472
- const originalMethod = descriptor.value;
473
- const methodWrapper = function (...args) {
474
- // eslint-disable-next-line @typescript-eslint/no-this-alias
475
- const self = this;
476
- return new Promise((resolve, reject) => {
477
- const cb = (err, result) => {
478
- Transaction.release(err).then(() => {
479
- if (err)
480
- return reject(err);
481
- resolve(result);
482
- });
483
- };
484
- let transaction = args.shift();
485
- if (transaction instanceof Transaction) {
486
- const updatedTransaction = new Transaction(this.constructor.name, propertyKey, async () => {
487
- originalMethod
488
- .call(updatedTransaction.bindToTransaction(self), ...args)
489
- .then(resolve)
490
- .catch(reject);
491
- }, data.length ? data : undefined);
492
- transaction.bindTransaction(updatedTransaction);
493
- transaction.fire();
494
- }
495
- else {
496
- args.unshift(transaction);
497
- transaction = new Transaction(this.constructor.name, propertyKey, () => {
498
- originalMethod
499
- .call(transaction.bindToTransaction(self), ...args)
500
- .then((result) => cb(undefined, result))
501
- .catch(cb);
502
- }, data.length ? data : undefined);
503
- Transaction.submit(transaction);
504
- }
505
- });
506
- };
507
- Object.defineProperty(methodWrapper, "name", {
508
- value: propertyKey,
509
- });
510
- descriptor.value = methodWrapper;
511
- };
512
- }
513
- //
514
- // /**
515
- // * @summary Sets a class Async method as transactional
516
- // *
517
- // * @param {any[]} [metadata] option metadata available to the {@link TransactionLock}
518
- // *
519
- // * @function transactionalAsync
520
- // *
521
- // * @memberOf module:db-decorators.Decorators.transactions
522
- // */
523
- // export function transactionalAsync(...metadata: any[]) {
524
- // return function (
525
- // target: any,
526
- // propertyKey: string,
527
- // descriptor: PropertyDescriptor,
528
- // ) {
529
- // metadasta(getTransactionalKey(TransactionalKeys.TRANSACTIONAL))
530
- // Reflect.defineMetadata(
531
- // ,
532
- // {
533
- // type: "async",
534
- // metadata: metadata.length ? metadata : undefined,
535
- // } as TransactionalMetadata,
536
- // target,
537
- // propertyKey,
538
- // );
539
- //
540
- // const originalMethod = descriptor.value;
541
- //
542
- // const methodWrapper = function (this: any, ...args: any[]) {
543
- // const callback: Callback = args.pop();
544
- // if (!callback || typeof callback !== "function")
545
- // throw new CriticalError(`Missing Callback`);
546
- //
547
- // const cb = (err?: Err, ...args: any[]) => {
548
- // Transaction.release(err).then((_) => callback(err, ...args));
549
- // };
550
- //
551
- // const self = this;
552
- //
553
- // let transaction = args.shift();
554
- // if (transaction instanceof Transaction) {
555
- // const updatedTransaction: Transaction = new Transaction(
556
- // this.constructor.name,
557
- // propertyKey,
558
- // () => {
559
- // try {
560
- // return originalMethod.call(
561
- // updatedTransaction.bindToTransaction(self),
562
- // ...args,
563
- // callback,
564
- // );
565
- // } catch (e: any) {
566
- // return callback(e);
567
- // }
568
- // },
569
- // metadata.length ? metadata : undefined,
570
- // );
571
- //
572
- // transaction.bindTransaction(updatedTransaction);
573
- // transaction.fire();
574
- // } else {
575
- // args.unshift(transaction);
576
- // transaction = undefined;
577
- // transaction = new Transaction(
578
- // this.constructor.name,
579
- // propertyKey,
580
- // () => {
581
- // try {
582
- // return originalMethod.call(
583
- // transaction.bindToTransaction(self),
584
- // ...args,
585
- // cb,
586
- // );
587
- // } catch (e: any) {
588
- // return cb(e);
589
- // }
590
- // },
591
- // metadata.length ? metadata : undefined,
592
- // );
593
- // Transaction.submit(transaction);
594
- // }
595
- // };
596
- //
597
- // Object.defineProperty(methodWrapper, "name", {
598
- // value: propertyKey,
599
- // });
600
- // descriptor.value = methodWrapper;
601
- // };
602
- // }
603
- /**
604
- * @description Utility for handling super calls in transactional methods
605
- * @summary Wraps super method calls with the current transaction context when the super's method is also transactional, ensuring transaction continuity through the inheritance chain
606
- * @param {Function} method - The super method (must be bound to the proper this), e.g., super.create.bind(this)
607
- * @param {any[]} args - The arguments to call the method with
608
- * @return {any} The result of the super method call
609
- * @function transactionalSuperCall
610
- * @memberOf module:transactions
611
- */
612
- function transactionalSuperCall(method, ...args) {
613
- const lock = Transaction.getLock();
614
- const currentTransaction = lock.currentTransaction;
615
- return method(currentTransaction, ...args);
616
- }
617
-
618
- /**
619
- * @description Transactional decorators for TypeScript
620
- * @summary A comprehensive module providing transaction management capabilities for TypeScript applications. This module exposes decorators, locks, and utilities for implementing transactional behavior in your code, allowing for atomic operations, concurrency control, and error handling.
621
- * @module transactions
622
- */
623
- /**
624
- * @description Package version identifier
625
- * @summary Stores the current package version string, used for version tracking and compatibility checks
626
- * @const VERSION
627
- * @memberOf module:transactions
628
- */
629
- const VERSION = "0.1.3";
630
-
631
- export { Lock, SyncronousLock, Transaction, TransactionalKeys, VERSION, transactional, transactionalSuperCall };
632
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25hbC1kZWNvcmF0b3JzLmVzbS5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2Nrcy9Mb2NrLnRzIiwiLi4vc3JjL2xvY2tzL1N5bmNyb25vdXNMb2NrLnRzIiwiLi4vc3JjL2NvbnN0YW50cy50cyIsIi4uL3NyYy91dGlscy50cyIsIi4uL3NyYy9UcmFuc2FjdGlvbi50cyIsIi4uL3NyYy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvY2tDYWxsYWJsZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGxvY2sgaW1wbGVtZW50YXRpb24gZm9yIGNvbmN1cnJlbmN5IGNvbnRyb2xcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgYmFzaWMgbG9jayBtZWNoYW5pc20gZm9yIGNvbnRyb2xsaW5nIGFjY2VzcyB0byBzaGFyZWQgcmVzb3VyY2VzLCB3aXRoIHN1cHBvcnQgZm9yIHF1ZXVpbmcgYW5kIGV4ZWN1dGluZyBmdW5jdGlvbnMgd2hlbiB0aGUgbG9jayBpcyBhdmFpbGFibGVcbiAqIEBjbGFzcyBMb2NrXG4gKiBAZXhhbXBsZVxuICogLy8gVXNpbmcgdGhlIExvY2sgY2xhc3MgdG8gZXhlY3V0ZSBhIGZ1bmN0aW9uIHdpdGggZXhjbHVzaXZlIGFjY2Vzc1xuICogY29uc3QgbG9jayA9IG5ldyBMb2NrKCk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBsb2NrLmV4ZWN1dGUoYXN5bmMgKCkgPT4ge1xuICogICAvLyBUaGlzIGNvZGUgd2lsbCBydW4gd2l0aCBleGNsdXNpdmUgYWNjZXNzXG4gKiAgIHJldHVybiBhd2FpdCBwZXJmb3JtQ3JpdGljYWxPcGVyYXRpb24oKTtcbiAqIH0pO1xuICovXG5leHBvcnQgY2xhc3MgTG9jayB7XG4gIHByaXZhdGUgcXVldWU6IExvY2tDYWxsYWJsZVtdID0gW107XG4gIHByaXZhdGUgbG9ja2VkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIGZ1bmN0aW9uIHdpdGggZXhjbHVzaXZlIGxvY2sgYWNjZXNzXG4gICAqIEBzdW1tYXJ5IEFjcXVpcmVzIHRoZSBsb2NrLCBleGVjdXRlcyB0aGUgcHJvdmlkZWQgZnVuY3Rpb24sIGFuZCByZWxlYXNlcyB0aGUgbG9jayBhZnRlcndhcmQsIGVuc3VyaW5nIHByb3BlciBjbGVhbnVwIGV2ZW4gaWYgdGhlIGZ1bmN0aW9uIHRocm93cyBhbiBlcnJvclxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIC0gVGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgd2hlbiB0aGUgbG9jayBpcyBhY3F1aXJlZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlc3VsdCBvZiB0aGUgZXhlY3V0ZWQgZnVuY3Rpb25cbiAgICovXG4gIGFzeW5jIGV4ZWN1dGUoZnVuYzogKCkgPT4gYW55KSB7XG4gICAgYXdhaXQgdGhpcy5hY3F1aXJlKCk7XG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoZnVuYygpKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRoaXMucmVsZWFzZSgpO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgdGhpcy5yZWxlYXNlKCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSB3YWl0cyB0byBhY3F1aXJlIHRoZSBsb2NrXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbaXNzdWVyXVxuICAgKi9cbiAgYXN5bmMgYWNxdWlyZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBpZiAoc2VsZi5sb2NrZWQpIHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gc2VsZi5xdWV1ZS5wdXNoKHJlc29sdmUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi5sb2NrZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZWxlYXNlcyB0aGUgbG9ja1xuICAgKi9cbiAgcmVsZWFzZSgpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBuZXh0OiBMb2NrQ2FsbGFibGUgfCB1bmRlZmluZWQgPSBzZWxmLnF1ZXVlLnNoaWZ0KCk7XG4gICAgaWYgKG5leHQpIHtcbiAgICAgIGlmIChcbiAgICAgICAgdHlwZW9mIChnbG9iYWxUaGlzIGFzIHVua25vd24gYXMgeyB3aW5kb3c6IGFueSB9KS53aW5kb3cgPT09IFwidW5kZWZpbmVkXCJcbiAgICAgIClcbiAgICAgICAgZ2xvYmFsVGhpcy5wcm9jZXNzLm5leHRUaWNrKG5leHQpOyAvLyBpZiB5b3UgYXJlIG9uIG5vZGVcbiAgICAgIGVsc2Ugc2V0VGltZW91dChuZXh0LCAwKTsgLy8gaWYgeW91IGFyZSBpbiB0aGUgYnJvd3NlclxuICAgIH0gZWxzZSB7XG4gICAgICBzZWxmLmxvY2tlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHsgVHJhbnNhY3Rpb24gfSBmcm9tIFwiLi4vVHJhbnNhY3Rpb25cIjtcbmltcG9ydCB7IFRyYW5zYWN0aW9uTG9jayB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL1RyYW5zYWN0aW9uTG9ja1wiO1xuaW1wb3J0IHsgTG9jayB9IGZyb20gXCIuL0xvY2tcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBTaW1wbGUgU3luY2hyb25vdXMgTG9jayBpbXBsZW1lbnRhdGlvblxuICogQGRlc2NyaXB0aW9uIGZvciB0cmFuc2FjdGlvbiBtYW5hZ2VtZW50XG4gKiBhZGFwdGVkIGZyb20ge0BsaW5rIGh0dHBzOi8vd3d3LnRhbGtpbmdoaWdodGVjaC5jb20vZW4vY3JlYXRpbmctYS1qcy1sb2NrLWZvci1hLXJlc291cmNlL31cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gW2NvdW50ZXJdIHRoZSBudW1iZXIgb2Ygc2ltdWx0YW5lb3VzIHRyYW5zYWN0aW9ucyBhbGxvd2VkLiBkZWZhdWx0cyB0byAxXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb25CZWdpbl0gdG8gYmUgY2FsbGVkIGF0IHRoZSBzdGFydCBvZiB0aGUgdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvbkVuZF0gdG8gYmUgY2FsbGVkIGF0IHRoZSBjb25jbHVzaW9uIG9mIHRoZSB0cmFuc2FjdGlvblxuICpcbiAqIEBjbGFzcyBTeW5jcm9ub3VzTG9ja1xuICogQGltcGxlbWVudHMgVHJhbnNhY3Rpb25Mb2NrXG4gKi9cbmV4cG9ydCBjbGFzcyBTeW5jcm9ub3VzTG9jayBpbXBsZW1lbnRzIFRyYW5zYWN0aW9uTG9jayB7XG4gIHByaXZhdGUgY291bnRlcjogbnVtYmVyO1xuICBwcml2YXRlIHBlbmRpbmdUcmFuc2FjdGlvbnM6IFRyYW5zYWN0aW9uW107XG4gIGN1cnJlbnRUcmFuc2FjdGlvbj86IFRyYW5zYWN0aW9uID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IG9uQmVnaW4/OiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IG9uRW5kPzogKGVycj86IEVycm9yKSA9PiBQcm9taXNlPHZvaWQ+O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9jayA9IG5ldyBMb2NrKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgY291bnRlcjogbnVtYmVyID0gMSxcbiAgICBvbkJlZ2luPzogKCkgPT4gUHJvbWlzZTx2b2lkPixcbiAgICBvbkVuZD86IChlcnI/OiBFcnJvcikgPT4gUHJvbWlzZTx2b2lkPlxuICApIHtcbiAgICB0aGlzLmNvdW50ZXIgPSBjb3VudGVyO1xuICAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucyA9IFtdO1xuICAgIHRoaXMub25CZWdpbiA9IG9uQmVnaW47XG4gICAgdGhpcy5vbkVuZCA9IG9uRW5kO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byBiZSBwcm9jZXNzZWRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbn0gdHJhbnNhY3Rpb25cbiAgICovXG4gIHN1Ym1pdCh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiB2b2lkIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBzZWxmLmxvY2suYWNxdWlyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICBzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbiAmJlxuICAgICAgICBzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbi5pZCA9PT0gdHJhbnNhY3Rpb24uaWRcbiAgICAgICkge1xuICAgICAgICBzZWxmLmxvY2sucmVsZWFzZSgpO1xuICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb24uZmlyZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2VsZi5jb3VudGVyID4gMCkge1xuICAgICAgICBzZWxmLmNvdW50ZXItLTtcbiAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcbiAgICAgICAgcmV0dXJuIHNlbGYuZmlyZVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYucGVuZGluZ1RyYW5zYWN0aW9ucy5wdXNoKHRyYW5zYWN0aW9uKTtcbiAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyBhIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb259IHRyYW5zYWN0aW9uXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGZpcmVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBzZWxmLmxvY2suYWNxdWlyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgc2VsZi5jdXJyZW50VHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbiAgICAgIHNlbGYubG9jay5yZWxlYXNlKCk7XG4gICAgICBpZiAoc2VsZi5vbkJlZ2luKVxuICAgICAgICBzZWxmLm9uQmVnaW4oKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAvLyBhbGwuY2FsbChcbiAgICAgICAgICAvLyAgIHNlbGYsXG4gICAgICAgICAgLy8gICBgRmlyaW5nIHRyYW5zYWN0aW9uIHswfS4gezF9IHJlbWFpbmluZy4uLmAsXG4gICAgICAgICAgLy8gICB0cmFuc2FjdGlvbi5pZCxcbiAgICAgICAgICAvLyAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucy5sZW5ndGgsXG4gICAgICAgICAgLy8gKTtcbiAgICAgICAgICB0cmFuc2FjdGlvbi5maXJlKCk7XG4gICAgICAgIH0pO1xuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIGFsbC5jYWxsKFxuICAgICAgICAvLyAgIHNlbGYsXG4gICAgICAgIC8vICAgYEZpcmluZyB0cmFuc2FjdGlvbiB7MH0uIHsxfSByZW1haW5pbmcuLi5gLFxuICAgICAgICAvLyAgIHRyYW5zYWN0aW9uLmlkLFxuICAgICAgICAvLyAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucy5sZW5ndGgsXG4gICAgICAgIC8vICk7XG4gICAgICAgIHRyYW5zYWN0aW9uLmZpcmUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogQHN1bW1hcnkgUmVsZWFzZXMgVGhlIGxvY2sgYWZ0ZXIgdGhlIGNvbmNsdXNpb24gb2YgYSB0cmFuc2FjdGlvblxuICAgKi9cbiAgYXN5bmMgcmVsZWFzZShlcnI/OiBFcnJvcik6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgc2VsZi5sb2NrLmFjcXVpcmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKCFzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbilcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBcIlRyeWluZyB0byByZWxlYXNlIGFuIHVuZXhpc3RpbmcgdHJhbnNhY3Rpb24uIHNob3VsZCBuZXZlciBoYXBwZW4uLi5cIlxuICAgICAgICAgICk7XG4gICAgICAgIC8vIGRlYnVnLmNhbGwoXG4gICAgICAgIC8vICAgc2VsZixcbiAgICAgICAgLy8gICBcIlJlbGVhc2luZyB0cmFuc2FjdGlvbjogezB9XCIsXG4gICAgICAgIC8vICAgc2VsZi5jdXJyZW50VHJhbnNhY3Rpb24/LnRvU3RyaW5nKHRydWUsIHRydWUpLFxuICAgICAgICAvLyApO1xuICAgICAgICBzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcblxuICAgICAgICBjb25zdCBhZnRlckNvbmNsdXNpb25DQiA9ICgpID0+IHtcbiAgICAgICAgICBzZWxmLmxvY2suYWNxdWlyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHNlbGYucGVuZGluZ1RyYW5zYWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID1cbiAgICAgICAgICAgICAgICBzZWxmLnBlbmRpbmdUcmFuc2FjdGlvbnMuc2hpZnQoKSBhcyBUcmFuc2FjdGlvbjtcblxuICAgICAgICAgICAgICBjb25zdCBjYiA9ICgpID0+IHNlbGYuZmlyZVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKTtcbiAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgLy8gYWxsKFxuICAgICAgICAgICAgICAvLyAgIGBSZWxlYXNpbmcgVHJhbnNhY3Rpb24gTG9jayBvbiB0cmFuc2FjdGlvbiB7MH1gLFxuICAgICAgICAgICAgICAvLyAgIHRyYW5zYWN0aW9uLmlkLFxuICAgICAgICAgICAgICAvLyApO1xuXG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICB0eXBlb2YgKGdsb2JhbFRoaXMgYXMgdW5rbm93biBhcyB7IHdpbmRvdzogYW55IH0pLndpbmRvdyA9PT1cbiAgICAgICAgICAgICAgICBcInVuZGVmaW5lZFwiXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLnByb2Nlc3MubmV4dFRpY2soY2IpOyAvLyBpZiB5b3UgYXJlIG9uIG5vZGVcbiAgICAgICAgICAgICAgZWxzZSBzZXRUaW1lb3V0KGNiLCAwKTsgLy8gaWYgeW91IGFyZSBpbiB0aGUgYnJvd3NlclxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgc2VsZi5jb3VudGVyKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLmxvY2sucmVsZWFzZSgpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzZWxmLm9uRW5kKSBzZWxmLm9uRW5kKGVycikudGhlbigoKSA9PiBhZnRlckNvbmNsdXNpb25DQigpKTtcbiAgICAgICAgZWxzZSBhZnRlckNvbmNsdXNpb25DQigpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbn1cbiIsIi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gVHJhbnNhY3Rpb25hbEtleXNUeXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVGTEVDVCAtIEtleSB1c2VkIGZvciByZWZsZWN0aW9uIG1ldGFkYXRhIHJlbGF0ZWQgdG8gdHJhbnNhY3Rpb25hbCBtb2RlbHNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUUkFOU0FDVElPTkFMIC0gS2V5IHVzZWQgdG8gaWRlbnRpZnkgdHJhbnNhY3Rpb25hbCBwcm9wZXJ0aWVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnRyYW5zYWN0aW9uc1xuICovXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEtleXMgdXNlZCBmb3IgdHJhbnNhY3Rpb25hbCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBDb25zdGFudCBvYmplY3QgY29udGFpbmluZyBzdHJpbmcga2V5cyB1c2VkIHRocm91Z2hvdXQgdGhlIHRyYW5zYWN0aW9uYWwgc3lzdGVtIGZvciByZWZsZWN0aW9uIGFuZCBpZGVudGlmaWNhdGlvblxuICogQHR5cGUge1RyYW5zYWN0aW9uYWxLZXlzVHlwZX1cbiAqIEBjb25zdCBUcmFuc2FjdGlvbmFsS2V5c1xuICogQG1lbWJlck9mIG1vZHVsZTp0cmFuc2FjdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IFRyYW5zYWN0aW9uYWxLZXlzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBSRUZMRUNUOiBcIm1vZGVsLnRyYW5zYWN0aW9uYWwuXCIsXG4gIFRSQU5TQUNUSU9OQUw6IFwidHJhbnNhY3Rpb25hbFwiLFxufTtcbiIsImV4cG9ydCBmdW5jdGlvbiBnZXRPYmplY3ROYW1lKG9iajogYW55KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFvYmopIHJldHVybjtcbiAgaWYgKHR5cGVvZiBvYmogPT09IFwic3RyaW5nXCIpIHJldHVybiBvYmo7XG4gIGlmIChcbiAgICBvYmouY29uc3RydWN0b3IgJiZcbiAgICBvYmouY29uc3RydWN0b3IubmFtZSAmJlxuICAgIFtcIkZ1bmN0aW9uXCIsIFwiT2JqZWN0XCJdLmluZGV4T2Yob2JqLmNvbnN0cnVjdG9yLm5hbWUpID09PSAtMVxuICApXG4gICAgcmV0dXJuIG9iai5jb25zdHJ1Y3Rvci5uYW1lO1xuICBpZiAodHlwZW9mIG9iaiA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5uYW1lKSByZXR1cm4gb2JqLm5hbWU7XG4gIHJldHVybiBvYmoudG9TdHJpbmcoKTtcbn1cbiIsImltcG9ydCB7IFRyYW5zYWN0aW9uTG9jayB9IGZyb20gXCIuL2ludGVyZmFjZXMvVHJhbnNhY3Rpb25Mb2NrXCI7XG5pbXBvcnQgeyBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBDYWxsYmFjayB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBTeW5jcm9ub3VzTG9jayB9IGZyb20gXCIuL2xvY2tzL1N5bmNyb25vdXNMb2NrXCI7XG5pbXBvcnQge1xuICBEQktleXMsXG4gIGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBnZXRPYmplY3ROYW1lIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IFRyYW5zYWN0aW9uYWxLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvcmUgdHJhbnNhY3Rpb24gbWFuYWdlbWVudCBjbGFzc1xuICogQHN1bW1hcnkgTWFuYWdlcyB0cmFuc2FjdGlvbiBsaWZlY3ljbGUsIGluY2x1ZGluZyBjcmVhdGlvbiwgZXhlY3V0aW9uLCBhbmQgY2xlYW51cC4gUHJvdmlkZXMgbWVjaGFuaXNtcyBmb3IgYmluZGluZyB0cmFuc2FjdGlvbnMgdG8gb2JqZWN0cyBhbmQgbWV0aG9kcywgZW5zdXJpbmcgcHJvcGVyIHRyYW5zYWN0aW9uIGNvbnRleHQgcHJvcGFnYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gVGhlIHNvdXJjZS9vcmlnaW4gb2YgdGhlIHRyYW5zYWN0aW9uICh0eXBpY2FsbHkgYSBjbGFzcyBuYW1lKVxuICogQHBhcmFtIHtzdHJpbmd9IFttZXRob2RdIC0gVGhlIG1ldGhvZCBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGUgdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKTogYW55fSBbYWN0aW9uXSAtIFRoZSBmdW5jdGlvbiB0byBleGVjdXRlIHdpdGhpbiB0aGUgdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSB7YW55W119IFttZXRhZGF0YV0gLSBBZGRpdGlvbmFsIG1ldGFkYXRhIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSB0cmFuc2FjdGlvblxuICogQGNsYXNzIFRyYW5zYWN0aW9uXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRpbmcgYW5kIHN1Ym1pdHRpbmcgYSB0cmFuc2FjdGlvblxuICogY29uc3QgdHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oXG4gKiAgICdVc2VyU2VydmljZScsXG4gKiAgICdjcmVhdGVVc2VyJyxcbiAqICAgYXN5bmMgKCkgPT4ge1xuICogICAgIC8vIFRyYW5zYWN0aW9uIGxvZ2ljIGhlcmVcbiAqICAgICBhd2FpdCBkYi5pbnNlcnQoJ3VzZXJzJywgeyBuYW1lOiAnSm9obicgfSk7XG4gKiAgIH1cbiAqICk7XG4gKiBUcmFuc2FjdGlvbi5zdWJtaXQodHJhbnNhY3Rpb24pO1xuICogXG4gKiAvLyBVc2luZyB0aGUgdHJhbnNhY3Rpb25hbCBkZWNvcmF0b3JcbiAqIGNsYXNzIFVzZXJTZXJ2aWNlIHtcbiAqICAgQHRyYW5zYWN0aW9uYWwoKVxuICogICBhc3luYyBjcmVhdGVVc2VyKGRhdGEpIHtcbiAqICAgICAvLyBNZXRob2Qgd2lsbCBiZSBleGVjdXRlZCB3aXRoaW4gYSB0cmFuc2FjdGlvblxuICogICAgIHJldHVybiBhd2FpdCBkYi5pbnNlcnQoJ3VzZXJzJywgZGF0YSk7XG4gKiAgIH1cbiAqIH1cbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDbGllbnQgQ29kZVxuICogICBwYXJ0aWNpcGFudCBUIGFzIFRyYW5zYWN0aW9uXG4gKiAgIHBhcnRpY2lwYW50IEwgYXMgVHJhbnNhY3Rpb25Mb2NrXG4gKiAgIHBhcnRpY2lwYW50IE8gYXMgT3JpZ2luYWwgTWV0aG9kXG4gKiAgIFxuICogICBDLT4+VDogbmV3IFRyYW5zYWN0aW9uKHNvdXJjZSwgbWV0aG9kLCBhY3Rpb24pXG4gKiAgIEMtPj5UOiBUcmFuc2FjdGlvbi5zdWJtaXQodHJhbnNhY3Rpb24pXG4gKiAgIFQtPj5MOiBzdWJtaXQodHJhbnNhY3Rpb24pXG4gKiAgIEwtPj5UOiBmaXJlKClcbiAqICAgVC0+Pk86IEV4ZWN1dGUgYWN0aW9uKClcbiAqICAgTy0tPj5UOiBSZXR1cm4gcmVzdWx0L2Vycm9yXG4gKiAgIFQtPj5MOiByZWxlYXNlKGVycm9yPylcbiAqICAgTC0tPj5DOiBSZXR1cm4gcmVzdWx0L2Vycm9yXG4gKi9cbmV4cG9ydCBjbGFzcyBUcmFuc2FjdGlvbiB7XG4gIHJlYWRvbmx5IGlkOiBudW1iZXI7XG4gIHByb3RlY3RlZCBhY3Rpb24/OiAoKSA9PiBhbnk7XG4gIHJlYWRvbmx5IG1ldGhvZD86IHN0cmluZztcbiAgcmVhZG9ubHkgc291cmNlPzogc3RyaW5nO1xuICByZWFkb25seSBsb2c6IHN0cmluZ1tdO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldGFkYXRhPzogYW55W107XG5cbiAgcHJpdmF0ZSBzdGF0aWMgbG9jazogVHJhbnNhY3Rpb25Mb2NrO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNvdXJjZTogc3RyaW5nLFxuICAgIG1ldGhvZD86IHN0cmluZyxcbiAgICBhY3Rpb24/OiAoKSA9PiBhbnksXG4gICAgbWV0YWRhdGE/OiBhbnlbXVxuICApIHtcbiAgICB0aGlzLmlkID0gRGF0ZS5ub3coKTtcbiAgICB0aGlzLmFjdGlvbiA9IGFjdGlvbjtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZDtcbiAgICB0aGlzLmxvZyA9IFtbdGhpcy5pZCwgc291cmNlLCBtZXRob2RdLmpvaW4oXCIgfCBcIildO1xuICAgIHRoaXMuc291cmNlID0gc291cmNlO1xuICAgIHRoaXMubWV0YWRhdGEgPSBtZXRhZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUXVldWVzIGEgdHJhbnNhY3Rpb24gZm9yIGV4ZWN1dGlvblxuICAgKiBAc3VtbWFyeSBQdXNoZXMgYSB0cmFuc2FjdGlvbiB0byB0aGUgcXVldWUgYW5kIHdhaXRzIGZvciBpdHMgcmVzb2x1dGlvbi4gQ3JlYXRlcyBhIG5ldyB0cmFuc2FjdGlvbiB3aXRoIHRoZSBwcm92aWRlZCBpc3N1ZXIgYW5kIGNhbGxiYWNrIG1ldGhvZCwgdGhlbiBzdWJtaXRzIGl0IHRvIHRoZSB0cmFuc2FjdGlvbiBsb2NrLlxuICAgKiBAcGFyYW0ge2FueX0gaXNzdWVyIC0gQW55IGNsYXNzIGluc3RhbmNlIHRoYXQgd2lsbCBiZSB1c2VkIGFzICd0aGlzJyB3aGVuIGNhbGxpbmcgdGhlIGNhbGxiYWNrTWV0aG9kXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrTWV0aG9kIC0gQ2FsbGJhY2sgZnVuY3Rpb24gY29udGFpbmluZyB0aGUgdHJhbnNhY3Rpb24gbG9naWMsIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIGlzc3VlciBhcyAndGhpcydcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuIExhc3Qgb25lIG11c3QgYmUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgcHVzaChcbiAgICBpc3N1ZXI6IGFueSxcbiAgICBjYWxsYmFja01ldGhvZDogKC4uLmFyZ3p6OiAoYW55IHwgQ2FsbGJhY2spW10pID0+IHZvaWQsXG4gICAgLi4uYXJnczogKGFueSB8IENhbGxiYWNrKVtdXG4gICkge1xuICAgIGNvbnN0IGNhbGxiYWNrOiBDYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgaWYgKCFjYWxsYmFjayB8fCB0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgY2FsbGJhY2tcIik7XG4gICAgY29uc3QgY2IgPSAoZXJyPzogRXJyb3IsIC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICBUcmFuc2FjdGlvbi5nZXRMb2NrKClcbiAgICAgICAgLnJlbGVhc2UoZXJyKVxuICAgICAgICAudGhlbigoKSA9PiBjYWxsYmFjayhlcnIsIC4uLmFyZ3MpKTtcbiAgICB9O1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihcbiAgICAgIGlzc3Vlci5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgY2FsbGJhY2tNZXRob2QubmFtZSA/IGdldE9iamVjdE5hbWUoY2FsbGJhY2tNZXRob2QpIDogXCJBbm9ueW1vdXNcIixcbiAgICAgICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrTWV0aG9kLmNhbGwoXG4gICAgICAgICAgdHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oaXNzdWVyKSxcbiAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgIGNiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcbiAgICBUcmFuc2FjdGlvbi5nZXRMb2NrKCkuc3VibWl0KHRyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29uZmlndXJlcyB0aGUgdHJhbnNhY3Rpb24gbG9jayBpbXBsZW1lbnRhdGlvblxuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBsb2NrIGltcGxlbWVudGF0aW9uIHRvIGJlIHVzZWQgZm9yIHRyYW5zYWN0aW9uIG1hbmFnZW1lbnQsIGFsbG93aW5nIGN1c3RvbWl6YXRpb24gb2YgdGhlIHRyYW5zYWN0aW9uIGJlaGF2aW9yXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25Mb2NrfSBsb2NrIC0gVGhlIGxvY2sgaW1wbGVtZW50YXRpb24gdG8gdXNlIGZvciBtYW5hZ2luZyB0cmFuc2FjdGlvbnNcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXRMb2NrKGxvY2s6IFRyYW5zYWN0aW9uTG9jaykge1xuICAgIHRoaXMubG9jayA9IGxvY2s7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiBsb2NrXG4gICAqIEBzdW1tYXJ5IEdldHMgdGhlIGN1cnJlbnQgdHJhbnNhY3Rpb24gbG9jayBpbnN0YW5jZSwgY3JlYXRpbmcgYSBkZWZhdWx0IFN5bmNyb25vdXNMb2NrIGlmIG5vbmUgZXhpc3RzXG4gICAqIEByZXR1cm4ge1RyYW5zYWN0aW9uTG9ja30gVGhlIGN1cnJlbnQgdHJhbnNhY3Rpb24gbG9jayBpbXBsZW1lbnRhdGlvblxuICAgKi9cbiAgc3RhdGljIGdldExvY2soKTogVHJhbnNhY3Rpb25Mb2NrIHtcbiAgICBpZiAoIXRoaXMubG9jaykgdGhpcy5sb2NrID0gbmV3IFN5bmNyb25vdXNMb2NrKCk7XG4gICAgcmV0dXJuIHRoaXMubG9jaztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3VibWl0cyBhIHRyYW5zYWN0aW9uIGZvciBwcm9jZXNzaW5nXG4gICAqIEBzdW1tYXJ5IFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiBsb2NrIGZvciBwcm9jZXNzaW5nIGFuZCBleGVjdXRpb25cbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbn0gdHJhbnNhY3Rpb24gLSBUaGUgdHJhbnNhY3Rpb24gdG8gc3VibWl0IGZvciBwcm9jZXNzaW5nXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgc3VibWl0KHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbikge1xuICAgIFRyYW5zYWN0aW9uLmdldExvY2soKS5zdWJtaXQodHJhbnNhY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWxlYXNlcyB0aGUgdHJhbnNhY3Rpb24gbG9ja1xuICAgKiBAc3VtbWFyeSBSZWxlYXNlcyB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiBsb2NrLCBvcHRpb25hbGx5IHdpdGggYW4gZXJyb3IsIGFsbG93aW5nIHRoZSBuZXh0IHRyYW5zYWN0aW9uIHRvIHByb2NlZWRcbiAgICogQHBhcmFtIHtFcnJvcn0gW2Vycl0gLSBPcHRpb25hbCBlcnJvciB0aGF0IG9jY3VycmVkIGR1cmluZyB0cmFuc2FjdGlvbiBleGVjdXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbG9jayBoYXMgYmVlbiByZWxlYXNlZFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIHJlbGVhc2UoZXJyPzogRXJyb3IpIHtcbiAgICByZXR1cm4gVHJhbnNhY3Rpb24uZ2V0TG9jaygpLnJlbGVhc2UoZXJyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHRyYW5zYWN0aW9uIG1ldGFkYXRhXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgYSBjb3B5IG9mIHRoZSBtZXRhZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhpcyB0cmFuc2FjdGlvbiwgZW5zdXJpbmcgdGhlIG9yaWdpbmFsIG1ldGFkYXRhIHJlbWFpbnMgdW5tb2RpZmllZFxuICAgKiBAcmV0dXJuIHthbnlbXSB8IHVuZGVmaW5lZH0gQSBjb3B5IG9mIHRoZSB0cmFuc2FjdGlvbiBtZXRhZGF0YSBvciB1bmRlZmluZWQgaWYgbm8gbWV0YWRhdGEgZXhpc3RzXG4gICAqL1xuICBnZXRNZXRhZGF0YSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXRhZGF0YSA/IFsuLi50aGlzLm1ldGFkYXRhXSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGlua3MgYSBuZXcgdHJhbnNhY3Rpb24gdG8gdGhlIGN1cnJlbnQgb25lXG4gICAqIEBzdW1tYXJ5IEJpbmRzIGEgbmV3IHRyYW5zYWN0aW9uIG9wZXJhdGlvbiB0byB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiwgdHJhbnNmZXJyaW5nIGxvZ3MgYW5kIGJpbmRpbmcgbWV0aG9kcyB0byBtYWludGFpbiB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb259IG5leHRUcmFuc2FjdGlvbiAtIFRoZSBuZXcgdHJhbnNhY3Rpb24gdG8gYmluZCB0byB0aGUgY3VycmVudCBvbmVcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIGJpbmRUcmFuc2FjdGlvbihuZXh0VHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKSB7XG4gICAgLy8gYWxsKGBCaW5kaW5nIHRoZSB7MH0gdG8gezF9YCwgbmV4dFRyYW5zYWN0aW9uLCB0aGlzKTtcbiAgICB0aGlzLmxvZy5wdXNoKC4uLm5leHRUcmFuc2FjdGlvbi5sb2cpO1xuICAgIG5leHRUcmFuc2FjdGlvbi5iaW5kVHJhbnNhY3Rpb24gPSB0aGlzLmJpbmRUb1RyYW5zYWN0aW9uLmJpbmQodGhpcyk7XG4gICAgbmV4dFRyYW5zYWN0aW9uLmJpbmRUb1RyYW5zYWN0aW9uID0gdGhpcy5iaW5kVG9UcmFuc2FjdGlvbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMuYWN0aW9uID0gbmV4dFRyYW5zYWN0aW9uLmFjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQmluZHMgYW4gb2JqZWN0IHRvIHRoZSBjdXJyZW50IHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHN1bW1hcnkgQmluZHMgYSB0cmFuc2FjdGlvbmFsIGRlY29yYXRlZCBvYmplY3QgdG8gdGhlIHRyYW5zYWN0aW9uIGJ5IGVuc3VyaW5nIGFsbCB0cmFuc2FjdGlvbmFsIG1ldGhvZHMgYXV0b21hdGljYWxseSByZWNlaXZlIHRoZSBjdXJyZW50IHRyYW5zYWN0aW9uIGFzIHRoZWlyIGZpcnN0IGFyZ3VtZW50XG4gICAqIEBwYXJhbSB7YW55fSBvYmogLSBUaGUgb2JqZWN0IHRvIGJpbmQgdG8gdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge2FueX0gVGhlIGJvdW5kIG9iamVjdCB3aXRoIHRyYW5zYWN0aW9uLWF3YXJlIG1ldGhvZCB3cmFwcGVyc1xuICAgKi9cbiAgYmluZFRvVHJhbnNhY3Rpb24ob2JqOiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uYWxNZXRob2RzID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgICAgb2JqLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgVHJhbnNhY3Rpb25hbEtleXMuUkVGTEVDVFxuICAgICk7XG4gICAgaWYgKCF0cmFuc2FjdGlvbmFsTWV0aG9kcykgcmV0dXJuIG9iajtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIGNvbnN0IGJvdW5kT2JqID0gUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0aWVzKG9iaikucmVkdWNlKFxuICAgICAgKGFjY3VtOiBhbnksIGs6IHN0cmluZykgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgT2JqZWN0LmtleXModHJhbnNhY3Rpb25hbE1ldGhvZHMpLmluZGV4T2YoaykgIT09IC0xICYmXG4gICAgICAgICAgdHJhbnNhY3Rpb25hbE1ldGhvZHNba10uZmluZChcbiAgICAgICAgICAgIChvKSA9PiBvLmtleSA9PT0gVHJhbnNhY3Rpb25hbEtleXMuVFJBTlNBQ1RJT05BTFxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgICAgIGFjY3VtW2tdID0gKC4uLmFyZ3M6IGFueVtdKSA9PlxuICAgICAgICAgICAgb2JqW2tdLmNhbGwob2JqLl9fb3JpZ2luYWxPYmogfHwgb2JqLCBzZWxmLCAuLi5hcmdzKTtcbiAgICAgICAgZWxzZSBpZiAoayA9PT0gXCJjbGF6elwiIHx8IGsgPT09IFwiY29uc3RydWN0b3JcIikgYWNjdW1ba10gPSBvYmpba107XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmpba10gPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgICBhY2N1bVtrXSA9IG9ialtrXS5iaW5kKG9iai5fX29yaWdpbmFsT2JqIHx8IG9iaik7XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmpba10gPT09IFwib2JqZWN0XCIgJiYgb2JqW2tdLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgY29uc3QgZGVjcyA9IFJlZmxlY3Rpb24uZ2V0Q2xhc3NEZWNvcmF0b3JzKFxuICAgICAgICAgICAgVHJhbnNhY3Rpb25hbEtleXMuUkVGTEVDVCxcbiAgICAgICAgICAgIG9ialtrXVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGRlY3MuZmluZCgoZTogYW55KSA9PiBlLmtleSA9PT0gVHJhbnNhY3Rpb25hbEtleXMuVFJBTlNBQ1RJT05BTCkpXG4gICAgICAgICAgICBhY2N1bVtrXSA9IHNlbGYuYmluZFRvVHJhbnNhY3Rpb24ob2JqW2tdKTtcbiAgICAgICAgICBlbHNlIGFjY3VtW2tdID0gb2JqW2tdO1xuICAgICAgICB9IGVsc2UgYWNjdW1ba10gPSBvYmpba107XG5cbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcblxuICAgIGJvdW5kT2JqW0RCS2V5cy5PUklHSU5BTF0gPSBvYmpbREJLZXlzLk9SSUdJTkFMXSB8fCBvYmo7XG4gICAgYm91bmRPYmoudG9TdHJpbmcgPSAoKSA9PlxuICAgICAgZ2V0T2JqZWN0TmFtZShib3VuZE9ialtEQktleXMuT1JJR0lOQUxdKSArXG4gICAgICBcIiBwcm94eSBmb3IgdHJhbnNhY3Rpb24gXCIgK1xuICAgICAgdGhpcy5pZDtcblxuICAgIHJldHVybiBib3VuZE9iajtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgdGhlIHRyYW5zYWN0aW9uIGFjdGlvblxuICAgKiBAc3VtbWFyeSBGaXJlcyB0aGUgdHJhbnNhY3Rpb24gYnkgZXhlY3V0aW5nIGl0cyBhc3NvY2lhdGVkIGFjdGlvbiBmdW5jdGlvbiwgdGhyb3dpbmcgYW4gZXJyb3IgaWYgbm8gYWN0aW9uIGlzIGRlZmluZWRcbiAgICogQHJldHVybiB7YW55fSBUaGUgcmVzdWx0IG9mIHRoZSB0cmFuc2FjdGlvbiBhY3Rpb25cbiAgICovXG4gIGZpcmUoKSB7XG4gICAgaWYgKCF0aGlzLmFjdGlvbikgdGhyb3cgbmV3IEVycm9yKGBNaXNzaW5nIHRoZSBtZXRob2RgKTtcbiAgICByZXR1cm4gdGhpcy5hY3Rpb24oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvdmlkZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgZGVmYXVsdCB0b1N0cmluZyBtZXRob2QgdG8gcHJvdmlkZSBhIGZvcm1hdHRlZCBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRyYW5zYWN0aW9uLCBvcHRpb25hbGx5IGluY2x1ZGluZyB0aGUgdHJhbnNhY3Rpb24gSUQgYW5kIGxvZ1xuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFt3aXRoSWQ9dHJ1ZV0gLSBXaGV0aGVyIHRvIGluY2x1ZGUgdGhlIHRyYW5zYWN0aW9uIElEIGluIHRoZSBvdXRwdXRcbiAgICogQHBhcmFtIHtib29sZWFufSBbd2l0aExvZz1mYWxzZV0gLSBXaGV0aGVyIHRvIGluY2x1ZGUgdGhlIHRyYW5zYWN0aW9uIGxvZyBpbiB0aGUgb3V0cHV0XG4gICAqIEByZXR1cm4ge3N0cmluZ30gQSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAqL1xuICB0b1N0cmluZyh3aXRoSWQgPSB0cnVlLCB3aXRoTG9nID0gZmFsc2UpIHtcbiAgICByZXR1cm4gYCR7d2l0aElkID8gYFske3RoaXMuaWR9XWAgOiBcIlwifVtUcmFuc2FjdGlvbl1bJHt0aGlzLnNvdXJjZX0uJHt0aGlzLm1ldGhvZH0ke1xuICAgICAgd2l0aExvZyA/IGBdXFxuVHJhbnNhY3Rpb24gTG9nOlxcbiR7dGhpcy5sb2cuam9pbihcIlxcblwiKX1gIDogXCJdXCJcbiAgICB9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgcmVmbGVjdGlvbiBtZXRhZGF0YSBrZXkgZm9yIHRyYW5zYWN0aW9uc1xuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgcHJlZml4ZWQgcmVmbGVjdGlvbiBrZXkgZm9yIHRyYW5zYWN0aW9uLXJlbGF0ZWQgbWV0YWRhdGEsIGVuc3VyaW5nIHByb3BlciBuYW1lc3BhY2luZ1xuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGJhc2Uga2V5IHRvIHByZWZpeCB3aXRoIHRoZSB0cmFuc2FjdGlvbiByZWZsZWN0aW9uIG5hbWVzcGFjZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjb21wbGV0ZSByZWZsZWN0aW9uIGtleSBmb3IgdHJhbnNhY3Rpb24gbWV0YWRhdGFcbiAgICogQGZ1bmN0aW9uIGtleVxuICAgKi9cbiAgc3RhdGljIGtleShrZXk6IHN0cmluZykge1xuICAgIHJldHVybiBUcmFuc2FjdGlvbmFsS2V5cy5SRUZMRUNUICsga2V5O1xuICB9XG59XG4iLCJpbXBvcnQgeyBUcmFuc2FjdGlvbmFsS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgbWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSBcIi4vVHJhbnNhY3Rpb25cIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciB0aGF0IGVuYWJsZXMgdHJhbnNhY3Rpb25hbCBiZWhhdmlvclxuICogQHN1bW1hcnkgU2V0cyBhIGNsYXNzIGFzeW5jIG1ldGhvZCBhcyB0cmFuc2FjdGlvbmFsLCB3cmFwcGluZyBpdCBpbiBhIHRyYW5zYWN0aW9uIGNvbnRleHQgdGhhdCBjYW4gYmUgbWFuYWdlZCBieSB0aGUgdHJhbnNhY3Rpb24gc3lzdGVtLiBUaGlzIGRlY29yYXRvciBoYW5kbGVzIHRyYW5zYWN0aW9uIGNyZWF0aW9uLCBiaW5kaW5nLCBhbmQgZXJyb3IgaGFuZGxpbmcuXG4gKiBAcGFyYW0ge2FueVtdfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSBhdmFpbGFibGUgdG8gdGhlIHtAbGluayBUcmFuc2FjdGlvbkxvY2t9IGltcGxlbWVudGF0aW9uXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCB3cmFwcyB0aGUgb3JpZ2luYWwgbWV0aG9kIHdpdGggdHJhbnNhY3Rpb25hbCBiZWhhdmlvclxuICogQGZ1bmN0aW9uIHRyYW5zYWN0aW9uYWxcbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudCBDb2RlXG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdG9yXG4gKiAgIHBhcnRpY2lwYW50IFQgYXMgVHJhbnNhY3Rpb25cbiAqICAgcGFydGljaXBhbnQgTyBhcyBPcmlnaW5hbCBNZXRob2RcbiAqXG4gKiAgIEMtPj5EOiBDYWxsIGRlY29yYXRlZCBtZXRob2RcbiAqICAgRC0+PkQ6IENoZWNrIGlmIHRyYW5zYWN0aW9uIGV4aXN0cyBpbiBhcmdzXG4gKlxuICogICBhbHQgVHJhbnNhY3Rpb24gZXhpc3RzIGluIGFyZ3NcbiAqICAgICBELT4+VDogQ3JlYXRlIHVwZGF0ZWQgdHJhbnNhY3Rpb25cbiAqICAgICBULT4+VDogQmluZCB0byBvcmlnaW5hbCB0cmFuc2FjdGlvblxuICogICAgIFQtPj5UOiBGaXJlIHRyYW5zYWN0aW9uXG4gKiAgIGVsc2UgTm8gdHJhbnNhY3Rpb25cbiAqICAgICBELT4+VDogQ3JlYXRlIG5ldyB0cmFuc2FjdGlvblxuICogICAgIFQtPj5UOiBTdWJtaXQgdHJhbnNhY3Rpb25cbiAqICAgZW5kXG4gKlxuICogICBULT4+TzogRXhlY3V0ZSBvcmlnaW5hbCBtZXRob2RcbiAqICAgTy0tPj5UOiBSZXR1cm4gcmVzdWx0L2Vycm9yXG4gKiAgIFQtPj5UOiBSZWxlYXNlIHRyYW5zYWN0aW9uXG4gKiAgIFQtLT4+QzogUmV0dXJuIHJlc3VsdC9lcnJvclxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zYWN0aW9uYWwoLi4uZGF0YTogYW55W10pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChcbiAgICB0YXJnZXQ6IGFueSxcbiAgICBwcm9wZXJ0eUtleT86IGFueSxcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkge1xuICAgIGlmICghZGVzY3JpcHRvcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTWlzc2luZyBkZXNjcmlwdG9yLiBTaG91bGQgYmUgaW1wb3NzaWJsZVwiKTtcbiAgICBtZXRhZGF0YShUcmFuc2FjdGlvbi5rZXkoVHJhbnNhY3Rpb25hbEtleXMuVFJBTlNBQ1RJT05BTCksIGRhdGEpKFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuXG4gICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgY29uc3QgbWV0aG9kV3JhcHBlciA9IGZ1bmN0aW9uICh0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2U8YW55PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGNiID0gKGVycj86IEVycm9yLCByZXN1bHQ/OiBhbnkpID0+IHtcbiAgICAgICAgICBUcmFuc2FjdGlvbi5yZWxlYXNlKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IHRyYW5zYWN0aW9uID0gYXJncy5zaGlmdCgpO1xuICAgICAgICBpZiAodHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBUcmFuc2FjdGlvbikge1xuICAgICAgICAgIGNvbnN0IHVwZGF0ZWRUcmFuc2FjdGlvbjogVHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgICAgICAgICBwcm9wZXJ0eUtleSxcbiAgICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxNZXRob2RcbiAgICAgICAgICAgICAgICAuY2FsbCh1cGRhdGVkVHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oc2VsZiksIC4uLmFyZ3MpXG4gICAgICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRhLmxlbmd0aCA/IGRhdGEgOiB1bmRlZmluZWRcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdHJhbnNhY3Rpb24uYmluZFRyYW5zYWN0aW9uKHVwZGF0ZWRUcmFuc2FjdGlvbik7XG4gICAgICAgICAgdHJhbnNhY3Rpb24uZmlyZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFyZ3MudW5zaGlmdCh0cmFuc2FjdGlvbik7XG4gICAgICAgICAgdHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgICAgICAgICBwcm9wZXJ0eUtleSxcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxNZXRob2RcbiAgICAgICAgICAgICAgICAuY2FsbCh0cmFuc2FjdGlvbi5iaW5kVG9UcmFuc2FjdGlvbihzZWxmKSwgLi4uYXJncylcbiAgICAgICAgICAgICAgICAudGhlbigocmVzdWx0OiBhbnkpID0+IGNiKHVuZGVmaW5lZCwgcmVzdWx0KSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goY2IpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRhdGEubGVuZ3RoID8gZGF0YSA6IHVuZGVmaW5lZFxuICAgICAgICAgICk7XG4gICAgICAgICAgVHJhbnNhY3Rpb24uc3VibWl0KHRyYW5zYWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtZXRob2RXcmFwcGVyLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IHByb3BlcnR5S2V5LFxuICAgIH0pO1xuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBtZXRob2RXcmFwcGVyO1xuICB9O1xufVxuLy9cbi8vIC8qKlxuLy8gICogQHN1bW1hcnkgU2V0cyBhIGNsYXNzIEFzeW5jIG1ldGhvZCBhcyB0cmFuc2FjdGlvbmFsXG4vLyAgKlxuLy8gICogQHBhcmFtIHthbnlbXX0gIFttZXRhZGF0YV0gb3B0aW9uIG1ldGFkYXRhIGF2YWlsYWJsZSB0byB0aGUge0BsaW5rIFRyYW5zYWN0aW9uTG9ja31cbi8vICAqXG4vLyAgKiBAZnVuY3Rpb24gdHJhbnNhY3Rpb25hbEFzeW5jXG4vLyAgKlxuLy8gICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLkRlY29yYXRvcnMudHJhbnNhY3Rpb25zXG4vLyAgKi9cbi8vIGV4cG9ydCBmdW5jdGlvbiB0cmFuc2FjdGlvbmFsQXN5bmMoLi4ubWV0YWRhdGE6IGFueVtdKSB7XG4vLyAgIHJldHVybiBmdW5jdGlvbiAoXG4vLyAgICAgdGFyZ2V0OiBhbnksXG4vLyAgICAgcHJvcGVydHlLZXk6IHN0cmluZyxcbi8vICAgICBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3IsXG4vLyAgICkge1xuLy8gICAgIG1ldGFkYXN0YShnZXRUcmFuc2FjdGlvbmFsS2V5KFRyYW5zYWN0aW9uYWxLZXlzLlRSQU5TQUNUSU9OQUwpKVxuLy8gICAgIFJlZmxlY3QuZGVmaW5lTWV0YWRhdGEoXG4vLyAgICAgICAsXG4vLyAgICAgICB7XG4vLyAgICAgICAgIHR5cGU6IFwiYXN5bmNcIixcbi8vICAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLmxlbmd0aCA/IG1ldGFkYXRhIDogdW5kZWZpbmVkLFxuLy8gICAgICAgfSBhcyBUcmFuc2FjdGlvbmFsTWV0YWRhdGEsXG4vLyAgICAgICB0YXJnZXQsXG4vLyAgICAgICBwcm9wZXJ0eUtleSxcbi8vICAgICApO1xuLy9cbi8vICAgICBjb25zdCBvcmlnaW5hbE1ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG4vL1xuLy8gICAgIGNvbnN0IG1ldGhvZFdyYXBwZXIgPSBmdW5jdGlvbiAodGhpczogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xuLy8gICAgICAgY29uc3QgY2FsbGJhY2s6IENhbGxiYWNrID0gYXJncy5wb3AoKTtcbi8vICAgICAgIGlmICghY2FsbGJhY2sgfHwgdHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpXG4vLyAgICAgICAgIHRocm93IG5ldyBDcml0aWNhbEVycm9yKGBNaXNzaW5nIENhbGxiYWNrYCk7XG4vL1xuLy8gICAgICAgY29uc3QgY2IgPSAoZXJyPzogRXJyLCAuLi5hcmdzOiBhbnlbXSkgPT4ge1xuLy8gICAgICAgICBUcmFuc2FjdGlvbi5yZWxlYXNlKGVycikudGhlbigoXykgPT4gY2FsbGJhY2soZXJyLCAuLi5hcmdzKSk7XG4vLyAgICAgICB9O1xuLy9cbi8vICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuLy9cbi8vICAgICAgIGxldCB0cmFuc2FjdGlvbiA9IGFyZ3Muc2hpZnQoKTtcbi8vICAgICAgIGlmICh0cmFuc2FjdGlvbiBpbnN0YW5jZW9mIFRyYW5zYWN0aW9uKSB7XG4vLyAgICAgICAgIGNvbnN0IHVwZGF0ZWRUcmFuc2FjdGlvbjogVHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oXG4vLyAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lLFxuLy8gICAgICAgICAgIHByb3BlcnR5S2V5LFxuLy8gICAgICAgICAgICgpID0+IHtcbi8vICAgICAgICAgICAgIHRyeSB7XG4vLyAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbE1ldGhvZC5jYWxsKFxuLy8gICAgICAgICAgICAgICAgIHVwZGF0ZWRUcmFuc2FjdGlvbi5iaW5kVG9UcmFuc2FjdGlvbihzZWxmKSxcbi8vICAgICAgICAgICAgICAgICAuLi5hcmdzLFxuLy8gICAgICAgICAgICAgICAgIGNhbGxiYWNrLFxuLy8gICAgICAgICAgICAgICApO1xuLy8gICAgICAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4vLyAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlKTtcbi8vICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICB9LFxuLy8gICAgICAgICAgIG1ldGFkYXRhLmxlbmd0aCA/IG1ldGFkYXRhIDogdW5kZWZpbmVkLFxuLy8gICAgICAgICApO1xuLy9cbi8vICAgICAgICAgdHJhbnNhY3Rpb24uYmluZFRyYW5zYWN0aW9uKHVwZGF0ZWRUcmFuc2FjdGlvbik7XG4vLyAgICAgICAgIHRyYW5zYWN0aW9uLmZpcmUoKTtcbi8vICAgICAgIH0gZWxzZSB7XG4vLyAgICAgICAgIGFyZ3MudW5zaGlmdCh0cmFuc2FjdGlvbik7XG4vLyAgICAgICAgIHRyYW5zYWN0aW9uID0gdW5kZWZpbmVkO1xuLy8gICAgICAgICB0cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihcbi8vICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLm5hbWUsXG4vLyAgICAgICAgICAgcHJvcGVydHlLZXksXG4vLyAgICAgICAgICAgKCkgPT4ge1xuLy8gICAgICAgICAgICAgdHJ5IHtcbi8vICAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsTWV0aG9kLmNhbGwoXG4vLyAgICAgICAgICAgICAgICAgdHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oc2VsZiksXG4vLyAgICAgICAgICAgICAgICAgLi4uYXJncyxcbi8vICAgICAgICAgICAgICAgICBjYixcbi8vICAgICAgICAgICAgICAgKTtcbi8vICAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuLy8gICAgICAgICAgICAgICByZXR1cm4gY2IoZSk7XG4vLyAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgfSxcbi8vICAgICAgICAgICBtZXRhZGF0YS5sZW5ndGggPyBtZXRhZGF0YSA6IHVuZGVmaW5lZCxcbi8vICAgICAgICAgKTtcbi8vICAgICAgICAgVHJhbnNhY3Rpb24uc3VibWl0KHRyYW5zYWN0aW9uKTtcbi8vICAgICAgIH1cbi8vICAgICB9O1xuLy9cbi8vICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobWV0aG9kV3JhcHBlciwgXCJuYW1lXCIsIHtcbi8vICAgICAgIHZhbHVlOiBwcm9wZXJ0eUtleSxcbi8vICAgICB9KTtcbi8vICAgICBkZXNjcmlwdG9yLnZhbHVlID0gbWV0aG9kV3JhcHBlcjtcbi8vICAgfTtcbi8vIH1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVXRpbGl0eSBmb3IgaGFuZGxpbmcgc3VwZXIgY2FsbHMgaW4gdHJhbnNhY3Rpb25hbCBtZXRob2RzXG4gKiBAc3VtbWFyeSBXcmFwcyBzdXBlciBtZXRob2QgY2FsbHMgd2l0aCB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiBjb250ZXh0IHdoZW4gdGhlIHN1cGVyJ3MgbWV0aG9kIGlzIGFsc28gdHJhbnNhY3Rpb25hbCwgZW5zdXJpbmcgdHJhbnNhY3Rpb24gY29udGludWl0eSB0aHJvdWdoIHRoZSBpbmhlcml0YW5jZSBjaGFpblxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIC0gVGhlIHN1cGVyIG1ldGhvZCAobXVzdCBiZSBib3VuZCB0byB0aGUgcHJvcGVyIHRoaXMpLCBlLmcuLCBzdXBlci5jcmVhdGUuYmluZCh0aGlzKVxuICogQHBhcmFtIHthbnlbXX0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gY2FsbCB0aGUgbWV0aG9kIHdpdGhcbiAqIEByZXR1cm4ge2FueX0gVGhlIHJlc3VsdCBvZiB0aGUgc3VwZXIgbWV0aG9kIGNhbGxcbiAqIEBmdW5jdGlvbiB0cmFuc2FjdGlvbmFsU3VwZXJDYWxsXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnRyYW5zYWN0aW9uc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNhY3Rpb25hbFN1cGVyQ2FsbChtZXRob2Q6IGFueSwgLi4uYXJnczogYW55KSB7XG4gIGNvbnN0IGxvY2sgPSBUcmFuc2FjdGlvbi5nZXRMb2NrKCk7XG4gIGNvbnN0IGN1cnJlbnRUcmFuc2FjdGlvbiA9IGxvY2suY3VycmVudFRyYW5zYWN0aW9uO1xuICByZXR1cm4gbWV0aG9kKGN1cnJlbnRUcmFuc2FjdGlvbiwgLi4uYXJncyk7XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9pbnRlcmZhY2VzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9sb2Nrc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9UcmFuc2FjdGlvblwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVHJhbnNhY3Rpb25hbCBkZWNvcmF0b3JzIGZvciBUeXBlU2NyaXB0XG4gKiBAc3VtbWFyeSBBIGNvbXByZWhlbnNpdmUgbW9kdWxlIHByb3ZpZGluZyB0cmFuc2FjdGlvbiBtYW5hZ2VtZW50IGNhcGFiaWxpdGllcyBmb3IgVHlwZVNjcmlwdCBhcHBsaWNhdGlvbnMuIFRoaXMgbW9kdWxlIGV4cG9zZXMgZGVjb3JhdG9ycywgbG9ja3MsIGFuZCB1dGlsaXRpZXMgZm9yIGltcGxlbWVudGluZyB0cmFuc2FjdGlvbmFsIGJlaGF2aW9yIGluIHlvdXIgY29kZSwgYWxsb3dpbmcgZm9yIGF0b21pYyBvcGVyYXRpb25zLCBjb25jdXJyZW5jeSBjb250cm9sLCBhbmQgZXJyb3IgaGFuZGxpbmcuXG4gKiBAbW9kdWxlIHRyYW5zYWN0aW9uc1xuICovXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhY2thZ2UgdmVyc2lvbiBpZGVudGlmaWVyXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGN1cnJlbnQgcGFja2FnZSB2ZXJzaW9uIHN0cmluZywgdXNlZCBmb3IgdmVyc2lvbiB0cmFja2luZyBhbmQgY29tcGF0aWJpbGl0eSBjaGVja3NcbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnRyYW5zYWN0aW9uc1xuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQTs7Ozs7Ozs7Ozs7QUFXRztNQUNVLElBQUksQ0FBQTtBQUFqQixJQUFBLFdBQUEsR0FBQTtRQUNVLElBQUssQ0FBQSxLQUFBLEdBQW1CLEVBQUU7UUFDMUIsSUFBTSxDQUFBLE1BQUEsR0FBRyxLQUFLOztBQUV0Qjs7Ozs7QUFLRztJQUNILE1BQU0sT0FBTyxDQUFDLElBQWUsRUFBQTtBQUMzQixRQUFBLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNwQixRQUFBLElBQUksTUFBVztBQUNmLFFBQUEsSUFBSTtZQUNGLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7O1FBQ3RDLE9BQU8sQ0FBTSxFQUFFO1lBQ2YsSUFBSSxDQUFDLE9BQU8sRUFB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