velocious 1.0.618 → 1.0.619
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/build/database/pool/async-tracked-multi-connection.js +25 -5
- package/build/database/pool/base.js +20 -10
- package/build/environment-handlers/base.js +1 -1
- package/build/environment-handlers/node.js +10 -4
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +19 -1
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +26 -4
- package/build/src/database/pool/base.d.ts +12 -1
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +20 -11
- package/build/src/environment-handlers/base.d.ts +2 -1
- package/build/src/environment-handlers/base.d.ts.map +1 -1
- package/build/src/environment-handlers/base.js +2 -2
- package/build/src/environment-handlers/node.d.ts +3 -2
- package/build/src/environment-handlers/node.d.ts.map +1 -1
- package/build/src/environment-handlers/node.js +13 -5
- package/build/src/testing/shared-transaction-broker-client.d.ts +4 -2
- package/build/src/testing/shared-transaction-broker-client.d.ts.map +1 -1
- package/build/src/testing/shared-transaction-broker-client.js +5 -3
- package/build/src/testing/shared-transaction-broker.d.ts +21 -0
- package/build/src/testing/shared-transaction-broker.d.ts.map +1 -1
- package/build/src/testing/shared-transaction-broker.js +61 -18
- package/build/src/testing/shared-transaction-proxy-driver.d.ts +22 -3
- package/build/src/testing/shared-transaction-proxy-driver.d.ts.map +1 -1
- package/build/src/testing/shared-transaction-proxy-driver.js +51 -14
- package/build/src/testing/test-transaction-session.d.ts +129 -0
- package/build/src/testing/test-transaction-session.d.ts.map +1 -0
- package/build/src/testing/test-transaction-session.js +255 -0
- package/build/testing/shared-transaction-broker-client.js +4 -2
- package/build/testing/shared-transaction-broker.js +58 -16
- package/build/testing/shared-transaction-proxy-driver.js +52 -13
- package/build/testing/test-transaction-session.js +240 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/database/pool/async-tracked-multi-connection.js +25 -5
- package/src/database/pool/base.js +20 -10
- package/src/environment-handlers/base.js +1 -1
- package/src/environment-handlers/node.js +10 -4
- package/src/testing/shared-transaction-broker-client.js +4 -2
- package/src/testing/shared-transaction-broker.js +58 -16
- package/src/testing/shared-transaction-proxy-driver.js +52 -13
- package/src/testing/test-transaction-session.js +240 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @typedef {{address?: string, capability?: string, databaseIdentifiers?: string[], expected: boolean}} SharedTransactionBrokerJobConfig */
|
|
1
|
+
/** @typedef {{address?: string, allowDynamicIdentities?: boolean, capability?: string, databaseIdentifiers?: string[], expected: boolean}} SharedTransactionBrokerJobConfig */
|
|
2
2
|
// @ts-check
|
|
3
3
|
import SharedTransactionBrokerClient from "./shared-transaction-broker-client.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -6,6 +6,21 @@ export const SHARED_TRANSACTION_BROKER_ENV = "VELOCIOUS_TEST_SHARED_TRANSACTION_
|
|
|
6
6
|
export const BACKGROUND_JOB_CHILD_ENV = "VELOCIOUS_BACKGROUND_JOB_CHILD";
|
|
7
7
|
/** @type {AsyncLocalStorage<SharedTransactionBrokerJobConfig>} */
|
|
8
8
|
const pooledJobBrokerConfig = new AsyncLocalStorage();
|
|
9
|
+
/**
|
|
10
|
+
* Returns the active live broker configuration without validating one database route.
|
|
11
|
+
* @returns {SharedTransactionBrokerJobConfig | undefined} - Active live or child configuration.
|
|
12
|
+
*/
|
|
13
|
+
function activeSharedTransactionBrokerConfig() {
|
|
14
|
+
const contextualConfig = pooledJobBrokerConfig.getStore();
|
|
15
|
+
if (contextualConfig)
|
|
16
|
+
return contextualConfig;
|
|
17
|
+
if (process.env[BACKGROUND_JOB_CHILD_ENV] !== "1")
|
|
18
|
+
return undefined;
|
|
19
|
+
const serialized = process.env[SHARED_TRANSACTION_BROKER_ENV];
|
|
20
|
+
if (!serialized)
|
|
21
|
+
return undefined;
|
|
22
|
+
return JSON.parse(Buffer.from(serialized, "base64url").toString("utf8"));
|
|
23
|
+
}
|
|
9
24
|
/**
|
|
10
25
|
* Runs one pooled job with dispatch-time broker configuration.
|
|
11
26
|
* @template T
|
|
@@ -16,6 +31,30 @@ const pooledJobBrokerConfig = new AsyncLocalStorage();
|
|
|
16
31
|
export function runWithSharedTransactionBrokerConfig(config, callback) {
|
|
17
32
|
return pooledJobBrokerConfig.run(config, callback);
|
|
18
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Checks whether the current live join selects one exact session capability.
|
|
36
|
+
* @param {{address: string, capability: string}} identity - Session control-message identity.
|
|
37
|
+
* @returns {boolean} - Whether this async context belongs to that session.
|
|
38
|
+
*/
|
|
39
|
+
export function sharedTransactionBrokerContextMatches(identity) {
|
|
40
|
+
const config = pooledJobBrokerConfig.getStore();
|
|
41
|
+
return config?.expected === true && config.address === identity.address && config.capability === identity.capability;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Preserves legacy real tenant connections omitted by automatic TestRunner mode.
|
|
45
|
+
* Explicit dynamic sessions never permit this fallback.
|
|
46
|
+
* @param {string} databaseIdentifier - Logical database identifier.
|
|
47
|
+
* @returns {boolean} - Whether an omitted automatic route stays independent.
|
|
48
|
+
*/
|
|
49
|
+
export function automaticSharedTransactionBrokerOmits(databaseIdentifier) {
|
|
50
|
+
const config = activeSharedTransactionBrokerConfig();
|
|
51
|
+
return Boolean(config?.expected === true &&
|
|
52
|
+
!config.allowDynamicIdentities &&
|
|
53
|
+
typeof config.address === "string" &&
|
|
54
|
+
typeof config.capability === "string" &&
|
|
55
|
+
Array.isArray(config.databaseIdentifiers) &&
|
|
56
|
+
!config.databaseIdentifiers.includes(databaseIdentifier));
|
|
57
|
+
}
|
|
19
58
|
/**
|
|
20
59
|
* Escapes a PostgreSQL literal without requiring a live child connection.
|
|
21
60
|
* @param {ReturnType<typeof JSON.parse>} value - PostgreSQL literal value.
|
|
@@ -41,24 +80,19 @@ function pgEscapeLiteral(value) {
|
|
|
41
80
|
* Parses the test-runner-owned child transport configuration when this logical
|
|
42
81
|
* database is registered for the active attempt.
|
|
43
82
|
* @param {string} databaseIdentifier - Logical database identifier.
|
|
44
|
-
* @returns {{address: string, capability: string} | undefined} - Broker coordinates.
|
|
83
|
+
* @returns {{address: string, allowDynamicIdentities?: boolean, capability: string} | undefined} - Broker coordinates.
|
|
45
84
|
*/
|
|
46
85
|
export function sharedTransactionBrokerConfig(databaseIdentifier) {
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
return validatedBrokerConfig(contextualConfig, databaseIdentifier);
|
|
50
|
-
if (process.env[BACKGROUND_JOB_CHILD_ENV] !== "1")
|
|
51
|
-
return undefined;
|
|
52
|
-
const serialized = process.env[SHARED_TRANSACTION_BROKER_ENV];
|
|
53
|
-
if (!serialized)
|
|
86
|
+
const config = activeSharedTransactionBrokerConfig();
|
|
87
|
+
if (!config)
|
|
54
88
|
return undefined;
|
|
55
|
-
return validatedBrokerConfig(
|
|
89
|
+
return validatedBrokerConfig(config, databaseIdentifier);
|
|
56
90
|
}
|
|
57
91
|
/**
|
|
58
92
|
* Validates dispatch-time broker configuration and fails closed when expected.
|
|
59
93
|
* @param {SharedTransactionBrokerJobConfig} config - Candidate configuration.
|
|
60
94
|
* @param {string} databaseIdentifier - Logical database identifier.
|
|
61
|
-
* @returns {{address: string, capability: string} | undefined} - Broker coordinates.
|
|
95
|
+
* @returns {{address: string, allowDynamicIdentities?: boolean, capability: string} | undefined} - Broker coordinates.
|
|
62
96
|
*/
|
|
63
97
|
function validatedBrokerConfig(config, databaseIdentifier) {
|
|
64
98
|
if (config.expected && (!config.address || !config.capability || !config.databaseIdentifiers)) {
|
|
@@ -69,9 +103,12 @@ function validatedBrokerConfig(config, databaseIdentifier) {
|
|
|
69
103
|
if (typeof config.address !== "string" || typeof config.capability !== "string" || !Array.isArray(config.databaseIdentifiers)) {
|
|
70
104
|
throw new Error("Invalid shared transaction broker child configuration");
|
|
71
105
|
}
|
|
72
|
-
if (!config.databaseIdentifiers.includes(databaseIdentifier)) {
|
|
106
|
+
if (!config.allowDynamicIdentities && !config.databaseIdentifiers.includes(databaseIdentifier)) {
|
|
73
107
|
throw new Error(`Transactional pooled job expected broker database identifier: ${databaseIdentifier}`);
|
|
74
108
|
}
|
|
109
|
+
if (config.allowDynamicIdentities) {
|
|
110
|
+
return { address: config.address, allowDynamicIdentities: true, capability: config.capability };
|
|
111
|
+
}
|
|
75
112
|
return { address: config.address, capability: config.capability };
|
|
76
113
|
}
|
|
77
114
|
/**
|
|
@@ -81,7 +118,7 @@ function validatedBrokerConfig(config, databaseIdentifier) {
|
|
|
81
118
|
* @param {import("../configuration-types.js").DatabaseConfigurationType} config - Database configuration.
|
|
82
119
|
* @param {import("../configuration.js").default} configuration - Child configuration.
|
|
83
120
|
* @param {string} databaseIdentifier - Logical identifier.
|
|
84
|
-
* @param {{address: string, capability: string}} brokerConfig - Broker coordinates.
|
|
121
|
+
* @param {{address: string, capability: string, reuseKey?: string}} brokerConfig - Broker coordinates.
|
|
85
122
|
* @returns {import("../database/drivers/base.js").default} - Unconnected physical proxy.
|
|
86
123
|
*/
|
|
87
124
|
export function createSharedTransactionProxyDriver(DriverClass, config, configuration, databaseIdentifier, brokerConfig) {
|
|
@@ -192,4 +229,4 @@ export function createSharedTransactionProxyDriver(DriverClass, config, configur
|
|
|
192
229
|
}
|
|
193
230
|
return new SharedTransactionProxyDriver();
|
|
194
231
|
}
|
|
195
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLXRyYW5zYWN0aW9uLXByb3h5LWRyaXZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL3NoYXJlZC10cmFuc2FjdGlvbi1wcm94eS1kcml2ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNklBQTZJO0FBRTdJLFlBQVk7QUFFWixPQUFPLDZCQUE2QixNQUFNLHVDQUF1QyxDQUFBO0FBQ2pGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBRXBELE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLDBDQUEwQyxDQUFBO0FBQ3ZGLE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLGdDQUFnQyxDQUFBO0FBRXhFLGtFQUFrRTtBQUNsRSxNQUFNLHFCQUFxQixHQUFHLElBQUksaUJBQWlCLEVBQUUsQ0FBQTtBQUVyRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsb0NBQW9DLENBQUMsTUFBTSxFQUFFLFFBQVE7SUFDbkUsT0FBTyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQ3BELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxlQUFlLENBQUMsS0FBSztJQUM1QixNQUFNLE1BQU0sR0FBRyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ2hFLElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQTtJQUNqQixJQUFJLFlBQVksR0FBRyxLQUFLLENBQUE7SUFFeEIsS0FBSyxNQUFNLFNBQVMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUMvQixJQUFJLFNBQVMsS0FBSyxHQUFHO1lBQUUsT0FBTyxJQUFJLFNBQVMsQ0FBQTtRQUMzQyxJQUFJLFNBQVMsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUN2QixPQUFPLElBQUksU0FBUyxDQUFBO1lB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QkFBRSxNQUFNLEdBQUcsQ0FBQTtRQUNuQyxDQUFDO1FBRUQ7OztXQUdHO1FBQ0gsS0FBSyxDQUFDLG1CQUFtQixLQUFLLE9BQU8sS0FBSyxDQUFBLENBQUMsQ0FBQztLQUM3QztJQUVELE9BQU8sSUFBSSw0QkFBNEIsRUFBRSxDQUFBO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQHR5cGVkZWYge3thZGRyZXNzPzogc3RyaW5nLCBjYXBhYmlsaXR5Pzogc3RyaW5nLCBkYXRhYmFzZUlkZW50aWZpZXJzPzogc3RyaW5nW10sIGV4cGVjdGVkOiBib29sZWFufX0gU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWcgKi9cblxuLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNsaWVudCBmcm9tIFwiLi9zaGFyZWQtdHJhbnNhY3Rpb24tYnJva2VyLWNsaWVudC5qc1wiXG5pbXBvcnQgeyBBc3luY0xvY2FsU3RvcmFnZSB9IGZyb20gXCJub2RlOmFzeW5jX2hvb2tzXCJcblxuZXhwb3J0IGNvbnN0IFNIQVJFRF9UUkFOU0FDVElPTl9CUk9LRVJfRU5WID0gXCJWRUxPQ0lPVVNfVEVTVF9TSEFSRURfVFJBTlNBQ1RJT05fQlJPS0VSXCJcbmV4cG9ydCBjb25zdCBCQUNLR1JPVU5EX0pPQl9DSElMRF9FTlYgPSBcIlZFTE9DSU9VU19CQUNLR1JPVU5EX0pPQl9DSElMRFwiXG5cbi8qKiBAdHlwZSB7QXN5bmNMb2NhbFN0b3JhZ2U8U2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWc+fSAqL1xuY29uc3QgcG9vbGVkSm9iQnJva2VyQ29uZmlnID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKClcblxuLyoqXG4gKiBSdW5zIG9uZSBwb29sZWQgam9iIHdpdGggZGlzcGF0Y2gtdGltZSBicm9rZXIgY29uZmlndXJhdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0ge1NoYXJlZFRyYW5zYWN0aW9uQnJva2VySm9iQ29uZmlnfSBjb25maWcgLSBQZXItam9iIGJyb2tlciBtb2RlIGFuZCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7KCkgPT4gVH0gY2FsbGJhY2sgLSBKb2IgY2FsbGJhY2suXG4gKiBAcmV0dXJucyB7VH0gLSBDYWxsYmFjayByZXN1bHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5XaXRoU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJDb25maWcoY29uZmlnLCBjYWxsYmFjaykge1xuICByZXR1cm4gcG9vbGVkSm9iQnJva2VyQ29uZmlnLnJ1bihjb25maWcsIGNhbGxiYWNrKVxufVxuXG4vKipcbiAqIEVzY2FwZXMgYSBQb3N0Z3JlU1FMIGxpdGVyYWwgd2l0aG91dCByZXF1aXJpbmcgYSBsaXZlIGNoaWxkIGNvbm5lY3Rpb24uXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSB2YWx1ZSAtIFBvc3RncmVTUUwgbGl0ZXJhbCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gUXVvdGVkIGxpdGVyYWwuXG4gKi9cbmZ1bmN0aW9uIHBnRXNjYXBlTGl0ZXJhbCh2YWx1ZSkge1xuICBjb25zdCBzdHJpbmcgPSB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgPyB2YWx1ZSA6IFN0cmluZyh2YWx1ZSlcbiAgbGV0IGVzY2FwZWQgPSBcIidcIlxuICBsZXQgaGFzQmFja3NsYXNoID0gZmFsc2VcblxuICBmb3IgKGNvbnN0IGNoYXJhY3RlciBvZiBzdHJpbmcpIHtcbiAgICBpZiAoY2hhcmFjdGVyID09PSBcIidcIikgZXNjYXBlZCArPSBjaGFyYWN0ZXJcbiAgICBpZiAoY2hhcmFjdGVyID09PSBcIlxcXFxcIikge1xuICAgICAgZXNjYXBlZCArPSBjaGFyYWN0ZXJcbiAgICAgIGhhc0JhY2tzbGFzaCA9IHRydWVcbiAgICB9XG4gICAgZXNjYXBlZCArPSBjaGFyYWN0ZXJcbiAgfVxuXG4gIGVzY2FwZWQgKz0gXCInXCJcbiAgcmV0dXJuIGhhc0JhY2tzbGFzaCA/IGAgRSR7ZXNjYXBlZH1gIDogZXNjYXBlZFxufVxuXG4vKipcbiAqIFBhcnNlcyB0aGUgdGVzdC1ydW5uZXItb3duZWQgY2hpbGQgdHJhbnNwb3J0IGNvbmZpZ3VyYXRpb24gd2hlbiB0aGlzIGxvZ2ljYWxcbiAqIGRhdGFiYXNlIGlzIHJlZ2lzdGVyZWQgZm9yIHRoZSBhY3RpdmUgYXR0ZW1wdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhYmFzZUlkZW50aWZpZXIgLSBMb2dpY2FsIGRhdGFiYXNlIGlkZW50aWZpZXIuXG4gKiBAcmV0dXJucyB7e2FkZHJlc3M6IHN0cmluZywgY2FwYWJpbGl0eTogc3RyaW5nfSB8IHVuZGVmaW5lZH0gLSBCcm9rZXIgY29vcmRpbmF0ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyhkYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgY29uc3QgY29udGV4dHVhbENvbmZpZyA9IHBvb2xlZEpvYkJyb2tlckNvbmZpZy5nZXRTdG9yZSgpXG4gIGlmIChjb250ZXh0dWFsQ29uZmlnKSByZXR1cm4gdmFsaWRhdGVkQnJva2VyQ29uZmlnKGNvbnRleHR1YWxDb25maWcsIGRhdGFiYXNlSWRlbnRpZmllcilcbiAgaWYgKHByb2Nlc3MuZW52W0JBQ0tHUk9VTkRfSk9CX0NISUxEX0VOVl0gIT09IFwiMVwiKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgY29uc3Qgc2VyaWFsaXplZCA9IHByb2Nlc3MuZW52W1NIQVJFRF9UUkFOU0FDVElPTl9CUk9LRVJfRU5WXVxuICBpZiAoIXNlcmlhbGl6ZWQpIHJldHVybiB1bmRlZmluZWRcblxuICByZXR1cm4gdmFsaWRhdGVkQnJva2VyQ29uZmlnKEpTT04ucGFyc2UoQnVmZmVyLmZyb20oc2VyaWFsaXplZCwgXCJiYXNlNjR1cmxcIikudG9TdHJpbmcoXCJ1dGY4XCIpKSwgZGF0YWJhc2VJZGVudGlmaWVyKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBkaXNwYXRjaC10aW1lIGJyb2tlciBjb25maWd1cmF0aW9uIGFuZCBmYWlscyBjbG9zZWQgd2hlbiBleHBlY3RlZC5cbiAqIEBwYXJhbSB7U2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWd9IGNvbmZpZyAtIENhbmRpZGF0ZSBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFiYXNlSWRlbnRpZmllciAtIExvZ2ljYWwgZGF0YWJhc2UgaWRlbnRpZmllci5cbiAqIEByZXR1cm5zIHt7YWRkcmVzczogc3RyaW5nLCBjYXBhYmlsaXR5OiBzdHJpbmd9IHwgdW5kZWZpbmVkfSAtIEJyb2tlciBjb29yZGluYXRlcy5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVkQnJva2VyQ29uZmlnKGNvbmZpZywgZGF0YWJhc2VJZGVudGlmaWVyKSB7XG4gIGlmIChjb25maWcuZXhwZWN0ZWQgJiYgKCFjb25maWcuYWRkcmVzcyB8fCAhY29uZmlnLmNhcGFiaWxpdHkgfHwgIWNvbmZpZy5kYXRhYmFzZUlkZW50aWZpZXJzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlRyYW5zYWN0aW9uYWwgcG9vbGVkIGpvYiBleHBlY3RlZCBzaGFyZWQgdHJhbnNhY3Rpb24gYnJva2VyIGNvb3JkaW5hdGVzXCIpXG4gIH1cbiAgaWYgKCFjb25maWcuZXhwZWN0ZWQpIHJldHVybiB1bmRlZmluZWRcbiAgaWYgKHR5cGVvZiBjb25maWcuYWRkcmVzcyAhPT0gXCJzdHJpbmdcIiB8fCB0eXBlb2YgY29uZmlnLmNhcGFiaWxpdHkgIT09IFwic3RyaW5nXCIgfHwgIUFycmF5LmlzQXJyYXkoY29uZmlnLmRhdGFiYXNlSWRlbnRpZmllcnMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaGFyZWQgdHJhbnNhY3Rpb24gYnJva2VyIGNoaWxkIGNvbmZpZ3VyYXRpb25cIilcbiAgfVxuICBpZiAoIWNvbmZpZy5kYXRhYmFzZUlkZW50aWZpZXJzLmluY2x1ZGVzKGRhdGFiYXNlSWRlbnRpZmllcikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRyYW5zYWN0aW9uYWwgcG9vbGVkIGpvYiBleHBlY3RlZCBicm9rZXIgZGF0YWJhc2UgaWRlbnRpZmllcjogJHtkYXRhYmFzZUlkZW50aWZpZXJ9YClcbiAgfVxuXG4gIHJldHVybiB7YWRkcmVzczogY29uZmlnLmFkZHJlc3MsIGNhcGFiaWxpdHk6IGNvbmZpZy5jYXBhYmlsaXR5fVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBjb25jcmV0ZS1kcml2ZXIgc3ViY2xhc3MgdGhhdCByZXRhaW5zIGFsbCBsb2NhbCBTUUwvcXVlcnkvbW9kZWxcbiAqIGJ1aWxkZXJzIHdoaWxlIGZvcndhcmRpbmcgb25seSBwaHlzaWNhbCBjb25uZWN0aW9uIGFjdGlvbnMgdG8gdGhlIHBhcmVudC5cbiAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBEcml2ZXJDbGFzcyAtIENvbmZpZ3VyZWQgY29uY3JldGUgZHJpdmVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkRhdGFiYXNlQ29uZmlndXJhdGlvblR5cGV9IGNvbmZpZyAtIERhdGFiYXNlIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gY29uZmlndXJhdGlvbiAtIENoaWxkIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YWJhc2VJZGVudGlmaWVyIC0gTG9naWNhbCBpZGVudGlmaWVyLlxuICogQHBhcmFtIHt7YWRkcmVzczogc3RyaW5nLCBjYXBhYmlsaXR5OiBzdHJpbmd9fSBicm9rZXJDb25maWcgLSBCcm9rZXIgY29vcmRpbmF0ZXMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IC0gVW5jb25uZWN0ZWQgcGh5c2ljYWwgcHJveHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTaGFyZWRUcmFuc2FjdGlvblByb3h5RHJpdmVyKERyaXZlckNsYXNzLCBjb25maWcsIGNvbmZpZ3VyYXRpb24sIGRhdGFiYXNlSWRlbnRpZmllciwgYnJva2VyQ29uZmlnKSB7XG4gIGNsYXNzIFNoYXJlZFRyYW5zYWN0aW9uUHJveHlEcml2ZXIgZXh0ZW5kcyBEcml2ZXJDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICBzdXBlcihjb25maWcsIGNvbmZpZ3VyYXRpb24pXG4gICAgICB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50ID0gbmV3IFNoYXJlZFRyYW5zYWN0aW9uQnJva2VyQ2xpZW50KHsuLi5icm9rZXJDb25maWcsIGRhdGFiYXNlSWRlbnRpZmllcn0pXG4gICAgICAvKiogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH0gKi9cbiAgICAgIHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50ID0gdW5kZWZpbmVkXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdGhlIHByb3h5IHRyYW5zcG9ydC5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbm5lY3RlZC5cbiAgICAgKi9cbiAgICBhc3luYyBjb25uZWN0KCkgeyBhd2FpdCB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50LmNvbm5lY3RlZCgpIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgb25seSB0aGUgcHJveHkgdHJhbnNwb3J0LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY2xvc2VkLlxuICAgICAqL1xuICAgIGFzeW5jIF9jbG9zZSgpIHsgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jbG9zZSgpIH1cbiAgICAvKipcbiAgICAgKiBLZWVwcyBhIGJyb2tlciBwcm94eSB0cmFuc3BvcnQgYWxpdmUgYWNyb3NzIGxvZ2ljYWwgTXlTUUwgY2hlY2tvdXRzLlxuICAgICAqIFBhcmVudCBUZXN0UnVubmVyIG93bnMgcGh5c2ljYWwgc2Vzc2lvbiBjbGVhbnVwIGFuZCByb2xsYmFjay5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aXRob3V0IGNsb3NpbmcgdGhlIHRyYW5zcG9ydC5cbiAgICAgKi9cbiAgICBhc3luYyBjbGVhbnVwU2Vzc2lvblN0YXRlQWZ0ZXJDaGVja291dCgpIHt9XG4gICAgLyoqXG4gICAgICogUm91dGVzIGEgcGh5c2ljYWwgcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNxbCAtIFNRTCBzdGF0ZW1lbnQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLlF1ZXJ5UmVzdWx0VHlwZT59IC0gUm93cy5cbiAgICAgKi9cbiAgICBhc3luYyBfcXVlcnlBY3R1YWwoc3FsKSB7IHJldHVybiBhd2FpdCB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50LmNhbGwoXCJfcXVlcnlBY3R1YWxcIiwgW3NxbF0pIH1cbiAgICAvKipcbiAgICAgKiBSb3V0ZXMgYW4gYWZmZWN0ZWQtcm93IHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzcWwgLSBTUUwgc3RhdGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IC0gQWZmZWN0ZWQgcm93cy5cbiAgICAgKi9cbiAgICBhc3luYyBfYWZmZWN0ZWRSb3dzQWN0dWFsKHNxbCkgeyByZXR1cm4gYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwiX2FmZmVjdGVkUm93c0FjdHVhbFwiLCBbc3FsXSkgfVxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIGEgY2hpbGQgdHJhbnNhY3Rpb24gYXMgYSBwYXJlbnQgc2F2ZXBvaW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gc3RhcnRlZC5cbiAgICAgKi9cbiAgICBhc3luYyBfc3RhcnRUcmFuc2FjdGlvbkFjdGlvbigpIHtcbiAgICAgIHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50ID0gdGhpcy5nZW5lcmF0ZVNhdmVQb2ludE5hbWUoKVxuICAgICAgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwicm9vdFRyYW5zYWN0aW9uU3RhcnRcIiwgW3RoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50XSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWxlYXNlcyB0aGUgY2hpbGQgdHJhbnNhY3Rpb24gc2F2ZXBvaW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gcmVsZWFzZWQuXG4gICAgICovXG4gICAgYXN5bmMgX2NvbW1pdFRyYW5zYWN0aW9uQWN0aW9uKCkge1xuICAgICAgaWYgKCF0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludCkgdGhyb3cgbmV3IEVycm9yKFwiU2hhcmVkIHRyYW5zYWN0aW9uIHByb3h5IGhhcyBubyByb290IHNhdmVwb2ludFwiKVxuICAgICAgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwicm9vdFRyYW5zYWN0aW9uUmVsZWFzZVwiLCBbdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnRdKVxuICAgICAgdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnQgPSB1bmRlZmluZWRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb2xscyBiYWNrIHRoZSBjaGlsZCB0cmFuc2FjdGlvbiBzYXZlcG9pbnQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiByb2xsZWQgYmFjay5cbiAgICAgKi9cbiAgICBhc3luYyBfcm9sbGJhY2tUcmFuc2FjdGlvbkFjdGlvbigpIHtcbiAgICAgIGlmICghdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnQpIHRocm93IG5ldyBFcnJvcihcIlNoYXJlZCB0cmFuc2FjdGlvbiBwcm94eSBoYXMgbm8gcm9vdCBzYXZlcG9pbnRcIilcbiAgICAgIGF3YWl0IHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25DbGllbnQuY2FsbChcInJvb3RUcmFuc2FjdGlvblJvbGxiYWNrXCIsIFt0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludF0pXG4gICAgICB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludCA9IHVuZGVmaW5lZFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZXMgYSBsb2NhbCBTUUwgdmFsdWUuXG4gICAgICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gdmFsdWUgLSBTUUwgdmFsdWUuXG4gICAgICogQHJldHVybnMge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSAtIEVzY2FwZWQgdmFsdWUuXG4gICAgICovXG4gICAgZXNjYXBlKHZhbHVlKSB7XG4gICAgICBpZiAodGhpcy5nZXRUeXBlKCkgIT09IFwicGdzcWxcIikgcmV0dXJuIHN1cGVyLmVzY2FwZSh2YWx1ZSlcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpIHJldHVybiB2YWx1ZVxuICAgICAgY29uc3QgZXNjYXBlZCA9IHBnRXNjYXBlTGl0ZXJhbCh0aGlzLl9jb252ZXJ0VmFsdWUodmFsdWUpKVxuICAgICAgcmV0dXJuIGVzY2FwZWQuc2xpY2UoMSwgLTEpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVvdGVzIGEgbG9jYWwgU1FMIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHZhbHVlIC0gU1FMIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmcgfCBudW1iZXJ9IC0gUXVvdGVkIHZhbHVlLlxuICAgICAqL1xuICAgIHF1b3RlKHZhbHVlKSB7XG4gICAgICBpZiAodGhpcy5nZXRUeXBlKCkgIT09IFwicGdzcWxcIikgcmV0dXJuIHN1cGVyLnF1b3RlKHZhbHVlKVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHZhbHVlXG4gICAgICByZXR1cm4gcGdFc2NhcGVMaXRlcmFsKHRoaXMuX2NvbnZlcnRWYWx1ZSh2YWx1ZSkpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RyZWFtcyBicm9rZXJlZCByb3dzIHRocm91Z2ggdGhlIGRyaXZlcidzIGJ1ZmZlcmVkIGZhbGxiYWNrLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzcWwgLSBTUUwgc3RhdGVtZW50LlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLlF1ZXJ5T3B0aW9uc30gW29wdGlvbnNdIC0gUXVlcnkgb3B0aW9ucy5cbiAgICAgKiBAeWllbGRzIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IC0gUmVzdWx0IHJvd3MuXG4gICAgICovXG4gICAgYXN5bmMgKnF1ZXJ5U3RyZWFtKHNxbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICBjb25zdCByb3dzID0gYXdhaXQgdGhpcy5xdWVyeShzcWwsIG9wdGlvbnMpXG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB5aWVsZCByb3dcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBLZWVwcyBzdHJ1Y3R1cmUgU1FMIG9uIG5vcm1hbCBicm9rZXJlZCBzdGF0ZW1lbnRzLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSAtIEFsd2F5cyBmYWxzZS5cbiAgICAgKi9cbiAgICBhc3luYyBleGVjU3RydWN0dXJlU2NyaXB0KCkgeyByZXR1cm4gZmFsc2UgfVxuICB9XG5cbiAgcmV0dXJuIG5ldyBTaGFyZWRUcmFuc2FjdGlvblByb3h5RHJpdmVyKClcbn1cbiJdfQ==
|
|
232
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLXRyYW5zYWN0aW9uLXByb3h5LWRyaXZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL3NoYXJlZC10cmFuc2FjdGlvbi1wcm94eS1kcml2ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0tBQStLO0FBRS9LLFlBQVk7QUFFWixPQUFPLDZCQUE2QixNQUFNLHVDQUF1QyxDQUFBO0FBQ2pGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBRXBELE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLDBDQUEwQyxDQUFBO0FBQ3ZGLE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLGdDQUFnQyxDQUFBO0FBRXhFLGtFQUFrRTtBQUNsRSxNQUFNLHFCQUFxQixHQUFHLElBQUksaUJBQWlCLEVBQUUsQ0FBQTtBQUVyRDs7O0dBR0c7QUFDSCxTQUFTLG1DQUFtQztJQUMxQyxNQUFNLGdCQUFnQixHQUFHLHFCQUFxQixDQUFDLFFBQVEsRUFBRSxDQUFBO0lBQ3pELElBQUksZ0JBQWdCO1FBQUUsT0FBTyxnQkFBZ0IsQ0FBQTtJQUM3QyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsS0FBSyxHQUFHO1FBQUUsT0FBTyxTQUFTLENBQUE7SUFDbkUsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFBO0lBQzdELElBQUksQ0FBQyxVQUFVO1FBQUUsT0FBTyxTQUFTLENBQUE7SUFDakMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFBO0FBQzFFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsb0NBQW9DLENBQUMsTUFBTSxFQUFFLFFBQVE7SUFDbkUsT0FBTyxxQkFBcUIs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O1FBRUQ7OztXQUdHO1FBQ0gsS0FBSyxDQUFDLG1CQUFtQixLQUFLLE9BQU8sS0FBSyxDQUFBLENBQUMsQ0FBQztLQUM3QztJQUVELE9BQU8sSUFBSSw0QkFBNEIsRUFBRSxDQUFBO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQHR5cGVkZWYge3thZGRyZXNzPzogc3RyaW5nLCBhbGxvd0R5bmFtaWNJZGVudGl0aWVzPzogYm9vbGVhbiwgY2FwYWJpbGl0eT86IHN0cmluZywgZGF0YWJhc2VJZGVudGlmaWVycz86IHN0cmluZ1tdLCBleHBlY3RlZDogYm9vbGVhbn19IFNoYXJlZFRyYW5zYWN0aW9uQnJva2VySm9iQ29uZmlnICovXG5cbi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJDbGllbnQgZnJvbSBcIi4vc2hhcmVkLXRyYW5zYWN0aW9uLWJyb2tlci1jbGllbnQuanNcIlxuaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwibm9kZTphc3luY19ob29rc1wiXG5cbmV4cG9ydCBjb25zdCBTSEFSRURfVFJBTlNBQ1RJT05fQlJPS0VSX0VOViA9IFwiVkVMT0NJT1VTX1RFU1RfU0hBUkVEX1RSQU5TQUNUSU9OX0JST0tFUlwiXG5leHBvcnQgY29uc3QgQkFDS0dST1VORF9KT0JfQ0hJTERfRU5WID0gXCJWRUxPQ0lPVVNfQkFDS0dST1VORF9KT0JfQ0hJTERcIlxuXG4vKiogQHR5cGUge0FzeW5jTG9jYWxTdG9yYWdlPFNoYXJlZFRyYW5zYWN0aW9uQnJva2VySm9iQ29uZmlnPn0gKi9cbmNvbnN0IHBvb2xlZEpvYkJyb2tlckNvbmZpZyA9IG5ldyBBc3luY0xvY2FsU3RvcmFnZSgpXG5cbi8qKlxuICogUmV0dXJucyB0aGUgYWN0aXZlIGxpdmUgYnJva2VyIGNvbmZpZ3VyYXRpb24gd2l0aG91dCB2YWxpZGF0aW5nIG9uZSBkYXRhYmFzZSByb3V0ZS5cbiAqIEByZXR1cm5zIHtTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckpvYkNvbmZpZyB8IHVuZGVmaW5lZH0gLSBBY3RpdmUgbGl2ZSBvciBjaGlsZCBjb25maWd1cmF0aW9uLlxuICovXG5mdW5jdGlvbiBhY3RpdmVTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZygpIHtcbiAgY29uc3QgY29udGV4dHVhbENvbmZpZyA9IHBvb2xlZEpvYkJyb2tlckNvbmZpZy5nZXRTdG9yZSgpXG4gIGlmIChjb250ZXh0dWFsQ29uZmlnKSByZXR1cm4gY29udGV4dHVhbENvbmZpZ1xuICBpZiAocHJvY2Vzcy5lbnZbQkFDS0dST1VORF9KT0JfQ0hJTERfRU5WXSAhPT0gXCIxXCIpIHJldHVybiB1bmRlZmluZWRcbiAgY29uc3Qgc2VyaWFsaXplZCA9IHByb2Nlc3MuZW52W1NIQVJFRF9UUkFOU0FDVElPTl9CUk9LRVJfRU5WXVxuICBpZiAoIXNlcmlhbGl6ZWQpIHJldHVybiB1bmRlZmluZWRcbiAgcmV0dXJuIEpTT04ucGFyc2UoQnVmZmVyLmZyb20oc2VyaWFsaXplZCwgXCJiYXNlNjR1cmxcIikudG9TdHJpbmcoXCJ1dGY4XCIpKVxufVxuXG4vKipcbiAqIFJ1bnMgb25lIHBvb2xlZCBqb2Igd2l0aCBkaXNwYXRjaC10aW1lIGJyb2tlciBjb25maWd1cmF0aW9uLlxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7U2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWd9IGNvbmZpZyAtIFBlci1qb2IgYnJva2VyIG1vZGUgYW5kIGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHsoKSA9PiBUfSBjYWxsYmFjayAtIEpvYiBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHtUfSAtIENhbGxiYWNrIHJlc3VsdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJ1bldpdGhTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyhjb25maWcsIGNhbGxiYWNrKSB7XG4gIHJldHVybiBwb29sZWRKb2JCcm9rZXJDb25maWcucnVuKGNvbmZpZywgY2FsbGJhY2spXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhlIGN1cnJlbnQgbGl2ZSBqb2luIHNlbGVjdHMgb25lIGV4YWN0IHNlc3Npb24gY2FwYWJpbGl0eS5cbiAqIEBwYXJhbSB7e2FkZHJlc3M6IHN0cmluZywgY2FwYWJpbGl0eTogc3RyaW5nfX0gaWRlbnRpdHkgLSBTZXNzaW9uIGNvbnRyb2wtbWVzc2FnZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgdGhpcyBhc3luYyBjb250ZXh0IGJlbG9uZ3MgdG8gdGhhdCBzZXNzaW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJDb250ZXh0TWF0Y2hlcyhpZGVudGl0eSkge1xuICBjb25zdCBjb25maWcgPSBwb29sZWRKb2JCcm9rZXJDb25maWcuZ2V0U3RvcmUoKVxuICByZXR1cm4gY29uZmlnPy5leHBlY3RlZCA9PT0gdHJ1ZSAmJiBjb25maWcuYWRkcmVzcyA9PT0gaWRlbnRpdHkuYWRkcmVzcyAmJiBjb25maWcuY2FwYWJpbGl0eSA9PT0gaWRlbnRpdHkuY2FwYWJpbGl0eVxufVxuXG4vKipcbiAqIFByZXNlcnZlcyBsZWdhY3kgcmVhbCB0ZW5hbnQgY29ubmVjdGlvbnMgb21pdHRlZCBieSBhdXRvbWF0aWMgVGVzdFJ1bm5lciBtb2RlLlxuICogRXhwbGljaXQgZHluYW1pYyBzZXNzaW9ucyBuZXZlciBwZXJtaXQgdGhpcyBmYWxsYmFjay5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhYmFzZUlkZW50aWZpZXIgLSBMb2dpY2FsIGRhdGFiYXNlIGlkZW50aWZpZXIuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIGFuIG9taXR0ZWQgYXV0b21hdGljIHJvdXRlIHN0YXlzIGluZGVwZW5kZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXV0b21hdGljU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJPbWl0cyhkYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgY29uc3QgY29uZmlnID0gYWN0aXZlU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJDb25maWcoKVxuICByZXR1cm4gQm9vbGVhbihcbiAgICBjb25maWc/LmV4cGVjdGVkID09PSB0cnVlICYmXG4gICAgIWNvbmZpZy5hbGxvd0R5bmFtaWNJZGVudGl0aWVzICYmXG4gICAgdHlwZW9mIGNvbmZpZy5hZGRyZXNzID09PSBcInN0cmluZ1wiICYmXG4gICAgdHlwZW9mIGNvbmZpZy5jYXBhYmlsaXR5ID09PSBcInN0cmluZ1wiICYmXG4gICAgQXJyYXkuaXNBcnJheShjb25maWcuZGF0YWJhc2VJZGVudGlmaWVycykgJiZcbiAgICAhY29uZmlnLmRhdGFiYXNlSWRlbnRpZmllcnMuaW5jbHVkZXMoZGF0YWJhc2VJZGVudGlmaWVyKVxuICApXG59XG5cbi8qKlxuICogRXNjYXBlcyBhIFBvc3RncmVTUUwgbGl0ZXJhbCB3aXRob3V0IHJlcXVpcmluZyBhIGxpdmUgY2hpbGQgY29ubmVjdGlvbi5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHZhbHVlIC0gUG9zdGdyZVNRTCBsaXRlcmFsIHZhbHVlLlxuICogQHJldHVybnMge3N0cmluZ30gLSBRdW90ZWQgbGl0ZXJhbC5cbiAqL1xuZnVuY3Rpb24gcGdFc2NhcGVMaXRlcmFsKHZhbHVlKSB7XG4gIGNvbnN0IHN0cmluZyA9IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlIDogU3RyaW5nKHZhbHVlKVxuICBsZXQgZXNjYXBlZCA9IFwiJ1wiXG4gIGxldCBoYXNCYWNrc2xhc2ggPSBmYWxzZVxuXG4gIGZvciAoY29uc3QgY2hhcmFjdGVyIG9mIHN0cmluZykge1xuICAgIGlmIChjaGFyYWN0ZXIgPT09IFwiJ1wiKSBlc2NhcGVkICs9IGNoYXJhY3RlclxuICAgIGlmIChjaGFyYWN0ZXIgPT09IFwiXFxcXFwiKSB7XG4gICAgICBlc2NhcGVkICs9IGNoYXJhY3RlclxuICAgICAgaGFzQmFja3NsYXNoID0gdHJ1ZVxuICAgIH1cbiAgICBlc2NhcGVkICs9IGNoYXJhY3RlclxuICB9XG5cbiAgZXNjYXBlZCArPSBcIidcIlxuICByZXR1cm4gaGFzQmFja3NsYXNoID8gYCBFJHtlc2NhcGVkfWAgOiBlc2NhcGVkXG59XG5cbi8qKlxuICogUGFyc2VzIHRoZSB0ZXN0LXJ1bm5lci1vd25lZCBjaGlsZCB0cmFuc3BvcnQgY29uZmlndXJhdGlvbiB3aGVuIHRoaXMgbG9naWNhbFxuICogZGF0YWJhc2UgaXMgcmVnaXN0ZXJlZCBmb3IgdGhlIGFjdGl2ZSBhdHRlbXB0LlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFiYXNlSWRlbnRpZmllciAtIExvZ2ljYWwgZGF0YWJhc2UgaWRlbnRpZmllci5cbiAqIEByZXR1cm5zIHt7YWRkcmVzczogc3RyaW5nLCBhbGxvd0R5bmFtaWNJZGVudGl0aWVzPzogYm9vbGVhbiwgY2FwYWJpbGl0eTogc3RyaW5nfSB8IHVuZGVmaW5lZH0gLSBCcm9rZXIgY29vcmRpbmF0ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyhkYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgY29uc3QgY29uZmlnID0gYWN0aXZlU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJDb25maWcoKVxuICBpZiAoIWNvbmZpZykgcmV0dXJuIHVuZGVmaW5lZFxuICByZXR1cm4gdmFsaWRhdGVkQnJva2VyQ29uZmlnKGNvbmZpZywgZGF0YWJhc2VJZGVudGlmaWVyKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBkaXNwYXRjaC10aW1lIGJyb2tlciBjb25maWd1cmF0aW9uIGFuZCBmYWlscyBjbG9zZWQgd2hlbiBleHBlY3RlZC5cbiAqIEBwYXJhbSB7U2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWd9IGNvbmZpZyAtIENhbmRpZGF0ZSBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFiYXNlSWRlbnRpZmllciAtIExvZ2ljYWwgZGF0YWJhc2UgaWRlbnRpZmllci5cbiAqIEByZXR1cm5zIHt7YWRkcmVzczogc3RyaW5nLCBhbGxvd0R5bmFtaWNJZGVudGl0aWVzPzogYm9vbGVhbiwgY2FwYWJpbGl0eTogc3RyaW5nfSB8IHVuZGVmaW5lZH0gLSBCcm9rZXIgY29vcmRpbmF0ZXMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlZEJyb2tlckNvbmZpZyhjb25maWcsIGRhdGFiYXNlSWRlbnRpZmllcikge1xuICBpZiAoY29uZmlnLmV4cGVjdGVkICYmICghY29uZmlnLmFkZHJlc3MgfHwgIWNvbmZpZy5jYXBhYmlsaXR5IHx8ICFjb25maWcuZGF0YWJhc2VJZGVudGlmaWVycykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJUcmFuc2FjdGlvbmFsIHBvb2xlZCBqb2IgZXhwZWN0ZWQgc2hhcmVkIHRyYW5zYWN0aW9uIGJyb2tlciBjb29yZGluYXRlc1wiKVxuICB9XG4gIGlmICghY29uZmlnLmV4cGVjdGVkKSByZXR1cm4gdW5kZWZpbmVkXG4gIGlmICh0eXBlb2YgY29uZmlnLmFkZHJlc3MgIT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIGNvbmZpZy5jYXBhYmlsaXR5ICE9PSBcInN0cmluZ1wiIHx8ICFBcnJheS5pc0FycmF5KGNvbmZpZy5kYXRhYmFzZUlkZW50aWZpZXJzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2hhcmVkIHRyYW5zYWN0aW9uIGJyb2tlciBjaGlsZCBjb25maWd1cmF0aW9uXCIpXG4gIH1cbiAgaWYgKCFjb25maWcuYWxsb3dEeW5hbWljSWRlbnRpdGllcyAmJiAhY29uZmlnLmRhdGFiYXNlSWRlbnRpZmllcnMuaW5jbHVkZXMoZGF0YWJhc2VJZGVudGlmaWVyKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVHJhbnNhY3Rpb25hbCBwb29sZWQgam9iIGV4cGVjdGVkIGJyb2tlciBkYXRhYmFzZSBpZGVudGlmaWVyOiAke2RhdGFiYXNlSWRlbnRpZmllcn1gKVxuICB9XG5cbiAgaWYgKGNvbmZpZy5hbGxvd0R5bmFtaWNJZGVudGl0aWVzKSB7XG4gICAgcmV0dXJuIHthZGRyZXNzOiBjb25maWcuYWRkcmVzcywgYWxsb3dEeW5hbWljSWRlbnRpdGllczogdHJ1ZSwgY2FwYWJpbGl0eTogY29uZmlnLmNhcGFiaWxpdHl9XG4gIH1cbiAgcmV0dXJuIHthZGRyZXNzOiBjb25maWcuYWRkcmVzcywgY2FwYWJpbGl0eTogY29uZmlnLmNhcGFiaWxpdHl9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbmNyZXRlLWRyaXZlciBzdWJjbGFzcyB0aGF0IHJldGFpbnMgYWxsIGxvY2FsIFNRTC9xdWVyeS9tb2RlbFxuICogYnVpbGRlcnMgd2hpbGUgZm9yd2FyZGluZyBvbmx5IHBoeXNpY2FsIGNvbm5lY3Rpb24gYWN0aW9ucyB0byB0aGUgcGFyZW50LlxuICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IERyaXZlckNsYXNzIC0gQ29uZmlndXJlZCBjb25jcmV0ZSBkcml2ZXIuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuRGF0YWJhc2VDb25maWd1cmF0aW9uVHlwZX0gY29uZmlnIC0gRGF0YWJhc2UgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBjb25maWd1cmF0aW9uIC0gQ2hpbGQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhYmFzZUlkZW50aWZpZXIgLSBMb2dpY2FsIGlkZW50aWZpZXIuXG4gKiBAcGFyYW0ge3thZGRyZXNzOiBzdHJpbmcsIGNhcGFiaWxpdHk6IHN0cmluZywgcmV1c2VLZXk/OiBzdHJpbmd9fSBicm9rZXJDb25maWcgLSBCcm9rZXIgY29vcmRpbmF0ZXMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IC0gVW5jb25uZWN0ZWQgcGh5c2ljYWwgcHJveHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTaGFyZWRUcmFuc2FjdGlvblByb3h5RHJpdmVyKERyaXZlckNsYXNzLCBjb25maWcsIGNvbmZpZ3VyYXRpb24sIGRhdGFiYXNlSWRlbnRpZmllciwgYnJva2VyQ29uZmlnKSB7XG4gIGNsYXNzIFNoYXJlZFRyYW5zYWN0aW9uUHJveHlEcml2ZXIgZXh0ZW5kcyBEcml2ZXJDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICBzdXBlcihjb25maWcsIGNvbmZpZ3VyYXRpb24pXG4gICAgICB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50ID0gbmV3IFNoYXJlZFRyYW5zYWN0aW9uQnJva2VyQ2xpZW50KHsuLi5icm9rZXJDb25maWcsIGRhdGFiYXNlSWRlbnRpZmllcn0pXG4gICAgICAvKiogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH0gKi9cbiAgICAgIHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50ID0gdW5kZWZpbmVkXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdGhlIHByb3h5IHRyYW5zcG9ydC5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbm5lY3RlZC5cbiAgICAgKi9cbiAgICBhc3luYyBjb25uZWN0KCkgeyBhd2FpdCB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50LmNvbm5lY3RlZCgpIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgb25seSB0aGUgcHJveHkgdHJhbnNwb3J0LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY2xvc2VkLlxuICAgICAqL1xuICAgIGFzeW5jIF9jbG9zZSgpIHsgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jbG9zZSgpIH1cbiAgICAvKipcbiAgICAgKiBLZWVwcyBhIGJyb2tlciBwcm94eSB0cmFuc3BvcnQgYWxpdmUgYWNyb3NzIGxvZ2ljYWwgTXlTUUwgY2hlY2tvdXRzLlxuICAgICAqIFBhcmVudCBUZXN0UnVubmVyIG93bnMgcGh5c2ljYWwgc2Vzc2lvbiBjbGVhbnVwIGFuZCByb2xsYmFjay5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aXRob3V0IGNsb3NpbmcgdGhlIHRyYW5zcG9ydC5cbiAgICAgKi9cbiAgICBhc3luYyBjbGVhbnVwU2Vzc2lvblN0YXRlQWZ0ZXJDaGVja291dCgpIHt9XG4gICAgLyoqXG4gICAgICogUm91dGVzIGEgcGh5c2ljYWwgcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNxbCAtIFNRTCBzdGF0ZW1lbnQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLlF1ZXJ5UmVzdWx0VHlwZT59IC0gUm93cy5cbiAgICAgKi9cbiAgICBhc3luYyBfcXVlcnlBY3R1YWwoc3FsKSB7IHJldHVybiBhd2FpdCB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uQ2xpZW50LmNhbGwoXCJfcXVlcnlBY3R1YWxcIiwgW3NxbF0pIH1cbiAgICAvKipcbiAgICAgKiBSb3V0ZXMgYW4gYWZmZWN0ZWQtcm93IHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzcWwgLSBTUUwgc3RhdGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IC0gQWZmZWN0ZWQgcm93cy5cbiAgICAgKi9cbiAgICBhc3luYyBfYWZmZWN0ZWRSb3dzQWN0dWFsKHNxbCkgeyByZXR1cm4gYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwiX2FmZmVjdGVkUm93c0FjdHVhbFwiLCBbc3FsXSkgfVxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIGEgY2hpbGQgdHJhbnNhY3Rpb24gYXMgYSBwYXJlbnQgc2F2ZXBvaW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gc3RhcnRlZC5cbiAgICAgKi9cbiAgICBhc3luYyBfc3RhcnRUcmFuc2FjdGlvbkFjdGlvbigpIHtcbiAgICAgIHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50ID0gdGhpcy5nZW5lcmF0ZVNhdmVQb2ludE5hbWUoKVxuICAgICAgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwicm9vdFRyYW5zYWN0aW9uU3RhcnRcIiwgW3RoaXMuc2hhcmVkVHJhbnNhY3Rpb25Sb290U2F2ZVBvaW50XSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWxlYXNlcyB0aGUgY2hpbGQgdHJhbnNhY3Rpb24gc2F2ZXBvaW50LlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gcmVsZWFzZWQuXG4gICAgICovXG4gICAgYXN5bmMgX2NvbW1pdFRyYW5zYWN0aW9uQWN0aW9uKCkge1xuICAgICAgaWYgKCF0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludCkgdGhyb3cgbmV3IEVycm9yKFwiU2hhcmVkIHRyYW5zYWN0aW9uIHByb3h5IGhhcyBubyByb290IHNhdmVwb2ludFwiKVxuICAgICAgYXdhaXQgdGhpcy5zaGFyZWRUcmFuc2FjdGlvbkNsaWVudC5jYWxsKFwicm9vdFRyYW5zYWN0aW9uUmVsZWFzZVwiLCBbdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnRdKVxuICAgICAgdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnQgPSB1bmRlZmluZWRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb2xscyBiYWNrIHRoZSBjaGlsZCB0cmFuc2FjdGlvbiBzYXZlcG9pbnQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiByb2xsZWQgYmFjay5cbiAgICAgKi9cbiAgICBhc3luYyBfcm9sbGJhY2tUcmFuc2FjdGlvbkFjdGlvbigpIHtcbiAgICAgIGlmICghdGhpcy5zaGFyZWRUcmFuc2FjdGlvblJvb3RTYXZlUG9pbnQpIHRocm93IG5ldyBFcnJvcihcIlNoYXJlZCB0cmFuc2FjdGlvbiBwcm94eSBoYXMgbm8gcm9vdCBzYXZlcG9pbnRcIilcbiAgICAgIGF3YWl0IHRoaXMuc2hhcmVkVHJhbnNhY3Rpb25DbGllbnQuY2FsbChcInJvb3RUcmFuc2FjdGlvblJvbGxiYWNrXCIsIFt0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludF0pXG4gICAgICB0aGlzLnNoYXJlZFRyYW5zYWN0aW9uUm9vdFNhdmVQb2ludCA9IHVuZGVmaW5lZFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZXMgYSBsb2NhbCBTUUwgdmFsdWUuXG4gICAgICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gdmFsdWUgLSBTUUwgdmFsdWUuXG4gICAgICogQHJldHVybnMge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSAtIEVzY2FwZWQgdmFsdWUuXG4gICAgICovXG4gICAgZXNjYXBlKHZhbHVlKSB7XG4gICAgICBpZiAodGhpcy5nZXRUeXBlKCkgIT09IFwicGdzcWxcIikgcmV0dXJuIHN1cGVyLmVzY2FwZSh2YWx1ZSlcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpIHJldHVybiB2YWx1ZVxuICAgICAgY29uc3QgZXNjYXBlZCA9IHBnRXNjYXBlTGl0ZXJhbCh0aGlzLl9jb252ZXJ0VmFsdWUodmFsdWUpKVxuICAgICAgcmV0dXJuIGVzY2FwZWQuc2xpY2UoMSwgLTEpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVvdGVzIGEgbG9jYWwgU1FMIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHZhbHVlIC0gU1FMIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmcgfCBudW1iZXJ9IC0gUXVvdGVkIHZhbHVlLlxuICAgICAqL1xuICAgIHF1b3RlKHZhbHVlKSB7XG4gICAgICBpZiAodGhpcy5nZXRUeXBlKCkgIT09IFwicGdzcWxcIikgcmV0dXJuIHN1cGVyLnF1b3RlKHZhbHVlKVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHZhbHVlXG4gICAgICByZXR1cm4gcGdFc2NhcGVMaXRlcmFsKHRoaXMuX2NvbnZlcnRWYWx1ZSh2YWx1ZSkpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RyZWFtcyBicm9rZXJlZCByb3dzIHRocm91Z2ggdGhlIGRyaXZlcidzIGJ1ZmZlcmVkIGZhbGxiYWNrLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzcWwgLSBTUUwgc3RhdGVtZW50LlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLlF1ZXJ5T3B0aW9uc30gW29wdGlvbnNdIC0gUXVlcnkgb3B0aW9ucy5cbiAgICAgKiBAeWllbGRzIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IC0gUmVzdWx0IHJvd3MuXG4gICAgICovXG4gICAgYXN5bmMgKnF1ZXJ5U3RyZWFtKHNxbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICBjb25zdCByb3dzID0gYXdhaXQgdGhpcy5xdWVyeShzcWwsIG9wdGlvbnMpXG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB5aWVsZCByb3dcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBLZWVwcyBzdHJ1Y3R1cmUgU1FMIG9uIG5vcm1hbCBicm9rZXJlZCBzdGF0ZW1lbnRzLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSAtIEFsd2F5cyBmYWxzZS5cbiAgICAgKi9cbiAgICBhc3luYyBleGVjU3RydWN0dXJlU2NyaXB0KCkgeyByZXR1cm4gZmFsc2UgfVxuICB9XG5cbiAgcmV0dXJuIG5ldyBTaGFyZWRUcmFuc2FjdGlvblByb3h5RHJpdmVyKClcbn1cbiJdfQ==
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import SharedTransactionBroker from "./shared-transaction-broker.js";
|
|
2
|
+
export type Enrollment = {
|
|
3
|
+
connection: import("../database/drivers/base.js").default;
|
|
4
|
+
databaseIdentifier: string;
|
|
5
|
+
release: () => Promise<void>;
|
|
6
|
+
reuseKey: string;
|
|
7
|
+
};
|
|
8
|
+
/** @typedef {{connection: import("../database/drivers/base.js").default, databaseIdentifier: string, release: () => Promise<void>, reuseKey: string}} Enrollment */
|
|
9
|
+
/**
|
|
10
|
+
* Backend-owned, capability-scoped transaction set for long-lived test services.
|
|
11
|
+
* Join coordinates are intentionally obtainable only as a live control message.
|
|
12
|
+
*/
|
|
13
|
+
export default class TestTransactionSession {
|
|
14
|
+
configuration: import("../configuration.js").default | undefined;
|
|
15
|
+
/** @type {SharedTransactionBroker | undefined} */
|
|
16
|
+
broker: SharedTransactionBroker | undefined;
|
|
17
|
+
/** @type {Map<string, Enrollment>} */
|
|
18
|
+
enrollments: Map<string, Enrollment>;
|
|
19
|
+
/** @type {Map<string, {pool: import("../database/pool/base.js").default, registration: import("../database/pool/base.js").TestSharedConnectionRegistration}>} */
|
|
20
|
+
sharedConnectionRegistrations: Map<string, {
|
|
21
|
+
pool: import("../database/pool/base.js").default;
|
|
22
|
+
registration: import("../database/pool/base.js").TestSharedConnectionRegistration;
|
|
23
|
+
}>;
|
|
24
|
+
/** @type {Promise<void> | undefined} */
|
|
25
|
+
cleanupPromise: Promise<void> | undefined;
|
|
26
|
+
/** @type {Promise<void> | undefined} */
|
|
27
|
+
rollbackPromise: Promise<void> | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an unstarted transaction session.
|
|
30
|
+
* @param {import("../configuration.js").default} [configuration] - Backend configuration owning enrolled pools.
|
|
31
|
+
*/
|
|
32
|
+
constructor(configuration?: import("../configuration.js").default);
|
|
33
|
+
/**
|
|
34
|
+
* Begins a test transaction session.
|
|
35
|
+
* @param {{configuration?: import("../configuration.js").default}} [args] - Backend owner.
|
|
36
|
+
* @returns {Promise<TestTransactionSession>} - Begun session.
|
|
37
|
+
*/
|
|
38
|
+
static begin({ configuration }?: {
|
|
39
|
+
configuration?: import("../configuration.js").default;
|
|
40
|
+
}): Promise<TestTransactionSession>;
|
|
41
|
+
/**
|
|
42
|
+
* Joins one request/job callback from a live backend control message.
|
|
43
|
+
* @template T
|
|
44
|
+
* @param {{address: string, capability: string}} message - Ephemeral coordinates received over live IPC.
|
|
45
|
+
* @param {() => T} callback - Backend request or worker work.
|
|
46
|
+
* @returns {T} - Callback result.
|
|
47
|
+
*/
|
|
48
|
+
static join<T>(message: {
|
|
49
|
+
address: string;
|
|
50
|
+
capability: string;
|
|
51
|
+
}, callback: () => T): T;
|
|
52
|
+
/**
|
|
53
|
+
* Lazily adds an exact physical connection to the common rollback set.
|
|
54
|
+
* @param {Enrollment} enrollment - Checked-out physical connection and owner release hook.
|
|
55
|
+
*/
|
|
56
|
+
enroll(enrollment: Enrollment): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Lazily checks out and enrolls the physical database selected by a tenant descriptor.
|
|
59
|
+
* @param {{databaseIdentifier: string, tenant?: object}} args - Logical and tenant identity.
|
|
60
|
+
*/
|
|
61
|
+
enrollDatabase({ databaseIdentifier, tenant }: {
|
|
62
|
+
databaseIdentifier: string;
|
|
63
|
+
tenant?: object;
|
|
64
|
+
}): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Makes in-process request/Scoundrel checkouts resolve by current physical identity.
|
|
67
|
+
* @param {string} databaseIdentifier - Logical database identifier.
|
|
68
|
+
* @param {import("../database/pool/base.js").default} pool - Owning pool.
|
|
69
|
+
*/
|
|
70
|
+
installSharedConnectionProvider(databaseIdentifier: string, pool: import("../database/pool/base.js").default): void;
|
|
71
|
+
/**
|
|
72
|
+
* Returns ephemeral coordinates for one live IPC/control message.
|
|
73
|
+
* @returns {{address: string, capability: string}} - Non-durable join coordinates.
|
|
74
|
+
*/
|
|
75
|
+
joinMessage(): {
|
|
76
|
+
address: string;
|
|
77
|
+
capability: string;
|
|
78
|
+
};
|
|
79
|
+
/** Stops admission to the capability. */
|
|
80
|
+
revoke(): void;
|
|
81
|
+
/** Drains work accepted before revocation. */
|
|
82
|
+
drain(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Rolls back and releases the complete enrolled set after admission stops.
|
|
85
|
+
* @returns {Promise<void>} - Resolves after rollback and release.
|
|
86
|
+
*/
|
|
87
|
+
rollback(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Performs rollback and release once.
|
|
90
|
+
* @returns {Promise<void>} - Resolves after actual rollback and release.
|
|
91
|
+
*/
|
|
92
|
+
rollbackActual(): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Revokes, drains, rolls back, and releases every enrolled physical connection exactly once.
|
|
95
|
+
* @returns {Promise<void>} - Resolves after idempotent cleanup.
|
|
96
|
+
*/
|
|
97
|
+
cleanup(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Performs idempotent cleanup once.
|
|
100
|
+
* @returns {Promise<void>} - Resolves after actual cleanup.
|
|
101
|
+
*/
|
|
102
|
+
cleanupActual(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Returns capability-free session diagnostics.
|
|
105
|
+
* @returns {{accepting: boolean, enrollmentCount: number}} - Capability-free diagnostics.
|
|
106
|
+
*/
|
|
107
|
+
debugSnapshot(): {
|
|
108
|
+
accepting: boolean;
|
|
109
|
+
enrollmentCount: number;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Returns the begun broker.
|
|
113
|
+
* @returns {SharedTransactionBroker} - Begun broker.
|
|
114
|
+
*/
|
|
115
|
+
requiredBroker(): SharedTransactionBroker;
|
|
116
|
+
/**
|
|
117
|
+
* Rolls back and releases one owned physical connection.
|
|
118
|
+
* @param {Enrollment} enrollment - Owned physical connection.
|
|
119
|
+
* @returns {Promise<void>} - Resolves after rollback and release.
|
|
120
|
+
*/
|
|
121
|
+
rollbackAndRelease(enrollment: Enrollment): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Normalizes a thrown cleanup value.
|
|
124
|
+
* @param {unknown} error - Opaque thrown cleanup value narrowed at this boundary.
|
|
125
|
+
* @returns {Error} - Error instance.
|
|
126
|
+
*/
|
|
127
|
+
normalizeError(error: unknown): Error;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=test-transaction-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-transaction-session.d.ts","sourceRoot":"","sources":["../../../src/testing/test-transaction-session.js"],"names":[],"mappings":"AAEA,OAAO,uBAAuB,MAAM,gCAAgC,CAAA;AAGhE,YAAmJ,UAAU,GAAnJ;IAAC,UAAU,EAAE,OAAO,6BAA6B,EAAE,OAAO,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAAY;AAAjK,oKAAoK;AAEpK;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IAMlC,aAAa;IAClB,kDAAkD;IAC7C,MAAM,EADA,uBAAuB,GAAG,SAAS;IAE9C,sCAAsC;IACjC,WAAW,EADL,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;IAElC,iKAAiK;IAC5J,6BAA6B,EADvB,GAAG,CAAC,MAAM,EAAE;QAAC,IAAI,EAAE,OAAO,0BAA0B,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,OAAO,0BAA0B,EAAE,gCAAgC,CAAA;KAAC,CAAC;IAE7J,wCAAwC;IACnC,cAAc,EADR,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS;IAEpC,wCAAwC;IACnC,eAAe,EADT,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS;IAdtC;;;OAGG;IACH,YAAY,aAAa,AAFtB,CACF,EADU,OAAO,qBAAqB,EAAE,OAEhB,EAYxB;IAED;;;;OAIG;IACH,OAAa,KAAK,CAAC,EAAC,aAAa,EAAC,AAH/B,CACA,EADQ;QAAC,aAAa,CAAC,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAA;KAG1B,GAF1B,OAAO,CAAC,sBAAsB,CAAC,CAM3C;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CALE,CAAC,EAKF,OAAO,EAJR;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAI5B,EAAE,QAAQ,EAHlB,MAAM,CAGY,GAFhB,CAAC,CAIb;IAED;;;OAGG;IACG,MAAM,CAAC,UAAU,EAFZ,UAEY,iBAkCtB;IAED;;;OAGG;IACG,cAAc,CAAC,EAAC,kBAAkB,EAAE,MAAM,EAAC,EAFtC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAEN,iBAiBhD;IAED;;;;OAIG;IACH,+BAA+B,CAAC,kBAAkB,EAHvC,MAGuC,EAAE,IAAI,EAF7C,OAAO,0BAA0B,EAAE,OAEU,QAevD;IAED;;;OAGG;IACH,WAAW,IAFE;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAMjD;IAED,yCAAyC;IACzC,MAAM,SAAqC;IAE3C,8CAA8C;IACxC,KAAK,kBAA0C;IAErD;;;OAGG;IACG,QAAQ,IAFD,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACG,cAAc,IAFP,OAAO,CAAC,IAAI,CAAC,CAiBzB;IAED;;;OAGG;IACG,OAAO,IAFA,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACG,aAAa,IAFN,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,aAAa,IAFA;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAC,CAIzD;IAED;;;OAGG;IACH,cAAc,IAFD,uBAAuB,CAKnC;IAED;;;;OAIG;IACG,kBAAkB,CAAC,UAAU,EAHxB,UAGwB,GAFtB,OAAO,CAAC,IAAI,CAAC,CAQzB;IAED;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAHT,OAGS,GAFP,KAAK,CAEwE;CAC3F"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import SharedTransactionBroker from "./shared-transaction-broker.js";
|
|
3
|
+
import { runWithSharedTransactionBrokerConfig, sharedTransactionBrokerContextMatches } from "./shared-transaction-proxy-driver.js";
|
|
4
|
+
/** @typedef {{connection: import("../database/drivers/base.js").default, databaseIdentifier: string, release: () => Promise<void>, reuseKey: string}} Enrollment */
|
|
5
|
+
/**
|
|
6
|
+
* Backend-owned, capability-scoped transaction set for long-lived test services.
|
|
7
|
+
* Join coordinates are intentionally obtainable only as a live control message.
|
|
8
|
+
*/
|
|
9
|
+
export default class TestTransactionSession {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an unstarted transaction session.
|
|
12
|
+
* @param {import("../configuration.js").default} [configuration] - Backend configuration owning enrolled pools.
|
|
13
|
+
*/
|
|
14
|
+
constructor(configuration) {
|
|
15
|
+
this.configuration = configuration;
|
|
16
|
+
/** @type {SharedTransactionBroker | undefined} */
|
|
17
|
+
this.broker = undefined;
|
|
18
|
+
/** @type {Map<string, Enrollment>} */
|
|
19
|
+
this.enrollments = new Map();
|
|
20
|
+
/** @type {Map<string, {pool: import("../database/pool/base.js").default, registration: import("../database/pool/base.js").TestSharedConnectionRegistration}>} */
|
|
21
|
+
this.sharedConnectionRegistrations = new Map();
|
|
22
|
+
/** @type {Promise<void> | undefined} */
|
|
23
|
+
this.cleanupPromise = undefined;
|
|
24
|
+
/** @type {Promise<void> | undefined} */
|
|
25
|
+
this.rollbackPromise = undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Begins a test transaction session.
|
|
29
|
+
* @param {{configuration?: import("../configuration.js").default}} [args] - Backend owner.
|
|
30
|
+
* @returns {Promise<TestTransactionSession>} - Begun session.
|
|
31
|
+
*/
|
|
32
|
+
static async begin({ configuration } = {}) {
|
|
33
|
+
const session = new TestTransactionSession(configuration);
|
|
34
|
+
session.broker = await SharedTransactionBroker.start({ connections: {} });
|
|
35
|
+
return session;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Joins one request/job callback from a live backend control message.
|
|
39
|
+
* @template T
|
|
40
|
+
* @param {{address: string, capability: string}} message - Ephemeral coordinates received over live IPC.
|
|
41
|
+
* @param {() => T} callback - Backend request or worker work.
|
|
42
|
+
* @returns {T} - Callback result.
|
|
43
|
+
*/
|
|
44
|
+
static join(message, callback) {
|
|
45
|
+
return runWithSharedTransactionBrokerConfig({ ...message, allowDynamicIdentities: true, databaseIdentifiers: [], expected: true }, callback);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Lazily adds an exact physical connection to the common rollback set.
|
|
49
|
+
* @param {Enrollment} enrollment - Checked-out physical connection and owner release hook.
|
|
50
|
+
*/
|
|
51
|
+
async enroll(enrollment) {
|
|
52
|
+
const broker = this.requiredBroker();
|
|
53
|
+
const identity = `${enrollment.databaseIdentifier}\0${enrollment.reuseKey}`;
|
|
54
|
+
const existing = this.enrollments.get(identity);
|
|
55
|
+
if (existing) {
|
|
56
|
+
if (existing.connection !== enrollment.connection)
|
|
57
|
+
await enrollment.release();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
await enrollment.connection.startTransaction();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
/** @type {Error | undefined} */
|
|
65
|
+
let releaseFailure;
|
|
66
|
+
try {
|
|
67
|
+
await enrollment.release();
|
|
68
|
+
}
|
|
69
|
+
catch (releaseError) {
|
|
70
|
+
releaseFailure = this.normalizeError(releaseError);
|
|
71
|
+
}
|
|
72
|
+
if (releaseFailure) {
|
|
73
|
+
throw new AggregateError([this.normalizeError(error), releaseFailure], "Test transaction enrollment start and release failed", { cause: error });
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
broker.enrollConnection(enrollment);
|
|
79
|
+
this.enrollments.set(identity, enrollment);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
await this.rollbackAndRelease(enrollment);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Lazily checks out and enrolls the physical database selected by a tenant descriptor.
|
|
88
|
+
* @param {{databaseIdentifier: string, tenant?: object}} args - Logical and tenant identity.
|
|
89
|
+
*/
|
|
90
|
+
async enrollDatabase({ databaseIdentifier, tenant }) {
|
|
91
|
+
if (!this.configuration)
|
|
92
|
+
throw new Error("Test transaction session requires a configuration to enroll a database");
|
|
93
|
+
const pool = this.configuration.getDatabasePool(databaseIdentifier);
|
|
94
|
+
const databaseConfiguration = this.configuration.resolveDatabaseConfiguration(databaseIdentifier, tenant);
|
|
95
|
+
const reuseKey = pool.getConfigurationReuseKey(databaseConfiguration);
|
|
96
|
+
const identity = `${databaseIdentifier}\0${reuseKey}`;
|
|
97
|
+
if (this.enrollments.has(identity))
|
|
98
|
+
return;
|
|
99
|
+
const connection = await this.configuration.runWithTenant(tenant, async () => {
|
|
100
|
+
return await pool.checkout({ name: "Test transaction session" });
|
|
101
|
+
});
|
|
102
|
+
await this.enroll({
|
|
103
|
+
connection,
|
|
104
|
+
databaseIdentifier,
|
|
105
|
+
release: async () => { await pool.checkin(connection); },
|
|
106
|
+
reuseKey
|
|
107
|
+
});
|
|
108
|
+
this.installSharedConnectionProvider(databaseIdentifier, pool);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Makes in-process request/Scoundrel checkouts resolve by current physical identity.
|
|
112
|
+
* @param {string} databaseIdentifier - Logical database identifier.
|
|
113
|
+
* @param {import("../database/pool/base.js").default} pool - Owning pool.
|
|
114
|
+
*/
|
|
115
|
+
installSharedConnectionProvider(databaseIdentifier, pool) {
|
|
116
|
+
if (this.sharedConnectionRegistrations.has(databaseIdentifier))
|
|
117
|
+
return;
|
|
118
|
+
const broker = this.requiredBroker();
|
|
119
|
+
const sessionIdentity = { address: broker.address(), capability: broker.capability() };
|
|
120
|
+
const registration = pool.registerTestSharedConnectionProvider({
|
|
121
|
+
matches: () => sharedTransactionBrokerContextMatches(sessionIdentity),
|
|
122
|
+
provider: () => {
|
|
123
|
+
if (!broker.accepting)
|
|
124
|
+
throw new Error("Test transaction session capability has been revoked");
|
|
125
|
+
const reuseKey = pool.getConfigurationReuseKey();
|
|
126
|
+
const connection = this.enrollments.get(`${databaseIdentifier}\0${reuseKey}`)?.connection;
|
|
127
|
+
if (!connection)
|
|
128
|
+
throw new Error(`Test transaction physical identity is not enrolled: ${databaseIdentifier}`);
|
|
129
|
+
return connection;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
if (registration)
|
|
133
|
+
this.sharedConnectionRegistrations.set(databaseIdentifier, { pool, registration });
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns ephemeral coordinates for one live IPC/control message.
|
|
137
|
+
* @returns {{address: string, capability: string}} - Non-durable join coordinates.
|
|
138
|
+
*/
|
|
139
|
+
joinMessage() {
|
|
140
|
+
const broker = this.requiredBroker();
|
|
141
|
+
if (!broker.accepting)
|
|
142
|
+
throw new Error("Test transaction session capability has been revoked");
|
|
143
|
+
return { address: broker.address(), capability: broker.capability() };
|
|
144
|
+
}
|
|
145
|
+
/** Stops admission to the capability. */
|
|
146
|
+
revoke() { this.requiredBroker().revoke(); }
|
|
147
|
+
/** Drains work accepted before revocation. */
|
|
148
|
+
async drain() { await this.requiredBroker().drain(); }
|
|
149
|
+
/**
|
|
150
|
+
* Rolls back and releases the complete enrolled set after admission stops.
|
|
151
|
+
* @returns {Promise<void>} - Resolves after rollback and release.
|
|
152
|
+
*/
|
|
153
|
+
async rollback() {
|
|
154
|
+
if (this.rollbackPromise)
|
|
155
|
+
return await this.rollbackPromise;
|
|
156
|
+
this.rollbackPromise = this.rollbackActual();
|
|
157
|
+
return await this.rollbackPromise;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Performs rollback and release once.
|
|
161
|
+
* @returns {Promise<void>} - Resolves after actual rollback and release.
|
|
162
|
+
*/
|
|
163
|
+
async rollbackActual() {
|
|
164
|
+
const broker = this.requiredBroker();
|
|
165
|
+
if (broker.accepting)
|
|
166
|
+
throw new Error("Test transaction session must be revoked before rollback");
|
|
167
|
+
/** @type {Array<Error>} */
|
|
168
|
+
const errors = [];
|
|
169
|
+
try {
|
|
170
|
+
await broker.close();
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
errors.push(this.normalizeError(error));
|
|
174
|
+
}
|
|
175
|
+
for (const { pool, registration } of this.sharedConnectionRegistrations.values()) {
|
|
176
|
+
pool.clearTestSharedConnection(registration);
|
|
177
|
+
}
|
|
178
|
+
this.sharedConnectionRegistrations.clear();
|
|
179
|
+
for (const enrollment of this.enrollments.values()) {
|
|
180
|
+
try {
|
|
181
|
+
await this.rollbackAndRelease(enrollment);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
errors.push(this.normalizeError(error));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
this.enrollments.clear();
|
|
188
|
+
if (errors.length > 0)
|
|
189
|
+
throw new AggregateError(errors, "Test transaction session rollback failed");
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Revokes, drains, rolls back, and releases every enrolled physical connection exactly once.
|
|
193
|
+
* @returns {Promise<void>} - Resolves after idempotent cleanup.
|
|
194
|
+
*/
|
|
195
|
+
async cleanup() {
|
|
196
|
+
if (this.cleanupPromise)
|
|
197
|
+
return await this.cleanupPromise;
|
|
198
|
+
this.cleanupPromise = this.cleanupActual();
|
|
199
|
+
return await this.cleanupPromise;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Performs idempotent cleanup once.
|
|
203
|
+
* @returns {Promise<void>} - Resolves after actual cleanup.
|
|
204
|
+
*/
|
|
205
|
+
async cleanupActual() {
|
|
206
|
+
this.revoke();
|
|
207
|
+
await this.rollback();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Returns capability-free session diagnostics.
|
|
211
|
+
* @returns {{accepting: boolean, enrollmentCount: number}} - Capability-free diagnostics.
|
|
212
|
+
*/
|
|
213
|
+
debugSnapshot() {
|
|
214
|
+
return { accepting: this.broker?.accepting === true, enrollmentCount: this.enrollments.size };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Returns the begun broker.
|
|
218
|
+
* @returns {SharedTransactionBroker} - Begun broker.
|
|
219
|
+
*/
|
|
220
|
+
requiredBroker() {
|
|
221
|
+
if (!this.broker)
|
|
222
|
+
throw new Error("Test transaction session has not begun");
|
|
223
|
+
return this.broker;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Rolls back and releases one owned physical connection.
|
|
227
|
+
* @param {Enrollment} enrollment - Owned physical connection.
|
|
228
|
+
* @returns {Promise<void>} - Resolves after rollback and release.
|
|
229
|
+
*/
|
|
230
|
+
async rollbackAndRelease(enrollment) {
|
|
231
|
+
/** @type {Array<Error>} */
|
|
232
|
+
const errors = [];
|
|
233
|
+
try {
|
|
234
|
+
await enrollment.connection.rollbackTransaction();
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
errors.push(this.normalizeError(error));
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
await enrollment.release();
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
errors.push(this.normalizeError(error));
|
|
244
|
+
}
|
|
245
|
+
if (errors.length > 0)
|
|
246
|
+
throw new AggregateError(errors, "Test transaction enrollment cleanup failed");
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Normalizes a thrown cleanup value.
|
|
250
|
+
* @param {unknown} error - Opaque thrown cleanup value narrowed at this boundary.
|
|
251
|
+
* @returns {Error} - Error instance.
|
|
252
|
+
*/
|
|
253
|
+
normalizeError(error) { return error instanceof Error ? error : new Error(String(error)); }
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC10cmFuc2FjdGlvbi1zZXNzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Rlc3RpbmcvdGVzdC10cmFuc2FjdGlvbi1zZXNzaW9uLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLHVCQUF1QixNQUFNLGdDQUFnQyxDQUFBO0FBQ3BFLE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxxQ0FBcUMsRUFBRSxNQUFNLHNDQUFzQyxDQUFBO0FBRWxJLG9LQUFvSztBQUVwSzs7O0dBR0c7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLHNCQUFzQjtJQUN6Qzs7O09BR0c7SUFDSCxZQUFZLGFBQWE7UUFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7UUFDbEMsa0RBQWtEO1FBQ2xELElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFBO1FBQ3ZCLHNDQUFzQztRQUN0QyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7UUFDNUIsaUtBQWlLO1FBQ2pLLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQzlDLHdDQUF3QztRQUN4QyxJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtRQUMvQix3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUE7SUFDbEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFDLGFBQWEsRUFBQyxHQUFHLEVBQUU7UUFDckMsTUFBTSxPQUFPLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUN6RCxPQUFPLENBQUMsTUFBTSxHQUFHLE1BQU0sdUJBQXVCLENBQUMsS0FBSyxDQUFDLEVBQUMsV0FBVyxFQUFFLEVBQUUsRUFBQyxDQUFDLENBQUE7UUFDdkUsT0FBTyxPQUFPLENBQUE7SUFDaEIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVE7UUFDM0IsT0FBTyxvQ0FBb0MsQ0FBQyxFQUFDLEdBQUcsT0FBTyxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBQyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBQzVJLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVU7UUFDckIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFBO1FBQ3BDLE1BQU0sUUFBUSxHQUFHLEdBQUcsVUFBVSxDQUFDLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUMzRSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUMvQyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsSUFBSSxRQUFRLENBQUMsVUFBVSxLQUFLLFVBQVUsQ0FBQyxVQUFVO2dCQUFFLE1BQU0sVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFBO1lBQzdFLE9BQU07UUFDUixDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLENBQUMsVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUE7UUFDaEQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixnQ0FBZ0M7WUFDaEMsSUFBSSxjQUFjLENBQUE7WUFDbEIsSUFBSSxDQUFDO2dCQUNILE1BQU0sVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFBO1lBQzVCLENBQUM7WUFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO2dCQUN0QixjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUNwRCxDQUFDO1lBQ0QsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDbkIsTUFBTSxJQUFJLGNBQWMsQ0FDdEIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLGNBQWMsQ0FBQyxFQUM1QyxzREFBc0QsRUFDdEQsRUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQ2YsQ0FBQTtZQUNILENBQUM7WUFDRCxNQUFNLEtBQUssQ0FBQTtRQUNiLENBQUM7UUFDRCxJQUFJLENBQUM7WUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUE7WUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFBO1FBQzVDLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLENBQUE7WUFDekMsTUFBTSxLQUFLLENBQUE7UUFDYixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBQyxrQkFBa0IsRUFBRSxNQUFNLEVBQUM7UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx3RUFBd0UsQ0FBQyxDQUFBO1FBQ2xILE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDLENBQUE7UUFDbkUsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLDRCQUE0QixDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3pHLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBO1FBQ3JFLE1BQU0sUUFBUSxHQUFHLEdBQUcsa0JBQWtCLEtBQUssUUFBUSxFQUFFLENBQUE7UUFDckQsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7WUFBRSxPQUFNO1FBQzFDLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzNFLE9BQU8sTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUMsSUFBSSxFQUFFLDBCQUEwQixFQUFDLENBQUMsQ0FBQTtRQUNoRSxDQUFDLENBQUMsQ0FBQTtRQUNGLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUNoQixVQUFVO1lBQ1Ysa0JBQWtCO1lBQ2xCLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQSxDQUFDLENBQUM7WUFDdkQsUUFBUTtTQUNULENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUNoRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILCtCQUErQixDQUFDLGtCQUFrQixFQUFFLElBQUk7UUFDdEQsSUFBSSxJQUFJLENBQUMsNkJBQTZCLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDO1lBQUUsT0FBTTtRQUN0RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUE7UUFDcEMsTUFBTSxlQUFlLEdBQUcsRUFBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUMsQ0FBQTtRQUNwRixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsb0NBQW9DLENBQUM7WUFDN0QsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLHFDQUFxQyxDQUFDLGVBQWUsQ0FBQztZQUNyRSxRQUFRLEVBQUUsR0FBRyxFQUFFO2dCQUNiLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUztvQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUE7Z0JBQzlGLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFBO2dCQUNoRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLGtCQUFrQixLQUFLLFFBQVEsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFBO2dCQUN6RixJQUFJLENBQUMsVUFBVTtvQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxrQkFBa0IsRUFBRSxDQUFDLENBQUE7Z0JBQzdHLE9BQU8sVUFBVSxDQUFBO1lBQ25CLENBQUM7U0FDRixDQUFDLENBQUE7UUFDRixJQUFJLFlBQVk7WUFBRSxJQUFJLENBQUMsNkJBQTZCLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLEVBQUMsSUFBSSxFQUFFLFlBQVksRUFBQyxDQUFDLENBQUE7SUFDcEcsQ0FBQztJQUVEOzs7T0FHRztJQUNILFdBQVc7UUFDVCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUE7UUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzREFBc0QsQ0FBQyxDQUFBO1FBQzlGLE9BQU8sRUFBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUMsQ0FBQTtJQUNyRSxDQUFDO0lBRUQseUNBQXlDO0lBQ3pDLE1BQU0sS0FBSyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUEsQ0FBQyxDQUFDO0lBRTNDLDhDQUE4QztJQUM5QyxLQUFLLENBQUMsS0FBSyxLQUFLLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBLENBQUMsQ0FBQztJQUVyRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsUUFBUTtRQUNaLElBQUksSUFBSSxDQUFDLGVBQWU7WUFBRSxPQUFPLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQTtRQUMzRCxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQTtRQUM1QyxPQUFPLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQTtJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGNBQWM7UUFDbEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFBO1FBQ3BDLElBQUksTUFBTSxDQUFDLFNBQVM7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxDQUFDLENBQUE7UUFDakcsMkJBQTJCO1FBQzNCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQTtRQUNqQixJQUFJLENBQUM7WUFBQyxNQUFNLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUFDLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7UUFBQyxDQUFDO1FBQ3RGLEtBQUssTUFBTSxFQUFDLElBQUksRUFBRSxZQUFZLEVBQUMsSUFBSSxJQUFJLENBQUMsNkJBQTZCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUMvRSxJQUFJLENBQUMseUJBQXlCLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDOUMsQ0FBQztRQUNELElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUMxQyxLQUFLLE1BQU0sVUFBVSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNuRCxJQUFJLENBQUM7Z0JBQUMsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLENBQUE7WUFBQyxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtZQUFDLENBQUM7UUFDN0csQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDeEIsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7WUFBRSxNQUFNLElBQUksY0FBYyxDQUFDLE1BQU0sRUFBRSwwQ0FBMEMsQ0FBQyxDQUFBO0lBQ3JHLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsT0FBTztRQUNYLElBQUksSUFBSSxDQUFDLGNBQWM7WUFBRSxPQUFPLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQTtRQUN6RCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUMxQyxPQUFPLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQTtJQUNsQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGFBQWE7UUFDakIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFBO1FBQ2IsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUE7SUFDdkIsQ0FBQztJQUVEOzs7T0FHRztJQUNILGFBQWE7UUFDWCxPQUFPLEVBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxLQUFLLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUMsQ0FBQTtJQUM3RixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQTtRQUMzRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUE7SUFDcEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsa0JBQWtCLENBQUMsVUFBVTtRQUNqQywyQkFBMkI7UUFDM0IsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFBO1FBQ2pCLElBQUksQ0FBQztZQUFDLE1BQU0sVUFBVSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO1FBQUMsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtRQUFDLENBQUM7UUFDbkgsSUFBSSxDQUFDO1lBQUMsTUFBTSxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUE7UUFBQyxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQUMsQ0FBQztRQUM1RixJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUFFLE1BQU0sSUFBSSxjQUFjLENBQUMsTUFBTSxFQUFFLDRDQUE0QyxDQUFDLENBQUE7SUFDdkcsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxjQUFjLENBQUMsS0FBSyxJQUFJLE9BQU8sS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQSxDQUFDLENBQUM7Q0FDM0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IFNoYXJlZFRyYW5zYWN0aW9uQnJva2VyIGZyb20gXCIuL3NoYXJlZC10cmFuc2FjdGlvbi1icm9rZXIuanNcIlxuaW1wb3J0IHsgcnVuV2l0aFNoYXJlZFRyYW5zYWN0aW9uQnJva2VyQ29uZmlnLCBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbnRleHRNYXRjaGVzIH0gZnJvbSBcIi4vc2hhcmVkLXRyYW5zYWN0aW9uLXByb3h5LWRyaXZlci5qc1wiXG5cbi8qKiBAdHlwZWRlZiB7e2Nvbm5lY3Rpb246IGltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0LCBkYXRhYmFzZUlkZW50aWZpZXI6IHN0cmluZywgcmVsZWFzZTogKCkgPT4gUHJvbWlzZTx2b2lkPiwgcmV1c2VLZXk6IHN0cmluZ319IEVucm9sbG1lbnQgKi9cblxuLyoqXG4gKiBCYWNrZW5kLW93bmVkLCBjYXBhYmlsaXR5LXNjb3BlZCB0cmFuc2FjdGlvbiBzZXQgZm9yIGxvbmctbGl2ZWQgdGVzdCBzZXJ2aWNlcy5cbiAqIEpvaW4gY29vcmRpbmF0ZXMgYXJlIGludGVudGlvbmFsbHkgb2J0YWluYWJsZSBvbmx5IGFzIGEgbGl2ZSBjb250cm9sIG1lc3NhZ2UuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRlc3RUcmFuc2FjdGlvblNlc3Npb24ge1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiB1bnN0YXJ0ZWQgdHJhbnNhY3Rpb24gc2Vzc2lvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IFtjb25maWd1cmF0aW9uXSAtIEJhY2tlbmQgY29uZmlndXJhdGlvbiBvd25pbmcgZW5yb2xsZWQgcG9vbHMuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uKSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIC8qKiBAdHlwZSB7U2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXIgfCB1bmRlZmluZWR9ICovXG4gICAgdGhpcy5icm9rZXIgPSB1bmRlZmluZWRcbiAgICAvKiogQHR5cGUge01hcDxzdHJpbmcsIEVucm9sbG1lbnQ+fSAqL1xuICAgIHRoaXMuZW5yb2xsbWVudHMgPSBuZXcgTWFwKClcbiAgICAvKiogQHR5cGUge01hcDxzdHJpbmcsIHtwb29sOiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9wb29sL2Jhc2UuanNcIikuZGVmYXVsdCwgcmVnaXN0cmF0aW9uOiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9wb29sL2Jhc2UuanNcIikuVGVzdFNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb259Pn0gKi9cbiAgICB0aGlzLnNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zID0gbmV3IE1hcCgpXG4gICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkfSAqL1xuICAgIHRoaXMuY2xlYW51cFByb21pc2UgPSB1bmRlZmluZWRcbiAgICAvKiogQHR5cGUge1Byb21pc2U8dm9pZD4gfCB1bmRlZmluZWR9ICovXG4gICAgdGhpcy5yb2xsYmFja1Byb21pc2UgPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBCZWdpbnMgYSB0ZXN0IHRyYW5zYWN0aW9uIHNlc3Npb24uXG4gICAqIEBwYXJhbSB7e2NvbmZpZ3VyYXRpb24/OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9fSBbYXJnc10gLSBCYWNrZW5kIG93bmVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUZXN0VHJhbnNhY3Rpb25TZXNzaW9uPn0gLSBCZWd1biBzZXNzaW9uLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGJlZ2luKHtjb25maWd1cmF0aW9ufSA9IHt9KSB7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IG5ldyBUZXN0VHJhbnNhY3Rpb25TZXNzaW9uKGNvbmZpZ3VyYXRpb24pXG4gICAgc2Vzc2lvbi5icm9rZXIgPSBhd2FpdCBTaGFyZWRUcmFuc2FjdGlvbkJyb2tlci5zdGFydCh7Y29ubmVjdGlvbnM6IHt9fSlcbiAgICByZXR1cm4gc2Vzc2lvblxuICB9XG5cbiAgLyoqXG4gICAqIEpvaW5zIG9uZSByZXF1ZXN0L2pvYiBjYWxsYmFjayBmcm9tIGEgbGl2ZSBiYWNrZW5kIGNvbnRyb2wgbWVzc2FnZS5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHt7YWRkcmVzczogc3RyaW5nLCBjYXBhYmlsaXR5OiBzdHJpbmd9fSBtZXNzYWdlIC0gRXBoZW1lcmFsIGNvb3JkaW5hdGVzIHJlY2VpdmVkIG92ZXIgbGl2ZSBJUEMuXG4gICAqIEBwYXJhbSB7KCkgPT4gVH0gY2FsbGJhY2sgLSBCYWNrZW5kIHJlcXVlc3Qgb3Igd29ya2VyIHdvcmsuXG4gICAqIEByZXR1cm5zIHtUfSAtIENhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIHN0YXRpYyBqb2luKG1lc3NhZ2UsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIHJ1bldpdGhTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyh7Li4ubWVzc2FnZSwgYWxsb3dEeW5hbWljSWRlbnRpdGllczogdHJ1ZSwgZGF0YWJhc2VJZGVudGlmaWVyczogW10sIGV4cGVjdGVkOiB0cnVlfSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogTGF6aWx5IGFkZHMgYW4gZXhhY3QgcGh5c2ljYWwgY29ubmVjdGlvbiB0byB0aGUgY29tbW9uIHJvbGxiYWNrIHNldC5cbiAgICogQHBhcmFtIHtFbnJvbGxtZW50fSBlbnJvbGxtZW50IC0gQ2hlY2tlZC1vdXQgcGh5c2ljYWwgY29ubmVjdGlvbiBhbmQgb3duZXIgcmVsZWFzZSBob29rLlxuICAgKi9cbiAgYXN5bmMgZW5yb2xsKGVucm9sbG1lbnQpIHtcbiAgICBjb25zdCBicm9rZXIgPSB0aGlzLnJlcXVpcmVkQnJva2VyKClcbiAgICBjb25zdCBpZGVudGl0eSA9IGAke2Vucm9sbG1lbnQuZGF0YWJhc2VJZGVudGlmaWVyfVxcMCR7ZW5yb2xsbWVudC5yZXVzZUtleX1gXG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmVucm9sbG1lbnRzLmdldChpZGVudGl0eSlcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIGlmIChleGlzdGluZy5jb25uZWN0aW9uICE9PSBlbnJvbGxtZW50LmNvbm5lY3Rpb24pIGF3YWl0IGVucm9sbG1lbnQucmVsZWFzZSgpXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGVucm9sbG1lbnQuY29ubmVjdGlvbi5zdGFydFRyYW5zYWN0aW9uKClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLyoqIEB0eXBlIHtFcnJvciB8IHVuZGVmaW5lZH0gKi9cbiAgICAgIGxldCByZWxlYXNlRmFpbHVyZVxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZW5yb2xsbWVudC5yZWxlYXNlKClcbiAgICAgIH0gY2F0Y2ggKHJlbGVhc2VFcnJvcikge1xuICAgICAgICByZWxlYXNlRmFpbHVyZSA9IHRoaXMubm9ybWFsaXplRXJyb3IocmVsZWFzZUVycm9yKVxuICAgICAgfVxuICAgICAgaWYgKHJlbGVhc2VGYWlsdXJlKSB7XG4gICAgICAgIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihcbiAgICAgICAgICBbdGhpcy5ub3JtYWxpemVFcnJvcihlcnJvciksIHJlbGVhc2VGYWlsdXJlXSxcbiAgICAgICAgICBcIlRlc3QgdHJhbnNhY3Rpb24gZW5yb2xsbWVudCBzdGFydCBhbmQgcmVsZWFzZSBmYWlsZWRcIixcbiAgICAgICAgICB7Y2F1c2U6IGVycm9yfVxuICAgICAgICApXG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cbiAgICB0cnkge1xuICAgICAgYnJva2VyLmVucm9sbENvbm5lY3Rpb24oZW5yb2xsbWVudClcbiAgICAgIHRoaXMuZW5yb2xsbWVudHMuc2V0KGlkZW50aXR5LCBlbnJvbGxtZW50KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLnJvbGxiYWNrQW5kUmVsZWFzZShlbnJvbGxtZW50KVxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGF6aWx5IGNoZWNrcyBvdXQgYW5kIGVucm9sbHMgdGhlIHBoeXNpY2FsIGRhdGFiYXNlIHNlbGVjdGVkIGJ5IGEgdGVuYW50IGRlc2NyaXB0b3IuXG4gICAqIEBwYXJhbSB7e2RhdGFiYXNlSWRlbnRpZmllcjogc3RyaW5nLCB0ZW5hbnQ/OiBvYmplY3R9fSBhcmdzIC0gTG9naWNhbCBhbmQgdGVuYW50IGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgZW5yb2xsRGF0YWJhc2Uoe2RhdGFiYXNlSWRlbnRpZmllciwgdGVuYW50fSkge1xuICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uKSB0aHJvdyBuZXcgRXJyb3IoXCJUZXN0IHRyYW5zYWN0aW9uIHNlc3Npb24gcmVxdWlyZXMgYSBjb25maWd1cmF0aW9uIHRvIGVucm9sbCBhIGRhdGFiYXNlXCIpXG4gICAgY29uc3QgcG9vbCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXREYXRhYmFzZVBvb2woZGF0YWJhc2VJZGVudGlmaWVyKVxuICAgIGNvbnN0IGRhdGFiYXNlQ29uZmlndXJhdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5yZXNvbHZlRGF0YWJhc2VDb25maWd1cmF0aW9uKGRhdGFiYXNlSWRlbnRpZmllciwgdGVuYW50KVxuICAgIGNvbnN0IHJldXNlS2V5ID0gcG9vbC5nZXRDb25maWd1cmF0aW9uUmV1c2VLZXkoZGF0YWJhc2VDb25maWd1cmF0aW9uKVxuICAgIGNvbnN0IGlkZW50aXR5ID0gYCR7ZGF0YWJhc2VJZGVudGlmaWVyfVxcMCR7cmV1c2VLZXl9YFxuICAgIGlmICh0aGlzLmVucm9sbG1lbnRzLmhhcyhpZGVudGl0eSkpIHJldHVyblxuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24ucnVuV2l0aFRlbmFudCh0ZW5hbnQsIGFzeW5jICgpID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCBwb29sLmNoZWNrb3V0KHtuYW1lOiBcIlRlc3QgdHJhbnNhY3Rpb24gc2Vzc2lvblwifSlcbiAgICB9KVxuICAgIGF3YWl0IHRoaXMuZW5yb2xsKHtcbiAgICAgIGNvbm5lY3Rpb24sXG4gICAgICBkYXRhYmFzZUlkZW50aWZpZXIsXG4gICAgICByZWxlYXNlOiBhc3luYyAoKSA9PiB7IGF3YWl0IHBvb2wuY2hlY2tpbihjb25uZWN0aW9uKSB9LFxuICAgICAgcmV1c2VLZXlcbiAgICB9KVxuICAgIHRoaXMuaW5zdGFsbFNoYXJlZENvbm5lY3Rpb25Qcm92aWRlcihkYXRhYmFzZUlkZW50aWZpZXIsIHBvb2wpXG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgaW4tcHJvY2VzcyByZXF1ZXN0L1Njb3VuZHJlbCBjaGVja291dHMgcmVzb2x2ZSBieSBjdXJyZW50IHBoeXNpY2FsIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZGF0YWJhc2VJZGVudGlmaWVyIC0gTG9naWNhbCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL3Bvb2wvYmFzZS5qc1wiKS5kZWZhdWx0fSBwb29sIC0gT3duaW5nIHBvb2wuXG4gICAqL1xuICBpbnN0YWxsU2hhcmVkQ29ubmVjdGlvblByb3ZpZGVyKGRhdGFiYXNlSWRlbnRpZmllciwgcG9vbCkge1xuICAgIGlmICh0aGlzLnNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zLmhhcyhkYXRhYmFzZUlkZW50aWZpZXIpKSByZXR1cm5cbiAgICBjb25zdCBicm9rZXIgPSB0aGlzLnJlcXVpcmVkQnJva2VyKClcbiAgICBjb25zdCBzZXNzaW9uSWRlbnRpdHkgPSB7YWRkcmVzczogYnJva2VyLmFkZHJlc3MoKSwgY2FwYWJpbGl0eTogYnJva2VyLmNhcGFiaWxpdHkoKX1cbiAgICBjb25zdCByZWdpc3RyYXRpb24gPSBwb29sLnJlZ2lzdGVyVGVzdFNoYXJlZENvbm5lY3Rpb25Qcm92aWRlcih7XG4gICAgICBtYXRjaGVzOiAoKSA9PiBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbnRleHRNYXRjaGVzKHNlc3Npb25JZGVudGl0eSksXG4gICAgICBwcm92aWRlcjogKCkgPT4ge1xuICAgICAgICBpZiAoIWJyb2tlci5hY2NlcHRpbmcpIHRocm93IG5ldyBFcnJvcihcIlRlc3QgdHJhbnNhY3Rpb24gc2Vzc2lvbiBjYXBhYmlsaXR5IGhhcyBiZWVuIHJldm9rZWRcIilcbiAgICAgICAgY29uc3QgcmV1c2VLZXkgPSBwb29sLmdldENvbmZpZ3VyYXRpb25SZXVzZUtleSgpXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLmVucm9sbG1lbnRzLmdldChgJHtkYXRhYmFzZUlkZW50aWZpZXJ9XFwwJHtyZXVzZUtleX1gKT8uY29ubmVjdGlvblxuICAgICAgICBpZiAoIWNvbm5lY3Rpb24pIHRocm93IG5ldyBFcnJvcihgVGVzdCB0cmFuc2FjdGlvbiBwaHlzaWNhbCBpZGVudGl0eSBpcyBub3QgZW5yb2xsZWQ6ICR7ZGF0YWJhc2VJZGVudGlmaWVyfWApXG4gICAgICAgIHJldHVybiBjb25uZWN0aW9uXG4gICAgICB9XG4gICAgfSlcbiAgICBpZiAocmVnaXN0cmF0aW9uKSB0aGlzLnNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zLnNldChkYXRhYmFzZUlkZW50aWZpZXIsIHtwb29sLCByZWdpc3RyYXRpb259KVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZXBoZW1lcmFsIGNvb3JkaW5hdGVzIGZvciBvbmUgbGl2ZSBJUEMvY29udHJvbCBtZXNzYWdlLlxuICAgKiBAcmV0dXJucyB7e2FkZHJlc3M6IHN0cmluZywgY2FwYWJpbGl0eTogc3RyaW5nfX0gLSBOb24tZHVyYWJsZSBqb2luIGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgam9pbk1lc3NhZ2UoKSB7XG4gICAgY29uc3QgYnJva2VyID0gdGhpcy5yZXF1aXJlZEJyb2tlcigpXG4gICAgaWYgKCFicm9rZXIuYWNjZXB0aW5nKSB0aHJvdyBuZXcgRXJyb3IoXCJUZXN0IHRyYW5zYWN0aW9uIHNlc3Npb24gY2FwYWJpbGl0eSBoYXMgYmVlbiByZXZva2VkXCIpXG4gICAgcmV0dXJuIHthZGRyZXNzOiBicm9rZXIuYWRkcmVzcygpLCBjYXBhYmlsaXR5OiBicm9rZXIuY2FwYWJpbGl0eSgpfVxuICB9XG5cbiAgLyoqIFN0b3BzIGFkbWlzc2lvbiB0byB0aGUgY2FwYWJpbGl0eS4gKi9cbiAgcmV2b2tlKCkgeyB0aGlzLnJlcXVpcmVkQnJva2VyKCkucmV2b2tlKCkgfVxuXG4gIC8qKiBEcmFpbnMgd29yayBhY2NlcHRlZCBiZWZvcmUgcmV2b2NhdGlvbi4gKi9cbiAgYXN5bmMgZHJhaW4oKSB7IGF3YWl0IHRoaXMucmVxdWlyZWRCcm9rZXIoKS5kcmFpbigpIH1cblxuICAvKipcbiAgICogUm9sbHMgYmFjayBhbmQgcmVsZWFzZXMgdGhlIGNvbXBsZXRlIGVucm9sbGVkIHNldCBhZnRlciBhZG1pc3Npb24gc3RvcHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIHJvbGxiYWNrIGFuZCByZWxlYXNlLlxuICAgKi9cbiAgYXN5bmMgcm9sbGJhY2soKSB7XG4gICAgaWYgKHRoaXMucm9sbGJhY2tQcm9taXNlKSByZXR1cm4gYXdhaXQgdGhpcy5yb2xsYmFja1Byb21pc2VcbiAgICB0aGlzLnJvbGxiYWNrUHJvbWlzZSA9IHRoaXMucm9sbGJhY2tBY3R1YWwoKVxuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGxiYWNrUHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIHJvbGxiYWNrIGFuZCByZWxlYXNlIG9uY2UuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGFjdHVhbCByb2xsYmFjayBhbmQgcmVsZWFzZS5cbiAgICovXG4gIGFzeW5jIHJvbGxiYWNrQWN0dWFsKCkge1xuICAgIGNvbnN0IGJyb2tlciA9IHRoaXMucmVxdWlyZWRCcm9rZXIoKVxuICAgIGlmIChicm9rZXIuYWNjZXB0aW5nKSB0aHJvdyBuZXcgRXJyb3IoXCJUZXN0IHRyYW5zYWN0aW9uIHNlc3Npb24gbXVzdCBiZSByZXZva2VkIGJlZm9yZSByb2xsYmFja1wiKVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8RXJyb3I+fSAqL1xuICAgIGNvbnN0IGVycm9ycyA9IFtdXG4gICAgdHJ5IHsgYXdhaXQgYnJva2VyLmNsb3NlKCkgfSBjYXRjaCAoZXJyb3IpIHsgZXJyb3JzLnB1c2godGhpcy5ub3JtYWxpemVFcnJvcihlcnJvcikpIH1cbiAgICBmb3IgKGNvbnN0IHtwb29sLCByZWdpc3RyYXRpb259IG9mIHRoaXMuc2hhcmVkQ29ubmVjdGlvblJlZ2lzdHJhdGlvbnMudmFsdWVzKCkpIHtcbiAgICAgIHBvb2wuY2xlYXJUZXN0U2hhcmVkQ29ubmVjdGlvbihyZWdpc3RyYXRpb24pXG4gICAgfVxuICAgIHRoaXMuc2hhcmVkQ29ubmVjdGlvblJlZ2lzdHJhdGlvbnMuY2xlYXIoKVxuICAgIGZvciAoY29uc3QgZW5yb2xsbWVudCBvZiB0aGlzLmVucm9sbG1lbnRzLnZhbHVlcygpKSB7XG4gICAgICB0cnkgeyBhd2FpdCB0aGlzLnJvbGxiYWNrQW5kUmVsZWFzZShlbnJvbGxtZW50KSB9IGNhdGNoIChlcnJvcikgeyBlcnJvcnMucHVzaCh0aGlzLm5vcm1hbGl6ZUVycm9yKGVycm9yKSkgfVxuICAgIH1cbiAgICB0aGlzLmVucm9sbG1lbnRzLmNsZWFyKClcbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihlcnJvcnMsIFwiVGVzdCB0cmFuc2FjdGlvbiBzZXNzaW9uIHJvbGxiYWNrIGZhaWxlZFwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldm9rZXMsIGRyYWlucywgcm9sbHMgYmFjaywgYW5kIHJlbGVhc2VzIGV2ZXJ5IGVucm9sbGVkIHBoeXNpY2FsIGNvbm5lY3Rpb24gZXhhY3RseSBvbmNlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciBpZGVtcG90ZW50IGNsZWFudXAuXG4gICAqL1xuICBhc3luYyBjbGVhbnVwKCkge1xuICAgIGlmICh0aGlzLmNsZWFudXBQcm9taXNlKSByZXR1cm4gYXdhaXQgdGhpcy5jbGVhbnVwUHJvbWlzZVxuICAgIHRoaXMuY2xlYW51cFByb21pc2UgPSB0aGlzLmNsZWFudXBBY3R1YWwoKVxuICAgIHJldHVybiBhd2FpdCB0aGlzLmNsZWFudXBQcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgaWRlbXBvdGVudCBjbGVhbnVwIG9uY2UuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGFjdHVhbCBjbGVhbnVwLlxuICAgKi9cbiAgYXN5bmMgY2xlYW51cEFjdHVhbCgpIHtcbiAgICB0aGlzLnJldm9rZSgpXG4gICAgYXdhaXQgdGhpcy5yb2xsYmFjaygpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBjYXBhYmlsaXR5LWZyZWUgc2Vzc2lvbiBkaWFnbm9zdGljcy5cbiAgICogQHJldHVybnMge3thY2NlcHRpbmc6IGJvb2xlYW4sIGVucm9sbG1lbnRDb3VudDogbnVtYmVyfX0gLSBDYXBhYmlsaXR5LWZyZWUgZGlhZ25vc3RpY3MuXG4gICAqL1xuICBkZWJ1Z1NuYXBzaG90KCkge1xuICAgIHJldHVybiB7YWNjZXB0aW5nOiB0aGlzLmJyb2tlcj8uYWNjZXB0aW5nID09PSB0cnVlLCBlbnJvbGxtZW50Q291bnQ6IHRoaXMuZW5yb2xsbWVudHMuc2l6ZX1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBiZWd1biBicm9rZXIuXG4gICAqIEByZXR1cm5zIHtTaGFyZWRUcmFuc2FjdGlvbkJyb2tlcn0gLSBCZWd1biBicm9rZXIuXG4gICAqL1xuICByZXF1aXJlZEJyb2tlcigpIHtcbiAgICBpZiAoIXRoaXMuYnJva2VyKSB0aHJvdyBuZXcgRXJyb3IoXCJUZXN0IHRyYW5zYWN0aW9uIHNlc3Npb24gaGFzIG5vdCBiZWd1blwiKVxuICAgIHJldHVybiB0aGlzLmJyb2tlclxuICB9XG5cbiAgLyoqXG4gICAqIFJvbGxzIGJhY2sgYW5kIHJlbGVhc2VzIG9uZSBvd25lZCBwaHlzaWNhbCBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge0Vucm9sbG1lbnR9IGVucm9sbG1lbnQgLSBPd25lZCBwaHlzaWNhbCBjb25uZWN0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciByb2xsYmFjayBhbmQgcmVsZWFzZS5cbiAgICovXG4gIGFzeW5jIHJvbGxiYWNrQW5kUmVsZWFzZShlbnJvbGxtZW50KSB7XG4gICAgLyoqIEB0eXBlIHtBcnJheTxFcnJvcj59ICovXG4gICAgY29uc3QgZXJyb3JzID0gW11cbiAgICB0cnkgeyBhd2FpdCBlbnJvbGxtZW50LmNvbm5lY3Rpb24ucm9sbGJhY2tUcmFuc2FjdGlvbigpIH0gY2F0Y2ggKGVycm9yKSB7IGVycm9ycy5wdXNoKHRoaXMubm9ybWFsaXplRXJyb3IoZXJyb3IpKSB9XG4gICAgdHJ5IHsgYXdhaXQgZW5yb2xsbWVudC5yZWxlYXNlKCkgfSBjYXRjaCAoZXJyb3IpIHsgZXJyb3JzLnB1c2godGhpcy5ub3JtYWxpemVFcnJvcihlcnJvcikpIH1cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihlcnJvcnMsIFwiVGVzdCB0cmFuc2FjdGlvbiBlbnJvbGxtZW50IGNsZWFudXAgZmFpbGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBhIHRocm93biBjbGVhbnVwIHZhbHVlLlxuICAgKiBAcGFyYW0ge3Vua25vd259IGVycm9yIC0gT3BhcXVlIHRocm93biBjbGVhbnVwIHZhbHVlIG5hcnJvd2VkIGF0IHRoaXMgYm91bmRhcnkuXG4gICAqIEByZXR1cm5zIHtFcnJvcn0gLSBFcnJvciBpbnN0YW5jZS5cbiAgICovXG4gIG5vcm1hbGl6ZUVycm9yKGVycm9yKSB7IHJldHVybiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSkgfVxufVxuIl19
|