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