@dbx-tools/postgres 0.9.32 → 0.9.36
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 +5 -3
- package/exports.ts +18 -0
- package/index.ts +2 -1
- package/lib/exports.d.ts +1 -1
- package/lib/exports.js +2 -2
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -2
- package/lib/src/advisory-lock.d.ts +0 -11
- package/lib/src/advisory-lock.js +4 -28
- package/lib/src/identity.d.ts +16 -0
- package/lib/src/identity.js +58 -0
- package/lib/src/persistence.d.ts +4 -0
- package/lib/src/persistence.js +5 -1
- package/lib/src/topic-bus.d.ts +0 -23
- package/lib/src/topic-bus.js +2 -61
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +42 -9
- package/src/advisory-lock.ts +3 -26
- package/src/identity.ts +73 -0
- package/src/persistence.ts +6 -0
- package/src/topic-bus.ts +1 -64
package/README.md
CHANGED
|
@@ -65,7 +65,8 @@ await withAdvisoryTransactionLock(pool, { schema: "my_feature", version: 1 }, as
|
|
|
65
65
|
});
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
`advisoryLockId(key)` exposes the same reduction
|
|
68
|
+
`identity.advisoryLockId(key)` exposes the same reduction as a JSON-safe decimal
|
|
69
|
+
string. A `bigint` key is
|
|
69
70
|
used directly (narrowed to 64 bits) rather than hashed, so a lock can interoperate
|
|
70
71
|
with another implementation that publishes its numeric lock id — `pgmq`'s
|
|
71
72
|
installer lock, for instance. Anything else is canonicalized with
|
|
@@ -282,7 +283,7 @@ order does not matter; a different spelling does. Read `bus.channelName` to see
|
|
|
282
283
|
what a set of parts resolved to, or to confirm two processes agree. Defaults to a
|
|
283
284
|
shared `dbx_tools_topic_bus` channel.
|
|
284
285
|
|
|
285
|
-
`
|
|
286
|
+
`identity.channelName(parts)` exposes the derivation without constructing a bus,
|
|
286
287
|
which is useful for configuration checks and cross-runtime contract tests.
|
|
287
288
|
|
|
288
289
|
## Why A Separate Package?
|
|
@@ -303,7 +304,8 @@ native surface to prefer here.
|
|
|
303
304
|
| Module | Purpose |
|
|
304
305
|
| -------------- | ---------------------------------------------------------------------- |
|
|
305
306
|
| `advisoryLock` | Stable lock IDs plus session- and transaction-scoped lock helpers. |
|
|
306
|
-
| `
|
|
307
|
+
| `identity` | Cross-runtime advisory-lock and channel identity policy. |
|
|
308
|
+
| `topicBus` | Topic bus and message contracts. |
|
|
307
309
|
| `persistence` | Stored-message schema, grants, TTL cleanup, history, and pointer wire. |
|
|
308
310
|
|
|
309
311
|
Both modules are also flattened onto the package root, so
|
package/exports.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Flat re-exports layered onto the generated `index.ts` barrel, which publishes
|
|
2
|
+
// each module as a namespace (`advisoryLock`, `topicBus`) and does not lift
|
|
3
|
+
// functions to the package root. These are the call-site names, so they are
|
|
4
|
+
// importable directly from `@dbx-tools/postgres`.
|
|
5
|
+
export { withAdvisoryLock, withAdvisoryTransactionLock } from "./src/advisory-lock.ts";
|
|
6
|
+
export {
|
|
7
|
+
decodePointer,
|
|
8
|
+
messageBusGrantStatements,
|
|
9
|
+
provisionMessageBusSchema,
|
|
10
|
+
resolvePersistenceOptions,
|
|
11
|
+
} from "./src/persistence.ts";
|
|
12
|
+
export type {
|
|
13
|
+
TopicPersistenceScope,
|
|
14
|
+
TopicBusPersistenceOptions,
|
|
15
|
+
StoredTopicMessage,
|
|
16
|
+
TopicHistoryPage,
|
|
17
|
+
TopicPointer,
|
|
18
|
+
} from "./src/persistence.ts";
|
package/index.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/postgres";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.36";
|
|
7
7
|
export * as advisoryLock from "./src/advisory-lock.ts";
|
|
8
|
+
export * as identity from "./src/identity.ts";
|
|
8
9
|
export * as persistence from "./src/persistence.ts";
|
|
9
10
|
export * as topicBus from "./src/topic-bus.ts";
|
|
10
11
|
export type { AdvisoryLockKey, PgPoolLike, PgQueryable } from "./src/advisory-lock.ts";
|
package/lib/exports.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { withAdvisoryLock, withAdvisoryTransactionLock } from "./src/advisory-lock.ts";
|
|
2
2
|
export { decodePointer, messageBusGrantStatements, provisionMessageBusSchema, resolvePersistenceOptions, } from "./src/persistence.ts";
|
|
3
3
|
export type { TopicPersistenceScope, TopicBusPersistenceOptions, StoredTopicMessage, TopicHistoryPage, TopicPointer, } from "./src/persistence.ts";
|
package/lib/exports.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
// each module as a namespace (`advisoryLock`, `topicBus`) and does not lift
|
|
3
3
|
// functions to the package root. These are the call-site names, so they are
|
|
4
4
|
// importable directly from `@dbx-tools/postgres`.
|
|
5
|
-
export {
|
|
5
|
+
export { withAdvisoryLock, withAdvisoryTransactionLock } from "./src/advisory-lock.js";
|
|
6
6
|
export { decodePointer, messageBusGrantStatements, provisionMessageBusSchema, resolvePersistenceOptions, } from "./src/persistence.js";
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL2V4cG9ydHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0ZBQWdGO0FBQ2hGLDRFQUE0RTtBQUM1RSw0RUFBNEU7QUFDNUUsa0RBQWtEO0FBQ2xELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZGLE9BQU8sRUFDTCxhQUFhLEVBQ2IseUJBQXlCLEVBQ3pCLHlCQUF5QixFQUN6Qix5QkFBeUIsR0FDMUIsTUFBTSxzQkFBc0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEZsYXQgcmUtZXhwb3J0cyBsYXllcmVkIG9udG8gdGhlIGdlbmVyYXRlZCBgaW5kZXgudHNgIGJhcnJlbCwgd2hpY2ggcHVibGlzaGVzXG4vLyBlYWNoIG1vZHVsZSBhcyBhIG5hbWVzcGFjZSAoYGFkdmlzb3J5TG9ja2AsIGB0b3BpY0J1c2ApIGFuZCBkb2VzIG5vdCBsaWZ0XG4vLyBmdW5jdGlvbnMgdG8gdGhlIHBhY2thZ2Ugcm9vdC4gVGhlc2UgYXJlIHRoZSBjYWxsLXNpdGUgbmFtZXMsIHNvIHRoZXkgYXJlXG4vLyBpbXBvcnRhYmxlIGRpcmVjdGx5IGZyb20gYEBkYngtdG9vbHMvcG9zdGdyZXNgLlxuZXhwb3J0IHsgd2l0aEFkdmlzb3J5TG9jaywgd2l0aEFkdmlzb3J5VHJhbnNhY3Rpb25Mb2NrIH0gZnJvbSBcIi4vc3JjL2Fkdmlzb3J5LWxvY2sudHNcIjtcbmV4cG9ydCB7XG4gIGRlY29kZVBvaW50ZXIsXG4gIG1lc3NhZ2VCdXNHcmFudFN0YXRlbWVudHMsXG4gIHByb3Zpc2lvbk1lc3NhZ2VCdXNTY2hlbWEsXG4gIHJlc29sdmVQZXJzaXN0ZW5jZU9wdGlvbnMsXG59IGZyb20gXCIuL3NyYy9wZXJzaXN0ZW5jZS50c1wiO1xuZXhwb3J0IHR5cGUge1xuICBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsXG4gIFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuICBTdG9yZWRUb3BpY01lc3NhZ2UsXG4gIFRvcGljSGlzdG9yeVBhZ2UsXG4gIFRvcGljUG9pbnRlcixcbn0gZnJvbSBcIi4vc3JjL3BlcnNpc3RlbmNlLnRzXCI7XG4iXX0=
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/postgres";
|
|
2
|
-
export declare const PACKAGE_VERSION = "0.9.
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.9.36";
|
|
3
3
|
export * as advisoryLock from "./src/advisory-lock.ts";
|
|
4
|
+
export * as identity from "./src/identity.ts";
|
|
4
5
|
export * as persistence from "./src/persistence.ts";
|
|
5
6
|
export * as topicBus from "./src/topic-bus.ts";
|
|
6
7
|
export type { AdvisoryLockKey, PgPoolLike, PgQueryable } from "./src/advisory-lock.ts";
|
package/lib/index.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/postgres";
|
|
5
|
-
export const PACKAGE_VERSION = "0.9.
|
|
5
|
+
export const PACKAGE_VERSION = "0.9.36";
|
|
6
6
|
export * as advisoryLock from "./src/advisory-lock.js";
|
|
7
|
+
export * as identity from "./src/identity.js";
|
|
7
8
|
export * as persistence from "./src/persistence.js";
|
|
8
9
|
export * as topicBus from "./src/topic-bus.js";
|
|
9
10
|
export { POINTER_VERSION } from "./src/persistence.js";
|
|
10
11
|
export { PostgresTopicBus } from "./src/topic-bus.js";
|
|
11
12
|
export * from "./exports.js";
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQztBQUN4RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssV0FBVyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxRQUFRLE1BQU0sb0JBQW9CLENBQUM7QUFFL0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXZELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXRELGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9wb3N0Z3Jlc1wiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjM2XCI7XG5leHBvcnQgKiBhcyBhZHZpc29yeUxvY2sgZnJvbSBcIi4vc3JjL2Fkdmlzb3J5LWxvY2sudHNcIjtcbmV4cG9ydCAqIGFzIGlkZW50aXR5IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0ICogYXMgcGVyc2lzdGVuY2UgZnJvbSBcIi4vc3JjL3BlcnNpc3RlbmNlLnRzXCI7XG5leHBvcnQgKiBhcyB0b3BpY0J1cyBmcm9tIFwiLi9zcmMvdG9waWMtYnVzLnRzXCI7XG5leHBvcnQgdHlwZSB7IEFkdmlzb3J5TG9ja0tleSwgUGdQb29sTGlrZSwgUGdRdWVyeWFibGUgfSBmcm9tIFwiLi9zcmMvYWR2aXNvcnktbG9jay50c1wiO1xuZXhwb3J0IHsgUE9JTlRFUl9WRVJTSU9OIH0gZnJvbSBcIi4vc3JjL3BlcnNpc3RlbmNlLnRzXCI7XG5leHBvcnQgdHlwZSB7IER1cmF0aW9uSW5wdXQsIFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvcGVyc2lzdGVuY2UudHNcIjtcbmV4cG9ydCB7IFBvc3RncmVzVG9waWNCdXMgfSBmcm9tIFwiLi9zcmMvdG9waWMtYnVzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFRvcGljTWV0YWRhdGEsIFRvcGljTWVzc2FnZSwgVG9waWNQdWJsaXNoSW5wdXQsIFRvcGljTGlzdGVuZXIsIFRvcGljTWV0YWRhdGFQcm92aWRlciwgUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMgfSBmcm9tIFwiLi9zcmMvdG9waWMtYnVzLnRzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9leHBvcnRzLnRzXCI7XG4iXX0=
|
|
@@ -24,17 +24,6 @@ export type PgPoolLike = Pick<Pool, "connect">;
|
|
|
24
24
|
export interface PgQueryable {
|
|
25
25
|
query<T extends QueryResultRow = QueryResultRow>(text: string, values?: unknown[]): Promise<QueryResult<T>>;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Convert an arbitrary structured key into PostgreSQL's signed 64-bit advisory
|
|
29
|
-
* lock namespace. A bigint is preserved directly so callers can interoperate
|
|
30
|
-
* with another implementation that publishes its lock ID.
|
|
31
|
-
*
|
|
32
|
-
* Everything else is canonicalized with `object.toStableKey` and hashed, so key
|
|
33
|
-
* order in an object does not matter while a `1` and a `"1"` stay different locks.
|
|
34
|
-
* A cycle, a non-finite number, or a function/symbol key throws `TypeError`
|
|
35
|
-
* rather than yielding an identity two callers could disagree about.
|
|
36
|
-
*/
|
|
37
|
-
export declare function advisoryLockId(key: AdvisoryLockKey): bigint;
|
|
38
27
|
/**
|
|
39
28
|
* Hold a session advisory lock for the duration of `fn`.
|
|
40
29
|
*
|
package/lib/src/advisory-lock.js
CHANGED
|
@@ -7,31 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
11
|
-
import { object } from "@dbx-tools/shared-core";
|
|
12
|
-
const SIGNED_BIGINT_BITS = 64;
|
|
13
|
-
/**
|
|
14
|
-
* Convert an arbitrary structured key into PostgreSQL's signed 64-bit advisory
|
|
15
|
-
* lock namespace. A bigint is preserved directly so callers can interoperate
|
|
16
|
-
* with another implementation that publishes its lock ID.
|
|
17
|
-
*
|
|
18
|
-
* Everything else is canonicalized with `object.toStableKey` and hashed, so key
|
|
19
|
-
* order in an object does not matter while a `1` and a `"1"` stay different locks.
|
|
20
|
-
* A cycle, a non-finite number, or a function/symbol key throws `TypeError`
|
|
21
|
-
* rather than yielding an identity two callers could disagree about.
|
|
22
|
-
*/
|
|
23
|
-
export function advisoryLockId(key) {
|
|
24
|
-
if (typeof key === "bigint")
|
|
25
|
-
return BigInt.asIntN(SIGNED_BIGINT_BITS, key);
|
|
26
|
-
const parts = object.toOneOrMany(key);
|
|
27
|
-
const digest = createHash("sha256");
|
|
28
|
-
parts.forEach((part, index) => {
|
|
29
|
-
if (index > 0)
|
|
30
|
-
digest.update(Buffer.from([0]));
|
|
31
|
-
digest.update(object.toStableKey(part), "utf8");
|
|
32
|
-
});
|
|
33
|
-
return digest.digest().readBigInt64BE(0);
|
|
34
|
-
}
|
|
10
|
+
import { advisoryLockId } from "./identity.js";
|
|
35
11
|
async function acquire(client, id, transaction) {
|
|
36
12
|
const fn = transaction ? "pg_advisory_xact_lock" : "pg_advisory_lock";
|
|
37
13
|
await client.query(`SELECT ${fn}($1::bigint)`, [id.toString()]);
|
|
@@ -49,7 +25,7 @@ async function unlock(client, id) {
|
|
|
49
25
|
* for any operation that must be protected by the lock.
|
|
50
26
|
*/
|
|
51
27
|
export async function withAdvisoryLock(pool, key, fn) {
|
|
52
|
-
const id = advisoryLockId(key);
|
|
28
|
+
const id = BigInt(advisoryLockId(key));
|
|
53
29
|
const client = await pool.connect();
|
|
54
30
|
let acquired = false;
|
|
55
31
|
let failed = false;
|
|
@@ -87,7 +63,7 @@ export async function withAdvisoryLock(pool, key, fn) {
|
|
|
87
63
|
* right primitive for one-time schema installation and migrations.
|
|
88
64
|
*/
|
|
89
65
|
export async function withAdvisoryTransactionLock(pool, key, fn) {
|
|
90
|
-
const id = advisoryLockId(key);
|
|
66
|
+
const id = BigInt(advisoryLockId(key));
|
|
91
67
|
const client = await pool.connect();
|
|
92
68
|
let releaseError;
|
|
93
69
|
try {
|
|
@@ -111,4 +87,4 @@ export async function withAdvisoryTransactionLock(pool, key, fn) {
|
|
|
111
87
|
client.release(releaseError);
|
|
112
88
|
}
|
|
113
89
|
}
|
|
114
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWR2aXNvcnktbG9jay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZHZpc29yeS1sb2NrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHaEQsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLENBQUM7QUEwQjlCOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBb0I7SUFDakQsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRO1FBQUUsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzNFLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEMsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDNUIsSUFBSSxLQUFLLEdBQUcsQ0FBQztZQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxPQUFPLENBQUMsTUFBbUIsRUFBRSxFQUFVLEVBQUUsV0FBb0I7SUFDMUUsTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFD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QUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUFDLE9BQU8sYUFBYSxFQUFFLENBQUM7WUFDdkIsWUFBWTtnQkFDVixhQUFhLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLENBQUM7UUFDRCxNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7WUFBUyxDQUFDO1FBQ1QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUMvQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWR2aXNvcnktbG9jayBoZWxwZXJzIGZvciBhbnkgYHBnLlBvb2xgLWNvbXBhdGlibGUgcG9vbC5cbiAqXG4gKiBQb3N0Z3JlU1FMIGFkdmlzb3J5IGxvY2tzIGJlbG9uZyB0byBhIGNvbm5lY3Rpb24sIG5vdCBhIHBvb2wuIFRoZXNlIGhlbHBlcnNcbiAqIHJlc2VydmUgb25lIHBvb2xlZCBjbGllbnQgZm9yIHRoZSBmdWxsIGNhbGxiYWNrLCBhY3F1aXJlIHRoZSBsb2NrIG9uIHRoYXRcbiAqIGNsaWVudCwgYW5kIHJlbGVhc2UgYm90aCBpbiB0aGUgY29ycmVjdCBvcmRlci5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUG9vbCwgUG9vbENsaWVudCwgUXVlcnlSZXN1bHQsIFF1ZXJ5UmVzdWx0Um93IH0gZnJvbSBcInBnXCI7XG5cbmNvbnN0IFNJR05FRF9CSUdJTlRfQklUUyA9IDY0O1xuXG4vKipcbiAqIFdoYXQgbmFtZXMgYSBsb2NrLiBBbnl0aGluZyByZWR1Y2libGUgdG8gYSBzdGFibGUgaWRlbnRpdHk6IGEgc3RyaW5nLCBhbiBpZCwgYVxuICogYFtcImludm9pY2VcIiwgaWRdYCBwYWlyLCBhIGNvbmZpZyBvYmplY3QsIG9yIGFuIGV4cGxpY2l0IGBiaWdpbnRgIHRvIGludGVyb3BlcmF0ZVxuICogd2l0aCBhbm90aGVyIGltcGxlbWVudGF0aW9uJ3MgcHVibGlzaGVkIGxvY2sgaWQuXG4gKlxuICogT25lIHZhbHVlIG9yIG1hbnk6IGFuIGFycmF5IGlzIHJlYWQgYXMgbXVsdGlwbGUgcGFydHMsIGFueXRoaW5nIGVsc2UgYXMgYSBzaW5nbGVcbiAqIHBhcnQuIFNvIGBbXCJpbnZvaWNlXCIsIDddYCBhbmQgYFwiaW52b2ljZV83XCJgIGFyZSBkaWZmZXJlbnQgbG9ja3MsIHNpbmNlIHRoZVxuICogY2Fub25pY2FsIGZvcm0gc2VlcyBkaWZmZXJlbnQgc3RydWN0dXJlLlxuICovXG5leHBvcnQgdHlwZSBBZHZpc29yeUxvY2tLZXkgPSB1bmtub3duO1xuXG4vKiogU3RydWN0dXJhbCBwb29sIHNoYXBlIGFjY2VwdGVkIGJ5IHRoZSBsb2NrIGhlbHBlcnMuICovXG5leHBvcnQgdHlwZSBQZ1Bvb2xMaWtlID0gUGljazxQb29sLCBcImNvbm5lY3RcIj47XG5cbi8qKiBTdHJ1Y3R1cmFsIHF1ZXJ5IHNoYXBlIHNoYXJlZCBieSBgcGcuUG9vbENsaWVudGAgYW5kIEFwcEtpdCBMYWtlYmFzZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGdRdWVyeWFibGUge1xuICBxdWVyeTxUIGV4dGVuZHMgUXVlcnlSZXN1bHRSb3cgPSBRdWVyeVJlc3VsdFJvdz4oXG4gICAgdGV4dDogc3RyaW5nLFxuICAgIHZhbHVlcz86IHVua25vd25bXSxcbiAgKTogUHJvbWlzZTxRdWVyeVJlc3VsdDxUPj47XG59XG5cbnR5cGUgVW5sb2NrUm93ID0gUXVlcnlSZXN1bHRSb3cgJiB7IHVubG9ja2VkOiBib29sZWFuIH07XG5cbi8qKlxuICogQ29udmVydCBhbiBhcmJpdHJhcnkgc3RydWN0dXJlZCBrZXkgaW50byBQb3N0Z3JlU1FMJ3Mgc2lnbmVkIDY0LWJpdCBhZHZpc29yeVxuICogbG9jayBuYW1lc3BhY2UuIEEgYmlnaW50IGlzIHByZXNlcnZlZCBkaXJlY3RseSBzbyBjYWxsZXJzIGNhbiBpbnRlcm9wZXJhdGVcbiAqIHdpdGggYW5vdGhlciBpbXBsZW1lbnRhdGlvbiB0aGF0IHB1Ymxpc2hlcyBpdHMgbG9jayBJRC5cbiAqXG4gKiBFdmVyeXRoaW5nIGVsc2UgaXMgY2Fub25pY2FsaXplZCB3aXRoIGBvYmplY3QudG9TdGFibGVLZXlgIGFuZCBoYXNoZWQsIHNvIGtleVxuICogb3JkZXIgaW4gYW4gb2JqZWN0IGRvZXMgbm90IG1hdHRlciB3aGlsZSBhIGAxYCBhbmQgYSBgXCIxXCJgIHN0YXkgZGlmZmVyZW50IGxvY2tzLlxuICogQSBjeWNsZSwgYSBub24tZmluaXRlIG51bWJlciwgb3IgYSBmdW5jdGlvbi9zeW1ib2wga2V5IHRocm93cyBgVHlwZUVycm9yYFxuICogcmF0aGVyIHRoYW4geWllbGRpbmcgYW4gaWRlbnRpdHkgdHdvIGNhbGxlcnMgY291bGQgZGlzYWdyZWUgYWJvdXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZHZpc29yeUxvY2tJZChrZXk6IEFkdmlzb3J5TG9ja0tleSk6IGJpZ2ludCB7XG4gIGlmICh0eXBlb2Yga2V5ID09PSBcImJpZ2ludFwiKSByZXR1cm4gQmlnSW50LmFzSW50TihTSUdORURfQklHSU5UX0JJVFMsIGtleSk7XG4gIGNvbnN0IHBhcnRzID0gb2JqZWN0LnRvT25lT3JNYW55KGtleSk7XG4gIGNvbnN0IGRpZ2VzdCA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIik7XG4gIHBhcnRzLmZvckVhY2goKHBhcnQsIGluZGV4KSA9PiB7XG4gICAgaWYgKGluZGV4ID4gMCkgZGlnZXN0LnVwZGF0ZShCdWZmZXIuZnJvbShbMF0pKTtcbiAgICBkaWdlc3QudXBkYXRlKG9iamVjdC50b1N0YWJsZUtleShwYXJ0KSwgXCJ1dGY4XCIpO1xuICB9KTtcbiAgcmV0dXJuIGRpZ2VzdC5kaWdlc3QoKS5yZWFkQmlnSW50NjRCRSgwKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYWNxdWlyZShjbGllbnQ6IFBnUXVlcnlhYmxlLCBpZDogYmlnaW50LCB0cmFuc2FjdGlvbjogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBmbiA9IHRyYW5zYWN0aW9uID8gXCJwZ19hZHZpc29yeV94YWN0X2xvY2tcIiA6IFwicGdfYWR2aXNvcnlfbG9ja1wiO1xuICBhd2FpdCBjbGllbnQucXVlcnkoYFNFTEVDVCAke2ZufSgkMTo6YmlnaW50KWAsIFtpZC50b1N0cmluZygpXSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVubG9jayhjbGllbnQ6IFBnUXVlcnlhYmxlLCBpZDogYmlnaW50KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeTxVbmxvY2tSb3c+KFxuICAgIFwiU0VMRUNUIHBnX2Fkdmlzb3J5X3VubG9jaygkMTo6YmlnaW50KSBBUyB1bmxvY2tlZFwiLFxuICAgIFtpZC50b1N0cmluZygpXSxcbiAgKTtcbiAgaWYgKHJlc3VsdC5yb3dzWzBdPy51bmxvY2tlZCAhPT0gdHJ1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUG9zdGdyZXMgYWR2aXNvcnkgbG9jayAke2lkfSB3YXMgbm90IGhlbGQgYnkgdGhpcyBjb25uZWN0aW9uYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBIb2xkIGEgc2Vzc2lvbiBhZHZpc29yeSBsb2NrIGZvciB0aGUgZHVyYXRpb24gb2YgYGZuYC5cbiAqXG4gKiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgdGhlIGRlZGljYXRlZCBgUG9vbENsaWVudGAgdGhhdCBvd25zIHRoZSBsb2NrLiBVc2UgaXRcbiAqIGZvciBhbnkgb3BlcmF0aW9uIHRoYXQgbXVzdCBiZSBwcm90ZWN0ZWQgYnkgdGhlIGxvY2suXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoQWR2aXNvcnlMb2NrPFQ+KFxuICBwb29sOiBQZ1Bvb2xMaWtlLFxuICBrZXk6IEFkdmlzb3J5TG9ja0tleSxcbiAgZm46IChjbGllbnQ6IFBvb2xDbGllbnQpID0+IFByb21pc2U8VD4gfCBULFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IGlkID0gYWR2aXNvcnlMb2NrSWQoa2V5KTtcbiAgY29uc3QgY2xpZW50ID0gYXdhaXQgcG9vbC5jb25uZWN0KCk7XG4gIGxldCBhY3F1aXJlZCA9IGZhbHNlO1xuICBsZXQgZmFpbGVkID0gZmFsc2U7XG4gIGxldCBmYWlsdXJlOiB1bmtub3duO1xuICBsZXQgdmFsdWU6IFQgfCB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBhY3F1aXJlKGNsaWVudCwgaWQsIGZhbHNlKTtcbiAgICBhY3F1aXJlZCA9IHRydWU7XG4gICAgdmFsdWUgPSBhd2FpdCBmbihjbGllbnQpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGZhaWxlZCA9IHRydWU7XG4gICAgZmFpbHVyZSA9IGVycm9yO1xuICB9XG5cbiAgbGV0IHVubG9ja0ZhaWx1cmU6IHVua25vd247XG4gIGlmIChhY3F1aXJlZCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB1bmxvY2soY2xpZW50LCBpZCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHVubG9ja0ZhaWx1cmUgPSBlcnJvcjtcbiAgICB9XG4gIH1cbiAgY2xpZW50LnJlbGVhc2UodW5sb2NrRmFpbHVyZSBpbnN0YW5jZW9mIEVycm9yID8gdW5sb2NrRmFpbHVyZSA6IHVuZGVmaW5lZCk7XG5cbiAgaWYgKGZhaWxlZCkgdGhyb3cgZmFpbHVyZTtcbiAgaWYgKHVubG9ja0ZhaWx1cmUgIT09IHVuZGVmaW5lZCkgdGhyb3cgdW5sb2NrRmFpbHVyZTtcbiAgcmV0dXJuIHZhbHVlIGFzIFQ7XG59XG5cbi8qKlxuICogUnVuIGBmbmAgaW4gYSB0cmFuc2FjdGlvbiB3aGlsZSBob2xkaW5nIGEgdHJhbnNhY3Rpb24gYWR2aXNvcnkgbG9jay5cbiAqXG4gKiBUaGUgbG9jayBpcyByZWxlYXNlZCBhdG9taWNhbGx5IGJ5IGBDT01NSVRgIG9yIGBST0xMQkFDS2AsIG1ha2luZyB0aGlzIHRoZVxuICogcmlnaHQgcHJpbWl0aXZlIGZvciBvbmUtdGltZSBzY2hlbWEgaW5zdGFsbGF0aW9uIGFuZCBtaWdyYXRpb25zLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2l0aEFkdmlzb3J5VHJhbnNhY3Rpb25Mb2NrPFQ+KFxuICBwb29sOiBQZ1Bvb2xMaWtlLFxuICBrZXk6IEFkdmlzb3J5TG9ja0tleSxcbiAgZm46IChjbGllbnQ6IFBvb2xDbGllbnQpID0+IFByb21pc2U8VD4gfCBULFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IGlkID0gYWR2aXNvcnlMb2NrSWQoa2V5KTtcbiAgY29uc3QgY2xpZW50ID0gYXdhaXQgcG9vbC5jb25uZWN0KCk7XG4gIGxldCByZWxlYXNlRXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkJFR0lOXCIpO1xuICAgIGF3YWl0IGFjcXVpcmUoY2xpZW50LCBpZCwgdHJ1ZSk7XG4gICAgY29uc3QgdmFsdWUgPSBhd2FpdCBmbihjbGllbnQpO1xuICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkNPTU1JVFwiKTtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIlJPTExCQUNLXCIpO1xuICAgIH0gY2F0Y2ggKHJvbGxiYWNrRXJyb3IpIHtcbiAgICAgIHJlbGVhc2VFcnJvciA9XG4gICAgICAgIHJvbGxiYWNrRXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IHJvbGxiYWNrRXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKHJvbGxiYWNrRXJyb3IpKTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0gZmluYWxseSB7XG4gICAgY2xpZW50LnJlbGVhc2UocmVsZWFzZUVycm9yKTtcbiAgfVxufVxuIl19
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWR2aXNvcnktbG9jay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZHZpc29yeS1sb2NrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBSUgsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQTBCL0MsS0FBSyxVQUFVLE9BQU8sQ0FBQyxNQUFtQixFQUFFLEVBQVUsRUFBRSxXQUFvQjtJQUMxRSxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQztJQUN0RSxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLGNBQWMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVELEtBQUssVUFBVSxNQUFNLENBQUMsTUFBbUIsRUFBRSxFQUFVO0lBQ25ELE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FDL0IsbURBQW1ELEVBQ25ELENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQ2hCLENBQUM7SUFDRixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztJQUNsRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FDcEMsSUFBZ0IsRUFDaEIsR0FBb0IsRUFDcEIsRUFBMEM7SUFFMUMsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3BDLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztJQUNyQixJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDbkIsSUFBSSxPQUFnQixDQUFDO0lBQ3JCLElBQUksS0FBb0IsQ0FBQztJQUV6QixJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDaEIsS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNkLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDbEIsQ0FBQztJQUVELElBQUksYUFBc0IsQ0FBQztJQUMzQixJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ2IsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUUzRSxJQUFJLE1BQU07UUFBRSxNQUFNLE9BQU8sQ0FBQztJQUMxQixJQUFJLGFBQWEsS0FBSyxTQUFTO1FBQUUsTUFBTSxhQUFhLENBQUM7SUFDckQsT0FBTyxLQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSwyQkFBMkIsQ0FDL0MsSUFBZ0IsRUFDaEIsR0FBb0IsRUFDcEIsRUFBMEM7SUFFMUMsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3BDLElBQUksWUFBK0IsQ0FBQztJQUNwQyxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUIsTUFBTSxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNoQyxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQixNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQUMsT0FBTyxhQUFhLEVBQUUsQ0FBQztZQUN2QixZQUFZO2dCQUNWLGFBQWEsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7UUFDdEYsQ0FBQztRQUNELE1BQU0sS0FBSyxDQUFDO0lBQ2QsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQy9CLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBZHZpc29yeS1sb2NrIGhlbHBlcnMgZm9yIGFueSBgcGcuUG9vbGAtY29tcGF0aWJsZSBwb29sLlxuICpcbiAqIFBvc3RncmVTUUwgYWR2aXNvcnkgbG9ja3MgYmVsb25nIHRvIGEgY29ubmVjdGlvbiwgbm90IGEgcG9vbC4gVGhlc2UgaGVscGVyc1xuICogcmVzZXJ2ZSBvbmUgcG9vbGVkIGNsaWVudCBmb3IgdGhlIGZ1bGwgY2FsbGJhY2ssIGFjcXVpcmUgdGhlIGxvY2sgb24gdGhhdFxuICogY2xpZW50LCBhbmQgcmVsZWFzZSBib3RoIGluIHRoZSBjb3JyZWN0IG9yZGVyLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFBvb2wsIFBvb2xDbGllbnQsIFF1ZXJ5UmVzdWx0LCBRdWVyeVJlc3VsdFJvdyB9IGZyb20gXCJwZ1wiO1xuXG5pbXBvcnQgeyBhZHZpc29yeUxvY2tJZCB9IGZyb20gXCIuL2lkZW50aXR5LnRzXCI7XG5cbi8qKlxuICogV2hhdCBuYW1lcyBhIGxvY2suIEFueXRoaW5nIHJlZHVjaWJsZSB0byBhIHN0YWJsZSBpZGVudGl0eTogYSBzdHJpbmcsIGFuIGlkLCBhXG4gKiBgW1wiaW52b2ljZVwiLCBpZF1gIHBhaXIsIGEgY29uZmlnIG9iamVjdCwgb3IgYW4gZXhwbGljaXQgYGJpZ2ludGAgdG8gaW50ZXJvcGVyYXRlXG4gKiB3aXRoIGFub3RoZXIgaW1wbGVtZW50YXRpb24ncyBwdWJsaXNoZWQgbG9jayBpZC5cbiAqXG4gKiBPbmUgdmFsdWUgb3IgbWFueTogYW4gYXJyYXkgaXMgcmVhZCBhcyBtdWx0aXBsZSBwYXJ0cywgYW55dGhpbmcgZWxzZSBhcyBhIHNpbmdsZVxuICogcGFydC4gU28gYFtcImludm9pY2VcIiwgN11gIGFuZCBgXCJpbnZvaWNlXzdcImAgYXJlIGRpZmZlcmVudCBsb2Nrcywgc2luY2UgdGhlXG4gKiBjYW5vbmljYWwgZm9ybSBzZWVzIGRpZmZlcmVudCBzdHJ1Y3R1cmUuXG4gKi9cbmV4cG9ydCB0eXBlIEFkdmlzb3J5TG9ja0tleSA9IHVua25vd247XG5cbi8qKiBTdHJ1Y3R1cmFsIHBvb2wgc2hhcGUgYWNjZXB0ZWQgYnkgdGhlIGxvY2sgaGVscGVycy4gKi9cbmV4cG9ydCB0eXBlIFBnUG9vbExpa2UgPSBQaWNrPFBvb2wsIFwiY29ubmVjdFwiPjtcblxuLyoqIFN0cnVjdHVyYWwgcXVlcnkgc2hhcGUgc2hhcmVkIGJ5IGBwZy5Qb29sQ2xpZW50YCBhbmQgQXBwS2l0IExha2ViYXNlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQZ1F1ZXJ5YWJsZSB7XG4gIHF1ZXJ5PFQgZXh0ZW5kcyBRdWVyeVJlc3VsdFJvdyA9IFF1ZXJ5UmVzdWx0Um93PihcbiAgICB0ZXh0OiBzdHJpbmcsXG4gICAgdmFsdWVzPzogdW5rbm93bltdLFxuICApOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PFQ+Pjtcbn1cblxudHlwZSBVbmxvY2tSb3cgPSBRdWVyeVJlc3VsdFJvdyAmIHsgdW5sb2NrZWQ6IGJvb2xlYW4gfTtcblxuYXN5bmMgZnVuY3Rpb24gYWNxdWlyZShjbGllbnQ6IFBnUXVlcnlhYmxlLCBpZDogYmlnaW50LCB0cmFuc2FjdGlvbjogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBmbiA9IHRyYW5zYWN0aW9uID8gXCJwZ19hZHZpc29yeV94YWN0X2xvY2tcIiA6IFwicGdfYWR2aXNvcnlfbG9ja1wiO1xuICBhd2FpdCBjbGllbnQucXVlcnkoYFNFTEVDVCAke2ZufSgkMTo6YmlnaW50KWAsIFtpZC50b1N0cmluZygpXSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVubG9jayhjbGllbnQ6IFBnUXVlcnlhYmxlLCBpZDogYmlnaW50KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeTxVbmxvY2tSb3c+KFxuICAgIFwiU0VMRUNUIHBnX2Fkdmlzb3J5X3VubG9jaygkMTo6YmlnaW50KSBBUyB1bmxvY2tlZFwiLFxuICAgIFtpZC50b1N0cmluZygpXSxcbiAgKTtcbiAgaWYgKHJlc3VsdC5yb3dzWzBdPy51bmxvY2tlZCAhPT0gdHJ1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUG9zdGdyZXMgYWR2aXNvcnkgbG9jayAke2lkfSB3YXMgbm90IGhlbGQgYnkgdGhpcyBjb25uZWN0aW9uYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBIb2xkIGEgc2Vzc2lvbiBhZHZpc29yeSBsb2NrIGZvciB0aGUgZHVyYXRpb24gb2YgYGZuYC5cbiAqXG4gKiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgdGhlIGRlZGljYXRlZCBgUG9vbENsaWVudGAgdGhhdCBvd25zIHRoZSBsb2NrLiBVc2UgaXRcbiAqIGZvciBhbnkgb3BlcmF0aW9uIHRoYXQgbXVzdCBiZSBwcm90ZWN0ZWQgYnkgdGhlIGxvY2suXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoQWR2aXNvcnlMb2NrPFQ+KFxuICBwb29sOiBQZ1Bvb2xMaWtlLFxuICBrZXk6IEFkdmlzb3J5TG9ja0tleSxcbiAgZm46IChjbGllbnQ6IFBvb2xDbGllbnQpID0+IFByb21pc2U8VD4gfCBULFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IGlkID0gQmlnSW50KGFkdmlzb3J5TG9ja0lkKGtleSkpO1xuICBjb25zdCBjbGllbnQgPSBhd2FpdCBwb29sLmNvbm5lY3QoKTtcbiAgbGV0IGFjcXVpcmVkID0gZmFsc2U7XG4gIGxldCBmYWlsZWQgPSBmYWxzZTtcbiAgbGV0IGZhaWx1cmU6IHVua25vd247XG4gIGxldCB2YWx1ZTogVCB8IHVuZGVmaW5lZDtcblxuICB0cnkge1xuICAgIGF3YWl0IGFjcXVpcmUoY2xpZW50LCBpZCwgZmFsc2UpO1xuICAgIGFjcXVpcmVkID0gdHJ1ZTtcbiAgICB2YWx1ZSA9IGF3YWl0IGZuKGNsaWVudCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgZmFpbGVkID0gdHJ1ZTtcbiAgICBmYWlsdXJlID0gZXJyb3I7XG4gIH1cblxuICBsZXQgdW5sb2NrRmFpbHVyZTogdW5rbm93bjtcbiAgaWYgKGFjcXVpcmVkKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHVubG9jayhjbGllbnQsIGlkKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdW5sb2NrRmFpbHVyZSA9IGVycm9yO1xuICAgIH1cbiAgfVxuICBjbGllbnQucmVsZWFzZSh1bmxvY2tGYWlsdXJlIGluc3RhbmNlb2YgRXJyb3IgPyB1bmxvY2tGYWlsdXJlIDogdW5kZWZpbmVkKTtcblxuICBpZiAoZmFpbGVkKSB0aHJvdyBmYWlsdXJlO1xuICBpZiAodW5sb2NrRmFpbHVyZSAhPT0gdW5kZWZpbmVkKSB0aHJvdyB1bmxvY2tGYWlsdXJlO1xuICByZXR1cm4gdmFsdWUgYXMgVDtcbn1cblxuLyoqXG4gKiBSdW4gYGZuYCBpbiBhIHRyYW5zYWN0aW9uIHdoaWxlIGhvbGRpbmcgYSB0cmFuc2FjdGlvbiBhZHZpc29yeSBsb2NrLlxuICpcbiAqIFRoZSBsb2NrIGlzIHJlbGVhc2VkIGF0b21pY2FsbHkgYnkgYENPTU1JVGAgb3IgYFJPTExCQUNLYCwgbWFraW5nIHRoaXMgdGhlXG4gKiByaWdodCBwcmltaXRpdmUgZm9yIG9uZS10aW1lIHNjaGVtYSBpbnN0YWxsYXRpb24gYW5kIG1pZ3JhdGlvbnMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoQWR2aXNvcnlUcmFuc2FjdGlvbkxvY2s8VD4oXG4gIHBvb2w6IFBnUG9vbExpa2UsXG4gIGtleTogQWR2aXNvcnlMb2NrS2V5LFxuICBmbjogKGNsaWVudDogUG9vbENsaWVudCkgPT4gUHJvbWlzZTxUPiB8IFQsXG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgaWQgPSBCaWdJbnQoYWR2aXNvcnlMb2NrSWQoa2V5KSk7XG4gIGNvbnN0IGNsaWVudCA9IGF3YWl0IHBvb2wuY29ubmVjdCgpO1xuICBsZXQgcmVsZWFzZUVycm9yOiBFcnJvciB8IHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBhd2FpdCBjbGllbnQucXVlcnkoXCJCRUdJTlwiKTtcbiAgICBhd2FpdCBhY3F1aXJlKGNsaWVudCwgaWQsIHRydWUpO1xuICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgZm4oY2xpZW50KTtcbiAgICBhd2FpdCBjbGllbnQucXVlcnkoXCJDT01NSVRcIik7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoXCJST0xMQkFDS1wiKTtcbiAgICB9IGNhdGNoIChyb2xsYmFja0Vycm9yKSB7XG4gICAgICByZWxlYXNlRXJyb3IgPVxuICAgICAgICByb2xsYmFja0Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyByb2xsYmFja0Vycm9yIDogbmV3IEVycm9yKFN0cmluZyhyb2xsYmFja0Vycm9yKSk7XG4gICAgfVxuICAgIHRocm93IGVycm9yO1xuICB9IGZpbmFsbHkge1xuICAgIGNsaWVudC5yZWxlYXNlKHJlbGVhc2VFcnJvcik7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-runtime Postgres lock and channel identity policy.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { LakebaseConnectionInputs, SslMode } from "@dbx-tools/lakebase/address";
|
|
7
|
+
/** Convert a structured key into a JSON-safe signed 64-bit lock identifier. */
|
|
8
|
+
export declare function advisoryLockId(key: unknown, explicit?: boolean): string;
|
|
9
|
+
/** Derive a legal deterministic Postgres channel name from structured input. */
|
|
10
|
+
export declare function channelName(value: unknown): string;
|
|
11
|
+
/** Parse a PostgreSQL URL, Lakebase resource path, hostname, or project ID. */
|
|
12
|
+
export declare function parseAddress(input: string | null | undefined): LakebaseConnectionInputs;
|
|
13
|
+
/** Parse a canonical Lakebase project, branch, endpoint, or database path. */
|
|
14
|
+
export declare function parseResourcePath(input: string | null | undefined): LakebaseConnectionInputs;
|
|
15
|
+
/** Parse a supported PostgreSQL SSL mode. */
|
|
16
|
+
export declare function parseSslMode(input: string | null | undefined): SslMode | undefined;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-runtime Postgres lock and channel identity policy.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { parseAddress as parseLakebaseAddress, parseResourcePath as parseLakebaseResourcePath, parseSslMode as parseLakebaseSslMode, } from "@dbx-tools/lakebase/address";
|
|
8
|
+
import * as hash from "@dbx-tools/shared-core/hash";
|
|
9
|
+
import * as object from "@dbx-tools/shared-core/object";
|
|
10
|
+
import * as stringUtils from "@dbx-tools/shared-core/string-utils";
|
|
11
|
+
const SIGNED_BIGINT_BITS = 64;
|
|
12
|
+
const MAX_CHANNEL_LENGTH = 63;
|
|
13
|
+
const CHANNEL_HASH_LENGTH = 6;
|
|
14
|
+
const CHANNEL_FALLBACK = "bus";
|
|
15
|
+
/** Convert a structured key into a JSON-safe signed 64-bit lock identifier. */
|
|
16
|
+
export function advisoryLockId(key, explicit = false) {
|
|
17
|
+
return resolveAdvisoryLockId(explicit ? BigInt(String(key)) : key).toString();
|
|
18
|
+
}
|
|
19
|
+
function resolveAdvisoryLockId(key) {
|
|
20
|
+
if (typeof key === "bigint")
|
|
21
|
+
return BigInt.asIntN(SIGNED_BIGINT_BITS, key);
|
|
22
|
+
const parts = object.toOneOrMany(key);
|
|
23
|
+
const digest = createHash("sha256");
|
|
24
|
+
parts.forEach((part, index) => {
|
|
25
|
+
if (index > 0)
|
|
26
|
+
digest.update(Buffer.from([0]));
|
|
27
|
+
digest.update(object.toStableKey(part), "utf8");
|
|
28
|
+
});
|
|
29
|
+
return digest.digest().readBigInt64BE(0);
|
|
30
|
+
}
|
|
31
|
+
/** Derive a legal deterministic Postgres channel name from structured input. */
|
|
32
|
+
export function channelName(value) {
|
|
33
|
+
const parts = object.toOneOrMany(value);
|
|
34
|
+
const suffix = hash.fnvHashWithOptions({ length: CHANNEL_HASH_LENGTH }, parts.map((part) => object.toStableKey(part)).join("\u0000"));
|
|
35
|
+
const labelled = parts.filter((part) => {
|
|
36
|
+
const type = typeof part;
|
|
37
|
+
return type === "string" || type === "number" || type === "boolean" || type === "bigint";
|
|
38
|
+
});
|
|
39
|
+
const body = stringUtils
|
|
40
|
+
.toIdentifierWithOptions({ delimiter: "_" }, ...labelled)
|
|
41
|
+
.slice(0, MAX_CHANNEL_LENGTH - suffix.length - 1)
|
|
42
|
+
.replace(/_+$/, "");
|
|
43
|
+
const prefix = /^[A-Za-z_]/.test(body) ? body : `${CHANNEL_FALLBACK}_${body}`;
|
|
44
|
+
return `${prefix}_${suffix}`.replace(/_+/g, "_");
|
|
45
|
+
}
|
|
46
|
+
/** Parse a PostgreSQL URL, Lakebase resource path, hostname, or project ID. */
|
|
47
|
+
export function parseAddress(input) {
|
|
48
|
+
return parseLakebaseAddress(input);
|
|
49
|
+
}
|
|
50
|
+
/** Parse a canonical Lakebase project, branch, endpoint, or database path. */
|
|
51
|
+
export function parseResourcePath(input) {
|
|
52
|
+
return parseLakebaseResourcePath(input);
|
|
53
|
+
}
|
|
54
|
+
/** Parse a supported PostgreSQL SSL mode. */
|
|
55
|
+
export function parseSslMode(input) {
|
|
56
|
+
return parseLakebaseSslMode(input);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekMsT0FBTyxFQUVMLFlBQVksSUFBSSxvQkFBb0IsRUFDcEMsaUJBQWlCLElBQUkseUJBQXlCLEVBQzlDLFlBQVksSUFBSSxvQkFBb0IsR0FFckMsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEtBQUssSUFBSSxNQUFNLDZCQUE2QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxNQUFNLE1BQU0sK0JBQStCLENBQUM7QUFDeEQsT0FBTyxLQUFLLFdBQVcsTUFBTSxxQ0FBcUMsQ0FBQztBQUVuRSxNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztBQUM5QixNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztBQUM5QixNQUFNLG1CQUFtQixHQUFHLENBQUMsQ0FBQztBQUM5QixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQztBQUUvQiwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLGNBQWMsQ0FBQyxHQUFZLEVBQUUsUUFBUSxHQUFHLEtBQUs7SUFDM0QsT0FBTyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDaEYsQ0FBQztBQUVELFNBQVMscUJBQXFCLENBQUMsR0FBWTtJQUN6QyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7UUFBRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDM0UsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRTtRQUM1QixJQUFJLEtBQUssR0FBRyxDQUFDO1lBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMzQyxDQUFDO0FBRUQsZ0ZBQWdGO0FBQ2hGLE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBYztJQUN4QyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FDcEMsRUFBRSxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsRUFDL0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FDN0QsQ0FBQztJQUNGLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUNyQyxNQUFNLElBQUksR0FBRyxPQUFPLElBQUksQ0FBQztRQUN6QixPQUFPLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLEtBQUssU0FBUyxJQUFJLElBQUksS0FBSyxRQUFRLENBQUM7SUFDM0YsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLElBQUksR0FBRyxXQUFXO1NBQ3JCLHVCQUF1QixDQUFDLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLEdBQUcsUUFBUSxDQUFDO1NBQ3hELEtBQUssQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7U0FDaEQsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN0QixNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0JBQWdCLElBQUksSUFBSSxFQUFFLENBQUM7SUFDOUUsT0FBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFnQztJQUMzRCxPQUFPLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRCw4RUFBOEU7QUFDOUUsTUFBTSxVQUFVLGlCQUFpQixDQUFDLEtBQWdDO0lBQ2hFLE9BQU8seUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUVELDZDQUE2QztBQUM3QyxNQUFNLFVBQVUsWUFBWSxDQUFDLEtBQWdDO0lBQzNELE9BQU8sb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ3Jvc3MtcnVudGltZSBQb3N0Z3JlcyBsb2NrIGFuZCBjaGFubmVsIGlkZW50aXR5IHBvbGljeS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuXG5pbXBvcnQge1xuICBMYWtlYmFzZUNvbm5lY3Rpb25JbnB1dHMsXG4gIHBhcnNlQWRkcmVzcyBhcyBwYXJzZUxha2ViYXNlQWRkcmVzcyxcbiAgcGFyc2VSZXNvdXJjZVBhdGggYXMgcGFyc2VMYWtlYmFzZVJlc291cmNlUGF0aCxcbiAgcGFyc2VTc2xNb2RlIGFzIHBhcnNlTGFrZWJhc2VTc2xNb2RlLFxuICBTc2xNb2RlLFxufSBmcm9tIFwiQGRieC10b29scy9sYWtlYmFzZS9hZGRyZXNzXCI7XG5pbXBvcnQgKiBhcyBoYXNoIGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlL2hhc2hcIjtcbmltcG9ydCAqIGFzIG9iamVjdCBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZS9vYmplY3RcIjtcbmltcG9ydCAqIGFzIHN0cmluZ1V0aWxzIGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlL3N0cmluZy11dGlsc1wiO1xuXG5jb25zdCBTSUdORURfQklHSU5UX0JJVFMgPSA2NDtcbmNvbnN0IE1BWF9DSEFOTkVMX0xFTkdUSCA9IDYzO1xuY29uc3QgQ0hBTk5FTF9IQVNIX0xFTkdUSCA9IDY7XG5jb25zdCBDSEFOTkVMX0ZBTExCQUNLID0gXCJidXNcIjtcblxuLyoqIENvbnZlcnQgYSBzdHJ1Y3R1cmVkIGtleSBpbnRvIGEgSlNPTi1zYWZlIHNpZ25lZCA2NC1iaXQgbG9jayBpZGVudGlmaWVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkdmlzb3J5TG9ja0lkKGtleTogdW5rbm93biwgZXhwbGljaXQgPSBmYWxzZSk6IHN0cmluZyB7XG4gIHJldHVybiByZXNvbHZlQWR2aXNvcnlMb2NrSWQoZXhwbGljaXQgPyBCaWdJbnQoU3RyaW5nKGtleSkpIDoga2V5KS50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQWR2aXNvcnlMb2NrSWQoa2V5OiB1bmtub3duKTogYmlnaW50IHtcbiAgaWYgKHR5cGVvZiBrZXkgPT09IFwiYmlnaW50XCIpIHJldHVybiBCaWdJbnQuYXNJbnROKFNJR05FRF9CSUdJTlRfQklUUywga2V5KTtcbiAgY29uc3QgcGFydHMgPSBvYmplY3QudG9PbmVPck1hbnkoa2V5KTtcbiAgY29uc3QgZGlnZXN0ID0gY3JlYXRlSGFzaChcInNoYTI1NlwiKTtcbiAgcGFydHMuZm9yRWFjaCgocGFydCwgaW5kZXgpID0+IHtcbiAgICBpZiAoaW5kZXggPiAwKSBkaWdlc3QudXBkYXRlKEJ1ZmZlci5mcm9tKFswXSkpO1xuICAgIGRpZ2VzdC51cGRhdGUob2JqZWN0LnRvU3RhYmxlS2V5KHBhcnQpLCBcInV0ZjhcIik7XG4gIH0pO1xuICByZXR1cm4gZGlnZXN0LmRpZ2VzdCgpLnJlYWRCaWdJbnQ2NEJFKDApO1xufVxuXG4vKiogRGVyaXZlIGEgbGVnYWwgZGV0ZXJtaW5pc3RpYyBQb3N0Z3JlcyBjaGFubmVsIG5hbWUgZnJvbSBzdHJ1Y3R1cmVkIGlucHV0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYW5uZWxOYW1lKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3QgcGFydHMgPSBvYmplY3QudG9PbmVPck1hbnkodmFsdWUpO1xuICBjb25zdCBzdWZmaXggPSBoYXNoLmZudkhhc2hXaXRoT3B0aW9ucyhcbiAgICB7IGxlbmd0aDogQ0hBTk5FTF9IQVNIX0xFTkdUSCB9LFxuICAgIHBhcnRzLm1hcCgocGFydCkgPT4gb2JqZWN0LnRvU3RhYmxlS2V5KHBhcnQpKS5qb2luKFwiXFx1MDAwMFwiKSxcbiAgKTtcbiAgY29uc3QgbGFiZWxsZWQgPSBwYXJ0cy5maWx0ZXIoKHBhcnQpID0+IHtcbiAgICBjb25zdCB0eXBlID0gdHlwZW9mIHBhcnQ7XG4gICAgcmV0dXJuIHR5cGUgPT09IFwic3RyaW5nXCIgfHwgdHlwZSA9PT0gXCJudW1iZXJcIiB8fCB0eXBlID09PSBcImJvb2xlYW5cIiB8fCB0eXBlID09PSBcImJpZ2ludFwiO1xuICB9KTtcbiAgY29uc3QgYm9keSA9IHN0cmluZ1V0aWxzXG4gICAgLnRvSWRlbnRpZmllcldpdGhPcHRpb25zKHsgZGVsaW1pdGVyOiBcIl9cIiB9LCAuLi5sYWJlbGxlZClcbiAgICAuc2xpY2UoMCwgTUFYX0NIQU5ORUxfTEVOR1RIIC0gc3VmZml4Lmxlbmd0aCAtIDEpXG4gICAgLnJlcGxhY2UoL18rJC8sIFwiXCIpO1xuICBjb25zdCBwcmVmaXggPSAvXltBLVphLXpfXS8udGVzdChib2R5KSA/IGJvZHkgOiBgJHtDSEFOTkVMX0ZBTExCQUNLfV8ke2JvZHl9YDtcbiAgcmV0dXJuIGAke3ByZWZpeH1fJHtzdWZmaXh9YC5yZXBsYWNlKC9fKy9nLCBcIl9cIik7XG59XG5cbi8qKiBQYXJzZSBhIFBvc3RncmVTUUwgVVJMLCBMYWtlYmFzZSByZXNvdXJjZSBwYXRoLCBob3N0bmFtZSwgb3IgcHJvamVjdCBJRC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFkZHJlc3MoaW5wdXQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBMYWtlYmFzZUNvbm5lY3Rpb25JbnB1dHMge1xuICByZXR1cm4gcGFyc2VMYWtlYmFzZUFkZHJlc3MoaW5wdXQpO1xufVxuXG4vKiogUGFyc2UgYSBjYW5vbmljYWwgTGFrZWJhc2UgcHJvamVjdCwgYnJhbmNoLCBlbmRwb2ludCwgb3IgZGF0YWJhc2UgcGF0aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJlc291cmNlUGF0aChpbnB1dDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IExha2ViYXNlQ29ubmVjdGlvbklucHV0cyB7XG4gIHJldHVybiBwYXJzZUxha2ViYXNlUmVzb3VyY2VQYXRoKGlucHV0KTtcbn1cblxuLyoqIFBhcnNlIGEgc3VwcG9ydGVkIFBvc3RncmVTUUwgU1NMIG1vZGUuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTc2xNb2RlKGlucHV0OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogU3NsTW9kZSB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBwYXJzZUxha2ViYXNlU3NsTW9kZShpbnB1dCk7XG59XG4iXX0=
|
package/lib/src/persistence.d.ts
CHANGED
|
@@ -39,13 +39,17 @@ export declare const POINTER_VERSION = 1;
|
|
|
39
39
|
export declare function resolvePersistenceOptions(value: true | TopicBusPersistenceOptions): ResolvedTopicBusPersistenceOptions;
|
|
40
40
|
export declare function provisionMessageBusSchema(pool: PgPoolLike, options: ResolvedTopicBusPersistenceOptions): Promise<void>;
|
|
41
41
|
export declare function messageBusGrantStatements(roles: string | readonly string[], scope: TopicPersistenceScope, options: ResolvedTopicBusPersistenceOptions): string[];
|
|
42
|
+
/** Convert a persistence TTL to milliseconds, preserving disabled retention. */
|
|
42
43
|
export declare function ttlMilliseconds(value: DurationInput | false): number | null;
|
|
44
|
+
/** Delete one bounded batch of expired persisted topic messages. */
|
|
43
45
|
export declare function cleanupExpired(queryable: PgQueryable, options: ResolvedTopicBusPersistenceOptions, scope: TopicPersistenceScope, limit?: number): Promise<number>;
|
|
46
|
+
/** Read a cursor-paginated page of persisted topic history. */
|
|
44
47
|
export declare function history<TBody extends object.SerializableValue>(queryable: PgQueryable, channel: string, topic: string, options: ResolvedTopicBusPersistenceOptions, input?: {
|
|
45
48
|
after?: string;
|
|
46
49
|
limit?: number;
|
|
47
50
|
scope?: TopicPersistenceScope;
|
|
48
51
|
}): Promise<TopicHistoryPage<TBody>>;
|
|
52
|
+
/** Persist a topic message and notify listeners in one transaction. */
|
|
49
53
|
export declare function persistedNotify(client: PgQueryable, channel: string, topic: string, message: TopicMessage, encoded: string, options: ResolvedTopicBusPersistenceOptions, scope: TopicPersistenceScope, ttl: DurationInput | false): Promise<void>;
|
|
50
54
|
/**
|
|
51
55
|
* The `payload: "pointer"` notification body: routing and identity only, so the
|
package/lib/src/persistence.js
CHANGED
|
@@ -60,6 +60,7 @@ function after(value, scope) {
|
|
|
60
60
|
}
|
|
61
61
|
return decoded[1];
|
|
62
62
|
}
|
|
63
|
+
/** Convert a persistence TTL to milliseconds, preserving disabled retention. */
|
|
63
64
|
export function ttlMilliseconds(value) {
|
|
64
65
|
if (value === false)
|
|
65
66
|
return null;
|
|
@@ -69,10 +70,12 @@ export function ttlMilliseconds(value) {
|
|
|
69
70
|
}
|
|
70
71
|
return milliseconds;
|
|
71
72
|
}
|
|
73
|
+
/** Delete one bounded batch of expired persisted topic messages. */
|
|
72
74
|
export async function cleanupExpired(queryable, options, scope, limit = options.cleanupBatchSize) {
|
|
73
75
|
const result = await queryable.query(`WITH expired AS (SELECT ctid FROM ${table(options, scope)} WHERE expires_at IS NOT NULL AND expires_at <= clock_timestamp() ORDER BY expires_at LIMIT $1) DELETE FROM ${table(options, scope)} AS messages USING expired WHERE messages.ctid = expired.ctid`, [limit]);
|
|
74
76
|
return result.rowCount ?? 0;
|
|
75
77
|
}
|
|
78
|
+
/** Read a cursor-paginated page of persisted topic history. */
|
|
76
79
|
export async function history(queryable, channel, topic, options, input = {}) {
|
|
77
80
|
const scope = input.scope ?? options.scope;
|
|
78
81
|
const limit = input.limit ?? 100;
|
|
@@ -88,6 +91,7 @@ export async function history(queryable, channel, topic, options, input = {}) {
|
|
|
88
91
|
...(messages.length === limit ? { nextCursor: messages.at(-1).cursor } : {}),
|
|
89
92
|
};
|
|
90
93
|
}
|
|
94
|
+
/** Persist a topic message and notify listeners in one transaction. */
|
|
91
95
|
export async function persistedNotify(client, channel, topic, message, encoded, options, scope, ttl) {
|
|
92
96
|
await cleanupExpired(client, options, scope);
|
|
93
97
|
const milliseconds = ttlMilliseconds(ttl);
|
|
@@ -144,4 +148,4 @@ export async function readPointer(queryable, channel, pointer, options) {
|
|
|
144
148
|
const result = await queryable.query(`SELECT envelope FROM ${table(options, pointer.scope)} WHERE channel = $1 AND message_id = $2 AND (expires_at IS NULL OR expires_at > clock_timestamp())`, [channel, pointer.id]);
|
|
145
149
|
return result.rows[0]?.envelope;
|
|
146
150
|
}
|
|
147
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyc2lzdGVuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGVyc2lzdGVuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBR2hELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBc0NqRSxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUM7QUFDL0I7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLEtBQUssR0FBRyxDQUFDLEtBQWEsRUFBVSxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDO0FBQzVFLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBMkMsRUFBRSxLQUE0QixFQUFVLEVBQUUsQ0FDbEcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUU3RCxNQUFNLFVBQVUseUJBQXlCLENBQ3ZDLEtBQXdDO0lBRXhDLE1BQU0sVUFBVSxHQUFHLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQy9DLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLElBQUksTUFBTSxDQUFDO0lBQ3pDLElBQUksS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLFNBQVMsQ0FBQyw4QkFBOEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsT0FBTztRQUNMLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxJQUFJLGlCQUFpQjtRQUM5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RSxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQy9CLFNBQXNCLEVBQ3RCLE9BQWUsRUFDZixPQUFxQixFQUNyQixPQUEyQztJQUUzQyxNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxLQUFLLENBQ2xDLHdCQUF3QixLQUFLLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0dBQW9HLEVBQ3pKLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FDdEIsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUEyQyxDQUFDO0FBQ3JFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBRdWVyeVJlc3VsdFJvdyB9IGZyb20gXCJwZ1wiO1xuaW1wb3J0IHR5cGUgeyBQZ1Bvb2xMaWtlLCBQZ1F1ZXJ5YWJsZSB9IGZyb20gXCIuL2Fkdmlzb3J5LWxvY2sudHNcIjtcbmltcG9ydCB7IHdpdGhBZHZpc29yeVRyYW5zYWN0aW9uTG9jayB9IGZyb20gXCIuL2Fkdmlzb3J5LWxvY2sudHNcIjtcbmltcG9ydCB0eXBlIHsgVG9waWNNZXNzYWdlIH0gZnJvbSBcIi4vdG9waWMtYnVzLnRzXCI7XG5cbmV4cG9ydCB0eXBlIFRvcGljUGVyc2lzdGVuY2VTY29wZSA9IFwib3BlblwiIHwgXCJyZXN0cmljdGVkXCI7XG5leHBvcnQgdHlwZSBEdXJhdGlvbklucHV0ID0gc3RyaW5nIHwgbnVtYmVyO1xuZXhwb3J0IGludGVyZmFjZSBUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyB7XG4gIHNjaGVtYT86IHN0cmluZztcbiAgc2NvcGU/OiBUb3BpY1BlcnNpc3RlbmNlU2NvcGU7XG4gIHRhYmxlcz86IFBhcnRpYWw8UmVjb3JkPFRvcGljUGVyc2lzdGVuY2VTY29wZSwgc3RyaW5nPj47XG4gIHR0bD86IER1cmF0aW9uSW5wdXQgfCBmYWxzZTtcbiAgcGF5bG9hZD86IFwiZW52ZWxvcGVcIiB8IFwicG9pbnRlclwiO1xuICBjbGVhbnVwQmF0Y2hTaXplPzogbnVtYmVyO1xuICBwcm92aXNpb24/OiBib29sZWFuO1xufVxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zIHtcbiAgc2NoZW1hOiBzdHJpbmc7XG4gIHNjb3BlOiBUb3BpY1BlcnNpc3RlbmNlU2NvcGU7XG4gIHRhYmxlczogUmVjb3JkPFRvcGljUGVyc2lzdGVuY2VTY29wZSwgc3RyaW5nPjtcbiAgdHRsOiBEdXJhdGlvbklucHV0IHwgZmFsc2U7XG4gIHBheWxvYWQ6IFwiZW52ZWxvcGVcIiB8IFwicG9pbnRlclwiO1xuICBjbGVhbnVwQmF0Y2hTaXplOiBudW1iZXI7XG4gIHByb3Zpc2lvbjogYm9vbGVhbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVkVG9waWNNZXNzYWdlPFxuICBUQm9keSBleHRlbmRzIG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZSA9IG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZSxcbj4ge1xuICBjdXJzb3I6IHN0cmluZztcbiAgZXhwaXJlc0F0OiBzdHJpbmcgfCBudWxsO1xuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlO1xuICBtZXNzYWdlOiBUb3BpY01lc3NhZ2U8VEJvZHk+O1xufVxuZXhwb3J0IGludGVyZmFjZSBUb3BpY0hpc3RvcnlQYWdlPFxuICBUQm9keSBleHRlbmRzIG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZSA9IG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZSxcbj4ge1xuICBtZXNzYWdlczogU3RvcmVkVG9waWNNZXNzYWdlPFRCb2R5PltdO1xuICBuZXh0Q3Vyc29yPzogc3RyaW5nO1xufVxuXG5jb25zdCBERUZBVUxUX1RUTCA9IFwiMjQgaG91cnNcIjtcbi8qKlxuICogUG9pbnRlci1wYXlsb2FkIHZlcnNpb24uIEEgbGlzdGVuZXIgdGhhdCBkb2VzIG5vdCByZWNvZ25pemUgdGhlIHZlcnNpb24gdHJlYXRzXG4gKiB0aGUgbm90aWZpY2F0aW9uIGFzIGZvcmVpZ24gdHJhZmZpYyByYXRoZXIgdGhhbiBndWVzc2luZyBhdCBpdHMgc2hhcGUuXG4gKi9cbmV4cG9ydCBjb25zdCBQT0lOVEVSX1ZFUlNJT04gPSAxO1xuY29uc3QgcXVvdGUgPSAodmFsdWU6IHN0cmluZyk6IHN0cmluZyA9PiBgXCIke3ZhbHVlLnJlcGxhY2VBbGwoJ1wiJywgJ1wiXCInKX1cImA7XG5jb25zdCB0YWJsZSA9IChvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLCBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlKTogc3RyaW5nID0+XG4gIGAke3F1b3RlKG9wdGlvbnMuc2NoZW1hKX0uJHtxdW90ZShvcHRpb25zLnRhYmxlc1tzY29wZV0pfWA7XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUGVyc2lzdGVuY2VPcHRpb25zKFxuICB2YWx1ZTogdHJ1ZSB8IFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuKTogUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyB7XG4gIGNvbnN0IGNvbmZpZ3VyZWQgPSB2YWx1ZSA9PT0gdHJ1ZSA/IHt9IDogdmFsdWU7XG4gIGNvbnN0IHNjb3BlID0gY29uZmlndXJlZC5zY29wZSA/PyBcIm9wZW5cIjtcbiAgaWYgKHNjb3BlICE9PSBcIm9wZW5cIiAmJiBzY29wZSAhPT0gXCJyZXN0cmljdGVkXCIpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbmtub3duIHBlcnNpc3RlbmNlIHNjb3BlOiAke1N0cmluZyhzY29wZSl9YCk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBzY2hlbWE6IGNvbmZpZ3VyZWQuc2NoZW1hID8/IFwiZGJ4X21lc3NhZ2VfYnVzXCIsXG4gICAgc2NvcGUsXG4gICAgdGFibGVzOiB7XG4gICAgICBvcGVuOiBjb25maWd1cmVkLnRhYmxlcz8ub3BlbiA/PyBcIm9wZW5fbWVzc2FnZXNcIixcbiAgICAgIHJlc3RyaWN0ZWQ6IGNvbmZpZ3VyZWQudGFibGVzPy5yZXN0cmljdGVkID8/IFwicmVzdHJpY3RlZF9tZXNzYWdlc1wiLFxuICAgIH0sXG4gICAgdHRsOiBjb25maWd1cmVkLnR0bCA/PyBERUZBVUxUX1RUTCxcbiAgICBwYXlsb2FkOiBjb25maWd1cmVkLnBheWxvYWQgPz8gXCJlbnZlbG9wZVwiLFxuICAgIGNsZWFudXBCYXRjaFNpemU6IGNvbmZpZ3VyZWQuY2xlYW51cEJhdGNoU2l6ZSA/PyAxMDAwLFxuICAgIHByb3Zpc2lvbjogY29uZmlndXJlZC5wcm92aXNpb24gPz8gdHJ1ZSxcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb3Zpc2lvbk1lc3NhZ2VCdXNTY2hlbWEoXG4gIHBvb2w6IFBnUG9vbExpa2UsXG4gIG9wdGlvbnM6IFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgd2l0aEFkdmlzb3J5VHJhbnNhY3Rpb25Mb2NrKHBvb2wsIFtcImRieF9tZXNzYWdlX2J1c1wiLCBcInNjaGVtYVwiXSwgYXN5bmMgKGNsaWVudCkgPT4ge1xuICAgIGF3YWl0IGNsaWVudC5xdWVyeShgQ1JFQVRFIFNDSEVNQSBJRiBOT1QgRVhJU1RTICR7cXVvdGUob3B0aW9ucy5zY2hlbWEpfWApO1xuICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgIGBDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAke3F1b3RlKG9wdGlvbnMuc2NoZW1hKX0uJHtxdW90ZShcInNjaGVtYV92ZXJzaW9uXCIpfSAodmVyc2lvbiBJTlRFR0VSIFBSSU1BUlkgS0VZKWAsXG4gICAgKTtcbiAgICBmb3IgKGNvbnN0IHNjb3BlIG9mIFtcIm9wZW5cIiwgXCJyZXN0cmljdGVkXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBuYW1lID0gdGFibGUob3B0aW9ucywgc2NvcGUpO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KFxuICAgICAgICBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJHtuYW1lfSAoc2VxdWVuY2UgQklHSU5UIEdFTkVSQVRFRCBBTFdBWVMgQVMgSURFTlRJVFkgUFJJTUFSWSBLRVksIGNoYW5uZWwgVEVYVCBOT1QgTlVMTCwgdG9waWMgVEVYVCBOT1QgTlVMTCwgbWVzc2FnZV9pZCBURVhUIE5PVCBOVUxMLCBwdWJsaXNoZWRfYXQgVElNRVNUQU1QVFogTk9UIE5VTEwsIGV4cGlyZXNfYXQgVElNRVNUQU1QVFosIHhhY3RfaWQgWElEOCBOT1QgTlVMTCBERUZBVUxUIHBnX2N1cnJlbnRfeGFjdF9pZCgpLCBlbnZlbG9wZSBKU09OQiBOT1QgTlVMTCwgVU5JUVVFIChjaGFubmVsLCBtZXNzYWdlX2lkKSwgQ0hFQ0sgKGpzb25iX3R5cGVvZihlbnZlbG9wZSkgPSAnb2JqZWN0JykpYCxcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICAgIGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyAke3F1b3RlKGAke29wdGlvbnMudGFibGVzW3Njb3BlXX1fcmVwbGF5X2lkeGApfSBPTiAke25hbWV9IChjaGFubmVsLCB0b3BpYywgc2VxdWVuY2UpYCxcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICAgIGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyAke3F1b3RlKGAke29wdGlvbnMudGFibGVzW3Njb3BlXX1fZXhwaXJ5X2lkeGApfSBPTiAke25hbWV9IChleHBpcmVzX2F0KSBXSEVSRSBleHBpcmVzX2F0IElTIE5PVCBOVUxMYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgIGBJTlNFUlQgSU5UTyAke3F1b3RlKG9wdGlvbnMuc2NoZW1hKX0uJHtxdW90ZShcInNjaGVtYV92ZXJzaW9uXCIpfSAodmVyc2lvbikgVkFMVUVTICgxKSBPTiBDT05GTElDVCAodmVyc2lvbikgRE8gTk9USElOR2AsXG4gICAgKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXNzYWdlQnVzR3JhbnRTdGF0ZW1lbnRzKFxuICByb2xlczogc3RyaW5nIHwgcmVhZG9ubHkgc3RyaW5nW10sXG4gIHNjb3BlOiBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsXG4gIG9wdGlvbnM6IFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHNlbGVjdGVkID0gdGFibGUob3B0aW9ucywgc2NvcGUpO1xuICByZXR1cm4gKHR5cGVvZiByb2xlcyA9PT0gXCJzdHJpbmdcIiA/IFtyb2xlc10gOiByb2xlcykuZmxhdE1hcCgocm9sZSkgPT4gW1xuICAgIGBHUkFOVCBVU0FHRSBPTiBTQ0hFTUEgJHtxdW90ZShvcHRpb25zLnNjaGVtYSl9IFRPICR7cXVvdGUocm9sZSl9O2AsXG4gICAgYEdSQU5UIFNFTEVDVCwgSU5TRVJULCBERUxFVEUgT04gVEFCTEUgJHtzZWxlY3RlZH0gVE8gJHtxdW90ZShyb2xlKX07YCxcbiAgICBgR1JBTlQgU0VMRUNUIE9OIFRBQkxFICR7cXVvdGUob3B0aW9ucy5zY2hlbWEpfS4ke3F1b3RlKFwic2NoZW1hX3ZlcnNpb25cIil9IFRPICR7cXVvdGUocm9sZSl9O2AsXG4gIF0pO1xufVxuXG5mdW5jdGlvbiBjdXJzb3Ioc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZSwgc2VxdWVuY2U6IHN0cmluZyB8IG51bWJlcik6IHN0cmluZyB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShbc2NvcGUsIFN0cmluZyhzZXF1ZW5jZSldKSkudG9TdHJpbmcoXCJiYXNlNjR1cmxcIik7XG59XG5mdW5jdGlvbiBhZnRlcih2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkLCBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlKTogc3RyaW5nIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIFwiMFwiO1xuICBjb25zdCBkZWNvZGVkID0gSlNPTi5wYXJzZShCdWZmZXIuZnJvbSh2YWx1ZSwgXCJiYXNlNjR1cmxcIikudG9TdHJpbmcoKSkgYXMgW3N0cmluZywgc3RyaW5nXTtcbiAgaWYgKGRlY29kZWRbMF0gIT09IHNjb3BlKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkhpc3RvcnkgY3Vyc29yIGJlbG9uZ3MgdG8gYW5vdGhlciBwZXJzaXN0ZW5jZSBzY29wZVwiKTtcbiAgfVxuICByZXR1cm4gZGVjb2RlZFsxXTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB0dGxNaWxsaXNlY29uZHModmFsdWU6IER1cmF0aW9uSW5wdXQgfCBmYWxzZSk6IG51bWJlciB8IG51bGwge1xuICBpZiAodmFsdWUgPT09IGZhbHNlKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWlsbGlzZWNvbmRzID0gb2JqZWN0LnRvRHVyYXRpb24odmFsdWUpO1xuICBpZiAobWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWQgfHwgbWlsbGlzZWNvbmRzIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIHBlcnNpc3RlbmNlIFRUTDogJHtTdHJpbmcodmFsdWUpfWApO1xuICB9XG4gIHJldHVybiBtaWxsaXNlY29uZHM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhbnVwRXhwaXJlZChcbiAgcXVlcnlhYmxlOiBQZ1F1ZXJ5YWJsZSxcbiAgb3B0aW9uczogUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbiAgc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZSxcbiAgbGltaXQgPSBvcHRpb25zLmNsZWFudXBCYXRjaFNpemUsXG4pOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBxdWVyeWFibGUucXVlcnkoXG4gICAgYFdJVEggZXhwaXJlZCBBUyAoU0VMRUNUIGN0aWQgRlJPTSAke3RhYmxlKG9wdGlvbnMsIHNjb3BlKX0gV0hFUkUgZXhwaXJlc19hdCBJUyBOT1QgTlVMTCBBTkQgZXhwaXJlc19hdCA8PSBjbG9ja190aW1lc3RhbXAoKSBPUkRFUiBCWSBleHBpcmVzX2F0IExJTUlUICQxKSBERUxFVEUgRlJPTSAke3RhYmxlKG9wdGlvbnMsIHNjb3BlKX0gQVMgbWVzc2FnZXMgVVNJTkcgZXhwaXJlZCBXSEVSRSBtZXNzYWdlcy5jdGlkID0gZXhwaXJlZC5jdGlkYCxcbiAgICBbbGltaXRdLFxuICApO1xuICByZXR1cm4gcmVzdWx0LnJvd0NvdW50ID8/IDA7XG59XG5cbnR5cGUgSGlzdG9yeVJvdyA9IFF1ZXJ5UmVzdWx0Um93ICYge1xuICBzZXF1ZW5jZTogc3RyaW5nO1xuICBleHBpcmVzX2F0OiBEYXRlIHwgc3RyaW5nIHwgbnVsbDtcbiAgZW52ZWxvcGU6IFRvcGljTWVzc2FnZTtcbn07XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGlzdG9yeTxUQm9keSBleHRlbmRzIG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZT4oXG4gIHF1ZXJ5YWJsZTogUGdRdWVyeWFibGUsXG4gIGNoYW5uZWw6IHN0cmluZyxcbiAgdG9waWM6IHN0cmluZyxcbiAgb3B0aW9uczogUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbiAgaW5wdXQ6IHsgYWZ0ZXI/OiBzdHJpbmc7IGxpbWl0PzogbnVtYmVyOyBzY29wZT86IFRvcGljUGVyc2lzdGVuY2VTY29wZSB9ID0ge30sXG4pOiBQcm9taXNlPFRvcGljSGlzdG9yeVBhZ2U8VEJvZHk+PiB7XG4gIGNvbnN0IHNjb3BlID0gaW5wdXQuc2NvcGUgPz8gb3B0aW9ucy5zY29wZTtcbiAgY29uc3QgbGltaXQgPSBpbnB1dC5saW1pdCA/PyAxMDA7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5YWJsZS5xdWVyeTxIaXN0b3J5Um93PihcbiAgICBgU0VMRUNUIHNlcXVlbmNlLCBleHBpcmVzX2F0LCBlbnZlbG9wZSBGUk9NICR7dGFibGUob3B0aW9ucywgc2NvcGUpfSBXSEVSRSBjaGFubmVsID0gJDEgQU5EIHRvcGljID0gJDIgQU5EIHNlcXVlbmNlID4gJDM6OmJpZ2ludCBBTkQgKGV4cGlyZXNfYXQgSVMgTlVMTCBPUiBleHBpcmVzX2F0ID4gY2xvY2tfdGltZXN0YW1wKCkpIE9SREVSIEJZIHNlcXVlbmNlIExJTUlUICQ0YCxcbiAgICBbY2hhbm5lbCwgdG9waWMsIGFmdGVyKGlucHV0LmFmdGVyLCBzY29wZSksIGxpbWl0XSxcbiAgKTtcbiAgY29uc3QgbWVzc2FnZXMgPSByZXN1bHQucm93cy5tYXAoKHJvdykgPT4gKHtcbiAgICBjdXJzb3I6IGN1cnNvcihzY29wZSwgcm93LnNlcXVlbmNlKSxcbiAgICBleHBpcmVzQXQ6IHJvdy5leHBpcmVzX2F0ID09PSBudWxsID8gbnVsbCA6IG5ldyBEYXRlKHJvdy5leHBpcmVzX2F0KS50b0lTT1N0cmluZygpLFxuICAgIHNjb3BlLFxuICAgIG1lc3NhZ2U6IHJvdy5lbnZlbG9wZSBhcyBUb3BpY01lc3NhZ2U8VEJvZHk+LFxuICB9KSk7XG4gIHJldHVybiB7XG4gICAgbWVzc2FnZXMsXG4gICAgLi4uKG1lc3NhZ2VzLmxlbmd0aCA9PT0gbGltaXQgPyB7IG5leHRDdXJzb3I6IG1lc3NhZ2VzLmF0KC0xKSEuY3Vyc29yIH0gOiB7fSksXG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwZXJzaXN0ZWROb3RpZnkoXG4gIGNsaWVudDogUGdRdWVyeWFibGUsXG4gIGNoYW5uZWw6IHN0cmluZyxcbiAgdG9waWM6IHN0cmluZyxcbiAgbWVzc2FnZTogVG9waWNNZXNzYWdlLFxuICBlbmNvZGVkOiBzdHJpbmcsXG4gIG9wdGlvbnM6IFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4gIHNjb3BlOiBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsXG4gIHR0bDogRHVyYXRpb25JbnB1dCB8IGZhbHNlLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IGNsZWFudXBFeHBpcmVkKGNsaWVudCwgb3B0aW9ucywgc2NvcGUpO1xuICBjb25zdCBtaWxsaXNlY29uZHMgPSB0dGxNaWxsaXNlY29uZHModHRsKTtcbiAgY29uc3QgaW5zZXJ0ZWQgPSBhd2FpdCBjbGllbnQucXVlcnk8UXVlcnlSZXN1bHRSb3cgJiB7IHNlcXVlbmNlOiBzdHJpbmcgfT4oXG4gICAgYElOU0VSVCBJTlRPICR7dGFibGUob3B0aW9ucywgc2NvcGUpfSAoY2hhbm5lbCwgdG9waWMsIG1lc3NhZ2VfaWQsIHB1Ymxpc2hlZF9hdCwgZXhwaXJlc19hdCwgZW52ZWxvcGUpIFZBTFVFUyAoJDEsICQyLCAkMywgJDQsIENBU0UgV0hFTiAkNTo6YmlnaW50IElTIE5VTEwgVEhFTiBOVUxMIEVMU0UgY2xvY2tfdGltZXN0YW1wKCkgKyAoJDU6OmJpZ2ludCAqIGludGVydmFsICcxIG1pbGxpc2Vjb25kJykgRU5ELCAkNjo6anNvbmIpIFJFVFVSTklORyBzZXF1ZW5jZWAsXG4gICAgW2NoYW5uZWwsIHRvcGljLCBtZXNzYWdlLmlkLCBtZXNzYWdlLnB1Ymxpc2hlZEF0LCBtaWxsaXNlY29uZHMsIGVuY29kZWRdLFxuICApO1xuICAvLyBUaGUgcm93IGFuZCB0aGUgbm90aWZpY2F0aW9uIGNvbW1pdCB0b2dldGhlciwgc28gYSBwb2ludGVyIGlzIG5ldmVyIGRlbGl2ZXJlZFxuICAvLyBiZWZvcmUgdGhlIHJvdyBpdCBuYW1lcyBpcyByZWFkYWJsZSAtIGBOT1RJRllgIGlzIGRlbGl2ZXJlZCBhdCBDT01NSVQsIG5vdCBhdFxuICAvLyBzdGF0ZW1lbnQgdGltZS5cbiAgY29uc3QgcGF5bG9hZCA9XG4gICAgb3B0aW9ucy5wYXlsb2FkID09PSBcInBvaW50ZXJcIlxuICAgICAgPyBwb2ludGVyUGF5bG9hZChzY29wZSwgdG9waWMsIG1lc3NhZ2UuaWQsIGluc2VydGVkLnJvd3NbMF0/LnNlcXVlbmNlID8/IFwiMFwiKVxuICAgICAgOiBlbmNvZGVkO1xuICBhd2FpdCBjbGllbnQucXVlcnkoXCJTRUxFQ1QgcGdfbm90aWZ5KCQxLCAkMilcIiwgW2NoYW5uZWwsIHBheWxvYWRdKTtcbn1cblxuLyoqXG4gKiBUaGUgYHBheWxvYWQ6IFwicG9pbnRlclwiYCBub3RpZmljYXRpb24gYm9keTogcm91dGluZyBhbmQgaWRlbnRpdHkgb25seSwgc28gdGhlXG4gKiBzaXplIGxpbWl0IGRvZXMgbm90IGFwcGx5IGFuZCBhIGxpc3RlbmVyIHdpdGhvdXQgdGhlIHRhYmxlIGdyYW50IGxlYXJucyB0aGF0XG4gKiBzb21ldGhpbmcgaGFwcGVuZWQgd2l0aG91dCBsZWFybmluZyB3aGF0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcG9pbnRlclBheWxvYWQoXG4gIHNjb3BlOiBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsXG4gIHRvcGljOiBzdHJpbmcsXG4gIGlkOiBzdHJpbmcsXG4gIHNlcXVlbmNlOiBzdHJpbmcgfCBudW1iZXIsXG4pOiBzdHJpbmcge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoeyB2OiBQT0lOVEVSX1ZFUlNJT04sIHNjb3BlLCB0b3BpYywgaWQsIHNlcXVlbmNlOiBTdHJpbmcoc2VxdWVuY2UpIH0pO1xufVxuXG4vKiogQSBkZWNvZGVkIHBvaW50ZXIgbm90aWZpY2F0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUb3BpY1BvaW50ZXIge1xuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlO1xuICB0b3BpYzogc3RyaW5nO1xuICBpZDogc3RyaW5nO1xuICBzZXF1ZW5jZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlYWQgYSBub3RpZmljYXRpb24gYXMgYSBwb2ludGVyLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGlzIG5vdCBvbmUuIFRoZSBjaGFubmVsXG4gKiBpcyBzaGFyZWQsIHNvIGFuIHVucmVjb2duaXplZCBwYXlsb2FkIGlzIG9yZGluYXJ5IHRyYWZmaWMgcmF0aGVyIHRoYW4gYW4gZXJyb3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVQb2ludGVyKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBUb3BpY1BvaW50ZXIgfCB1bmRlZmluZWQge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICBsZXQgcmVjb3JkOiB1bmtub3duO1xuICB0cnkge1xuICAgIHJlY29yZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGlmICghcmVjb3JkIHx8IHR5cGVvZiByZWNvcmQgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShyZWNvcmQpKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBjYW5kaWRhdGUgPSByZWNvcmQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGlmIChjYW5kaWRhdGUudiAhPT0gUE9JTlRFUl9WRVJTSU9OKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCB7IHNjb3BlLCB0b3BpYywgaWQsIHNlcXVlbmNlIH0gPSBjYW5kaWRhdGU7XG4gIGlmIChzY29wZSAhPT0gXCJvcGVuXCIgJiYgc2NvcGUgIT09IFwicmVzdHJpY3RlZFwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIHRvcGljICE9PSBcInN0cmluZ1wiIHx8IHR5cGVvZiBpZCAhPT0gXCJzdHJpbmdcIiB8fCB0eXBlb2Ygc2VxdWVuY2UgIT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiB7IHNjb3BlLCB0b3BpYywgaWQsIHNlcXVlbmNlIH07XG59XG5cbi8qKlxuICogRmV0Y2ggdGhlIG9uZSBzdG9yZWQgZW52ZWxvcGUgYSBwb2ludGVyIG5hbWVzLiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gdGhlIHJvd1xuICogaXMgZ29uZSAoVFRMIGNsZWFudXAgd29uIHRoZSByYWNlKSBvciB0aGUgcmVhZGVyIGxhY2tzIHRoZSB0YWJsZSdzIGdyYW50LCBib3RoXG4gKiBvZiB3aGljaCBhcmUgZXhwZWN0ZWQgb24gdGhlIGByZXN0cmljdGVkYCB0aWVyIHJhdGhlciB0aGFuIGVycm9ycy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRQb2ludGVyPFRCb2R5IGV4dGVuZHMgb2JqZWN0LlNlcmlhbGl6YWJsZVZhbHVlPihcbiAgcXVlcnlhYmxlOiBQZ1F1ZXJ5YWJsZSxcbiAgY2hhbm5lbDogc3RyaW5nLFxuICBwb2ludGVyOiBUb3BpY1BvaW50ZXIsXG4gIG9wdGlvbnM6IFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4pOiBQcm9taXNlPFRvcGljTWVzc2FnZTxUQm9keT4gfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcXVlcnlhYmxlLnF1ZXJ5PFF1ZXJ5UmVzdWx0Um93ICYgeyBlbnZlbG9wZTogVG9waWNNZXNzYWdlIH0+KFxuICAgIGBTRUxFQ1QgZW52ZWxvcGUgRlJPTSAke3RhYmxlKG9wdGlvbnMsIHBvaW50ZXIuc2NvcGUpfSBXSEVSRSBjaGFubmVsID0gJDEgQU5EIG1lc3NhZ2VfaWQgPSAkMiBBTkQgKGV4cGlyZXNfYXQgSVMgTlVMTCBPUiBleHBpcmVzX2F0ID4gY2xvY2tfdGltZXN0YW1wKCkpYCxcbiAgICBbY2hhbm5lbCwgcG9pbnRlci5pZF0sXG4gICk7XG4gIHJldHVybiByZXN1bHQucm93c1swXT8uZW52ZWxvcGUgYXMgVG9waWNNZXNzYWdlPFRCb2R5PiB8IHVuZGVmaW5lZDtcbn1cbiJdfQ==
|
|
151
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyc2lzdGVuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGVyc2lzdGVuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBR2hELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBc0NqRSxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUM7QUFDL0I7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLEtBQUssR0FBRyxDQUFDLEtBQWEsRUFBVSxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDO0FBQzVFLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBMkMsRUFBRSxLQUE0QixFQUFVLEVBQUUsQ0FDbEcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUU3RCxNQUFNLFVBQVUseUJBQXlCLENBQ3ZDLEtBQXdDO0lBRXhDLE1BQU0sVUFBVSxHQUFHLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQy9DLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLElBQUksTUFBTSxDQUFDO0lBQ3pDLElBQUksS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLFNBQVMsQ0FBQyw4QkFBOEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsT0FBTztRQUNMLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxJQUFJLGlCQUFpQjtRQUM5QyxLQUFLO1FBQ0wsTUFBTSxFQUFFO1lBQ04sSUFBSSxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxJQUFJLGVBQWU7WUFDaEQsVUFBVSxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxJQUFJLHFCQUFxQjtTQUNuRTtRQUNELEdBQUcsRUFBRSxVQUFVLENBQUMsR0FBRyxJQUFJLFdBQVc7UUFDbEMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxPQUFPLElBQUksVUFBVTtRQUN6QyxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsZ0JBQWdCLElBQUksSUFBSTtRQUNyRCxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsSUFBSSxJQUFJO0tBQ3hDLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSx5QkFBeUIsQ0FDN0MsSUFBZ0IsRUFDaEIsT0FBMkM7SUFFM0MsTUFBTSwyQkFBMkIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxRQUFRLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDdEYsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzRSxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQ2hCLDhCQUE4QixLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxnQ0FBZ0MsQ0FDL0csQ0FBQztRQUNGLEtBQUssTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFVLEVBQUUsQ0FBQztZQUNwRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ25DLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FDaEIsOEJBQThCLElBQUksb1ZBQW9WLENBQ3ZYLENBQUM7WUFDRixNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQ2hCLDhCQUE4QixLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBTyxJQUFJLDZCQUE2QixDQUNuSCxDQUFDO1lBQ0YsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUNoQiw4QkFBOEIsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLE9BQU8sSUFBSSw0Q0FBNEMsQ0FDbEksQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQ2hCLGVBQWUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsd0RBQXdELENBQ3hILENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLFVBQVUseUJBQXlCLENBQ3ZDLEtBQWlDLEVBQ2pDLEtBQTRCLEVBQzVCLE9BQTJDO0lBRTNDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDdkMsT0FBTyxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNyRSx5QkFBeUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUc7UUFDbkUseUNBQXlDLFFBQVEsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUc7UUFDdEUseUJBQXlCLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHO0tBQy9GLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxLQUE0QixFQUFFLFFBQXlCO0lBQ3JFLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDdEYsQ0FBQztBQUNELFNBQVMsS0FBSyxDQUFDLEtBQXlCLEVBQUUsS0FBNEI7SUFDcEUsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUN2QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFxQixDQUFDO0lBQzNGLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxTQUFTLENBQUMscURBQXFELENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDcEIsQ0FBQztBQUVELGdGQUFnRjtBQUNoRixNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQTRCO0lBQzFELElBQUksS0FBSyxLQUFLLEtBQUs7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNqQyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLElBQUksWUFBWSxLQUFLLFNBQVMsSUFBSSxZQUFZLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDcEQsTUFBTSxJQUFJLFNBQVMsQ0FBQyw0QkFBNEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQ0QsT0FBTyxZQUFZLENBQUM7QUFDdEIsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsU0FBc0IsRUFDdEIsT0FBMkMsRUFDM0MsS0FBNEIsRUFDNUIsS0FBSyxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0I7SUFFaEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUNsQyxxQ0FBcUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsK0dBQStHLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLCtEQUErRCxFQUM3UCxDQUFDLEtBQUssQ0FBQyxDQUNSLENBQUM7SUFDRixPQUFPLE1BQU0sQ0FBQyxRQUFRLElBQUksQ0FBQyxDQUFDO0FBQzlCLENBQUM7QUFRRCwrREFBK0Q7QUFDL0QsTUFBTSxDQUFDLEtBQUssVUFBVSxPQUFPLENBQzNCLFNBQXNCLEVBQ3RCLE9BQWUsRUFDZixLQUFhLEVBQ2IsT0FBMkMsRUFDM0MsUUFBMkUsRUFBRTtJQUU3RSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDM0MsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUM7SUFDakMsTUFBTSxNQUFNLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUNsQyw4Q0FBOEMsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsb0pBQW9KLEVBQ3ZOLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FDbkQsQ0FBQztJQUNGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDbkMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUU7UUFDbEYsS0FBSztRQUNMLE9BQU8sRUFBRSxHQUFHLENBQUMsUUFBK0I7S0FDN0MsQ0FBQyxDQUFDLENBQUM7SUFDSixPQUFPO1FBQ0wsUUFBUTtRQUNSLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDOUUsQ0FBQztBQUNKLENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQ25DLE1BQW1CLEVBQ25CLE9BQWUsRUFDZixLQUFhLEVBQ2IsT0FBcUIsRUFDckIsT0FBZSxFQUNmLE9BQTJDLEVBQzNDLEtBQTRCLEVBQzVCLEdBQTBCO0lBRTFCLE1BQU0sY0FBYyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDN0MsTUFBTSxZQUFZLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FDakMsZUFBZSxLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxzT0FBc08sRUFDMVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLFdBQVcsRUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQ3pFLENBQUM7SUFDRixnRkFBZ0Y7SUFDaEYsZ0ZBQWdGO0lBQ2hGLGtCQUFrQjtJQUNsQixNQUFNLE9BQU8sR0FDWCxPQUFPLENBQUMsT0FBTyxLQUFLLFNBQVM7UUFDM0IsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLElBQUksR0FBRyxDQUFDO1FBQzdFLENBQUMsQ0FBQyxPQUFPLENBQUM7SUFDZCxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNyRSxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQzVCLEtBQTRCLEVBQzVCLEtBQWEsRUFDYixFQUFVLEVBQ1YsUUFBeUI7SUFFekIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM5RixDQUFDO0FBVUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxLQUF5QjtJQUNyRCxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzdCLElBQUksTUFBZSxDQUFDO0lBQ3BCLElBQUksQ0FBQztRQUNILE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNyRixNQUFNLFNBQVMsR0FBRyxNQUFpQyxDQUFDO0lBQ3BELElBQUksU0FBUyxDQUFDLENBQUMsS0FBSyxlQUFlO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDdEQsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNqRCxJQUFJLEtBQUssS0FBSyxNQUFNLElBQUksS0FBSyxLQUFLLFlBQVk7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNqRSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxPQUFPLEVBQUUsS0FBSyxRQUFRLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDeEYsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUN4QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUMvQixTQUFzQixFQUN0QixPQUFlLEVBQ2YsT0FBcUIsRUFDckIsT0FBMkM7SUFFM0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUNsQyx3QkFBd0IsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLG9HQUFvRyxFQUN6SixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQ3RCLENBQUM7SUFDRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBMkMsQ0FBQztBQUNyRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUXVlcnlSZXN1bHRSb3cgfSBmcm9tIFwicGdcIjtcbmltcG9ydCB0eXBlIHsgUGdQb29sTGlrZSwgUGdRdWVyeWFibGUgfSBmcm9tIFwiLi9hZHZpc29yeS1sb2NrLnRzXCI7XG5pbXBvcnQgeyB3aXRoQWR2aXNvcnlUcmFuc2FjdGlvbkxvY2sgfSBmcm9tIFwiLi9hZHZpc29yeS1sb2NrLnRzXCI7XG5pbXBvcnQgdHlwZSB7IFRvcGljTWVzc2FnZSB9IGZyb20gXCIuL3RvcGljLWJ1cy50c1wiO1xuXG5leHBvcnQgdHlwZSBUb3BpY1BlcnNpc3RlbmNlU2NvcGUgPSBcIm9wZW5cIiB8IFwicmVzdHJpY3RlZFwiO1xuZXhwb3J0IHR5cGUgRHVyYXRpb25JbnB1dCA9IHN0cmluZyB8IG51bWJlcjtcbmV4cG9ydCBpbnRlcmZhY2UgVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMge1xuICBzY2hlbWE/OiBzdHJpbmc7XG4gIHNjb3BlPzogVG9waWNQZXJzaXN0ZW5jZVNjb3BlO1xuICB0YWJsZXM/OiBQYXJ0aWFsPFJlY29yZDxUb3BpY1BlcnNpc3RlbmNlU2NvcGUsIHN0cmluZz4+O1xuICB0dGw/OiBEdXJhdGlvbklucHV0IHwgZmFsc2U7XG4gIHBheWxvYWQ/OiBcImVudmVsb3BlXCIgfCBcInBvaW50ZXJcIjtcbiAgY2xlYW51cEJhdGNoU2l6ZT86IG51bWJlcjtcbiAgcHJvdmlzaW9uPzogYm9vbGVhbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyB7XG4gIHNjaGVtYTogc3RyaW5nO1xuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlO1xuICB0YWJsZXM6IFJlY29yZDxUb3BpY1BlcnNpc3RlbmNlU2NvcGUsIHN0cmluZz47XG4gIHR0bDogRHVyYXRpb25JbnB1dCB8IGZhbHNlO1xuICBwYXlsb2FkOiBcImVudmVsb3BlXCIgfCBcInBvaW50ZXJcIjtcbiAgY2xlYW51cEJhdGNoU2l6ZTogbnVtYmVyO1xuICBwcm92aXNpb246IGJvb2xlYW47XG59XG5leHBvcnQgaW50ZXJmYWNlIFN0b3JlZFRvcGljTWVzc2FnZTxcbiAgVEJvZHkgZXh0ZW5kcyBvYmplY3QuU2VyaWFsaXphYmxlVmFsdWUgPSBvYmplY3QuU2VyaWFsaXphYmxlVmFsdWUsXG4+IHtcbiAgY3Vyc29yOiBzdHJpbmc7XG4gIGV4cGlyZXNBdDogc3RyaW5nIHwgbnVsbDtcbiAgc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZTtcbiAgbWVzc2FnZTogVG9waWNNZXNzYWdlPFRCb2R5Pjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgVG9waWNIaXN0b3J5UGFnZTxcbiAgVEJvZHkgZXh0ZW5kcyBvYmplY3QuU2VyaWFsaXphYmxlVmFsdWUgPSBvYmplY3QuU2VyaWFsaXphYmxlVmFsdWUsXG4+IHtcbiAgbWVzc2FnZXM6IFN0b3JlZFRvcGljTWVzc2FnZTxUQm9keT5bXTtcbiAgbmV4dEN1cnNvcj86IHN0cmluZztcbn1cblxuY29uc3QgREVGQVVMVF9UVEwgPSBcIjI0IGhvdXJzXCI7XG4vKipcbiAqIFBvaW50ZXItcGF5bG9hZCB2ZXJzaW9uLiBBIGxpc3RlbmVyIHRoYXQgZG9lcyBub3QgcmVjb2duaXplIHRoZSB2ZXJzaW9uIHRyZWF0c1xuICogdGhlIG5vdGlmaWNhdGlvbiBhcyBmb3JlaWduIHRyYWZmaWMgcmF0aGVyIHRoYW4gZ3Vlc3NpbmcgYXQgaXRzIHNoYXBlLlxuICovXG5leHBvcnQgY29uc3QgUE9JTlRFUl9WRVJTSU9OID0gMTtcbmNvbnN0IHF1b3RlID0gKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcgPT4gYFwiJHt2YWx1ZS5yZXBsYWNlQWxsKCdcIicsICdcIlwiJyl9XCJgO1xuY29uc3QgdGFibGUgPSAob3B0aW9uczogUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucywgc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZSk6IHN0cmluZyA9PlxuICBgJHtxdW90ZShvcHRpb25zLnNjaGVtYSl9LiR7cXVvdGUob3B0aW9ucy50YWJsZXNbc2NvcGVdKX1gO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVBlcnNpc3RlbmNlT3B0aW9ucyhcbiAgdmFsdWU6IHRydWUgfCBUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbik6IFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMge1xuICBjb25zdCBjb25maWd1cmVkID0gdmFsdWUgPT09IHRydWUgPyB7fSA6IHZhbHVlO1xuICBjb25zdCBzY29wZSA9IGNvbmZpZ3VyZWQuc2NvcGUgPz8gXCJvcGVuXCI7XG4gIGlmIChzY29wZSAhPT0gXCJvcGVuXCIgJiYgc2NvcGUgIT09IFwicmVzdHJpY3RlZFwiKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5rbm93biBwZXJzaXN0ZW5jZSBzY29wZTogJHtTdHJpbmcoc2NvcGUpfWApO1xuICB9XG4gIHJldHVybiB7XG4gICAgc2NoZW1hOiBjb25maWd1cmVkLnNjaGVtYSA/PyBcImRieF9tZXNzYWdlX2J1c1wiLFxuICAgIHNjb3BlLFxuICAgIHRhYmxlczoge1xuICAgICAgb3BlbjogY29uZmlndXJlZC50YWJsZXM/Lm9wZW4gPz8gXCJvcGVuX21lc3NhZ2VzXCIsXG4gICAgICByZXN0cmljdGVkOiBjb25maWd1cmVkLnRhYmxlcz8ucmVzdHJpY3RlZCA/PyBcInJlc3RyaWN0ZWRfbWVzc2FnZXNcIixcbiAgICB9LFxuICAgIHR0bDogY29uZmlndXJlZC50dGwgPz8gREVGQVVMVF9UVEwsXG4gICAgcGF5bG9hZDogY29uZmlndXJlZC5wYXlsb2FkID8/IFwiZW52ZWxvcGVcIixcbiAgICBjbGVhbnVwQmF0Y2hTaXplOiBjb25maWd1cmVkLmNsZWFudXBCYXRjaFNpemUgPz8gMTAwMCxcbiAgICBwcm92aXNpb246IGNvbmZpZ3VyZWQucHJvdmlzaW9uID8/IHRydWUsXG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm92aXNpb25NZXNzYWdlQnVzU2NoZW1hKFxuICBwb29sOiBQZ1Bvb2xMaWtlLFxuICBvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IHdpdGhBZHZpc29yeVRyYW5zYWN0aW9uTG9jayhwb29sLCBbXCJkYnhfbWVzc2FnZV9idXNcIiwgXCJzY2hlbWFcIl0sIGFzeW5jIChjbGllbnQpID0+IHtcbiAgICBhd2FpdCBjbGllbnQucXVlcnkoYENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUUyAke3F1b3RlKG9wdGlvbnMuc2NoZW1hKX1gKTtcbiAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJHtxdW90ZShvcHRpb25zLnNjaGVtYSl9LiR7cXVvdGUoXCJzY2hlbWFfdmVyc2lvblwiKX0gKHZlcnNpb24gSU5URUdFUiBQUklNQVJZIEtFWSlgLFxuICAgICk7XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiBbXCJvcGVuXCIsIFwicmVzdHJpY3RlZFwiXSBhcyBjb25zdCkge1xuICAgICAgY29uc3QgbmFtZSA9IHRhYmxlKG9wdGlvbnMsIHNjb3BlKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTICR7bmFtZX0gKHNlcXVlbmNlIEJJR0lOVCBHRU5FUkFURUQgQUxXQVlTIEFTIElERU5USVRZIFBSSU1BUlkgS0VZLCBjaGFubmVsIFRFWFQgTk9UIE5VTEwsIHRvcGljIFRFWFQgTk9UIE5VTEwsIG1lc3NhZ2VfaWQgVEVYVCBOT1QgTlVMTCwgcHVibGlzaGVkX2F0IFRJTUVTVEFNUFRaIE5PVCBOVUxMLCBleHBpcmVzX2F0IFRJTUVTVEFNUFRaLCB4YWN0X2lkIFhJRDggTk9UIE5VTEwgREVGQVVMVCBwZ19jdXJyZW50X3hhY3RfaWQoKSwgZW52ZWxvcGUgSlNPTkIgTk9UIE5VTEwsIFVOSVFVRSAoY2hhbm5lbCwgbWVzc2FnZV9pZCksIENIRUNLIChqc29uYl90eXBlb2YoZW52ZWxvcGUpID0gJ29iamVjdCcpKWAsXG4gICAgICApO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KFxuICAgICAgICBgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgJHtxdW90ZShgJHtvcHRpb25zLnRhYmxlc1tzY29wZV19X3JlcGxheV9pZHhgKX0gT04gJHtuYW1lfSAoY2hhbm5lbCwgdG9waWMsIHNlcXVlbmNlKWAsXG4gICAgICApO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KFxuICAgICAgICBgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgJHtxdW90ZShgJHtvcHRpb25zLnRhYmxlc1tzY29wZV19X2V4cGlyeV9pZHhgKX0gT04gJHtuYW1lfSAoZXhwaXJlc19hdCkgV0hFUkUgZXhwaXJlc19hdCBJUyBOT1QgTlVMTGAsXG4gICAgICApO1xuICAgIH1cbiAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICBgSU5TRVJUIElOVE8gJHtxdW90ZShvcHRpb25zLnNjaGVtYSl9LiR7cXVvdGUoXCJzY2hlbWFfdmVyc2lvblwiKX0gKHZlcnNpb24pIFZBTFVFUyAoMSkgT04gQ09ORkxJQ1QgKHZlcnNpb24pIERPIE5PVEhJTkdgLFxuICAgICk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWVzc2FnZUJ1c0dyYW50U3RhdGVtZW50cyhcbiAgcm9sZXM6IHN0cmluZyB8IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlLFxuICBvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuKTogc3RyaW5nW10ge1xuICBjb25zdCBzZWxlY3RlZCA9IHRhYmxlKG9wdGlvbnMsIHNjb3BlKTtcbiAgcmV0dXJuICh0eXBlb2Ygcm9sZXMgPT09IFwic3RyaW5nXCIgPyBbcm9sZXNdIDogcm9sZXMpLmZsYXRNYXAoKHJvbGUpID0+IFtcbiAgICBgR1JBTlQgVVNBR0UgT04gU0NIRU1BICR7cXVvdGUob3B0aW9ucy5zY2hlbWEpfSBUTyAke3F1b3RlKHJvbGUpfTtgLFxuICAgIGBHUkFOVCBTRUxFQ1QsIElOU0VSVCwgREVMRVRFIE9OIFRBQkxFICR7c2VsZWN0ZWR9IFRPICR7cXVvdGUocm9sZSl9O2AsXG4gICAgYEdSQU5UIFNFTEVDVCBPTiBUQUJMRSAke3F1b3RlKG9wdGlvbnMuc2NoZW1hKX0uJHtxdW90ZShcInNjaGVtYV92ZXJzaW9uXCIpfSBUTyAke3F1b3RlKHJvbGUpfTtgLFxuICBdKTtcbn1cblxuZnVuY3Rpb24gY3Vyc29yKHNjb3BlOiBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsIHNlcXVlbmNlOiBzdHJpbmcgfCBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoW3Njb3BlLCBTdHJpbmcoc2VxdWVuY2UpXSkpLnRvU3RyaW5nKFwiYmFzZTY0dXJsXCIpO1xufVxuZnVuY3Rpb24gYWZ0ZXIodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCwgc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZSk6IHN0cmluZyB7XG4gIGlmICghdmFsdWUpIHJldHVybiBcIjBcIjtcbiAgY29uc3QgZGVjb2RlZCA9IEpTT04ucGFyc2UoQnVmZmVyLmZyb20odmFsdWUsIFwiYmFzZTY0dXJsXCIpLnRvU3RyaW5nKCkpIGFzIFtzdHJpbmcsIHN0cmluZ107XG4gIGlmIChkZWNvZGVkWzBdICE9PSBzY29wZSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJIaXN0b3J5IGN1cnNvciBiZWxvbmdzIHRvIGFub3RoZXIgcGVyc2lzdGVuY2Ugc2NvcGVcIik7XG4gIH1cbiAgcmV0dXJuIGRlY29kZWRbMV07XG59XG5cbi8qKiBDb252ZXJ0IGEgcGVyc2lzdGVuY2UgVFRMIHRvIG1pbGxpc2Vjb25kcywgcHJlc2VydmluZyBkaXNhYmxlZCByZXRlbnRpb24uICovXG5leHBvcnQgZnVuY3Rpb24gdHRsTWlsbGlzZWNvbmRzKHZhbHVlOiBEdXJhdGlvbklucHV0IHwgZmFsc2UpOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKHZhbHVlID09PSBmYWxzZSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG1pbGxpc2Vjb25kcyA9IG9iamVjdC50b0R1cmF0aW9uKHZhbHVlKTtcbiAgaWYgKG1pbGxpc2Vjb25kcyA9PT0gdW5kZWZpbmVkIHx8IG1pbGxpc2Vjb25kcyA8PSAwKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBwZXJzaXN0ZW5jZSBUVEw6ICR7U3RyaW5nKHZhbHVlKX1gKTtcbiAgfVxuICByZXR1cm4gbWlsbGlzZWNvbmRzO1xufVxuXG4vKiogRGVsZXRlIG9uZSBib3VuZGVkIGJhdGNoIG9mIGV4cGlyZWQgcGVyc2lzdGVkIHRvcGljIG1lc3NhZ2VzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsZWFudXBFeHBpcmVkKFxuICBxdWVyeWFibGU6IFBnUXVlcnlhYmxlLFxuICBvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlLFxuICBsaW1pdCA9IG9wdGlvbnMuY2xlYW51cEJhdGNoU2l6ZSxcbik6IFByb21pc2U8bnVtYmVyPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5YWJsZS5xdWVyeShcbiAgICBgV0lUSCBleHBpcmVkIEFTIChTRUxFQ1QgY3RpZCBGUk9NICR7dGFibGUob3B0aW9ucywgc2NvcGUpfSBXSEVSRSBleHBpcmVzX2F0IElTIE5PVCBOVUxMIEFORCBleHBpcmVzX2F0IDw9IGNsb2NrX3RpbWVzdGFtcCgpIE9SREVSIEJZIGV4cGlyZXNfYXQgTElNSVQgJDEpIERFTEVURSBGUk9NICR7dGFibGUob3B0aW9ucywgc2NvcGUpfSBBUyBtZXNzYWdlcyBVU0lORyBleHBpcmVkIFdIRVJFIG1lc3NhZ2VzLmN0aWQgPSBleHBpcmVkLmN0aWRgLFxuICAgIFtsaW1pdF0sXG4gICk7XG4gIHJldHVybiByZXN1bHQucm93Q291bnQgPz8gMDtcbn1cblxudHlwZSBIaXN0b3J5Um93ID0gUXVlcnlSZXN1bHRSb3cgJiB7XG4gIHNlcXVlbmNlOiBzdHJpbmc7XG4gIGV4cGlyZXNfYXQ6IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICBlbnZlbG9wZTogVG9waWNNZXNzYWdlO1xufTtcblxuLyoqIFJlYWQgYSBjdXJzb3ItcGFnaW5hdGVkIHBhZ2Ugb2YgcGVyc2lzdGVkIHRvcGljIGhpc3RvcnkuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGlzdG9yeTxUQm9keSBleHRlbmRzIG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZT4oXG4gIHF1ZXJ5YWJsZTogUGdRdWVyeWFibGUsXG4gIGNoYW5uZWw6IHN0cmluZyxcbiAgdG9waWM6IHN0cmluZyxcbiAgb3B0aW9uczogUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbiAgaW5wdXQ6IHsgYWZ0ZXI/OiBzdHJpbmc7IGxpbWl0PzogbnVtYmVyOyBzY29wZT86IFRvcGljUGVyc2lzdGVuY2VTY29wZSB9ID0ge30sXG4pOiBQcm9taXNlPFRvcGljSGlzdG9yeVBhZ2U8VEJvZHk+PiB7XG4gIGNvbnN0IHNjb3BlID0gaW5wdXQuc2NvcGUgPz8gb3B0aW9ucy5zY29wZTtcbiAgY29uc3QgbGltaXQgPSBpbnB1dC5saW1pdCA/PyAxMDA7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5YWJsZS5xdWVyeTxIaXN0b3J5Um93PihcbiAgICBgU0VMRUNUIHNlcXVlbmNlLCBleHBpcmVzX2F0LCBlbnZlbG9wZSBGUk9NICR7dGFibGUob3B0aW9ucywgc2NvcGUpfSBXSEVSRSBjaGFubmVsID0gJDEgQU5EIHRvcGljID0gJDIgQU5EIHNlcXVlbmNlID4gJDM6OmJpZ2ludCBBTkQgKGV4cGlyZXNfYXQgSVMgTlVMTCBPUiBleHBpcmVzX2F0ID4gY2xvY2tfdGltZXN0YW1wKCkpIE9SREVSIEJZIHNlcXVlbmNlIExJTUlUICQ0YCxcbiAgICBbY2hhbm5lbCwgdG9waWMsIGFmdGVyKGlucHV0LmFmdGVyLCBzY29wZSksIGxpbWl0XSxcbiAgKTtcbiAgY29uc3QgbWVzc2FnZXMgPSByZXN1bHQucm93cy5tYXAoKHJvdykgPT4gKHtcbiAgICBjdXJzb3I6IGN1cnNvcihzY29wZSwgcm93LnNlcXVlbmNlKSxcbiAgICBleHBpcmVzQXQ6IHJvdy5leHBpcmVzX2F0ID09PSBudWxsID8gbnVsbCA6IG5ldyBEYXRlKHJvdy5leHBpcmVzX2F0KS50b0lTT1N0cmluZygpLFxuICAgIHNjb3BlLFxuICAgIG1lc3NhZ2U6IHJvdy5lbnZlbG9wZSBhcyBUb3BpY01lc3NhZ2U8VEJvZHk+LFxuICB9KSk7XG4gIHJldHVybiB7XG4gICAgbWVzc2FnZXMsXG4gICAgLi4uKG1lc3NhZ2VzLmxlbmd0aCA9PT0gbGltaXQgPyB7IG5leHRDdXJzb3I6IG1lc3NhZ2VzLmF0KC0xKSEuY3Vyc29yIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKiBQZXJzaXN0IGEgdG9waWMgbWVzc2FnZSBhbmQgbm90aWZ5IGxpc3RlbmVycyBpbiBvbmUgdHJhbnNhY3Rpb24uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGVyc2lzdGVkTm90aWZ5KFxuICBjbGllbnQ6IFBnUXVlcnlhYmxlLFxuICBjaGFubmVsOiBzdHJpbmcsXG4gIHRvcGljOiBzdHJpbmcsXG4gIG1lc3NhZ2U6IFRvcGljTWVzc2FnZSxcbiAgZW5jb2RlZDogc3RyaW5nLFxuICBvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlLFxuICB0dGw6IER1cmF0aW9uSW5wdXQgfCBmYWxzZSxcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBjbGVhbnVwRXhwaXJlZChjbGllbnQsIG9wdGlvbnMsIHNjb3BlKTtcbiAgY29uc3QgbWlsbGlzZWNvbmRzID0gdHRsTWlsbGlzZWNvbmRzKHR0bCk7XG4gIGNvbnN0IGluc2VydGVkID0gYXdhaXQgY2xpZW50LnF1ZXJ5PFF1ZXJ5UmVzdWx0Um93ICYgeyBzZXF1ZW5jZTogc3RyaW5nIH0+KFxuICAgIGBJTlNFUlQgSU5UTyAke3RhYmxlKG9wdGlvbnMsIHNjb3BlKX0gKGNoYW5uZWwsIHRvcGljLCBtZXNzYWdlX2lkLCBwdWJsaXNoZWRfYXQsIGV4cGlyZXNfYXQsIGVudmVsb3BlKSBWQUxVRVMgKCQxLCAkMiwgJDMsICQ0LCBDQVNFIFdIRU4gJDU6OmJpZ2ludCBJUyBOVUxMIFRIRU4gTlVMTCBFTFNFIGNsb2NrX3RpbWVzdGFtcCgpICsgKCQ1OjpiaWdpbnQgKiBpbnRlcnZhbCAnMSBtaWxsaXNlY29uZCcpIEVORCwgJDY6Ompzb25iKSBSRVRVUk5JTkcgc2VxdWVuY2VgLFxuICAgIFtjaGFubmVsLCB0b3BpYywgbWVzc2FnZS5pZCwgbWVzc2FnZS5wdWJsaXNoZWRBdCwgbWlsbGlzZWNvbmRzLCBlbmNvZGVkXSxcbiAgKTtcbiAgLy8gVGhlIHJvdyBhbmQgdGhlIG5vdGlmaWNhdGlvbiBjb21taXQgdG9nZXRoZXIsIHNvIGEgcG9pbnRlciBpcyBuZXZlciBkZWxpdmVyZWRcbiAgLy8gYmVmb3JlIHRoZSByb3cgaXQgbmFtZXMgaXMgcmVhZGFibGUgLSBgTk9USUZZYCBpcyBkZWxpdmVyZWQgYXQgQ09NTUlULCBub3QgYXRcbiAgLy8gc3RhdGVtZW50IHRpbWUuXG4gIGNvbnN0IHBheWxvYWQgPVxuICAgIG9wdGlvbnMucGF5bG9hZCA9PT0gXCJwb2ludGVyXCJcbiAgICAgID8gcG9pbnRlclBheWxvYWQoc2NvcGUsIHRvcGljLCBtZXNzYWdlLmlkLCBpbnNlcnRlZC5yb3dzWzBdPy5zZXF1ZW5jZSA/PyBcIjBcIilcbiAgICAgIDogZW5jb2RlZDtcbiAgYXdhaXQgY2xpZW50LnF1ZXJ5KFwiU0VMRUNUIHBnX25vdGlmeSgkMSwgJDIpXCIsIFtjaGFubmVsLCBwYXlsb2FkXSk7XG59XG5cbi8qKlxuICogVGhlIGBwYXlsb2FkOiBcInBvaW50ZXJcImAgbm90aWZpY2F0aW9uIGJvZHk6IHJvdXRpbmcgYW5kIGlkZW50aXR5IG9ubHksIHNvIHRoZVxuICogc2l6ZSBsaW1pdCBkb2VzIG5vdCBhcHBseSBhbmQgYSBsaXN0ZW5lciB3aXRob3V0IHRoZSB0YWJsZSBncmFudCBsZWFybnMgdGhhdFxuICogc29tZXRoaW5nIGhhcHBlbmVkIHdpdGhvdXQgbGVhcm5pbmcgd2hhdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBvaW50ZXJQYXlsb2FkKFxuICBzY29wZTogVG9waWNQZXJzaXN0ZW5jZVNjb3BlLFxuICB0b3BpYzogc3RyaW5nLFxuICBpZDogc3RyaW5nLFxuICBzZXF1ZW5jZTogc3RyaW5nIHwgbnVtYmVyLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHsgdjogUE9JTlRFUl9WRVJTSU9OLCBzY29wZSwgdG9waWMsIGlkLCBzZXF1ZW5jZTogU3RyaW5nKHNlcXVlbmNlKSB9KTtcbn1cblxuLyoqIEEgZGVjb2RlZCBwb2ludGVyIG5vdGlmaWNhdGlvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVG9waWNQb2ludGVyIHtcbiAgc2NvcGU6IFRvcGljUGVyc2lzdGVuY2VTY29wZTtcbiAgdG9waWM6IHN0cmluZztcbiAgaWQ6IHN0cmluZztcbiAgc2VxdWVuY2U6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWFkIGEgbm90aWZpY2F0aW9uIGFzIGEgcG9pbnRlciwgb3IgYHVuZGVmaW5lZGAgd2hlbiBpdCBpcyBub3Qgb25lLiBUaGUgY2hhbm5lbFxuICogaXMgc2hhcmVkLCBzbyBhbiB1bnJlY29nbml6ZWQgcGF5bG9hZCBpcyBvcmRpbmFyeSB0cmFmZmljIHJhdGhlciB0aGFuIGFuIGVycm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlUG9pbnRlcih2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogVG9waWNQb2ludGVyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgbGV0IHJlY29yZDogdW5rbm93bjtcbiAgdHJ5IHtcbiAgICByZWNvcmQgPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBpZiAoIXJlY29yZCB8fCB0eXBlb2YgcmVjb3JkICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkocmVjb3JkKSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgY2FuZGlkYXRlID0gcmVjb3JkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBpZiAoY2FuZGlkYXRlLnYgIT09IFBPSU5URVJfVkVSU0lPTikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgeyBzY29wZSwgdG9waWMsIGlkLCBzZXF1ZW5jZSB9ID0gY2FuZGlkYXRlO1xuICBpZiAoc2NvcGUgIT09IFwib3BlblwiICYmIHNjb3BlICE9PSBcInJlc3RyaWN0ZWRcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKHR5cGVvZiB0b3BpYyAhPT0gXCJzdHJpbmdcIiB8fCB0eXBlb2YgaWQgIT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIHNlcXVlbmNlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4geyBzY29wZSwgdG9waWMsIGlkLCBzZXF1ZW5jZSB9O1xufVxuXG4vKipcbiAqIEZldGNoIHRoZSBvbmUgc3RvcmVkIGVudmVsb3BlIGEgcG9pbnRlciBuYW1lcy4gUmV0dXJucyBgdW5kZWZpbmVkYCB3aGVuIHRoZSByb3dcbiAqIGlzIGdvbmUgKFRUTCBjbGVhbnVwIHdvbiB0aGUgcmFjZSkgb3IgdGhlIHJlYWRlciBsYWNrcyB0aGUgdGFibGUncyBncmFudCwgYm90aFxuICogb2Ygd2hpY2ggYXJlIGV4cGVjdGVkIG9uIHRoZSBgcmVzdHJpY3RlZGAgdGllciByYXRoZXIgdGhhbiBlcnJvcnMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUG9pbnRlcjxUQm9keSBleHRlbmRzIG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZT4oXG4gIHF1ZXJ5YWJsZTogUGdRdWVyeWFibGUsXG4gIGNoYW5uZWw6IHN0cmluZyxcbiAgcG9pbnRlcjogVG9waWNQb2ludGVyLFxuICBvcHRpb25zOiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zLFxuKTogUHJvbWlzZTxUb3BpY01lc3NhZ2U8VEJvZHk+IHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5YWJsZS5xdWVyeTxRdWVyeVJlc3VsdFJvdyAmIHsgZW52ZWxvcGU6IFRvcGljTWVzc2FnZSB9PihcbiAgICBgU0VMRUNUIGVudmVsb3BlIEZST00gJHt0YWJsZShvcHRpb25zLCBwb2ludGVyLnNjb3BlKX0gV0hFUkUgY2hhbm5lbCA9ICQxIEFORCBtZXNzYWdlX2lkID0gJDIgQU5EIChleHBpcmVzX2F0IElTIE5VTEwgT1IgZXhwaXJlc19hdCA+IGNsb2NrX3RpbWVzdGFtcCgpKWAsXG4gICAgW2NoYW5uZWwsIHBvaW50ZXIuaWRdLFxuICApO1xuICByZXR1cm4gcmVzdWx0LnJvd3NbMF0/LmVudmVsb3BlIGFzIFRvcGljTWVzc2FnZTxUQm9keT4gfCB1bmRlZmluZWQ7XG59XG4iXX0=
|
package/lib/src/topic-bus.d.ts
CHANGED
|
@@ -133,29 +133,6 @@ export interface PostgresTopicBusOptions {
|
|
|
133
133
|
onError?: (cause: unknown) => void;
|
|
134
134
|
persist?: boolean | TopicBusPersistenceOptions;
|
|
135
135
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Derive a legal Postgres channel name from whatever a caller used to identify
|
|
138
|
-
* the channel.
|
|
139
|
-
*
|
|
140
|
-
* Callers think in terms of what the channel IS - an app name, a tenant id, a
|
|
141
|
-
* `[env, feature]` pair, a config object - and none of those are identifiers.
|
|
142
|
-
* Rejecting them pushed the sanitizing onto every call site, which is how two
|
|
143
|
-
* services end up disagreeing about whether the channel is `my-app`, `my_app`,
|
|
144
|
-
* or `myApp` and silently never hear each other.
|
|
145
|
-
*
|
|
146
|
-
* The parts are tokenized and joined into an identifier, then a short hash of the
|
|
147
|
-
* ORIGINAL parts is appended. The hash is what makes the mapping trustworthy:
|
|
148
|
-
* tokenizing alone is lossy, so `my-app` and `my_app` and `myApp` would collapse
|
|
149
|
-
* onto one channel, and a name long enough to hit `NAMEDATALEN` would collide
|
|
150
|
-
* with anything sharing its leading tokens. With the suffix, the readable part
|
|
151
|
-
* stays readable and distinct inputs stay distinct.
|
|
152
|
-
*
|
|
153
|
-
* Deterministic across processes and runs, which is the whole point - two
|
|
154
|
-
* services given the same parts must land on the same channel without
|
|
155
|
-
* coordinating. Hash inputs are structure-aware, so `["a", "b"]` and `["a_b"]`
|
|
156
|
-
* differ, and object key order does not.
|
|
157
|
-
*/
|
|
158
|
-
export declare function channelName(value: unknown): string;
|
|
159
136
|
/**
|
|
160
137
|
* Broadcasts structured messages by topic and delivers them to every process
|
|
161
138
|
* listening on the same channel.
|
package/lib/src/topic-bus.js
CHANGED
|
@@ -25,19 +25,10 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { hostname } from "node:os";
|
|
27
27
|
import { asyncUtils, errorUtils, hash, json, object, stringUtils } from "@dbx-tools/shared-core";
|
|
28
|
+
import { channelName } from "./identity.js";
|
|
28
29
|
import { cleanupExpired, decodePointer, history, persistedNotify, provisionMessageBusSchema, readPointer, resolvePersistenceOptions, } from "./persistence.js";
|
|
29
30
|
/** Channel parts used when a caller names no channel of its own. */
|
|
30
31
|
const DEFAULT_CHANNEL = "dbx_tools_topic_bus";
|
|
31
|
-
/**
|
|
32
|
-
* `NAMEDATALEN - 1`. Postgres TRUNCATES a longer channel name rather than
|
|
33
|
-
* rejecting it, which would split publishers and listeners onto different
|
|
34
|
-
* channels while every call looked like it succeeded.
|
|
35
|
-
*/
|
|
36
|
-
const MAX_CHANNEL_LENGTH = 63;
|
|
37
|
-
/** Base-32 chars of the channel's identity suffix. Max 7 - the digest is 32 bits. */
|
|
38
|
-
const CHANNEL_HASH_LENGTH = 6;
|
|
39
|
-
/** Body used when the parts tokenize to nothing, or lead with a digit. */
|
|
40
|
-
const CHANNEL_FALLBACK = "bus";
|
|
41
32
|
/**
|
|
42
33
|
* Encoded-envelope ceiling. PostgreSQL caps a `NOTIFY` payload at 8000 bytes and
|
|
43
34
|
* fails the statement past that, so the bus rejects the message first with a size
|
|
@@ -121,56 +112,6 @@ async function senderMetadata() {
|
|
|
121
112
|
return {};
|
|
122
113
|
}
|
|
123
114
|
}
|
|
124
|
-
/**
|
|
125
|
-
* Derive a legal Postgres channel name from whatever a caller used to identify
|
|
126
|
-
* the channel.
|
|
127
|
-
*
|
|
128
|
-
* Callers think in terms of what the channel IS - an app name, a tenant id, a
|
|
129
|
-
* `[env, feature]` pair, a config object - and none of those are identifiers.
|
|
130
|
-
* Rejecting them pushed the sanitizing onto every call site, which is how two
|
|
131
|
-
* services end up disagreeing about whether the channel is `my-app`, `my_app`,
|
|
132
|
-
* or `myApp` and silently never hear each other.
|
|
133
|
-
*
|
|
134
|
-
* The parts are tokenized and joined into an identifier, then a short hash of the
|
|
135
|
-
* ORIGINAL parts is appended. The hash is what makes the mapping trustworthy:
|
|
136
|
-
* tokenizing alone is lossy, so `my-app` and `my_app` and `myApp` would collapse
|
|
137
|
-
* onto one channel, and a name long enough to hit `NAMEDATALEN` would collide
|
|
138
|
-
* with anything sharing its leading tokens. With the suffix, the readable part
|
|
139
|
-
* stays readable and distinct inputs stay distinct.
|
|
140
|
-
*
|
|
141
|
-
* Deterministic across processes and runs, which is the whole point - two
|
|
142
|
-
* services given the same parts must land on the same channel without
|
|
143
|
-
* coordinating. Hash inputs are structure-aware, so `["a", "b"]` and `["a_b"]`
|
|
144
|
-
* differ, and object key order does not.
|
|
145
|
-
*/
|
|
146
|
-
export function channelName(value) {
|
|
147
|
-
const parts = object.toOneOrMany(value);
|
|
148
|
-
// Hash the CANONICAL form, the same rule `advisoryLockId` uses, so structure and
|
|
149
|
-
// types decide identity: `["a","b"]` differs from `["ab"]`, `1` from `"1"`, and
|
|
150
|
-
// object key order does not matter. Hashing the raw parts would instead lean on
|
|
151
|
-
// the hash module's canonicalizer, which folds every `Date` onto one token.
|
|
152
|
-
const suffix = hash.fnvHashWithOptions({ length: CHANNEL_HASH_LENGTH }, parts.map((part) => object.toStableKey(part)).join("\u0000"));
|
|
153
|
-
// Only parts that stringify to something a reader recognizes contribute to the
|
|
154
|
-
// readable half. An object would tokenize from `String(value)` as
|
|
155
|
-
// `object_object`, which is noise - it still shapes the hash, so identity is
|
|
156
|
-
// unaffected.
|
|
157
|
-
const labelled = parts.filter((part) => {
|
|
158
|
-
const type = typeof part;
|
|
159
|
-
return type === "string" || type === "number" || type === "boolean" || type === "bigint";
|
|
160
|
-
});
|
|
161
|
-
// Truncate rather than cap through the tokenizer: `trim` would DROP a single
|
|
162
|
-
// token longer than the budget, turning one long name into the bare fallback and
|
|
163
|
-
// making every long name look alike. The hash still separates them, but the
|
|
164
|
-
// channel is unreadable in a log.
|
|
165
|
-
const body = stringUtils
|
|
166
|
-
.toIdentifierWithOptions({ delimiter: "_" }, ...labelled)
|
|
167
|
-
.slice(0, MAX_CHANNEL_LENGTH - suffix.length - 1)
|
|
168
|
-
.replace(/_+$/, "");
|
|
169
|
-
// An identifier cannot start with a digit and the hash alphabet is
|
|
170
|
-
// digit-leading, so a numeric or empty body needs a letter in front.
|
|
171
|
-
const prefix = /^[A-Za-z_]/.test(body) ? body : `${CHANNEL_FALLBACK}_${body}`;
|
|
172
|
-
return `${prefix}_${suffix}`.replace(/_+/g, "_");
|
|
173
|
-
}
|
|
174
115
|
/** Quote a validated channel for `LISTEN`/`UNLISTEN`, which take no parameters. */
|
|
175
116
|
function quoteIdentifier(value) {
|
|
176
117
|
return `"${value.replaceAll('"', '""')}"`;
|
|
@@ -562,4 +503,4 @@ export class PostgresTopicBus {
|
|
|
562
503
|
}
|
|
563
504
|
}
|
|
564
505
|
}
|
|
565
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9waWMtYnVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RvcGljLWJ1cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNuQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUlqRyxPQUFPLEVBQ0wsY0FBYyxFQUNkLGFBQWEsRUFDYixPQUFPLEVBQ1AsZUFBZSxFQUNmLHlCQUF5QixFQUN6QixXQUFXLEVBQ1gseUJBQXlCLEdBTTFCLE1BQU0sa0JBQWtCLENBQUM7QUFRMUIsb0VBQW9FO0FBQ3BFLE1BQU0sZUFBZSxHQUFHLHFCQUFxQixDQUFDO0FBQzlDOzs7O0dBSUc7QUFDSCxNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztBQUM5QixxRkFBcUY7QUFDckYsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLENBQUM7QUFDOUIsMEVBQTBFO0FBQzFFLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0FBQy9COzs7O0dBSUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQztBQUMvQixNQUFNLHNCQUFzQixHQUFHLEdBQUcsQ0FBQztBQUNuQyxNQUFNLHNCQUFzQixHQUFHLEtBQUssQ0FBQztBQWtCckM7Ozs7R0FJRztBQUNILElBQUksWUFBMkQsQ0FBQztBQWdIaEU7Ozs7R0FJRztBQUNILFNBQVMsZUFBZSxDQUFDLE1BQXFEO0lBQzVFLE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FDdkIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQXdDLEVBQUU7UUFDNUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxD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QUFDO1lBQ0QsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNuQixPQUFPO1lBQ1QsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxJQUFJLENBQUMsTUFBTTtvQkFBRSxPQUFPO2dCQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNwQixLQUFLLEdBQUcsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLENBQUMsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO1lBQzdGLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUb3BpYyBmYW4tb3V0IG92ZXIgUG9zdGdyZVNRTCBgTElTVEVOYC9gTk9USUZZYCwgZm9yIHRlbGxpbmcgZXZlcnkgcnVubmluZ1xuICogaW5zdGFuY2Ugb2YgYW4gYXBwIHRoYXQgc29tZXRoaW5nIGhhcHBlbmVkLlxuICpcbiAqIFRoZSBzaWJsaW5nIGBhZHZpc29yeS1sb2NrYCBtb2R1bGUgaXMgYWJvdXQgbWFraW5nIHN1cmUgb25seSBPTkUgY29ubmVjdGlvblxuICogZG9lcyBhIHRoaW5nOyB0aGlzIG9uZSBpcyB0aGUgb3Bwb3NpdGUgLSBFVkVSWSBsaXN0ZW5pbmcgc2Vzc2lvbiBnZXRzIGV2ZXJ5XG4gKiBub3RpZmljYXRpb24uIFRoYXQgbWFrZXMgaXQgdGhlIHJpZ2h0IHByaW1pdGl2ZSBmb3IgbGl2ZSBVSSB1cGRhdGVzXG4gKiAoYW4gU1NFIHN0cmVhbSBwZXIgYnJvd3NlciB0YWIsIGEgY2FjaGUgaW52YWxpZGF0aW9uLCBhIHByZXNlbmNlIHBpbmcpIGFuZCB0aGVcbiAqIHdyb25nIG9uZSBmb3Igd29yayBkaXN0cmlidXRpb246IHRoZXJlIGFyZSBubyBjb21wZXRpbmcgY29uc3VtZXJzLCBubyBhY2tzLCBhbmRcbiAqIG5vIHJlcGxheS5cbiAqXG4gKiBEZWxpdmVyeSBpcyBiZXN0LWVmZm9ydCBhbmQgbGl2ZS4gYE5PVElGWWAgcmVhY2hlcyBzZXNzaW9ucyB0aGF0IGFyZSBsaXN0ZW5pbmdcbiAqIGF0IHRoZSBtb21lbnQgaXQgY29tbWl0cywgc28gYSBsaXN0ZW5lciB0aGF0IGNvbm5lY3RzIGEgc2Vjb25kIGxhdGVyIG5ldmVyIHNlZXNcbiAqIGl0LCBhbmQgYSBsaXN0ZW5lciB3aG9zZSBjb25uZWN0aW9uIGRyb3BzIG1pc3NlcyBldmVyeXRoaW5nIHVudGlsIHRoZSBidXNcbiAqIHJlY29ubmVjdHMuIFVzZSBhIHRhYmxlIG9yIGEgcXVldWUgd2hlbiBhIHN1YnNjcmliZXIgbmVlZHMgZHVyYWJpbGl0eS5cbiAqXG4gKiBPTkUgQ0hBTk5FTCwgTUFOWSBUT1BJQ1MuIEV2ZXJ5IGJ1cyBpbnN0YW5jZSBsaXN0ZW5zIG9uIGEgc2luZ2xlIFBvc3RncmVzXG4gKiBjaGFubmVsIChgY2hhbm5lbGAsIGRlZmF1bHQgYGRieF90b29sc190b3BpY19idXNgKSBhbmQgZmlsdGVycyBieSB0aGVcbiAqIGVudmVsb3BlJ3MgYHRvcGljYCBpbi1wcm9jZXNzLCBzbyBhZGRpbmcgYSB0b3BpYyBjb3N0cyBubyBjb25uZWN0aW9uIGFuZCBub1xuICogYExJU1RFTmAuIFRoZSB0cmFkZW9mZiBpcyB0aGF0IGV2ZXJ5IGxpc3RlbmluZyBzZXNzaW9uIGRlY29kZXMgZXZlcnkgbWVzc2FnZSBvblxuICogdGhlIGNoYW5uZWw7IGdpdmUgYSBnZW51aW5lbHkgaGlnaC12b2x1bWUsIHVucmVsYXRlZCBzdHJlYW0gaXRzIG93biBgY2hhbm5lbGBcbiAqIHJhdGhlciB0aGFuIGEgdG9waWMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGhvc3RuYW1lIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGFzeW5jVXRpbHMsIGVycm9yVXRpbHMsIGhhc2gsIGpzb24sIG9iamVjdCwgc3RyaW5nVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBOb3RpZmljYXRpb24sIFBvb2xDbGllbnQgfSBmcm9tIFwicGdcIjtcblxuaW1wb3J0IHR5cGUgeyBQZ1Bvb2xMaWtlLCBQZ1F1ZXJ5YWJsZSB9IGZyb20gXCIuL2Fkdmlzb3J5LWxvY2sudHNcIjtcbmltcG9ydCB7XG4gIGNsZWFudXBFeHBpcmVkLFxuICBkZWNvZGVQb2ludGVyLFxuICBoaXN0b3J5LFxuICBwZXJzaXN0ZWROb3RpZnksXG4gIHByb3Zpc2lvbk1lc3NhZ2VCdXNTY2hlbWEsXG4gIHJlYWRQb2ludGVyLFxuICByZXNvbHZlUGVyc2lzdGVuY2VPcHRpb25zLFxuICB0eXBlIER1cmF0aW9uSW5wdXQsXG4gIHR5cGUgUmVzb2x2ZWRUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbiAgdHlwZSBUb3BpY0J1c1BlcnNpc3RlbmNlT3B0aW9ucyxcbiAgdHlwZSBUb3BpY0hpc3RvcnlQYWdlLFxuICB0eXBlIFRvcGljUGVyc2lzdGVuY2VTY29wZSxcbn0gZnJvbSBcIi4vcGVyc2lzdGVuY2UudHNcIjtcblxuLyoqXG4gKiBgQGRieC10b29scy9zaGFyZWQtY29yZWAgb3ducyB0aGUgSlNPTi1yb3VuZC10cmlwIHJ1bGU7IHRoaXMgYWxpYXMganVzdCBrZWVwcyB0aGVcbiAqIGdlbmVyaWMgc2lnbmF0dXJlcyBiZWxvdyByZWFkYWJsZS4gQ29uc3VtZXJzIGltcG9ydCB0aGUgdHlwZSBmcm9tIHNoYXJlZC1jb3JlLlxuICovXG50eXBlIFNlcmlhbGl6YWJsZVZhbHVlID0gb2JqZWN0LlNlcmlhbGl6YWJsZVZhbHVlO1xuXG4vKiogQ2hhbm5lbCBwYXJ0cyB1c2VkIHdoZW4gYSBjYWxsZXIgbmFtZXMgbm8gY2hhbm5lbCBvZiBpdHMgb3duLiAqL1xuY29uc3QgREVGQVVMVF9DSEFOTkVMID0gXCJkYnhfdG9vbHNfdG9waWNfYnVzXCI7XG4vKipcbiAqIGBOQU1FREFUQUxFTiAtIDFgLiBQb3N0Z3JlcyBUUlVOQ0FURVMgYSBsb25nZXIgY2hhbm5lbCBuYW1lIHJhdGhlciB0aGFuXG4gKiByZWplY3RpbmcgaXQsIHdoaWNoIHdvdWxkIHNwbGl0IHB1Ymxpc2hlcnMgYW5kIGxpc3RlbmVycyBvbnRvIGRpZmZlcmVudFxuICogY2hhbm5lbHMgd2hpbGUgZXZlcnkgY2FsbCBsb29rZWQgbGlrZSBpdCBzdWNjZWVkZWQuXG4gKi9cbmNvbnN0IE1BWF9DSEFOTkVMX0xFTkdUSCA9IDYzO1xuLyoqIEJhc2UtMzIgY2hhcnMgb2YgdGhlIGNoYW5uZWwncyBpZGVudGl0eSBzdWZmaXguIE1heCA3IC0gdGhlIGRpZ2VzdCBpcyAzMiBiaXRzLiAqL1xuY29uc3QgQ0hBTk5FTF9IQVNIX0xFTkdUSCA9IDY7XG4vKiogQm9keSB1c2VkIHdoZW4gdGhlIHBhcnRzIHRva2VuaXplIHRvIG5vdGhpbmcsIG9yIGxlYWQgd2l0aCBhIGRpZ2l0LiAqL1xuY29uc3QgQ0hBTk5FTF9GQUxMQkFDSyA9IFwiYnVzXCI7XG4vKipcbiAqIEVuY29kZWQtZW52ZWxvcGUgY2VpbGluZy4gUG9zdGdyZVNRTCBjYXBzIGEgYE5PVElGWWAgcGF5bG9hZCBhdCA4MDAwIGJ5dGVzIGFuZFxuICogZmFpbHMgdGhlIHN0YXRlbWVudCBwYXN0IHRoYXQsIHNvIHRoZSBidXMgcmVqZWN0cyB0aGUgbWVzc2FnZSBmaXJzdCB3aXRoIGEgc2l6ZVxuICogaXQgY2FuIG5hbWUuIFRoZSBtYXJnaW4gYmVsb3cgODAwMCBjb3ZlcnMgdGhlIHNlcnZlcidzIG93biBhY2NvdW50aW5nLlxuICovXG5jb25zdCBNQVhfTk9USUZZX0JZVEVTID0gN185MDA7XG5jb25zdCBNSU5fUkVDT05ORUNUX0RFTEFZX01TID0gMjUwO1xuY29uc3QgTUFYX1JFQ09OTkVDVF9ERUxBWV9NUyA9IDVfMDAwO1xuXG4vKipcbiAqIFRoZSBzdWJzZXQgb2YgQXBwS2l0J3MgcGVyLXJlcXVlc3QgZXhlY3V0aW9uIGNvbnRleHQgdGhlIGJ1cyByZWFkcyBmb3Igc2VuZGVyXG4gKiBpZGVudGl0eS4gRmllbGRzIGFyZSBgdW5rbm93bmAgYmVjYXVzZSB0aGlzIGlzIGEgc3RydWN0dXJhbCB2aWV3IG9mIGFuIE9QVElPTkFMXG4gKiBwZWVyOiB0aGUgdmFsdWVzIGFyZSB0cmltbWVkIGFuZCB2YWxpZGF0ZWQgcmF0aGVyIHRoYW4gdHJ1c3RlZC5cbiAqL1xudHlwZSBBcHBLaXRFeGVjdXRpb25Db250ZXh0ID0ge1xuICB1c2VyRW1haWw/OiB1bmtub3duO1xuICB1c2VySWQ/OiB1bmtub3duO1xuICB1c2VyTmFtZT86IHVua25vd247XG59O1xuXG4vKiogU3RydWN0dXJhbCB2aWV3IG9mIGBAZGF0YWJyaWNrcy9hcHBraXRgLCBpbXBvcnRlZCBsYXppbHkgYW5kIG5ldmVyIHJlcXVpcmVkLiAqL1xudHlwZSBBcHBLaXRNb2R1bGUgPSB7XG4gIGdldEV4ZWN1dGlvbkNvbnRleHQoKTogQXBwS2l0RXhlY3V0aW9uQ29udGV4dDtcbn07XG5cbi8qKlxuICogQ2FjaGVkIHJlc3VsdCBvZiB0aGUgb25lIG9wdGlvbmFsLXBlZXIgaW1wb3J0LCByZXNvbHZlZCB0byBgdW5kZWZpbmVkYCB3aGVuXG4gKiBBcHBLaXQgaXMgbm90IGluc3RhbGxlZC4gTWVtb2l6ZWQgc28gYSBidXMgaW4gYSBwbGFpbiBQb3N0Z3JlcyBwcm9jZXNzIHBheXMgZm9yXG4gKiB0aGUgZmFpbGVkIHJlc29sdXRpb24gb25jZSBpbnN0ZWFkIG9mIHBlciBicm9hZGNhc3QuXG4gKi9cbmxldCBhcHBLaXRNb2R1bGU6IFByb21pc2U8QXBwS2l0TW9kdWxlIHwgdW5kZWZpbmVkPiB8IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBGbGF0LWtleWVkIGNvbnRleHQgdHJhdmVsbGluZyBhbG9uZ3NpZGUgYSBtZXNzYWdlIGJvZHk6IHdobyBzZW50IGl0LCBmcm9tXG4gKiB3aGVyZSwgaW4gd2hpY2ggZGVwbG95bWVudC4gVmFsdWVzIG1heSBuZXN0LCBidXQgdGhlIGtleXMgYXJlIHRoZSBhZGRyZXNzYWJsZVxuICogcGFydCAtIGEgbGlzdGVuZXIgZmlsdGVyaW5nIG9yIGxhYmVsbGluZyBtZXNzYWdlcyByZWFkcyBgbWV0YWRhdGEudXNlcmAsIG5vdCBhXG4gKiBwYXRoIGludG8gdGhlIGJvZHkuXG4gKi9cbmV4cG9ydCB0eXBlIFRvcGljTWV0YWRhdGEgPSBSZWNvcmQ8c3RyaW5nLCBTZXJpYWxpemFibGVWYWx1ZT47XG5cbi8qKlxuICogVGhlIHdpcmUgZW52ZWxvcGUgZXZlcnkgc3Vic2NyaWJlciByZWNlaXZlcywgYW5kIHdoYXQge0BsaW5rXG4gKiBQb3N0Z3Jlc1RvcGljQnVzLmJyb2FkY2FzdH0gcmV0dXJucyB0byB0aGUgcHVibGlzaGVyLlxuICpcbiAqIGBpZGAsIGB0b3BpY2AsIGFuZCBgcHVibGlzaGVkQXRgIGFyZSBhc3NpZ25lZCBieSB0aGUgYnVzOyBgdHlwZWAsIGBtZXRhZGF0YWAsXG4gKiBhbmQgYGJvZHlgIGNvbWUgZnJvbSB0aGUgY2FsbGVyICh3aXRoIGF1dG9tYXRpYyBjb250ZXh0IG1lcmdlZCB1bmRlclxuICogYG1ldGFkYXRhYCkuIFRoZSBzaGFwZSBpcyBzdGFibGUgZW5vdWdoIHRvIGhhbmQgc3RyYWlnaHQgdG8gYW4gU1NFIGBkYXRhOmBcbiAqIGZyYW1lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRvcGljTWVzc2FnZTxUQm9keSBleHRlbmRzIFNlcmlhbGl6YWJsZVZhbHVlID0gU2VyaWFsaXphYmxlVmFsdWU+IHtcbiAgLyoqXG4gICAqIFBlci1tZXNzYWdlIGlkZW50aXR5IGdlbmVyYXRlZCBieSB0aGUgcHVibGlzaGVyLCB1bmlxdWUgYWNyb3NzIGluc3RhbmNlcy5cbiAgICogU3VpdGFibGUgZm9yIGRlZHVwZSB3aGVuIGEgY2xpZW50IHJlY29ubmVjdHMgYW5kIGZvciBhbiBTU0UgYGlkOmAgZmllbGQuIE5vdFxuICAgKiBvcmRlcmVkLCBhbmQgbm90IGEgZGF0YWJhc2Uga2V5LlxuICAgKi9cbiAgaWQ6IHN0cmluZztcbiAgLyoqIFRoZSB0b3BpYyB0aGlzIHdhcyBicm9hZGNhc3Qgb247IGxpc3RlbmVycyBvbiBvdGhlciB0b3BpY3MgbmV2ZXIgc2VlIGl0LiAqL1xuICB0b3BpYzogc3RyaW5nO1xuICAvKiogQ2FsbGVyLWNob3NlbiBldmVudCBuYW1lLCBlLmcuIGBvcmRlci51cGRhdGVkYC4gTmV2ZXIgZW1wdHkuICovXG4gIHR5cGU6IHN0cmluZztcbiAgLyoqIEF1dG9tYXRpYyBjb250ZXh0IG1lcmdlZCB3aXRoIGNhbGxlciBtZXRhZGF0YS4gU2VlIHtAbGluayBUb3BpY01ldGFkYXRhfS4gKi9cbiAgbWV0YWRhdGE6IFRvcGljTWV0YWRhdGE7XG4gIC8qKiBUaGUgY2FsbGVyJ3MgcGF5bG9hZCwgdW5jaGFuZ2VkLiAqL1xuICBib2R5OiBUQm9keTtcbiAgLyoqXG4gICAqIElTTy04NjAxIHB1Ymxpc2ggdGltZSBmcm9tIHRoZSBQVUJMSVNISU5HIHByb2Nlc3MncyBjbG9jaywgbm90IHRoZSBkYXRhYmFzZSdzLlxuICAgKiBGaW5lIGZvciBkaXNwbGF5OyBkbyBub3Qgb3JkZXIgbWVzc2FnZXMgZnJvbSBkaWZmZXJlbnQgaW5zdGFuY2VzIGJ5IGl0LlxuICAgKi9cbiAgcHVibGlzaGVkQXQ6IHN0cmluZztcbn1cblxuLyoqIFdoYXQgYSBjYWxsZXIgc3VwcGxpZXMgdG8ge0BsaW5rIFBvc3RncmVzVG9waWNCdXMuYnJvYWRjYXN0fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVG9waWNQdWJsaXNoSW5wdXQ8VEJvZHkgZXh0ZW5kcyBTZXJpYWxpemFibGVWYWx1ZSA9IFNlcmlhbGl6YWJsZVZhbHVlPiB7XG4gIC8qKiBFdmVudCBuYW1lLCBlLmcuIGBjaGF0Lm1lc3NhZ2VgLiBNdXN0IGJlIG5vbi1ibGFuay4gKi9cbiAgdHlwZTogc3RyaW5nO1xuICAvKipcbiAgICogQ29udGV4dCB0byBhdHRhY2guIFdpbnMgb3ZlciBhbnkgYXV0b21hdGljIGtleSBvZiB0aGUgc2FtZSBuYW1lLCBzbyBhIGNhbGxlclxuICAgKiBjYW4gb3ZlcnJpZGUgYSBtYWNoaW5lIGRlZmF1bHQgKGBwcm9qZWN0YCkgb3IgYWRkIGl0cyBvd24gKGB0cmFjZUlkYCkuXG4gICAqL1xuICBtZXRhZGF0YT86IFRvcGljTWV0YWRhdGE7XG4gIC8qKiBUaGUgcGF5bG9hZC4gTXVzdCBzYXRpc2Z5IGBvYmplY3QuaXNTZXJpYWxpemFibGVWYWx1ZWAuICovXG4gIGJvZHk6IFRCb2R5O1xuICBzY29wZT86IFRvcGljUGVyc2lzdGVuY2VTY29wZTtcbiAgdHRsPzogRHVyYXRpb25JbnB1dCB8IGZhbHNlO1xufVxuXG4vKipcbiAqIFN1YnNjcmliZXIgY2FsbGJhY2suIEludm9rZWQgb25jZSBwZXIgbWF0Y2hpbmcgbWVzc2FnZSBvbiB0aGUgbm90aWZpY2F0aW9uXG4gKiBjb25uZWN0aW9uJ3MgY2FsbGJhY2ssIHNvIGl0IHNob3VsZCBub3QgYmxvY2s6IGEgcmV0dXJuZWQgcHJvbWlzZSBpcyBhd2FpdGVkXG4gKiBvbmx5IHRvIHJvdXRlIGEgcmVqZWN0aW9uIHRvIGBvbkVycm9yYCwgYW5kIGxpc3RlbmVycyBmb3Igb25lIG1lc3NhZ2UgcnVuXG4gKiBjb25jdXJyZW50bHkgcmF0aGVyIHRoYW4gaW4gcmVnaXN0cmF0aW9uIG9yZGVyLlxuICpcbiAqIGBUQm9keWAgaXMgdW5jaGVja2VkIGF0IHJ1bnRpbWUuIFRoZSBidXMgZ3VhcmFudGVlcyB0aGUgYm9keSBpcyBzZXJpYWxpemFibGUsXG4gKiBub3QgdGhhdCBpdCBtYXRjaGVzIHRoZSB0eXBlIHBhcmFtZXRlciwgc28gdmFsaWRhdGUgYW55dGhpbmcgYSBsaXN0ZW5lclxuICogYnJhbmNoZXMgb24uXG4gKi9cbmV4cG9ydCB0eXBlIFRvcGljTGlzdGVuZXI8VEJvZHkgZXh0ZW5kcyBTZXJpYWxpemFibGVWYWx1ZSA9IFNlcmlhbGl6YWJsZVZhbHVlPiA9IChcbiAgbWVzc2FnZTogVG9waWNNZXNzYWdlPFRCb2R5PixcbikgPT4gdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xuXG4vKipcbiAqIFJlc29sdmVzIG1ldGFkYXRhIGF0IHB1Ymxpc2ggdGltZSBpbnN0ZWFkIG9mIGNvbnN0cnVjdGlvbiB0aW1lLCBmb3IgY29udGV4dCBhXG4gKiBwcm9jZXNzIGxlYXJucyBsYXRlIG9yIGFzeW5jaHJvbm91c2x5IC0gYW4gaW5zdGFuY2UgaWQgZnJvbSBhIGNvbnRyb2wgcGxhbmUsIGFcbiAqIGRpc2NvdmVyZWQgYWRkcmVzcyBhIGNhbGxlciBjaG9vc2VzIHRvIGF0dGFjaC4gQ2FsbGVkIG9uIGV2ZXJ5IGJyb2FkY2FzdCwgc29cbiAqIG1lbW9pemUgYW55dGhpbmcgZXhwZW5zaXZlOyBhIHJlamVjdGlvbiBmYWlscyB0aGUgYnJvYWRjYXN0LlxuICovXG5leHBvcnQgdHlwZSBUb3BpY01ldGFkYXRhUHJvdmlkZXIgPSAoKSA9PiBUb3BpY01ldGFkYXRhIHwgUHJvbWlzZUxpa2U8VG9waWNNZXRhZGF0YT47XG5cbi8qKiBDb25zdHJ1Y3Rpb24gb3B0aW9ucyBmb3Ige0BsaW5rIFBvc3RncmVzVG9waWNCdXN9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb3N0Z3Jlc1RvcGljQnVzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGF0IGlkZW50aWZpZXMgdGhpcyBjaGFubmVsIC0gYW55dGhpbmcsIG5vdCBqdXN0IGFuIGlkZW50aWZpZXI6IGEgbmFtZSwgYW5cbiAgICogaWQsIGEgYFtlbnYsIGZlYXR1cmVdYCBwYWlyLCBhIGNvbmZpZyBvYmplY3QuIFRoZSBwYXJ0cyBhcmUgdG9rZW5pemVkIGludG8gYVxuICAgKiBsZWdhbCBQb3N0Z3JlcyBjaGFubmVsIG5hbWUgd2l0aCBhIHNob3J0IGhhc2ggb2YgdGhlIG9yaWdpbmFscyBhcHBlbmRlZCwgc29cbiAgICogdGhlIGRlcml2YXRpb24gaXMgZGV0ZXJtaW5pc3RpYyBhbmQgbm8gY2FsbCBzaXRlIGhhcyB0byBzYW5pdGl6ZS4gU2VlXG4gICAqIHtAbGluayBQb3N0Z3Jlc1RvcGljQnVzLmNoYW5uZWxOYW1lfSBmb3IgdGhlIHJlc29sdmVkIG5hbWUuXG4gICAqXG4gICAqIE9uZSB2YWx1ZSBvciBtYW55OiBhbiBhcnJheSBpcyByZWFkIGFzIG11bHRpcGxlIHBhcnRzXG4gICAqICh7QGxpbmsgb2JqZWN0Lk9uZU9yTWFueX0pLCBhbnl0aGluZyBlbHNlIGFzIGEgc2luZ2xlIHBhcnQuIFNvXG4gICAqIGBbXCJiaWxsaW5nXCIsIFwicHJvZFwiXWAgYW5kIGBcImJpbGxpbmdfcHJvZFwiYCBhcmUgZGlmZmVyZW50IGNoYW5uZWxzLCBzaW5jZSB0aGVcbiAgICogaGFzaCBzZWVzIGRpZmZlcmVudCBzdHJ1Y3R1cmUuXG4gICAqXG4gICAqIEV2ZXJ5IHBhcnRpY2lwYXRpbmcgcHJvY2VzcyBtdXN0IHBhc3MgRVFVSVZBTEVOVCBwYXJ0cywgc2luY2UgYSBkaWZmZXJlbnRcbiAgICogc3BlbGxpbmcgaGFzaGVzIHRvIGEgZGlmZmVyZW50IGNoYW5uZWwuIERlZmF1bHRzIHRvIGEgc2hhcmVkXG4gICAqIGBkYnhfdG9vbHNfdG9waWNfYnVzYCBjaGFubmVsLlxuICAgKi9cbiAgY2hhbm5lbD86IHVua25vd247XG4gIC8qKlxuICAgKiBFeHRyYSBjb250ZXh0IGFkZGVkIHRvIGV2ZXJ5IG1lc3NhZ2UgdGhpcyBidXMgcHVibGlzaGVzLCBlaXRoZXIgYSBmaXhlZFxuICAgKiByZWNvcmQgb3IgYSB7QGxpbmsgVG9waWNNZXRhZGF0YVByb3ZpZGVyfSBjYWxsZWQgcGVyIGJyb2FkY2FzdC4gT3ZlcnJpZGVzXG4gICAqIGF1dG9tYXRpYyBtYWNoaW5lIGtleXM7IHBlci1jYWxsIGBtZXRhZGF0YWAgb3ZlcnJpZGVzIHRoaXMuXG4gICAqL1xuICBtZXRhZGF0YT86IFRvcGljTWV0YWRhdGEgfCBUb3BpY01ldGFkYXRhUHJvdmlkZXI7XG4gIC8qKlxuICAgKiBTaW5rIGZvciBmYWlsdXJlcyB0aGF0IGhhdmUgbm8gY2FsbGVyIHRvIHRocm93IHRvOiBhIGxpc3RlbmVyIHRoYXQgcmVqZWN0ZWQsXG4gICAqIGEgZHJvcHBlZCBub3RpZmljYXRpb24gY29ubmVjdGlvbiwgYSBmYWlsZWQgcmVjb25uZWN0IGF0dGVtcHQuIERlZmF1bHRzIHRvXG4gICAqIHN3YWxsb3dpbmcgdGhlbSwgc28gd2lyZSB0aGlzIHRvIGEgbG9nZ2VyIGluIGFueXRoaW5nIGxvbmctcnVubmluZy5cbiAgICovXG4gIG9uRXJyb3I/OiAoY2F1c2U6IHVua25vd24pID0+IHZvaWQ7XG4gIHBlcnNpc3Q/OiBib29sZWFuIHwgVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnM7XG59XG5cbi8qKlxuICogRHJvcCBrZXlzIHdob3NlIHZhbHVlIGlzIGB1bmRlZmluZWRgLCBzbyBhbiB1bnNldCBlbnZpcm9ubWVudCB2YXJpYWJsZSBsZWF2ZXNcbiAqIHRoZSBrZXkgQUJTRU5UIHJhdGhlciB0aGFuIHByZXNlbnQtYW5kLW51bGwuIEFic2VuY2UgaXMgd2hhdCBsZXRzIGNhbGxlclxuICogbWV0YWRhdGEgYW5kIGxhdGVyIG1lcmdlIGxheWVycyBzdXBwbHkgdGhlIGtleSBpbnN0ZWFkLlxuICovXG5mdW5jdGlvbiBkZWZpbmVkTWV0YWRhdGEodmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBTZXJpYWxpemFibGVWYWx1ZSB8IHVuZGVmaW5lZD4pOiBUb3BpY01ldGFkYXRhIHtcbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICBPYmplY3QuZW50cmllcyh2YWx1ZXMpLmZpbHRlcigoZW50cnkpOiBlbnRyeSBpcyBbc3RyaW5nLCBTZXJpYWxpemFibGVWYWx1ZV0gPT4ge1xuICAgICAgcmV0dXJuIGVudHJ5WzFdICE9PSB1bmRlZmluZWQ7XG4gICAgfSksXG4gICk7XG59XG5cbi8qKlxuICogQ29udGV4dCBldmVyeSBtZXNzYWdlIGdldHMgZm9yIGZyZWU6IHdoaWNoIHByb2plY3QsIGhvc3QsIGFuZCBkZXBsb3ltZW50XG4gKiBwdWJsaXNoZWQgaXQuXG4gKlxuICogUmVhZCBmcmVzaCBwZXIgYnJvYWRjYXN0IHJhdGhlciB0aGFuIGNhY2hlZCwgYmVjYXVzZSBhIGxvbmctbGl2ZWQgcHJvY2VzcyBjYW5cbiAqIGJlIHJlLXBhcmVudGVkIChhIGRlcGxveW1lbnQgaWQgYXBwZWFyaW5nIGFmdGVyIGJvb3QpLiBLZXlzIHRoYXQgcmVzb2x2ZSB0b1xuICogbm90aGluZyBhcmUgb21pdHRlZC5cbiAqXG4gKiBEZWxpYmVyYXRlbHkgTk9UIGluY2x1ZGVkOiBwdWJsaWMvY2xpZW50IElQLCBwcm9jZXNzIGlkLCBDUFUgYXJjaGl0ZWN0dXJlLFxuICogcnVudGltZSBuYW1lLCBhbmQgcnVudGltZSB2ZXJzaW9uLiBJUHMgYW5kIHBpZHMgYXJlIG5vaXN5LCBvZnRlbiBzZW5zaXRpdmUsXG4gKiBhbmQgYnVybiBgTk9USUZZYCBwYXlsb2FkIGJ1ZGdldDsgYXJjaGl0ZWN0dXJlL3J1bnRpbWUgYXJlIGNvbnN0YW50IHBlclxuICogZGVwbG95bWVudCBhbmQgcGF5IHRoZSBzYW1lIGNvc3QuIEEgcHJvY2VzcyB0aGF0IHdhbnRzIGFueSBvZiB0aGVtIHBhc3NlcyBhXG4gKiB7QGxpbmsgVG9waWNNZXRhZGF0YVByb3ZpZGVyfSBvciBwZXItbWVzc2FnZSBgbWV0YWRhdGFgLlxuICovXG5mdW5jdGlvbiBtYWNoaW5lTWV0YWRhdGEoKTogVG9waWNNZXRhZGF0YSB7XG4gIHJldHVybiBkZWZpbmVkTWV0YWRhdGEoe1xuICAgIHByb2plY3Q6XG4gICAgICBzdHJpbmdVdGlscy5maXJzdE5vbkVtcHR5KFtcbiAgICAgICAgcHJvY2Vzcy5lbnYuREFUQUJSSUNLU19BUFBfTkFNRSxcbiAgICAgICAgcHJvY2Vzcy5lbnYuREFUQUJSSUNLU19CVU5ETEVfTkFNRSxcbiAgICAgICAgcHJvY2Vzcy5lbnYuUFJPSkVDVF9OQU1FLFxuICAgICAgICBwcm9jZXNzLmVudi5ucG1fcGFja2FnZV9uYW1lLFxuICAgICAgXSkgPz8gdW5kZWZpbmVkLFxuICAgIGhvc3RuYW1lOiBob3N0bmFtZSgpLFxuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIGVudmlyb25tZW50OiBzdHJpbmdVdGlscy50cmltVG9OdWxsKHByb2Nlc3MuZW52Lk5PREVfRU5WKSA/PyB1bmRlZmluZWQsXG4gICAgYXBwTmFtZTogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0FQUF9OQU1FKSA/PyB1bmRlZmluZWQsXG4gICAgZGVwbG95bWVudElkOiBzdHJpbmdVdGlscy50cmltVG9OdWxsKHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQVBQX0RFUExPWU1FTlRfSUQpID8/IHVuZGVmaW5lZCxcbiAgICBkYXRhYnJpY2tzSG9zdDogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QpID8/IHVuZGVmaW5lZCxcbiAgfSk7XG59XG5cbi8qKlxuICogSWRlbnRpdHkgb2YgdGhlIHNpZ25lZC1pbiB1c2VyIG9uIHdob3NlIGJlaGFsZiB0aGlzIGJyb2FkY2FzdCBoYXBwZW5zLCB3aGVuIHRoZVxuICogcHJvY2VzcyBjYW4gdGVsbC5cbiAqXG4gKiBgQGRhdGFicmlja3MvYXBwa2l0YCBpcyBhbiBPUFRJT05BTCBwZWVyLCBzbyB0aGUgaW1wb3J0IGlzIGxhenkgYW5kIGEgbWlzc2luZ1xuICogbW9kdWxlIGlzIG5vdCBhbiBlcnJvciAtIHRoaXMgaXMgYSBwbGFpbiBQb3N0Z3JlcyBwYWNrYWdlIHRoYXQgYWRkcyBzZW5kZXJcbiAqIGlkZW50aXR5IHdoZW4gaXQgaGFwcGVucyB0byBydW4gaW5zaWRlIGFuIEFwcEtpdCBhcHAuIE91dHNpZGUgYW4gYWN0aXZlXG4gKiBwZXItcmVxdWVzdCBleGVjdXRpb24gY29udGV4dCBBcHBLaXQgdGhyb3dzLCB3aGljaCBtZWFucyBcIm5vIHVzZXIgaGVyZVwiLCBzbyB0aGVcbiAqIHJlc3VsdCBpcyBlbXB0eSBtZXRhZGF0YSByYXRoZXIgdGhhbiBhIGZhaWxlZCBicm9hZGNhc3QuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNlbmRlck1ldGFkYXRhKCk6IFByb21pc2U8VG9waWNNZXRhZGF0YT4ge1xuICBhcHBLaXRNb2R1bGUgPz89IGltcG9ydChcIkBkYXRhYnJpY2tzL2FwcGtpdFwiKVxuICAgIC50aGVuKChtb2R1bGUpID0+IG1vZHVsZSBhcyBBcHBLaXRNb2R1bGUpXG4gICAgLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gIGNvbnN0IGFwcGtpdCA9IGF3YWl0IGFwcEtpdE1vZHVsZTtcbiAgaWYgKCFhcHBraXQpIHJldHVybiB7fTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjb250ZXh0ID0gYXBwa2l0LmdldEV4ZWN1dGlvbkNvbnRleHQoKTtcbiAgICByZXR1cm4gZGVmaW5lZE1ldGFkYXRhKHtcbiAgICAgIHNlbmRlcklkOiBzdHJpbmdVdGlscy50cmltVG9OdWxsKGNvbnRleHQudXNlcklkKSA/PyB1bmRlZmluZWQsXG4gICAgICBzZW5kZXJOYW1lOiBzdHJpbmdVdGlscy50cmltVG9OdWxsKGNvbnRleHQudXNlck5hbWUpID8/IHVuZGVmaW5lZCxcbiAgICAgIHNlbmRlckVtYWlsOiBzdHJpbmdVdGlscy50cmltVG9OdWxsKGNvbnRleHQudXNlckVtYWlsKSA/PyB1bmRlZmluZWQsXG4gICAgfSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7fTtcbiAgfVxufVxuXG4vKipcbiAqIERlcml2ZSBhIGxlZ2FsIFBvc3RncmVzIGNoYW5uZWwgbmFtZSBmcm9tIHdoYXRldmVyIGEgY2FsbGVyIHVzZWQgdG8gaWRlbnRpZnlcbiAqIHRoZSBjaGFubmVsLlxuICpcbiAqIENhbGxlcnMgdGhpbmsgaW4gdGVybXMgb2Ygd2hhdCB0aGUgY2hhbm5lbCBJUyAtIGFuIGFwcCBuYW1lLCBhIHRlbmFudCBpZCwgYVxuICogYFtlbnYsIGZlYXR1cmVdYCBwYWlyLCBhIGNvbmZpZyBvYmplY3QgLSBhbmQgbm9uZSBvZiB0aG9zZSBhcmUgaWRlbnRpZmllcnMuXG4gKiBSZWplY3RpbmcgdGhlbSBwdXNoZWQgdGhlIHNhbml0aXppbmcgb250byBldmVyeSBjYWxsIHNpdGUsIHdoaWNoIGlzIGhvdyB0d29cbiAqIHNlcnZpY2VzIGVuZCB1cCBkaXNhZ3JlZWluZyBhYm91dCB3aGV0aGVyIHRoZSBjaGFubmVsIGlzIGBteS1hcHBgLCBgbXlfYXBwYCxcbiAqIG9yIGBteUFwcGAgYW5kIHNpbGVudGx5IG5ldmVyIGhlYXIgZWFjaCBvdGhlci5cbiAqXG4gKiBUaGUgcGFydHMgYXJlIHRva2VuaXplZCBhbmQgam9pbmVkIGludG8gYW4gaWRlbnRpZmllciwgdGhlbiBhIHNob3J0IGhhc2ggb2YgdGhlXG4gKiBPUklHSU5BTCBwYXJ0cyBpcyBhcHBlbmRlZC4gVGhlIGhhc2ggaXMgd2hhdCBtYWtlcyB0aGUgbWFwcGluZyB0cnVzdHdvcnRoeTpcbiAqIHRva2VuaXppbmcgYWxvbmUgaXMgbG9zc3ksIHNvIGBteS1hcHBgIGFuZCBgbXlfYXBwYCBhbmQgYG15QXBwYCB3b3VsZCBjb2xsYXBzZVxuICogb250byBvbmUgY2hhbm5lbCwgYW5kIGEgbmFtZSBsb25nIGVub3VnaCB0byBoaXQgYE5BTUVEQVRBTEVOYCB3b3VsZCBjb2xsaWRlXG4gKiB3aXRoIGFueXRoaW5nIHNoYXJpbmcgaXRzIGxlYWRpbmcgdG9rZW5zLiBXaXRoIHRoZSBzdWZmaXgsIHRoZSByZWFkYWJsZSBwYXJ0XG4gKiBzdGF5cyByZWFkYWJsZSBhbmQgZGlzdGluY3QgaW5wdXRzIHN0YXkgZGlzdGluY3QuXG4gKlxuICogRGV0ZXJtaW5pc3RpYyBhY3Jvc3MgcHJvY2Vzc2VzIGFuZCBydW5zLCB3aGljaCBpcyB0aGUgd2hvbGUgcG9pbnQgLSB0d29cbiAqIHNlcnZpY2VzIGdpdmVuIHRoZSBzYW1lIHBhcnRzIG11c3QgbGFuZCBvbiB0aGUgc2FtZSBjaGFubmVsIHdpdGhvdXRcbiAqIGNvb3JkaW5hdGluZy4gSGFzaCBpbnB1dHMgYXJlIHN0cnVjdHVyZS1hd2FyZSwgc28gYFtcImFcIiwgXCJiXCJdYCBhbmQgYFtcImFfYlwiXWBcbiAqIGRpZmZlciwgYW5kIG9iamVjdCBrZXkgb3JkZXIgZG9lcyBub3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFubmVsTmFtZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gIGNvbnN0IHBhcnRzID0gb2JqZWN0LnRvT25lT3JNYW55KHZhbHVlKTtcbiAgLy8gSGFzaCB0aGUgQ0FOT05JQ0FMIGZvcm0sIHRoZSBzYW1lIHJ1bGUgYGFkdmlzb3J5TG9ja0lkYCB1c2VzLCBzbyBzdHJ1Y3R1cmUgYW5kXG4gIC8vIHR5cGVzIGRlY2lkZSBpZGVudGl0eTogYFtcImFcIixcImJcIl1gIGRpZmZlcnMgZnJvbSBgW1wiYWJcIl1gLCBgMWAgZnJvbSBgXCIxXCJgLCBhbmRcbiAgLy8gb2JqZWN0IGtleSBvcmRlciBkb2VzIG5vdCBtYXR0ZXIuIEhhc2hpbmcgdGhlIHJhdyBwYXJ0cyB3b3VsZCBpbnN0ZWFkIGxlYW4gb25cbiAgLy8gdGhlIGhhc2ggbW9kdWxlJ3MgY2Fub25pY2FsaXplciwgd2hpY2ggZm9sZHMgZXZlcnkgYERhdGVgIG9udG8gb25lIHRva2VuLlxuICBjb25zdCBzdWZmaXggPSBoYXNoLmZudkhhc2hXaXRoT3B0aW9ucyhcbiAgICB7IGxlbmd0aDogQ0hBTk5FTF9IQVNIX0xFTkdUSCB9LFxuICAgIHBhcnRzLm1hcCgocGFydCkgPT4gb2JqZWN0LnRvU3RhYmxlS2V5KHBhcnQpKS5qb2luKFwiXFx1MDAwMFwiKSxcbiAgKTtcbiAgLy8gT25seSBwYXJ0cyB0aGF0IHN0cmluZ2lmeSB0byBzb21ldGhpbmcgYSByZWFkZXIgcmVjb2duaXplcyBjb250cmlidXRlIHRvIHRoZVxuICAvLyByZWFkYWJsZSBoYWxmLiBBbiBvYmplY3Qgd291bGQgdG9rZW5pemUgZnJvbSBgU3RyaW5nKHZhbHVlKWAgYXNcbiAgLy8gYG9iamVjdF9vYmplY3RgLCB3aGljaCBpcyBub2lzZSAtIGl0IHN0aWxsIHNoYXBlcyB0aGUgaGFzaCwgc28gaWRlbnRpdHkgaXNcbiAgLy8gdW5hZmZlY3RlZC5cbiAgY29uc3QgbGFiZWxsZWQgPSBwYXJ0cy5maWx0ZXIoKHBhcnQpID0+IHtcbiAgICBjb25zdCB0eXBlID0gdHlwZW9mIHBhcnQ7XG4gICAgcmV0dXJuIHR5cGUgPT09IFwic3RyaW5nXCIgfHwgdHlwZSA9PT0gXCJudW1iZXJcIiB8fCB0eXBlID09PSBcImJvb2xlYW5cIiB8fCB0eXBlID09PSBcImJpZ2ludFwiO1xuICB9KTtcbiAgLy8gVHJ1bmNhdGUgcmF0aGVyIHRoYW4gY2FwIHRocm91Z2ggdGhlIHRva2VuaXplcjogYHRyaW1gIHdvdWxkIERST1AgYSBzaW5nbGVcbiAgLy8gdG9rZW4gbG9uZ2VyIHRoYW4gdGhlIGJ1ZGdldCwgdHVybmluZyBvbmUgbG9uZyBuYW1lIGludG8gdGhlIGJhcmUgZmFsbGJhY2sgYW5kXG4gIC8vIG1ha2luZyBldmVyeSBsb25nIG5hbWUgbG9vayBhbGlrZS4gVGhlIGhhc2ggc3RpbGwgc2VwYXJhdGVzIHRoZW0sIGJ1dCB0aGVcbiAgLy8gY2hhbm5lbCBpcyB1bnJlYWRhYmxlIGluIGEgbG9nLlxuICBjb25zdCBib2R5ID0gc3RyaW5nVXRpbHNcbiAgICAudG9JZGVudGlmaWVyV2l0aE9wdGlvbnMoeyBkZWxpbWl0ZXI6IFwiX1wiIH0sIC4uLmxhYmVsbGVkKVxuICAgIC5zbGljZSgwLCBNQVhfQ0hBTk5FTF9MRU5HVEggLSBzdWZmaXgubGVuZ3RoIC0gMSlcbiAgICAucmVwbGFjZSgvXyskLywgXCJcIik7XG4gIC8vIEFuIGlkZW50aWZpZXIgY2Fubm90IHN0YXJ0IHdpdGggYSBkaWdpdCBhbmQgdGhlIGhhc2ggYWxwaGFiZXQgaXNcbiAgLy8gZGlnaXQtbGVhZGluZywgc28gYSBudW1lcmljIG9yIGVtcHR5IGJvZHkgbmVlZHMgYSBsZXR0ZXIgaW4gZnJvbnQuXG4gIGNvbnN0IHByZWZpeCA9IC9eW0EtWmEtel9dLy50ZXN0KGJvZHkpID8gYm9keSA6IGAke0NIQU5ORUxfRkFMTEJBQ0t9XyR7Ym9keX1gO1xuICByZXR1cm4gYCR7cHJlZml4fV8ke3N1ZmZpeH1gLnJlcGxhY2UoL18rL2csIFwiX1wiKTtcbn1cblxuLyoqIFF1b3RlIGEgdmFsaWRhdGVkIGNoYW5uZWwgZm9yIGBMSVNURU5gL2BVTkxJU1RFTmAsIHdoaWNoIHRha2Ugbm8gcGFyYW1ldGVycy4gKi9cbmZ1bmN0aW9uIHF1b3RlSWRlbnRpZmllcih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBcIiR7dmFsdWUucmVwbGFjZUFsbCgnXCInLCAnXCJcIicpfVwiYDtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIGBOT1RJRllgIHBheWxvYWQgaW50byBhbiBlbnZlbG9wZSwgcmV0dXJuaW5nIGB1bmRlZmluZWRgIGZvciBhbnl0aGluZ1xuICogdGhhdCBpcyBub3Qgb25lLlxuICpcbiAqIFRoZSBjaGFubmVsIGlzIHNoYXJlZCBhbmQgYW55IFBvc3RncmVzIHNlc3Npb24gY2FuIGBwZ19ub3RpZnlgIG9uIGl0LCBzbyBhblxuICogdW5yZWNvZ25pemVkIHBheWxvYWQgaXMgZXhwZWN0ZWQgaW5wdXQsIG5vdCBhbiBleGNlcHRpb24uIFB1Ymxpc2hlcnMgcnVuIHRoaXNcbiAqIG92ZXIgdGhlaXIgb3duIGVuY29kZWQgbWVzc2FnZSB0b28sIHdoaWNoIGlzIGhvdyBhIGJvZHkgdGhhdCBzdHJpbmdpZmllcyBidXRcbiAqIGRvZXMgbm90IHJvdW5kLXRyaXAgaXMgY2F1Z2h0IGJlZm9yZSBpdCBzaGlwcy5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBUb3BpY01lc3NhZ2UgfCB1bmRlZmluZWQge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCByZWNvcmQgPSBqc29uLnBhcnNlUmVjb3JkKHZhbHVlKTtcbiAgaWYgKFxuICAgICFyZWNvcmQgfHxcbiAgICB0eXBlb2YgcmVjb3JkLmlkICE9PSBcInN0cmluZ1wiIHx8XG4gICAgdHlwZW9mIHJlY29yZC50b3BpYyAhPT0gXCJzdHJpbmdcIiB8fFxuICAgIHR5cGVvZiByZWNvcmQudHlwZSAhPT0gXCJzdHJpbmdcIiB8fFxuICAgIHR5cGVvZiByZWNvcmQucHVibGlzaGVkQXQgIT09IFwic3RyaW5nXCIgfHxcbiAgICAhcmVjb3JkLm1ldGFkYXRhIHx8XG4gICAgdHlwZW9mIHJlY29yZC5tZXRhZGF0YSAhPT0gXCJvYmplY3RcIiB8fFxuICAgIEFycmF5LmlzQXJyYXkocmVjb3JkLm1ldGFkYXRhKSB8fFxuICAgICEoXCJib2R5XCIgaW4gcmVjb3JkKSB8fFxuICAgICFvYmplY3QuaXNTZXJpYWxpemFibGVWYWx1ZShyZWNvcmQubWV0YWRhdGEpIHx8XG4gICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKHJlY29yZC5ib2R5KVxuICApIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiB7XG4gICAgaWQ6IHJlY29yZC5pZCxcbiAgICB0b3BpYzogcmVjb3JkLnRvcGljLFxuICAgIHR5cGU6IHJlY29yZC50eXBlLFxuICAgIG1ldGFkYXRhOiByZWNvcmQubWV0YWRhdGEgYXMgVG9waWNNZXRhZGF0YSxcbiAgICBib2R5OiByZWNvcmQuYm9keSBhcyBTZXJpYWxpemFibGVWYWx1ZSxcbiAgICBwdWJsaXNoZWRBdDogcmVjb3JkLnB1Ymxpc2hlZEF0LFxuICB9O1xufVxuXG4vKipcbiAqIEJyb2FkY2FzdHMgc3RydWN0dXJlZCBtZXNzYWdlcyBieSB0b3BpYyBhbmQgZGVsaXZlcnMgdGhlbSB0byBldmVyeSBwcm9jZXNzXG4gKiBsaXN0ZW5pbmcgb24gdGhlIHNhbWUgY2hhbm5lbC5cbiAqXG4gKiBDT05ORUNUSU9OIFNIQVBFLiBQdWJsaXNoaW5nIGJvcnJvd3MgYSBwb29sZWQgY29ubmVjdGlvbiBwZXIgY2FsbCwgbGlrZSBhbnlcbiAqIG90aGVyIHF1ZXJ5LiBMaXN0ZW5pbmcgY2Fubm90OiBgTElTVEVOYCBpcyBzZXNzaW9uIHN0YXRlLCBzbyB0aGUgYnVzIGhvbGRzIE9ORVxuICogZGVkaWNhdGVkIGNsaWVudCBvdXQgb2YgdGhlIHBvb2wgZm9yIGFzIGxvbmcgYXMgaXQgaGFzIHN1YnNjcmliZXJzLCBubyBtYXR0ZXJcbiAqIGhvdyBtYW55IHRvcGljcyBvciBsaXN0ZW5lcnMgYXJlIHJlZ2lzdGVyZWQuIFNpemUgdGhlIHBvb2wgd2l0aCB0aGF0IG9uZVxuICogbG9uZy1saXZlZCBjaGVja291dCBpbiBtaW5kLlxuICpcbiAqIExJRkVDWUNMRS4gQ29uc3RydWN0aW9uIGlzIGluZXJ0IC0gbm90aGluZyBjb25uZWN0cyB1bnRpbCB0aGUgZmlyc3RcbiAqIHtAbGluayBsaXN0ZW59IChvciBhbiBleHBsaWNpdCB7QGxpbmsgc3RhcnR9KS4ge0BsaW5rIGNsb3NlfSBpcyByZXF1aXJlZCB0byBnaXZlXG4gKiB0aGUgY29ubmVjdGlvbiBiYWNrOyBhIGNsb3NlZCBidXMgc3RheXMgY2xvc2VkIGFuZCB0aHJvd3Mgb24gZnVydGhlciB1c2UgcmF0aGVyXG4gKiB0aGFuIHNpbGVudGx5IHJlY29ubmVjdGluZy4gUmVnaXN0ZXIgaXQgd2l0aCB0aGUgaG9zdCdzIHNodXRkb3duIGhvb2suXG4gKlxuICogRkFJTFVSRSBIQU5ETElORy4gQSBsb3N0IG5vdGlmaWNhdGlvbiBjb25uZWN0aW9uIHJlY29ubmVjdHMgb24gaXRzIG93biB3aXRoXG4gKiBib3VuZGVkIGJhY2tvZmYgd2hpbGUgc3Vic2NyaWJlcnMgcmVtYWluLCByZXBvcnRpbmcgZWFjaCBmYWlsZWQgYXR0ZW1wdCB0aHJvdWdoXG4gKiBgb25FcnJvcmAuIE1lc3NhZ2VzIHB1Ymxpc2hlZCBkdXJpbmcgdGhlIGdhcCBhcmUgbG9zdCAtIGBOT1RJRllgIGhhcyBubyByZXBsYXkuXG4gKiBBIHRocm93aW5nIG9yIHJlamVjdGluZyBsaXN0ZW5lciBuZXZlciBhZmZlY3RzIHRoZSBwdWJsaXNoZXIgb3IgdGhlIG90aGVyXG4gKiBsaXN0ZW5lcnM7IGl0cyBmYWlsdXJlIGdvZXMgdG8gYG9uRXJyb3JgLlxuICpcbiAqIE5vdCBzYWZlIHRvIHNoYXJlIG9uZSBpbnN0YW5jZSBhY3Jvc3MgdW5yZWxhdGVkIGNoYW5uZWxzIC0gY29uc3RydWN0IG9uZSBidXNcbiAqIHBlciBjaGFubmVsLiBUaGUgY2hhbm5lbCBpdHNlbGYgaXMgREVSSVZFRCBmcm9tIHRoZSBgY2hhbm5lbGAgb3B0aW9uIHJhdGhlclxuICogdGhhbiB0YWtlbiBsaXRlcmFsbHk7IHNlZSB7QGxpbmsgUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMuY2hhbm5lbH0gYW5kXG4gKiB7QGxpbmsgUG9zdGdyZXNUb3BpY0J1cy5jaGFubmVsTmFtZX0uXG4gKi9cbmV4cG9ydCBjbGFzcyBQb3N0Z3Jlc1RvcGljQnVzIHtcbiAgLyoqXG4gICAqIFRoZSByZXNvbHZlZCBQb3N0Z3JlcyBjaGFubmVsIHRoaXMgYnVzIGxpc3RlbnMgYW5kIHB1Ymxpc2hlcyBvbiwgZGVyaXZlZCBmcm9tXG4gICAqIHRoZSBgY2hhbm5lbGAgb3B0aW9uLiBSZWFkIGl0IHRvIGNvbmZpcm0gdHdvIHByb2Nlc3NlcyBhZ3JlZSwgb3IgdG8gbG9nIHdoYXQgYVxuICAgKiBzZXQgb2YgcGFydHMgYWN0dWFsbHkgcmVzb2x2ZWQgdG8uXG4gICAqL1xuICByZWFkb25seSBjaGFubmVsTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldGFkYXRhOiBUb3BpY01ldGFkYXRhIHwgVG9waWNNZXRhZGF0YVByb3ZpZGVyIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IG9uRXJyb3I6IChjYXVzZTogdW5rbm93bikgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBsaXN0ZW5lcnMgPSBuZXcgTWFwPHN0cmluZywgU2V0PFRvcGljTGlzdGVuZXI+PigpO1xuICBwcml2YXRlIGNsaWVudDogUG9vbENsaWVudCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBzdGFydGluZzogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWNvbm5lY3Rpbmc6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb25uZWN0QWJvcnQgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIHByaXZhdGUgY2xvc2VkID0gZmFsc2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVyc2lzdGVuY2U/OiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zO1xuICBwcml2YXRlIHByb3Zpc2lvbmluZz86IFByb21pc2U8dm9pZD47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb29sOiBQZ1Bvb2xMaWtlICYgUGdRdWVyeWFibGUsXG4gICAgb3B0aW9uczogUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMgPSB7fSxcbiAgKSB7XG4gICAgdGhpcy5jaGFubmVsTmFtZSA9IGNoYW5uZWxOYW1lKFxuICAgICAgb3B0aW9ucy5jaGFubmVsID09PSB1bmRlZmluZWQgPyBERUZBVUxUX0NIQU5ORUwgOiBvcHRpb25zLmNoYW5uZWwsXG4gICAgKTtcbiAgICB0aGlzLm1ldGFkYXRhID0gb3B0aW9ucy5tZXRhZGF0YTtcbiAgICB0aGlzLm9uRXJyb3IgPSBvcHRpb25zLm9uRXJyb3IgPz8gKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgdGhpcy5wZXJzaXN0ZW5jZSA9IG9wdGlvbnMucGVyc2lzdFxuICAgICAgPyByZXNvbHZlUGVyc2lzdGVuY2VPcHRpb25zKG9wdGlvbnMucGVyc2lzdCA9PT0gdHJ1ZSA/IHRydWUgOiBvcHRpb25zLnBlcnNpc3QpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIHRoZSBkZWRpY2F0ZWQgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gYW5kIGBMSVNURU5gLlxuICAgKlxuICAgKiBJZGVtcG90ZW50LCBhbmQgc2FmZSB0byBjYWxsIGNvbmN1cnJlbnRseSAtIG92ZXJsYXBwaW5nIGNhbGxzIGF3YWl0IHRoZSBzYW1lXG4gICAqIGluLWZsaWdodCBjb25uZWN0LiB7QGxpbmsgbGlzdGVufSBjYWxscyB0aGlzLCBzbyBpdCBpcyBvbmx5IG5lZWRlZCB0byBzdXJmYWNlXG4gICAqIGEgY29ubmVjdGlvbiBwcm9ibGVtIGF0IHN0YXJ0dXAgcmF0aGVyIHRoYW4gb24gZmlyc3Qgc3Vic2NyaWJlLiBUaHJvd3MgaWYgdGhlXG4gICAqIGJ1cyBpcyBjbG9zZWQsIG9yIGlmIHRoZSBwb29sIGNhbm5vdCBoYW5kIG91dCBhIGNvbm5lY3Rpb24uXG4gICAqL1xuICBhc3luYyBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5jbGllbnQpIHJldHVybjtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihcIlBvc3RncmVzIHRvcGljIGJ1cyBpcyBjbG9zZWRcIik7XG4gICAgdGhpcy5zdGFydGluZyA/Pz0gdGhpcy5jb25uZWN0KCkuZmluYWxseSgoKSA9PiB7XG4gICAgICB0aGlzLnN0YXJ0aW5nID0gdW5kZWZpbmVkO1xuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuc3RhcnRpbmc7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhIG1lc3NhZ2UgdG8gYHRvcGljYCwgcmV0dXJuaW5nIHRoZSBlbnZlbG9wZSB0aGF0IHdhcyBzZW50LlxuICAgKlxuICAgKiBSZXNvbHZlcyBvbmNlIFBvc3RncmVzIGhhcyBhY2NlcHRlZCB0aGUgYE5PVElGWWAsIHdoaWNoIHNheXMgbm90aGluZyBhYm91dFxuICAgKiBhbnlvbmUgcmVjZWl2aW5nIGl0OiBzZXNzaW9ucyBub3QgbGlzdGVuaW5nIGF0IHRoYXQgbW9tZW50IG1pc3MgaXQuIFB1Ymxpc2hpbmdcbiAgICogbmVlZHMgbm8ge0BsaW5rIHN0YXJ0fSBhbmQgbm8gc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIFZhbGlkYXRpb24gaXMgZGVsaWJlcmF0ZWx5IGZyb250LWxvYWRlZCwgc2luY2UgYSBtZXNzYWdlIHRoYXQgZmFpbHMgb24gdGhlXG4gICAqIHdpcmUgaXMgZmFyIGhhcmRlciB0byBkaWFnbm9zZSB0aGFuIG9uZSByZWplY3RlZCBhdCB0aGUgY2FsbDogYFR5cGVFcnJvcmAgZm9yIGFcbiAgICogYmxhbmsgdG9waWMgb3IgdHlwZSwgb3IgYSBib2R5L21ldGFkYXRhIHRoYXQgd291bGQgbm90IHJvdW5kLXRyaXAgdGhyb3VnaCBKU09OXG4gICAqIHVuY2hhbmdlZCAoYG9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlYCk7IGBSYW5nZUVycm9yYCB3aGVuIHRoZSBlbmNvZGVkXG4gICAqIGVudmVsb3BlIGV4Y2VlZHMgdGhlIGBOT1RJRllgIHBheWxvYWQgbGltaXQsIHdoaWNoIHRoZSBhdXRvbWF0aWMgbWV0YWRhdGFcbiAgICogY291bnRzIGFnYWluc3QgLSBzZW5kIGEgcmVmZXJlbmNlIGFuZCBsZXQgdGhlIHJlY2VpdmVyIGZldGNoIHRoZSBwYXlsb2FkLlxuICAgKiBUaHJvd3MgaWYgdGhlIGJ1cyBpcyBjbG9zZWQuXG4gICAqL1xuICBhc3luYyBicm9hZGNhc3Q8VEJvZHkgZXh0ZW5kcyBTZXJpYWxpemFibGVWYWx1ZT4oXG4gICAgdG9waWM6IHN0cmluZyxcbiAgICBpbnB1dDogVG9waWNQdWJsaXNoSW5wdXQ8VEJvZHk+LFxuICApOiBQcm9taXNlPFRvcGljTWVzc2FnZTxUQm9keT4+IHtcbiAgICBpZiAoIXRvcGljLnRyaW0oKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRvcGljIG11c3Qgbm90IGJlIGVtcHR5XCIpO1xuICAgIGlmICghaW5wdXQudHlwZS50cmltKCkpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNZXNzYWdlIHR5cGUgbXVzdCBub3QgYmUgZW1wdHlcIik7XG4gICAgaWYgKFxuICAgICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKGlucHV0Lm1ldGFkYXRhID8/IHt9KSB8fFxuICAgICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKGlucHV0LmJvZHkpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBtZXRhZGF0YSBhbmQgYm9keSBtdXN0IGJlIEpTT04gc2VyaWFsaXphYmxlIHdpdGhvdXQgY29lcmNpb25cIik7XG4gICAgfVxuICAgIGlmICh0aGlzLmNsb3NlZCkgdGhyb3cgbmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIGlzIGNsb3NlZFwiKTtcbiAgICBjb25zdCBhdXRvbWF0aWMgPSBhd2FpdCB0aGlzLnJlc29sdmVNZXRhZGF0YSgpO1xuICAgIGNvbnN0IG1lc3NhZ2U6IFRvcGljTWVzc2FnZTxUQm9keT4gPSB7XG4gICAgICBpZDogaGFzaC5pZCgpLFxuICAgICAgdG9waWMsXG4gICAgICB0eXBlOiBpbnB1dC50eXBlLFxuICAgICAgbWV0YWRhdGE6IHsgLi4uYXV0b21hdGljLCAuLi5pbnB1dC5tZXRhZGF0YSB9LFxuICAgICAgYm9keTogaW5wdXQuYm9keSxcbiAgICAgIHB1Ymxpc2hlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgfTtcbiAgICBsZXQgZW5jb2RlZDogc3RyaW5nO1xuICAgIHRyeSB7XG4gICAgICBlbmNvZGVkID0gSlNPTi5zdHJpbmdpZnkobWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE1lc3NhZ2UgbXVzdCBiZSBKU09OIHNlcmlhbGl6YWJsZTogJHtlcnJvclV0aWxzLmVycm9yTWVzc2FnZShjYXVzZSl9YCk7XG4gICAgfVxuICAgIGlmICghZGVjb2RlKGVuY29kZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSB0eXBlLCBtZXRhZGF0YSwgYW5kIGJvZHkgbXVzdCBiZSBKU09OIHNlcmlhbGl6YWJsZVwiKTtcbiAgICB9XG4gICAgLy8gT25seSB0aGUgZW52ZWxvcGUgcGF5bG9hZCBpcyBib3VuZGVkIGJ5IHRoZSBgTk9USUZZYCBsaW1pdC4gQSBwb2ludGVyXG4gICAgLy8gbm90aWZpY2F0aW9uIGlzIGEgZml4ZWQgaGFuZGZ1bCBvZiBieXRlcywgc28gcGVyc2lzdGVuY2Ugd2l0aFxuICAgIC8vIGBwYXlsb2FkOiBcInBvaW50ZXJcImAgbGlmdHMgdGhlIGNhcCBlbnRpcmVseS5cbiAgICBpZiAoXG4gICAgICBCdWZmZXIuYnl0ZUxlbmd0aChlbmNvZGVkLCBcInV0ZjhcIikgPiBNQVhfTk9USUZZX0JZVEVTICYmXG4gICAgICB0aGlzLnBlcnNpc3RlbmNlPy5wYXlsb2FkICE9PSBcInBvaW50ZXJcIlxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYFBvc3RncmVzIG5vdGlmaWNhdGlvbiBleGNlZWRzICR7TUFYX05PVElGWV9CWVRFU30gYnl0ZXNgKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnBlcnNpc3RlbmNlKSB7XG4gICAgICBhd2FpdCB0aGlzLnBvb2wucXVlcnkoXCJTRUxFQ1QgcGdfbm90aWZ5KCQxLCAkMilcIiwgW3RoaXMuY2hhbm5lbE5hbWUsIGVuY29kZWRdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMucGVyc2lzdGVuY2UucHJvdmlzaW9uKSB7XG4gICAgICAgIHRoaXMucHJvdmlzaW9uaW5nID8/PSBwcm92aXNpb25NZXNzYWdlQnVzU2NoZW1hKHRoaXMucG9vbCwgdGhpcy5wZXJzaXN0ZW5jZSk7XG4gICAgICAgIGF3YWl0IHRoaXMucHJvdmlzaW9uaW5nO1xuICAgICAgfVxuICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wb29sLmNvbm5lY3QoKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkJFR0lOXCIpO1xuICAgICAgICBhd2FpdCBwZXJzaXN0ZWROb3RpZnkoXG4gICAgICAgICAgY2xpZW50LFxuICAgICAgICAgIHRoaXMuY2hhbm5lbE5hbWUsXG4gICAgICAgICAgdG9waWMsXG4gICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICBlbmNvZGVkLFxuICAgICAgICAgIHRoaXMucGVyc2lzdGVuY2UsXG4gICAgICAgICAgaW5wdXQuc2NvcGUgPz8gdGhpcy5wZXJzaXN0ZW5jZS5zY29wZSxcbiAgICAgICAgICBpbnB1dC50dGwgPz8gdGhpcy5wZXJzaXN0ZW5jZS50dGwsXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkNPTU1JVFwiKTtcbiAgICAgIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIlJPTExCQUNLXCIpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgIHRocm93IGNhdXNlO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgY2xpZW50LnJlbGVhc2UoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH1cblxuICBhc3luYyBoaXN0b3J5PFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWU+KFxuICAgIHRvcGljOiBzdHJpbmcsXG4gICAgb3B0aW9uczogeyBhZnRlcj86IHN0cmluZzsgbGltaXQ/OiBudW1iZXI7IHNjb3BlPzogVG9waWNQZXJzaXN0ZW5jZVNjb3BlIH0gPSB7fSxcbiAgKTogUHJvbWlzZTxUb3BpY0hpc3RvcnlQYWdlPFRCb2R5Pj4ge1xuICAgIGlmICghdGhpcy5wZXJzaXN0ZW5jZSkgdGhyb3cgbmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIHBlcnNpc3RlbmNlIGlzIGRpc2FibGVkXCIpO1xuICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlLnByb3Zpc2lvbikge1xuICAgICAgdGhpcy5wcm92aXNpb25pbmcgPz89IHByb3Zpc2lvbk1lc3NhZ2VCdXNTY2hlbWEodGhpcy5wb29sLCB0aGlzLnBlcnNpc3RlbmNlKTtcbiAgICAgIGF3YWl0IHRoaXMucHJvdmlzaW9uaW5nO1xuICAgIH1cbiAgICByZXR1cm4gaGlzdG9yeTxUQm9keT4odGhpcy5wb29sLCB0aGlzLmNoYW5uZWxOYW1lLCB0b3BpYywgdGhpcy5wZXJzaXN0ZW5jZSwgb3B0aW9ucyk7XG4gIH1cblxuICBhc3luYyBjbGVhbnVwRXhwaXJlZChcbiAgICBvcHRpb25zOiB7IHNjb3BlPzogVG9waWNQZXJzaXN0ZW5jZVNjb3BlOyBsaW1pdD86IG51bWJlciB9ID0ge30sXG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgaWYgKCF0aGlzLnBlcnNpc3RlbmNlKSB0aHJvdyBuZXcgRXJyb3IoXCJQb3N0Z3JlcyB0b3BpYyBidXMgcGVyc2lzdGVuY2UgaXMgZGlzYWJsZWRcIik7XG4gICAgcmV0dXJuIGNsZWFudXBFeHBpcmVkKFxuICAgICAgdGhpcy5wb29sLFxuICAgICAgdGhpcy5wZXJzaXN0ZW5jZSxcbiAgICAgIG9wdGlvbnMuc2NvcGUgPz8gdGhpcy5wZXJzaXN0ZW5jZS5zY29wZSxcbiAgICAgIG9wdGlvbnMubGltaXQsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJzY3JpYmUgdG8gYHRvcGljYCwgcmV0dXJuaW5nIHRoZSBmdW5jdGlvbiB0aGF0IHVuc3Vic2NyaWJlcy5cbiAgICpcbiAgICogQ29ubmVjdHMgb24gZmlyc3QgdXNlLiBTZXZlcmFsIGxpc3RlbmVycyBtYXkgc2hhcmUgYSB0b3BpYzsgZWFjaCBpcyBjYWxsZWRcbiAgICogb25jZSBwZXIgbWVzc2FnZS4gT25seSBtZXNzYWdlcyBwdWJsaXNoZWQgQUZURVIgdGhpcyByZXNvbHZlcyBhcnJpdmUsIHNvXG4gICAqIHN1YnNjcmliZSBiZWZvcmUgdHJpZ2dlcmluZyB3aGF0ZXZlciB5b3UgZXhwZWN0IHRvIG9ic2VydmUuXG4gICAqXG4gICAqIFRoZSByZXR1cm5lZCBmdW5jdGlvbiByZW1vdmVzIGp1c3QgdGhpcyBsaXN0ZW5lciBhbmQgaXMgc2FmZSB0byBjYWxsIHR3aWNlLlxuICAgKiBUaGUgY29ubmVjdGlvbiBzdGF5cyBvcGVuIG9uY2UgdGhlIGxhc3QgbGlzdGVuZXIgbGVhdmVzIC0ge0BsaW5rIGNsb3NlfVxuICAgKiByZWxlYXNlcyBpdCAtIHNvIGEgYnVzIHRoYXQgc3Vic2NyaWJlcyBhbmQgdW5zdWJzY3JpYmVzIHBlciByZXF1ZXN0IGRvZXMgbm90XG4gICAqIGNodXJuIGNvbm5lY3Rpb25zLlxuICAgKi9cbiAgYXN5bmMgbGlzdGVuPFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWU+KFxuICAgIHRvcGljOiBzdHJpbmcsXG4gICAgbGlzdGVuZXI6IFRvcGljTGlzdGVuZXI8VEJvZHk+LFxuICApOiBQcm9taXNlPCgpID0+IFByb21pc2U8dm9pZD4+IHtcbiAgICBpZiAoIXRvcGljLnRyaW0oKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRvcGljIG11c3Qgbm90IGJlIGVtcHR5XCIpO1xuICAgIGF3YWl0IHRoaXMuc3RhcnQoKTtcbiAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmxpc3RlbmVycy5nZXQodG9waWMpID8/IG5ldyBTZXQ8VG9waWNMaXN0ZW5lcj4oKTtcbiAgICBsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyIGFzIFRvcGljTGlzdGVuZXIpO1xuICAgIHRoaXMubGlzdGVuZXJzLnNldCh0b3BpYywgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgbGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lciBhcyBUb3BpY0xpc3RlbmVyKTtcbiAgICAgIGlmIChsaXN0ZW5lcnMuc2l6ZSA9PT0gMCkgdGhpcy5saXN0ZW5lcnMuZGVsZXRlKHRvcGljKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHRoZSBhdXRvbWF0aWMgaGFsZiBvZiBhIG1lc3NhZ2UncyBtZXRhZGF0YS5cbiAgICpcbiAgICogUHJlY2VkZW5jZSwgd2Vha2VzdCBmaXJzdDogbWFjaGluZS9wcm9jZXNzIGNvbnRleHQsIHRoZW4gQXBwS2l0IHNlbmRlclxuICAgKiBpZGVudGl0eSwgdGhlbiB0aGlzIGJ1cydzIGNvbmZpZ3VyZWQgbWV0YWRhdGEuIFRoZSBjYWxsZXIncyBwZXItbWVzc2FnZVxuICAgKiBtZXRhZGF0YSBpcyBsYXllcmVkIG92ZXIgdGhlIHJlc3VsdCBpbiB7QGxpbmsgYnJvYWRjYXN0fSwgc28gdGhlIG1vc3Qgc3BlY2lmaWNcbiAgICogc291cmNlIGFsd2F5cyB3aW5zIGFuZCBub3RoaW5nIGhlcmUgY2FuIG92ZXJ3cml0ZSBhbiBleHBsaWNpdCBrZXkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlc29sdmVNZXRhZGF0YSgpOiBQcm9taXNlPFRvcGljTWV0YWRhdGE+IHtcbiAgICBjb25zdCBzZW5kZXIgPSBhd2FpdCBzZW5kZXJNZXRhZGF0YSgpO1xuICAgIGNvbnN0IGNvbmZpZ3VyZWQgPVxuICAgICAgdHlwZW9mIHRoaXMubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIiA/IGF3YWl0IHRoaXMubWV0YWRhdGEoKSA6ICh0aGlzLm1ldGFkYXRhID8/IHt9KTtcbiAgICByZXR1cm4geyAuLi5tYWNoaW5lTWV0YWRhdGEoKSwgLi4uc2VuZGVyLCAuLi5jb25maWd1cmVkIH07XG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZSB0aGUgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gYW5kIHN0b3AgZGVsaXZlcmluZyBtZXNzYWdlcy4gSWRlbXBvdGVudC5cbiAgICpcbiAgICogQ2FuY2VscyBhbnkgcGVuZGluZyByZWNvbm5lY3QsIGRyb3BzIGFsbCBsaXN0ZW5lcnMsIHRoZW4gYFVOTElTVEVOYHMgYW5kXG4gICAqIHJldHVybnMgdGhlIGNsaWVudCB0byB0aGUgcG9vbC4gQSBmYWlsZWQgYFVOTElTVEVOYCBpcyByZXBvcnRlZCB0byB0aGUgcG9vbCBhc1xuICAgKiBhIHJlbGVhc2UgZXJyb3Igc28gdGhlIGNvbm5lY3Rpb24gaXMgRElTQ0FSREVEIHJhdGhlciB0aGFuIGhhbmRlZCB0byB0aGUgbmV4dFxuICAgKiBjYWxsZXIgc3RpbGwgc3Vic2NyaWJlZCB0byB0aGUgY2hhbm5lbC4gRG9lcyBub3QgdGhyb3c7IHRoZSBidXMgc3RheXMgY2xvc2VkLlxuICAgKi9cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSByZXR1cm47XG4gICAgdGhpcy5jbG9zZWQgPSB0cnVlO1xuICAgIHRoaXMucmVjb25uZWN0QWJvcnQuYWJvcnQobmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIGlzIGNsb3NlZFwiKSk7XG4gICAgYXdhaXQgdGhpcy5zdGFydGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBhd2FpdCB0aGlzLnJlY29ubmVjdGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudDtcbiAgICB0aGlzLmNsaWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxpc3RlbmVycy5jbGVhcigpO1xuICAgIGlmICghY2xpZW50KSByZXR1cm47XG4gICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICBjbGllbnQucmVtb3ZlTGlzdGVuZXIoXCJlcnJvclwiLCB0aGlzLmhhbmRsZUNsaWVudEVycm9yKTtcbiAgICBsZXQgcmVsZWFzZUVycm9yOiBFcnJvciB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KGBVTkxJU1RFTiAke3F1b3RlSWRlbnRpZmllcih0aGlzLmNoYW5uZWxOYW1lKX1gKTtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgcmVsZWFzZUVycm9yID0gZXJyb3JVdGlscy50b0Vycm9yKGNhdXNlKTtcbiAgICB9XG4gICAgY2xpZW50LnJlbGVhc2UocmVsZWFzZUVycm9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBvdXQgb25lIGNsaWVudCwgYXR0YWNoIHRoZSBoYW5kbGVycywgYW5kIGBMSVNURU5gLlxuICAgKlxuICAgKiBUaGUgaGFuZGxlcnMgYXJlIGF0dGFjaGVkIEJFRk9SRSB0aGUgYExJU1RFTmAgcm91bmQgdHJpcCBzbyBhIG5vdGlmaWNhdGlvbiBvclxuICAgKiBlcnJvciBhcnJpdmluZyBtaWQtc2V0dXAgaXMgbm90IG1pc3NlZC4gQW55IGZhaWx1cmUgLSBpbmNsdWRpbmcgdGhlIGJ1cyBiZWluZ1xuICAgKiBjbG9zZWQgd2hpbGUgdGhlIGNvbm5lY3Qgd2FzIGluIGZsaWdodCAtIGRldGFjaGVzIHRoZSBoYW5kbGVycyBhbmQgcmVsZWFzZXNcbiAgICogdGhlIGNsaWVudCBhcyBlcnJvcmVkLCBzbyBhIGhhbGYtY29uZmlndXJlZCBjb25uZWN0aW9uIG5ldmVyIHJldHVybnMgdG8gdGhlXG4gICAqIHBvb2wuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wb29sLmNvbm5lY3QoKTtcbiAgICB0cnkge1xuICAgICAgY2xpZW50Lm9uKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICAgIGNsaWVudC5vbihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KGBMSVNURU4gJHtxdW90ZUlkZW50aWZpZXIodGhpcy5jaGFubmVsTmFtZSl9YCk7XG4gICAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihcIlBvc3RncmVzIHRvcGljIGJ1cyBpcyBjbG9zZWRcIik7XG4gICAgICB0aGlzLmNsaWVudCA9IGNsaWVudDtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgICAgY2xpZW50LnJlbGVhc2UoZXJyb3JVdGlscy50b0Vycm9yKGNhdXNlKSk7XG4gICAgICB0aHJvdyBjYXVzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUm91dGUgb25lIGluYm91bmQgbm90aWZpY2F0aW9uIHRvIHRoZSB0b3BpYydzIGxpc3RlbmVycy5cbiAgICpcbiAgICogSWdub3JlcyBvdGhlciBjaGFubmVscyBhbmQgdW5kZWNvZGFibGUgcGF5bG9hZHMgLSB0aGUgY2hhbm5lbCBpcyBzaGFyZWQsIHNvXG4gICAqIGJvdGggYXJlIG9yZGluYXJ5IHRyYWZmaWMuIExpc3RlbmVycyBhcmUgaW52b2tlZCBjb25jdXJyZW50bHkgYW5kIHRoZWlyXG4gICAqIHJlamVjdGlvbnMgZ28gdG8gYG9uRXJyb3JgLCBrZWVwaW5nIG9uZSBzbG93IG9yIGJyb2tlbiBzdWJzY3JpYmVyIGZyb21cbiAgICogc3RhbGxpbmcgdGhlIG5vdGlmaWNhdGlvbiBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVOb3RpZmljYXRpb24gPSAobm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb24pOiB2b2lkID0+IHtcbiAgICBpZiAobm90aWZpY2F0aW9uLmNoYW5uZWwgIT09IHRoaXMuY2hhbm5lbE5hbWUpIHJldHVybjtcbiAgICBjb25zdCBtZXNzYWdlID0gZGVjb2RlKG5vdGlmaWNhdGlvbi5wYXlsb2FkKTtcbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgdGhpcy5kZWxpdmVyKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBgcGF5bG9hZDogXCJwb2ludGVyXCJgIGNhcnJpZXMgb25seSByb3V0aW5nIGFuZCBpZGVudGl0eSwgc28gdGhlIGVudmVsb3BlIGhhc1xuICAgIC8vIHRvIGJlIHJlYWQgYmFjayBiZWZvcmUgYW55dGhpbmcgY2FuIGJlIGRlbGl2ZXJlZC4gT25seSBhdHRlbXB0ZWQgd2hlbiB0aGlzXG4gICAgLy8gYnVzIGlzIGNvbmZpZ3VyZWQgZm9yIHBlcnNpc3RlbmNlOyBvdGhlcndpc2UgdGhlIHBheWxvYWQgaXMgZm9yZWlnbiB0cmFmZmljXG4gICAgLy8gb24gYSBzaGFyZWQgY2hhbm5lbCBhbmQgaWdub3JlZCBhcyBiZWZvcmUuXG4gICAgY29uc3QgcG9pbnRlciA9IHRoaXMucGVyc2lzdGVuY2UgPyBkZWNvZGVQb2ludGVyKG5vdGlmaWNhdGlvbi5wYXlsb2FkKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIXBvaW50ZXIpIHJldHVybjtcbiAgICBpZiAoIXRoaXMubGlzdGVuZXJzLmhhcyhwb2ludGVyLnRvcGljKSkgcmV0dXJuO1xuICAgIHJlYWRQb2ludGVyKHRoaXMucG9vbCwgdGhpcy5jaGFubmVsTmFtZSwgcG9pbnRlciwgdGhpcy5wZXJzaXN0ZW5jZSEpXG4gICAgICAudGhlbigoc3RvcmVkKSA9PiB7XG4gICAgICAgIGlmIChzdG9yZWQpIHRoaXMuZGVsaXZlcihzdG9yZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCh0aGlzLm9uRXJyb3IpO1xuICB9O1xuXG4gIC8qKiBIYW5kIG9uZSBkZWNvZGVkIG1lc3NhZ2UgdG8gdGhlIHRvcGljJ3MgbGlzdGVuZXJzLiAqL1xuICBwcml2YXRlIGRlbGl2ZXIobWVzc2FnZTogVG9waWNNZXNzYWdlKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBsaXN0ZW5lciBvZiB0aGlzLmxpc3RlbmVycy5nZXQobWVzc2FnZS50b3BpYykgPz8gW10pIHtcbiAgICAgIFByb21pc2UucmVzb2x2ZShsaXN0ZW5lcihtZXNzYWdlKSkuY2F0Y2godGhpcy5vbkVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBub3RpZmljYXRpb24gY29ubmVjdGlvbiBkeWluZywgd2hpY2ggYHBnYCByZXBvcnRzIGFzIGFuIGBlcnJvcmBcbiAgICogZXZlbnQgcmF0aGVyIHRoYW4gYSByZWplY3RlZCBxdWVyeS5cbiAgICpcbiAgICogVGhlIGNsaWVudCBpcyB1bnVzYWJsZSBhdCB0aGlzIHBvaW50LCBzbyBpdCBpcyBkZXRhY2hlZCBhbmQgcmVsZWFzZWQgYXNcbiAgICogZXJyb3JlZCAod2hpY2ggZGlzY2FyZHMgaXQpIGJlZm9yZSBhbnl0aGluZyBlbHNlLiBSZWNvbm5lY3Rpb24gb25seSBzdGFydHNcbiAgICogd2hlbiB0aGVyZSBpcyBzdGlsbCBzb21lb25lIHRvIGRlbGl2ZXIgdG8sIHNvIGFuIGlkbGUgb3IgY2xvc2luZyBidXMgZG9lcyBub3RcbiAgICogaG9sZCBhIGNvbm5lY3Rpb24gb3BlbiBjaGFzaW5nIGEgY2hhbm5lbCBub2JvZHkgcmVhZHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZUNsaWVudEVycm9yID0gKGNhdXNlOiBFcnJvcik6IHZvaWQgPT4ge1xuICAgIHRoaXMub25FcnJvcihjYXVzZSk7XG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnQ7XG4gICAgaWYgKCFjbGllbnQpIHJldHVybjtcbiAgICB0aGlzLmNsaWVudCA9IHVuZGVmaW5lZDtcbiAgICBjbGllbnQucmVtb3ZlTGlzdGVuZXIoXCJub3RpZmljYXRpb25cIiwgdGhpcy5oYW5kbGVOb3RpZmljYXRpb24pO1xuICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgIGNsaWVudC5yZWxlYXNlKGNhdXNlKTtcbiAgICBpZiAodGhpcy5jbG9zZWQgfHwgdGhpcy5saXN0ZW5lcnMuc2l6ZSA9PT0gMCkgcmV0dXJuO1xuICAgIHRoaXMucmVjb25uZWN0aW5nID8/PSB0aGlzLnJlY29ubmVjdCgpLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgdGhpcy5yZWNvbm5lY3RpbmcgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlLWVzdGFibGlzaCB0aGUgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gd2l0aCBib3VuZGVkIGV4cG9uZW50aWFsIGJhY2tvZmYuXG4gICAqXG4gICAqIFRoZSBmaXJzdCBhdHRlbXB0IGlzIGltbWVkaWF0ZSwgc2luY2UgdGhlIGNvbW1vbiBjYXNlIGlzIGEgc2luZ2xlIGRyb3BwZWRcbiAgICogY29ubmVjdGlvbiB0aGF0IHJlY29ubmVjdHMgYXQgb25jZTsgc3Vic2VxdWVudCBkZWxheXMgZG91YmxlIGZyb20gMjUwbXMgdXAgdG9cbiAgICogNXMgYW5kIHN0YXkgdGhlcmUuIFJldHJpZXMgaW5kZWZpbml0ZWx5IHJhdGhlciB0aGFuIGdpdmluZyB1cCwgYmVjYXVzZSBhIFBvc3RncmVzIHJlc3RhcnRcbiAgICogb3IgYSByb3RhdGVkIExha2ViYXNlIGNyZWRlbnRpYWwgaXMgYSByZWNvdmVyYWJsZSBvdXRhZ2UgYW5kIGEgc2lsZW50bHkgZGVhZFxuICAgKiBsaXN0ZW5lciBpcyB3b3JzZSB0aGFuIGEgbm9pc3kgb25lLiBTdG9wcyB3aGVuIHRoZSBidXMgY2xvc2VzIG9yIHRoZSBsYXN0XG4gICAqIGxpc3RlbmVyIGxlYXZlcywgYW5kIHJlcG9ydHMgZXZlcnkgZmFpbGVkIGF0dGVtcHQgdGhyb3VnaCBgb25FcnJvcmAuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgZGVsYXkgPSAwO1xuICAgIHdoaWxlICghdGhpcy5jbG9zZWQgJiYgdGhpcy5saXN0ZW5lcnMuc2l6ZSA+IDApIHtcbiAgICAgIGlmIChkZWxheSA+IDApIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBhc3luY1V0aWxzLnNsZWVwKGRlbGF5LCB0aGlzLnJlY29ubmVjdEFib3J0LnNpZ25hbCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zdGFydCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgICBpZiAodGhpcy5jbG9zZWQpIHJldHVybjtcbiAgICAgICAgdGhpcy5vbkVycm9yKGNhdXNlKTtcbiAgICAgICAgZGVsYXkgPSBkZWxheSA9PT0gMCA/IE1JTl9SRUNPTk5FQ1RfREVMQVlfTVMgOiBNYXRoLm1pbihkZWxheSAqIDIsIE1BWF9SRUNPTk5FQ1RfREVMQVlfTVMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19
|
|
506
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9waWMtYnVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RvcGljLWJ1cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNuQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUlqRyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzVDLE9BQU8sRUFDTCxjQUFjLEVBQ2QsYUFBYSxFQUNiLE9BQU8sRUFDUCxlQUFlLEVBQ2YseUJBQXlCLEVBQ3pCLFdBQVcsRUFDWCx5QkFBeUIsR0FNMUIsTUFBTSxrQkFBa0IsQ0FBQztBQVExQixvRUFBb0U7QUFDcEUsTUFBTSxlQUFlLEdBQUcscUJBQXFCLENBQUM7QUFDOUM7Ozs7R0FJRztBQUNILE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0FBQy9CLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDO0FBQ25DLE1BQU0sc0JBQXNCLEdBQUcsS0FBSyxDQUFDO0FBa0JyQzs7OztHQUlHO0FBQ0gsSUFBSSxZQUEyRCxDQUFDO0FBZ0hoRTs7OztHQUlHO0FBQ0gsU0FBUyxlQUFlLENBQUMsTUFBcUQ7SUFDNUUsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUN2QixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBd0MsRUFBRTtRQUM1RSxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxTQUFTLENBQUM7SUFDaEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsU0FBUyxlQUFlO0lBQ3RCLE9BQU8sZUFBZSxDQUFD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LENBQUMsQ0FBQztZQUM3RixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVG9waWMgZmFuLW91dCBvdmVyIFBvc3RncmVTUUwgYExJU1RFTmAvYE5PVElGWWAsIGZvciB0ZWxsaW5nIGV2ZXJ5IHJ1bm5pbmdcbiAqIGluc3RhbmNlIG9mIGFuIGFwcCB0aGF0IHNvbWV0aGluZyBoYXBwZW5lZC5cbiAqXG4gKiBUaGUgc2libGluZyBgYWR2aXNvcnktbG9ja2AgbW9kdWxlIGlzIGFib3V0IG1ha2luZyBzdXJlIG9ubHkgT05FIGNvbm5lY3Rpb25cbiAqIGRvZXMgYSB0aGluZzsgdGhpcyBvbmUgaXMgdGhlIG9wcG9zaXRlIC0gRVZFUlkgbGlzdGVuaW5nIHNlc3Npb24gZ2V0cyBldmVyeVxuICogbm90aWZpY2F0aW9uLiBUaGF0IG1ha2VzIGl0IHRoZSByaWdodCBwcmltaXRpdmUgZm9yIGxpdmUgVUkgdXBkYXRlc1xuICogKGFuIFNTRSBzdHJlYW0gcGVyIGJyb3dzZXIgdGFiLCBhIGNhY2hlIGludmFsaWRhdGlvbiwgYSBwcmVzZW5jZSBwaW5nKSBhbmQgdGhlXG4gKiB3cm9uZyBvbmUgZm9yIHdvcmsgZGlzdHJpYnV0aW9uOiB0aGVyZSBhcmUgbm8gY29tcGV0aW5nIGNvbnN1bWVycywgbm8gYWNrcywgYW5kXG4gKiBubyByZXBsYXkuXG4gKlxuICogRGVsaXZlcnkgaXMgYmVzdC1lZmZvcnQgYW5kIGxpdmUuIGBOT1RJRllgIHJlYWNoZXMgc2Vzc2lvbnMgdGhhdCBhcmUgbGlzdGVuaW5nXG4gKiBhdCB0aGUgbW9tZW50IGl0IGNvbW1pdHMsIHNvIGEgbGlzdGVuZXIgdGhhdCBjb25uZWN0cyBhIHNlY29uZCBsYXRlciBuZXZlciBzZWVzXG4gKiBpdCwgYW5kIGEgbGlzdGVuZXIgd2hvc2UgY29ubmVjdGlvbiBkcm9wcyBtaXNzZXMgZXZlcnl0aGluZyB1bnRpbCB0aGUgYnVzXG4gKiByZWNvbm5lY3RzLiBVc2UgYSB0YWJsZSBvciBhIHF1ZXVlIHdoZW4gYSBzdWJzY3JpYmVyIG5lZWRzIGR1cmFiaWxpdHkuXG4gKlxuICogT05FIENIQU5ORUwsIE1BTlkgVE9QSUNTLiBFdmVyeSBidXMgaW5zdGFuY2UgbGlzdGVucyBvbiBhIHNpbmdsZSBQb3N0Z3Jlc1xuICogY2hhbm5lbCAoYGNoYW5uZWxgLCBkZWZhdWx0IGBkYnhfdG9vbHNfdG9waWNfYnVzYCkgYW5kIGZpbHRlcnMgYnkgdGhlXG4gKiBlbnZlbG9wZSdzIGB0b3BpY2AgaW4tcHJvY2Vzcywgc28gYWRkaW5nIGEgdG9waWMgY29zdHMgbm8gY29ubmVjdGlvbiBhbmQgbm9cbiAqIGBMSVNURU5gLiBUaGUgdHJhZGVvZmYgaXMgdGhhdCBldmVyeSBsaXN0ZW5pbmcgc2Vzc2lvbiBkZWNvZGVzIGV2ZXJ5IG1lc3NhZ2Ugb25cbiAqIHRoZSBjaGFubmVsOyBnaXZlIGEgZ2VudWluZWx5IGhpZ2gtdm9sdW1lLCB1bnJlbGF0ZWQgc3RyZWFtIGl0cyBvd24gYGNoYW5uZWxgXG4gKiByYXRoZXIgdGhhbiBhIHRvcGljLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBob3N0bmFtZSB9IGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBhc3luY1V0aWxzLCBlcnJvclV0aWxzLCBoYXNoLCBqc29uLCBvYmplY3QsIHN0cmluZ1V0aWxzIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgTm90aWZpY2F0aW9uLCBQb29sQ2xpZW50IH0gZnJvbSBcInBnXCI7XG5cbmltcG9ydCB0eXBlIHsgUGdQb29sTGlrZSwgUGdRdWVyeWFibGUgfSBmcm9tIFwiLi9hZHZpc29yeS1sb2NrLnRzXCI7XG5pbXBvcnQgeyBjaGFubmVsTmFtZSB9IGZyb20gXCIuL2lkZW50aXR5LnRzXCI7XG5pbXBvcnQge1xuICBjbGVhbnVwRXhwaXJlZCxcbiAgZGVjb2RlUG9pbnRlcixcbiAgaGlzdG9yeSxcbiAgcGVyc2lzdGVkTm90aWZ5LFxuICBwcm92aXNpb25NZXNzYWdlQnVzU2NoZW1hLFxuICByZWFkUG9pbnRlcixcbiAgcmVzb2x2ZVBlcnNpc3RlbmNlT3B0aW9ucyxcbiAgdHlwZSBEdXJhdGlvbklucHV0LFxuICB0eXBlIFJlc29sdmVkVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4gIHR5cGUgVG9waWNCdXNQZXJzaXN0ZW5jZU9wdGlvbnMsXG4gIHR5cGUgVG9waWNIaXN0b3J5UGFnZSxcbiAgdHlwZSBUb3BpY1BlcnNpc3RlbmNlU2NvcGUsXG59IGZyb20gXCIuL3BlcnNpc3RlbmNlLnRzXCI7XG5cbi8qKlxuICogYEBkYngtdG9vbHMvc2hhcmVkLWNvcmVgIG93bnMgdGhlIEpTT04tcm91bmQtdHJpcCBydWxlOyB0aGlzIGFsaWFzIGp1c3Qga2VlcHMgdGhlXG4gKiBnZW5lcmljIHNpZ25hdHVyZXMgYmVsb3cgcmVhZGFibGUuIENvbnN1bWVycyBpbXBvcnQgdGhlIHR5cGUgZnJvbSBzaGFyZWQtY29yZS5cbiAqL1xudHlwZSBTZXJpYWxpemFibGVWYWx1ZSA9IG9iamVjdC5TZXJpYWxpemFibGVWYWx1ZTtcblxuLyoqIENoYW5uZWwgcGFydHMgdXNlZCB3aGVuIGEgY2FsbGVyIG5hbWVzIG5vIGNoYW5uZWwgb2YgaXRzIG93bi4gKi9cbmNvbnN0IERFRkFVTFRfQ0hBTk5FTCA9IFwiZGJ4X3Rvb2xzX3RvcGljX2J1c1wiO1xuLyoqXG4gKiBFbmNvZGVkLWVudmVsb3BlIGNlaWxpbmcuIFBvc3RncmVTUUwgY2FwcyBhIGBOT1RJRllgIHBheWxvYWQgYXQgODAwMCBieXRlcyBhbmRcbiAqIGZhaWxzIHRoZSBzdGF0ZW1lbnQgcGFzdCB0aGF0LCBzbyB0aGUgYnVzIHJlamVjdHMgdGhlIG1lc3NhZ2UgZmlyc3Qgd2l0aCBhIHNpemVcbiAqIGl0IGNhbiBuYW1lLiBUaGUgbWFyZ2luIGJlbG93IDgwMDAgY292ZXJzIHRoZSBzZXJ2ZXIncyBvd24gYWNjb3VudGluZy5cbiAqL1xuY29uc3QgTUFYX05PVElGWV9CWVRFUyA9IDdfOTAwO1xuY29uc3QgTUlOX1JFQ09OTkVDVF9ERUxBWV9NUyA9IDI1MDtcbmNvbnN0IE1BWF9SRUNPTk5FQ1RfREVMQVlfTVMgPSA1XzAwMDtcblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIEFwcEtpdCdzIHBlci1yZXF1ZXN0IGV4ZWN1dGlvbiBjb250ZXh0IHRoZSBidXMgcmVhZHMgZm9yIHNlbmRlclxuICogaWRlbnRpdHkuIEZpZWxkcyBhcmUgYHVua25vd25gIGJlY2F1c2UgdGhpcyBpcyBhIHN0cnVjdHVyYWwgdmlldyBvZiBhbiBPUFRJT05BTFxuICogcGVlcjogdGhlIHZhbHVlcyBhcmUgdHJpbW1lZCBhbmQgdmFsaWRhdGVkIHJhdGhlciB0aGFuIHRydXN0ZWQuXG4gKi9cbnR5cGUgQXBwS2l0RXhlY3V0aW9uQ29udGV4dCA9IHtcbiAgdXNlckVtYWlsPzogdW5rbm93bjtcbiAgdXNlcklkPzogdW5rbm93bjtcbiAgdXNlck5hbWU/OiB1bmtub3duO1xufTtcblxuLyoqIFN0cnVjdHVyYWwgdmlldyBvZiBgQGRhdGFicmlja3MvYXBwa2l0YCwgaW1wb3J0ZWQgbGF6aWx5IGFuZCBuZXZlciByZXF1aXJlZC4gKi9cbnR5cGUgQXBwS2l0TW9kdWxlID0ge1xuICBnZXRFeGVjdXRpb25Db250ZXh0KCk6IEFwcEtpdEV4ZWN1dGlvbkNvbnRleHQ7XG59O1xuXG4vKipcbiAqIENhY2hlZCByZXN1bHQgb2YgdGhlIG9uZSBvcHRpb25hbC1wZWVyIGltcG9ydCwgcmVzb2x2ZWQgdG8gYHVuZGVmaW5lZGAgd2hlblxuICogQXBwS2l0IGlzIG5vdCBpbnN0YWxsZWQuIE1lbW9pemVkIHNvIGEgYnVzIGluIGEgcGxhaW4gUG9zdGdyZXMgcHJvY2VzcyBwYXlzIGZvclxuICogdGhlIGZhaWxlZCByZXNvbHV0aW9uIG9uY2UgaW5zdGVhZCBvZiBwZXIgYnJvYWRjYXN0LlxuICovXG5sZXQgYXBwS2l0TW9kdWxlOiBQcm9taXNlPEFwcEtpdE1vZHVsZSB8IHVuZGVmaW5lZD4gfCB1bmRlZmluZWQ7XG5cbi8qKlxuICogRmxhdC1rZXllZCBjb250ZXh0IHRyYXZlbGxpbmcgYWxvbmdzaWRlIGEgbWVzc2FnZSBib2R5OiB3aG8gc2VudCBpdCwgZnJvbVxuICogd2hlcmUsIGluIHdoaWNoIGRlcGxveW1lbnQuIFZhbHVlcyBtYXkgbmVzdCwgYnV0IHRoZSBrZXlzIGFyZSB0aGUgYWRkcmVzc2FibGVcbiAqIHBhcnQgLSBhIGxpc3RlbmVyIGZpbHRlcmluZyBvciBsYWJlbGxpbmcgbWVzc2FnZXMgcmVhZHMgYG1ldGFkYXRhLnVzZXJgLCBub3QgYVxuICogcGF0aCBpbnRvIHRoZSBib2R5LlxuICovXG5leHBvcnQgdHlwZSBUb3BpY01ldGFkYXRhID0gUmVjb3JkPHN0cmluZywgU2VyaWFsaXphYmxlVmFsdWU+O1xuXG4vKipcbiAqIFRoZSB3aXJlIGVudmVsb3BlIGV2ZXJ5IHN1YnNjcmliZXIgcmVjZWl2ZXMsIGFuZCB3aGF0IHtAbGlua1xuICogUG9zdGdyZXNUb3BpY0J1cy5icm9hZGNhc3R9IHJldHVybnMgdG8gdGhlIHB1Ymxpc2hlci5cbiAqXG4gKiBgaWRgLCBgdG9waWNgLCBhbmQgYHB1Ymxpc2hlZEF0YCBhcmUgYXNzaWduZWQgYnkgdGhlIGJ1czsgYHR5cGVgLCBgbWV0YWRhdGFgLFxuICogYW5kIGBib2R5YCBjb21lIGZyb20gdGhlIGNhbGxlciAod2l0aCBhdXRvbWF0aWMgY29udGV4dCBtZXJnZWQgdW5kZXJcbiAqIGBtZXRhZGF0YWApLiBUaGUgc2hhcGUgaXMgc3RhYmxlIGVub3VnaCB0byBoYW5kIHN0cmFpZ2h0IHRvIGFuIFNTRSBgZGF0YTpgXG4gKiBmcmFtZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUb3BpY01lc3NhZ2U8VEJvZHkgZXh0ZW5kcyBTZXJpYWxpemFibGVWYWx1ZSA9IFNlcmlhbGl6YWJsZVZhbHVlPiB7XG4gIC8qKlxuICAgKiBQZXItbWVzc2FnZSBpZGVudGl0eSBnZW5lcmF0ZWQgYnkgdGhlIHB1Ymxpc2hlciwgdW5pcXVlIGFjcm9zcyBpbnN0YW5jZXMuXG4gICAqIFN1aXRhYmxlIGZvciBkZWR1cGUgd2hlbiBhIGNsaWVudCByZWNvbm5lY3RzIGFuZCBmb3IgYW4gU1NFIGBpZDpgIGZpZWxkLiBOb3RcbiAgICogb3JkZXJlZCwgYW5kIG5vdCBhIGRhdGFiYXNlIGtleS5cbiAgICovXG4gIGlkOiBzdHJpbmc7XG4gIC8qKiBUaGUgdG9waWMgdGhpcyB3YXMgYnJvYWRjYXN0IG9uOyBsaXN0ZW5lcnMgb24gb3RoZXIgdG9waWNzIG5ldmVyIHNlZSBpdC4gKi9cbiAgdG9waWM6IHN0cmluZztcbiAgLyoqIENhbGxlci1jaG9zZW4gZXZlbnQgbmFtZSwgZS5nLiBgb3JkZXIudXBkYXRlZGAuIE5ldmVyIGVtcHR5LiAqL1xuICB0eXBlOiBzdHJpbmc7XG4gIC8qKiBBdXRvbWF0aWMgY29udGV4dCBtZXJnZWQgd2l0aCBjYWxsZXIgbWV0YWRhdGEuIFNlZSB7QGxpbmsgVG9waWNNZXRhZGF0YX0uICovXG4gIG1ldGFkYXRhOiBUb3BpY01ldGFkYXRhO1xuICAvKiogVGhlIGNhbGxlcidzIHBheWxvYWQsIHVuY2hhbmdlZC4gKi9cbiAgYm9keTogVEJvZHk7XG4gIC8qKlxuICAgKiBJU08tODYwMSBwdWJsaXNoIHRpbWUgZnJvbSB0aGUgUFVCTElTSElORyBwcm9jZXNzJ3MgY2xvY2ssIG5vdCB0aGUgZGF0YWJhc2Uncy5cbiAgICogRmluZSBmb3IgZGlzcGxheTsgZG8gbm90IG9yZGVyIG1lc3NhZ2VzIGZyb20gZGlmZmVyZW50IGluc3RhbmNlcyBieSBpdC5cbiAgICovXG4gIHB1Ymxpc2hlZEF0OiBzdHJpbmc7XG59XG5cbi8qKiBXaGF0IGEgY2FsbGVyIHN1cHBsaWVzIHRvIHtAbGluayBQb3N0Z3Jlc1RvcGljQnVzLmJyb2FkY2FzdH0uICovXG5leHBvcnQgaW50ZXJmYWNlIFRvcGljUHVibGlzaElucHV0PFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWUgPSBTZXJpYWxpemFibGVWYWx1ZT4ge1xuICAvKiogRXZlbnQgbmFtZSwgZS5nLiBgY2hhdC5tZXNzYWdlYC4gTXVzdCBiZSBub24tYmxhbmsuICovXG4gIHR5cGU6IHN0cmluZztcbiAgLyoqXG4gICAqIENvbnRleHQgdG8gYXR0YWNoLiBXaW5zIG92ZXIgYW55IGF1dG9tYXRpYyBrZXkgb2YgdGhlIHNhbWUgbmFtZSwgc28gYSBjYWxsZXJcbiAgICogY2FuIG92ZXJyaWRlIGEgbWFjaGluZSBkZWZhdWx0IChgcHJvamVjdGApIG9yIGFkZCBpdHMgb3duIChgdHJhY2VJZGApLlxuICAgKi9cbiAgbWV0YWRhdGE/OiBUb3BpY01ldGFkYXRhO1xuICAvKiogVGhlIHBheWxvYWQuIE11c3Qgc2F0aXNmeSBgb2JqZWN0LmlzU2VyaWFsaXphYmxlVmFsdWVgLiAqL1xuICBib2R5OiBUQm9keTtcbiAgc2NvcGU/OiBUb3BpY1BlcnNpc3RlbmNlU2NvcGU7XG4gIHR0bD86IER1cmF0aW9uSW5wdXQgfCBmYWxzZTtcbn1cblxuLyoqXG4gKiBTdWJzY3JpYmVyIGNhbGxiYWNrLiBJbnZva2VkIG9uY2UgcGVyIG1hdGNoaW5nIG1lc3NhZ2Ugb24gdGhlIG5vdGlmaWNhdGlvblxuICogY29ubmVjdGlvbidzIGNhbGxiYWNrLCBzbyBpdCBzaG91bGQgbm90IGJsb2NrOiBhIHJldHVybmVkIHByb21pc2UgaXMgYXdhaXRlZFxuICogb25seSB0byByb3V0ZSBhIHJlamVjdGlvbiB0byBgb25FcnJvcmAsIGFuZCBsaXN0ZW5lcnMgZm9yIG9uZSBtZXNzYWdlIHJ1blxuICogY29uY3VycmVudGx5IHJhdGhlciB0aGFuIGluIHJlZ2lzdHJhdGlvbiBvcmRlci5cbiAqXG4gKiBgVEJvZHlgIGlzIHVuY2hlY2tlZCBhdCBydW50aW1lLiBUaGUgYnVzIGd1YXJhbnRlZXMgdGhlIGJvZHkgaXMgc2VyaWFsaXphYmxlLFxuICogbm90IHRoYXQgaXQgbWF0Y2hlcyB0aGUgdHlwZSBwYXJhbWV0ZXIsIHNvIHZhbGlkYXRlIGFueXRoaW5nIGEgbGlzdGVuZXJcbiAqIGJyYW5jaGVzIG9uLlxuICovXG5leHBvcnQgdHlwZSBUb3BpY0xpc3RlbmVyPFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWUgPSBTZXJpYWxpemFibGVWYWx1ZT4gPSAoXG4gIG1lc3NhZ2U6IFRvcGljTWVzc2FnZTxUQm9keT4sXG4pID0+IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPjtcblxuLyoqXG4gKiBSZXNvbHZlcyBtZXRhZGF0YSBhdCBwdWJsaXNoIHRpbWUgaW5zdGVhZCBvZiBjb25zdHJ1Y3Rpb24gdGltZSwgZm9yIGNvbnRleHQgYVxuICogcHJvY2VzcyBsZWFybnMgbGF0ZSBvciBhc3luY2hyb25vdXNseSAtIGFuIGluc3RhbmNlIGlkIGZyb20gYSBjb250cm9sIHBsYW5lLCBhXG4gKiBkaXNjb3ZlcmVkIGFkZHJlc3MgYSBjYWxsZXIgY2hvb3NlcyB0byBhdHRhY2guIENhbGxlZCBvbiBldmVyeSBicm9hZGNhc3QsIHNvXG4gKiBtZW1vaXplIGFueXRoaW5nIGV4cGVuc2l2ZTsgYSByZWplY3Rpb24gZmFpbHMgdGhlIGJyb2FkY2FzdC5cbiAqL1xuZXhwb3J0IHR5cGUgVG9waWNNZXRhZGF0YVByb3ZpZGVyID0gKCkgPT4gVG9waWNNZXRhZGF0YSB8IFByb21pc2VMaWtlPFRvcGljTWV0YWRhdGE+O1xuXG4vKiogQ29uc3RydWN0aW9uIG9wdGlvbnMgZm9yIHtAbGluayBQb3N0Z3Jlc1RvcGljQnVzfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMge1xuICAvKipcbiAgICogV2hhdCBpZGVudGlmaWVzIHRoaXMgY2hhbm5lbCAtIGFueXRoaW5nLCBub3QganVzdCBhbiBpZGVudGlmaWVyOiBhIG5hbWUsIGFuXG4gICAqIGlkLCBhIGBbZW52LCBmZWF0dXJlXWAgcGFpciwgYSBjb25maWcgb2JqZWN0LiBUaGUgcGFydHMgYXJlIHRva2VuaXplZCBpbnRvIGFcbiAgICogbGVnYWwgUG9zdGdyZXMgY2hhbm5lbCBuYW1lIHdpdGggYSBzaG9ydCBoYXNoIG9mIHRoZSBvcmlnaW5hbHMgYXBwZW5kZWQsIHNvXG4gICAqIHRoZSBkZXJpdmF0aW9uIGlzIGRldGVybWluaXN0aWMgYW5kIG5vIGNhbGwgc2l0ZSBoYXMgdG8gc2FuaXRpemUuIFNlZVxuICAgKiB7QGxpbmsgUG9zdGdyZXNUb3BpY0J1cy5jaGFubmVsTmFtZX0gZm9yIHRoZSByZXNvbHZlZCBuYW1lLlxuICAgKlxuICAgKiBPbmUgdmFsdWUgb3IgbWFueTogYW4gYXJyYXkgaXMgcmVhZCBhcyBtdWx0aXBsZSBwYXJ0c1xuICAgKiAoe0BsaW5rIG9iamVjdC5PbmVPck1hbnl9KSwgYW55dGhpbmcgZWxzZSBhcyBhIHNpbmdsZSBwYXJ0LiBTb1xuICAgKiBgW1wiYmlsbGluZ1wiLCBcInByb2RcIl1gIGFuZCBgXCJiaWxsaW5nX3Byb2RcImAgYXJlIGRpZmZlcmVudCBjaGFubmVscywgc2luY2UgdGhlXG4gICAqIGhhc2ggc2VlcyBkaWZmZXJlbnQgc3RydWN0dXJlLlxuICAgKlxuICAgKiBFdmVyeSBwYXJ0aWNpcGF0aW5nIHByb2Nlc3MgbXVzdCBwYXNzIEVRVUlWQUxFTlQgcGFydHMsIHNpbmNlIGEgZGlmZmVyZW50XG4gICAqIHNwZWxsaW5nIGhhc2hlcyB0byBhIGRpZmZlcmVudCBjaGFubmVsLiBEZWZhdWx0cyB0byBhIHNoYXJlZFxuICAgKiBgZGJ4X3Rvb2xzX3RvcGljX2J1c2AgY2hhbm5lbC5cbiAgICovXG4gIGNoYW5uZWw/OiB1bmtub3duO1xuICAvKipcbiAgICogRXh0cmEgY29udGV4dCBhZGRlZCB0byBldmVyeSBtZXNzYWdlIHRoaXMgYnVzIHB1Ymxpc2hlcywgZWl0aGVyIGEgZml4ZWRcbiAgICogcmVjb3JkIG9yIGEge0BsaW5rIFRvcGljTWV0YWRhdGFQcm92aWRlcn0gY2FsbGVkIHBlciBicm9hZGNhc3QuIE92ZXJyaWRlc1xuICAgKiBhdXRvbWF0aWMgbWFjaGluZSBrZXlzOyBwZXItY2FsbCBgbWV0YWRhdGFgIG92ZXJyaWRlcyB0aGlzLlxuICAgKi9cbiAgbWV0YWRhdGE/OiBUb3BpY01ldGFkYXRhIHwgVG9waWNNZXRhZGF0YVByb3ZpZGVyO1xuICAvKipcbiAgICogU2luayBmb3IgZmFpbHVyZXMgdGhhdCBoYXZlIG5vIGNhbGxlciB0byB0aHJvdyB0bzogYSBsaXN0ZW5lciB0aGF0IHJlamVjdGVkLFxuICAgKiBhIGRyb3BwZWQgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24sIGEgZmFpbGVkIHJlY29ubmVjdCBhdHRlbXB0LiBEZWZhdWx0cyB0b1xuICAgKiBzd2FsbG93aW5nIHRoZW0sIHNvIHdpcmUgdGhpcyB0byBhIGxvZ2dlciBpbiBhbnl0aGluZyBsb25nLXJ1bm5pbmcuXG4gICAqL1xuICBvbkVycm9yPzogKGNhdXNlOiB1bmtub3duKSA9PiB2b2lkO1xuICBwZXJzaXN0PzogYm9vbGVhbiB8IFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zO1xufVxuXG4vKipcbiAqIERyb3Aga2V5cyB3aG9zZSB2YWx1ZSBpcyBgdW5kZWZpbmVkYCwgc28gYW4gdW5zZXQgZW52aXJvbm1lbnQgdmFyaWFibGUgbGVhdmVzXG4gKiB0aGUga2V5IEFCU0VOVCByYXRoZXIgdGhhbiBwcmVzZW50LWFuZC1udWxsLiBBYnNlbmNlIGlzIHdoYXQgbGV0cyBjYWxsZXJcbiAqIG1ldGFkYXRhIGFuZCBsYXRlciBtZXJnZSBsYXllcnMgc3VwcGx5IHRoZSBrZXkgaW5zdGVhZC5cbiAqL1xuZnVuY3Rpb24gZGVmaW5lZE1ldGFkYXRhKHZhbHVlczogUmVjb3JkPHN0cmluZywgU2VyaWFsaXphYmxlVmFsdWUgfCB1bmRlZmluZWQ+KTogVG9waWNNZXRhZGF0YSB7XG4gIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXModmFsdWVzKS5maWx0ZXIoKGVudHJ5KTogZW50cnkgaXMgW3N0cmluZywgU2VyaWFsaXphYmxlVmFsdWVdID0+IHtcbiAgICAgIHJldHVybiBlbnRyeVsxXSAhPT0gdW5kZWZpbmVkO1xuICAgIH0pLFxuICApO1xufVxuXG4vKipcbiAqIENvbnRleHQgZXZlcnkgbWVzc2FnZSBnZXRzIGZvciBmcmVlOiB3aGljaCBwcm9qZWN0LCBob3N0LCBhbmQgZGVwbG95bWVudFxuICogcHVibGlzaGVkIGl0LlxuICpcbiAqIFJlYWQgZnJlc2ggcGVyIGJyb2FkY2FzdCByYXRoZXIgdGhhbiBjYWNoZWQsIGJlY2F1c2UgYSBsb25nLWxpdmVkIHByb2Nlc3MgY2FuXG4gKiBiZSByZS1wYXJlbnRlZCAoYSBkZXBsb3ltZW50IGlkIGFwcGVhcmluZyBhZnRlciBib290KS4gS2V5cyB0aGF0IHJlc29sdmUgdG9cbiAqIG5vdGhpbmcgYXJlIG9taXR0ZWQuXG4gKlxuICogRGVsaWJlcmF0ZWx5IE5PVCBpbmNsdWRlZDogcHVibGljL2NsaWVudCBJUCwgcHJvY2VzcyBpZCwgQ1BVIGFyY2hpdGVjdHVyZSxcbiAqIHJ1bnRpbWUgbmFtZSwgYW5kIHJ1bnRpbWUgdmVyc2lvbi4gSVBzIGFuZCBwaWRzIGFyZSBub2lzeSwgb2Z0ZW4gc2Vuc2l0aXZlLFxuICogYW5kIGJ1cm4gYE5PVElGWWAgcGF5bG9hZCBidWRnZXQ7IGFyY2hpdGVjdHVyZS9ydW50aW1lIGFyZSBjb25zdGFudCBwZXJcbiAqIGRlcGxveW1lbnQgYW5kIHBheSB0aGUgc2FtZSBjb3N0LiBBIHByb2Nlc3MgdGhhdCB3YW50cyBhbnkgb2YgdGhlbSBwYXNzZXMgYVxuICoge0BsaW5rIFRvcGljTWV0YWRhdGFQcm92aWRlcn0gb3IgcGVyLW1lc3NhZ2UgYG1ldGFkYXRhYC5cbiAqL1xuZnVuY3Rpb24gbWFjaGluZU1ldGFkYXRhKCk6IFRvcGljTWV0YWRhdGEge1xuICByZXR1cm4gZGVmaW5lZE1ldGFkYXRhKHtcbiAgICBwcm9qZWN0OlxuICAgICAgc3RyaW5nVXRpbHMuZmlyc3ROb25FbXB0eShbXG4gICAgICAgIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQVBQX05BTUUsXG4gICAgICAgIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQlVORExFX05BTUUsXG4gICAgICAgIHByb2Nlc3MuZW52LlBST0pFQ1RfTkFNRSxcbiAgICAgICAgcHJvY2Vzcy5lbnYubnBtX3BhY2thZ2VfbmFtZSxcbiAgICAgIF0pID8/IHVuZGVmaW5lZCxcbiAgICBob3N0bmFtZTogaG9zdG5hbWUoKSxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICBlbnZpcm9ubWVudDogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChwcm9jZXNzLmVudi5OT0RFX0VOVikgPz8gdW5kZWZpbmVkLFxuICAgIGFwcE5hbWU6IHN0cmluZ1V0aWxzLnRyaW1Ub051bGwocHJvY2Vzcy5lbnYuREFUQUJSSUNLU19BUFBfTkFNRSkgPz8gdW5kZWZpbmVkLFxuICAgIGRlcGxveW1lbnRJZDogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0FQUF9ERVBMT1lNRU5UX0lEKSA/PyB1bmRlZmluZWQsXG4gICAgZGF0YWJyaWNrc0hvc3Q6IHN0cmluZ1V0aWxzLnRyaW1Ub051bGwocHJvY2Vzcy5lbnYuREFUQUJSSUNLU19IT1NUKSA/PyB1bmRlZmluZWQsXG4gIH0pO1xufVxuXG4vKipcbiAqIElkZW50aXR5IG9mIHRoZSBzaWduZWQtaW4gdXNlciBvbiB3aG9zZSBiZWhhbGYgdGhpcyBicm9hZGNhc3QgaGFwcGVucywgd2hlbiB0aGVcbiAqIHByb2Nlc3MgY2FuIHRlbGwuXG4gKlxuICogYEBkYXRhYnJpY2tzL2FwcGtpdGAgaXMgYW4gT1BUSU9OQUwgcGVlciwgc28gdGhlIGltcG9ydCBpcyBsYXp5IGFuZCBhIG1pc3NpbmdcbiAqIG1vZHVsZSBpcyBub3QgYW4gZXJyb3IgLSB0aGlzIGlzIGEgcGxhaW4gUG9zdGdyZXMgcGFja2FnZSB0aGF0IGFkZHMgc2VuZGVyXG4gKiBpZGVudGl0eSB3aGVuIGl0IGhhcHBlbnMgdG8gcnVuIGluc2lkZSBhbiBBcHBLaXQgYXBwLiBPdXRzaWRlIGFuIGFjdGl2ZVxuICogcGVyLXJlcXVlc3QgZXhlY3V0aW9uIGNvbnRleHQgQXBwS2l0IHRocm93cywgd2hpY2ggbWVhbnMgXCJubyB1c2VyIGhlcmVcIiwgc28gdGhlXG4gKiByZXN1bHQgaXMgZW1wdHkgbWV0YWRhdGEgcmF0aGVyIHRoYW4gYSBmYWlsZWQgYnJvYWRjYXN0LlxuICovXG5hc3luYyBmdW5jdGlvbiBzZW5kZXJNZXRhZGF0YSgpOiBQcm9taXNlPFRvcGljTWV0YWRhdGE+IHtcbiAgYXBwS2l0TW9kdWxlID8/PSBpbXBvcnQoXCJAZGF0YWJyaWNrcy9hcHBraXRcIilcbiAgICAudGhlbigobW9kdWxlKSA9PiBtb2R1bGUgYXMgQXBwS2l0TW9kdWxlKVxuICAgIC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICBjb25zdCBhcHBraXQgPSBhd2FpdCBhcHBLaXRNb2R1bGU7XG4gIGlmICghYXBwa2l0KSByZXR1cm4ge307XG4gIHRyeSB7XG4gICAgY29uc3QgY29udGV4dCA9IGFwcGtpdC5nZXRFeGVjdXRpb25Db250ZXh0KCk7XG4gICAgcmV0dXJuIGRlZmluZWRNZXRhZGF0YSh7XG4gICAgICBzZW5kZXJJZDogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChjb250ZXh0LnVzZXJJZCkgPz8gdW5kZWZpbmVkLFxuICAgICAgc2VuZGVyTmFtZTogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChjb250ZXh0LnVzZXJOYW1lKSA/PyB1bmRlZmluZWQsXG4gICAgICBzZW5kZXJFbWFpbDogc3RyaW5nVXRpbHMudHJpbVRvTnVsbChjb250ZXh0LnVzZXJFbWFpbCkgPz8gdW5kZWZpbmVkLFxuICAgIH0pO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4ge307XG4gIH1cbn1cblxuLyoqIFF1b3RlIGEgdmFsaWRhdGVkIGNoYW5uZWwgZm9yIGBMSVNURU5gL2BVTkxJU1RFTmAsIHdoaWNoIHRha2Ugbm8gcGFyYW1ldGVycy4gKi9cbmZ1bmN0aW9uIHF1b3RlSWRlbnRpZmllcih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBcIiR7dmFsdWUucmVwbGFjZUFsbCgnXCInLCAnXCJcIicpfVwiYDtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIGBOT1RJRllgIHBheWxvYWQgaW50byBhbiBlbnZlbG9wZSwgcmV0dXJuaW5nIGB1bmRlZmluZWRgIGZvciBhbnl0aGluZ1xuICogdGhhdCBpcyBub3Qgb25lLlxuICpcbiAqIFRoZSBjaGFubmVsIGlzIHNoYXJlZCBhbmQgYW55IFBvc3RncmVzIHNlc3Npb24gY2FuIGBwZ19ub3RpZnlgIG9uIGl0LCBzbyBhblxuICogdW5yZWNvZ25pemVkIHBheWxvYWQgaXMgZXhwZWN0ZWQgaW5wdXQsIG5vdCBhbiBleGNlcHRpb24uIFB1Ymxpc2hlcnMgcnVuIHRoaXNcbiAqIG92ZXIgdGhlaXIgb3duIGVuY29kZWQgbWVzc2FnZSB0b28sIHdoaWNoIGlzIGhvdyBhIGJvZHkgdGhhdCBzdHJpbmdpZmllcyBidXRcbiAqIGRvZXMgbm90IHJvdW5kLXRyaXAgaXMgY2F1Z2h0IGJlZm9yZSBpdCBzaGlwcy5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBUb3BpY01lc3NhZ2UgfCB1bmRlZmluZWQge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCByZWNvcmQgPSBqc29uLnBhcnNlUmVjb3JkKHZhbHVlKTtcbiAgaWYgKFxuICAgICFyZWNvcmQgfHxcbiAgICB0eXBlb2YgcmVjb3JkLmlkICE9PSBcInN0cmluZ1wiIHx8XG4gICAgdHlwZW9mIHJlY29yZC50b3BpYyAhPT0gXCJzdHJpbmdcIiB8fFxuICAgIHR5cGVvZiByZWNvcmQudHlwZSAhPT0gXCJzdHJpbmdcIiB8fFxuICAgIHR5cGVvZiByZWNvcmQucHVibGlzaGVkQXQgIT09IFwic3RyaW5nXCIgfHxcbiAgICAhcmVjb3JkLm1ldGFkYXRhIHx8XG4gICAgdHlwZW9mIHJlY29yZC5tZXRhZGF0YSAhPT0gXCJvYmplY3RcIiB8fFxuICAgIEFycmF5LmlzQXJyYXkocmVjb3JkLm1ldGFkYXRhKSB8fFxuICAgICEoXCJib2R5XCIgaW4gcmVjb3JkKSB8fFxuICAgICFvYmplY3QuaXNTZXJpYWxpemFibGVWYWx1ZShyZWNvcmQubWV0YWRhdGEpIHx8XG4gICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKHJlY29yZC5ib2R5KVxuICApIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiB7XG4gICAgaWQ6IHJlY29yZC5pZCxcbiAgICB0b3BpYzogcmVjb3JkLnRvcGljLFxuICAgIHR5cGU6IHJlY29yZC50eXBlLFxuICAgIG1ldGFkYXRhOiByZWNvcmQubWV0YWRhdGEgYXMgVG9waWNNZXRhZGF0YSxcbiAgICBib2R5OiByZWNvcmQuYm9keSBhcyBTZXJpYWxpemFibGVWYWx1ZSxcbiAgICBwdWJsaXNoZWRBdDogcmVjb3JkLnB1Ymxpc2hlZEF0LFxuICB9O1xufVxuXG4vKipcbiAqIEJyb2FkY2FzdHMgc3RydWN0dXJlZCBtZXNzYWdlcyBieSB0b3BpYyBhbmQgZGVsaXZlcnMgdGhlbSB0byBldmVyeSBwcm9jZXNzXG4gKiBsaXN0ZW5pbmcgb24gdGhlIHNhbWUgY2hhbm5lbC5cbiAqXG4gKiBDT05ORUNUSU9OIFNIQVBFLiBQdWJsaXNoaW5nIGJvcnJvd3MgYSBwb29sZWQgY29ubmVjdGlvbiBwZXIgY2FsbCwgbGlrZSBhbnlcbiAqIG90aGVyIHF1ZXJ5LiBMaXN0ZW5pbmcgY2Fubm90OiBgTElTVEVOYCBpcyBzZXNzaW9uIHN0YXRlLCBzbyB0aGUgYnVzIGhvbGRzIE9ORVxuICogZGVkaWNhdGVkIGNsaWVudCBvdXQgb2YgdGhlIHBvb2wgZm9yIGFzIGxvbmcgYXMgaXQgaGFzIHN1YnNjcmliZXJzLCBubyBtYXR0ZXJcbiAqIGhvdyBtYW55IHRvcGljcyBvciBsaXN0ZW5lcnMgYXJlIHJlZ2lzdGVyZWQuIFNpemUgdGhlIHBvb2wgd2l0aCB0aGF0IG9uZVxuICogbG9uZy1saXZlZCBjaGVja291dCBpbiBtaW5kLlxuICpcbiAqIExJRkVDWUNMRS4gQ29uc3RydWN0aW9uIGlzIGluZXJ0IC0gbm90aGluZyBjb25uZWN0cyB1bnRpbCB0aGUgZmlyc3RcbiAqIHtAbGluayBsaXN0ZW59IChvciBhbiBleHBsaWNpdCB7QGxpbmsgc3RhcnR9KS4ge0BsaW5rIGNsb3NlfSBpcyByZXF1aXJlZCB0byBnaXZlXG4gKiB0aGUgY29ubmVjdGlvbiBiYWNrOyBhIGNsb3NlZCBidXMgc3RheXMgY2xvc2VkIGFuZCB0aHJvd3Mgb24gZnVydGhlciB1c2UgcmF0aGVyXG4gKiB0aGFuIHNpbGVudGx5IHJlY29ubmVjdGluZy4gUmVnaXN0ZXIgaXQgd2l0aCB0aGUgaG9zdCdzIHNodXRkb3duIGhvb2suXG4gKlxuICogRkFJTFVSRSBIQU5ETElORy4gQSBsb3N0IG5vdGlmaWNhdGlvbiBjb25uZWN0aW9uIHJlY29ubmVjdHMgb24gaXRzIG93biB3aXRoXG4gKiBib3VuZGVkIGJhY2tvZmYgd2hpbGUgc3Vic2NyaWJlcnMgcmVtYWluLCByZXBvcnRpbmcgZWFjaCBmYWlsZWQgYXR0ZW1wdCB0aHJvdWdoXG4gKiBgb25FcnJvcmAuIE1lc3NhZ2VzIHB1Ymxpc2hlZCBkdXJpbmcgdGhlIGdhcCBhcmUgbG9zdCAtIGBOT1RJRllgIGhhcyBubyByZXBsYXkuXG4gKiBBIHRocm93aW5nIG9yIHJlamVjdGluZyBsaXN0ZW5lciBuZXZlciBhZmZlY3RzIHRoZSBwdWJsaXNoZXIgb3IgdGhlIG90aGVyXG4gKiBsaXN0ZW5lcnM7IGl0cyBmYWlsdXJlIGdvZXMgdG8gYG9uRXJyb3JgLlxuICpcbiAqIE5vdCBzYWZlIHRvIHNoYXJlIG9uZSBpbnN0YW5jZSBhY3Jvc3MgdW5yZWxhdGVkIGNoYW5uZWxzIC0gY29uc3RydWN0IG9uZSBidXNcbiAqIHBlciBjaGFubmVsLiBUaGUgY2hhbm5lbCBpdHNlbGYgaXMgREVSSVZFRCBmcm9tIHRoZSBgY2hhbm5lbGAgb3B0aW9uIHJhdGhlclxuICogdGhhbiB0YWtlbiBsaXRlcmFsbHk7IHNlZSB7QGxpbmsgUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMuY2hhbm5lbH0gYW5kXG4gKiB7QGxpbmsgUG9zdGdyZXNUb3BpY0J1cy5jaGFubmVsTmFtZX0uXG4gKi9cbmV4cG9ydCBjbGFzcyBQb3N0Z3Jlc1RvcGljQnVzIHtcbiAgLyoqXG4gICAqIFRoZSByZXNvbHZlZCBQb3N0Z3JlcyBjaGFubmVsIHRoaXMgYnVzIGxpc3RlbnMgYW5kIHB1Ymxpc2hlcyBvbiwgZGVyaXZlZCBmcm9tXG4gICAqIHRoZSBgY2hhbm5lbGAgb3B0aW9uLiBSZWFkIGl0IHRvIGNvbmZpcm0gdHdvIHByb2Nlc3NlcyBhZ3JlZSwgb3IgdG8gbG9nIHdoYXQgYVxuICAgKiBzZXQgb2YgcGFydHMgYWN0dWFsbHkgcmVzb2x2ZWQgdG8uXG4gICAqL1xuICByZWFkb25seSBjaGFubmVsTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldGFkYXRhOiBUb3BpY01ldGFkYXRhIHwgVG9waWNNZXRhZGF0YVByb3ZpZGVyIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IG9uRXJyb3I6IChjYXVzZTogdW5rbm93bikgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBsaXN0ZW5lcnMgPSBuZXcgTWFwPHN0cmluZywgU2V0PFRvcGljTGlzdGVuZXI+PigpO1xuICBwcml2YXRlIGNsaWVudDogUG9vbENsaWVudCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBzdGFydGluZzogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWNvbm5lY3Rpbmc6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb25uZWN0QWJvcnQgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIHByaXZhdGUgY2xvc2VkID0gZmFsc2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVyc2lzdGVuY2U/OiBSZXNvbHZlZFRvcGljQnVzUGVyc2lzdGVuY2VPcHRpb25zO1xuICBwcml2YXRlIHByb3Zpc2lvbmluZz86IFByb21pc2U8dm9pZD47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb29sOiBQZ1Bvb2xMaWtlICYgUGdRdWVyeWFibGUsXG4gICAgb3B0aW9uczogUG9zdGdyZXNUb3BpY0J1c09wdGlvbnMgPSB7fSxcbiAgKSB7XG4gICAgdGhpcy5jaGFubmVsTmFtZSA9IGNoYW5uZWxOYW1lKFxuICAgICAgb3B0aW9ucy5jaGFubmVsID09PSB1bmRlZmluZWQgPyBERUZBVUxUX0NIQU5ORUwgOiBvcHRpb25zLmNoYW5uZWwsXG4gICAgKTtcbiAgICB0aGlzLm1ldGFkYXRhID0gb3B0aW9ucy5tZXRhZGF0YTtcbiAgICB0aGlzLm9uRXJyb3IgPSBvcHRpb25zLm9uRXJyb3IgPz8gKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgdGhpcy5wZXJzaXN0ZW5jZSA9IG9wdGlvbnMucGVyc2lzdFxuICAgICAgPyByZXNvbHZlUGVyc2lzdGVuY2VPcHRpb25zKG9wdGlvbnMucGVyc2lzdCA9PT0gdHJ1ZSA/IHRydWUgOiBvcHRpb25zLnBlcnNpc3QpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIHRoZSBkZWRpY2F0ZWQgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gYW5kIGBMSVNURU5gLlxuICAgKlxuICAgKiBJZGVtcG90ZW50LCBhbmQgc2FmZSB0byBjYWxsIGNvbmN1cnJlbnRseSAtIG92ZXJsYXBwaW5nIGNhbGxzIGF3YWl0IHRoZSBzYW1lXG4gICAqIGluLWZsaWdodCBjb25uZWN0LiB7QGxpbmsgbGlzdGVufSBjYWxscyB0aGlzLCBzbyBpdCBpcyBvbmx5IG5lZWRlZCB0byBzdXJmYWNlXG4gICAqIGEgY29ubmVjdGlvbiBwcm9ibGVtIGF0IHN0YXJ0dXAgcmF0aGVyIHRoYW4gb24gZmlyc3Qgc3Vic2NyaWJlLiBUaHJvd3MgaWYgdGhlXG4gICAqIGJ1cyBpcyBjbG9zZWQsIG9yIGlmIHRoZSBwb29sIGNhbm5vdCBoYW5kIG91dCBhIGNvbm5lY3Rpb24uXG4gICAqL1xuICBhc3luYyBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5jbGllbnQpIHJldHVybjtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihcIlBvc3RncmVzIHRvcGljIGJ1cyBpcyBjbG9zZWRcIik7XG4gICAgdGhpcy5zdGFydGluZyA/Pz0gdGhpcy5jb25uZWN0KCkuZmluYWxseSgoKSA9PiB7XG4gICAgICB0aGlzLnN0YXJ0aW5nID0gdW5kZWZpbmVkO1xuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuc3RhcnRpbmc7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhIG1lc3NhZ2UgdG8gYHRvcGljYCwgcmV0dXJuaW5nIHRoZSBlbnZlbG9wZSB0aGF0IHdhcyBzZW50LlxuICAgKlxuICAgKiBSZXNvbHZlcyBvbmNlIFBvc3RncmVzIGhhcyBhY2NlcHRlZCB0aGUgYE5PVElGWWAsIHdoaWNoIHNheXMgbm90aGluZyBhYm91dFxuICAgKiBhbnlvbmUgcmVjZWl2aW5nIGl0OiBzZXNzaW9ucyBub3QgbGlzdGVuaW5nIGF0IHRoYXQgbW9tZW50IG1pc3MgaXQuIFB1Ymxpc2hpbmdcbiAgICogbmVlZHMgbm8ge0BsaW5rIHN0YXJ0fSBhbmQgbm8gc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIFZhbGlkYXRpb24gaXMgZGVsaWJlcmF0ZWx5IGZyb250LWxvYWRlZCwgc2luY2UgYSBtZXNzYWdlIHRoYXQgZmFpbHMgb24gdGhlXG4gICAqIHdpcmUgaXMgZmFyIGhhcmRlciB0byBkaWFnbm9zZSB0aGFuIG9uZSByZWplY3RlZCBhdCB0aGUgY2FsbDogYFR5cGVFcnJvcmAgZm9yIGFcbiAgICogYmxhbmsgdG9waWMgb3IgdHlwZSwgb3IgYSBib2R5L21ldGFkYXRhIHRoYXQgd291bGQgbm90IHJvdW5kLXRyaXAgdGhyb3VnaCBKU09OXG4gICAqIHVuY2hhbmdlZCAoYG9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlYCk7IGBSYW5nZUVycm9yYCB3aGVuIHRoZSBlbmNvZGVkXG4gICAqIGVudmVsb3BlIGV4Y2VlZHMgdGhlIGBOT1RJRllgIHBheWxvYWQgbGltaXQsIHdoaWNoIHRoZSBhdXRvbWF0aWMgbWV0YWRhdGFcbiAgICogY291bnRzIGFnYWluc3QgLSBzZW5kIGEgcmVmZXJlbmNlIGFuZCBsZXQgdGhlIHJlY2VpdmVyIGZldGNoIHRoZSBwYXlsb2FkLlxuICAgKiBUaHJvd3MgaWYgdGhlIGJ1cyBpcyBjbG9zZWQuXG4gICAqL1xuICBhc3luYyBicm9hZGNhc3Q8VEJvZHkgZXh0ZW5kcyBTZXJpYWxpemFibGVWYWx1ZT4oXG4gICAgdG9waWM6IHN0cmluZyxcbiAgICBpbnB1dDogVG9waWNQdWJsaXNoSW5wdXQ8VEJvZHk+LFxuICApOiBQcm9taXNlPFRvcGljTWVzc2FnZTxUQm9keT4+IHtcbiAgICBpZiAoIXRvcGljLnRyaW0oKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRvcGljIG11c3Qgbm90IGJlIGVtcHR5XCIpO1xuICAgIGlmICghaW5wdXQudHlwZS50cmltKCkpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNZXNzYWdlIHR5cGUgbXVzdCBub3QgYmUgZW1wdHlcIik7XG4gICAgaWYgKFxuICAgICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKGlucHV0Lm1ldGFkYXRhID8/IHt9KSB8fFxuICAgICAgIW9iamVjdC5pc1NlcmlhbGl6YWJsZVZhbHVlKGlucHV0LmJvZHkpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBtZXRhZGF0YSBhbmQgYm9keSBtdXN0IGJlIEpTT04gc2VyaWFsaXphYmxlIHdpdGhvdXQgY29lcmNpb25cIik7XG4gICAgfVxuICAgIGlmICh0aGlzLmNsb3NlZCkgdGhyb3cgbmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIGlzIGNsb3NlZFwiKTtcbiAgICBjb25zdCBhdXRvbWF0aWMgPSBhd2FpdCB0aGlzLnJlc29sdmVNZXRhZGF0YSgpO1xuICAgIGNvbnN0IG1lc3NhZ2U6IFRvcGljTWVzc2FnZTxUQm9keT4gPSB7XG4gICAgICBpZDogaGFzaC5pZCgpLFxuICAgICAgdG9waWMsXG4gICAgICB0eXBlOiBpbnB1dC50eXBlLFxuICAgICAgbWV0YWRhdGE6IHsgLi4uYXV0b21hdGljLCAuLi5pbnB1dC5tZXRhZGF0YSB9LFxuICAgICAgYm9keTogaW5wdXQuYm9keSxcbiAgICAgIHB1Ymxpc2hlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgfTtcbiAgICBsZXQgZW5jb2RlZDogc3RyaW5nO1xuICAgIHRyeSB7XG4gICAgICBlbmNvZGVkID0gSlNPTi5zdHJpbmdpZnkobWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYE1lc3NhZ2UgbXVzdCBiZSBKU09OIHNlcmlhbGl6YWJsZTogJHtlcnJvclV0aWxzLmVycm9yTWVzc2FnZShjYXVzZSl9YCk7XG4gICAgfVxuICAgIGlmICghZGVjb2RlKGVuY29kZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSB0eXBlLCBtZXRhZGF0YSwgYW5kIGJvZHkgbXVzdCBiZSBKU09OIHNlcmlhbGl6YWJsZVwiKTtcbiAgICB9XG4gICAgLy8gT25seSB0aGUgZW52ZWxvcGUgcGF5bG9hZCBpcyBib3VuZGVkIGJ5IHRoZSBgTk9USUZZYCBsaW1pdC4gQSBwb2ludGVyXG4gICAgLy8gbm90aWZpY2F0aW9uIGlzIGEgZml4ZWQgaGFuZGZ1bCBvZiBieXRlcywgc28gcGVyc2lzdGVuY2Ugd2l0aFxuICAgIC8vIGBwYXlsb2FkOiBcInBvaW50ZXJcImAgbGlmdHMgdGhlIGNhcCBlbnRpcmVseS5cbiAgICBpZiAoXG4gICAgICBCdWZmZXIuYnl0ZUxlbmd0aChlbmNvZGVkLCBcInV0ZjhcIikgPiBNQVhfTk9USUZZX0JZVEVTICYmXG4gICAgICB0aGlzLnBlcnNpc3RlbmNlPy5wYXlsb2FkICE9PSBcInBvaW50ZXJcIlxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYFBvc3RncmVzIG5vdGlmaWNhdGlvbiBleGNlZWRzICR7TUFYX05PVElGWV9CWVRFU30gYnl0ZXNgKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnBlcnNpc3RlbmNlKSB7XG4gICAgICBhd2FpdCB0aGlzLnBvb2wucXVlcnkoXCJTRUxFQ1QgcGdfbm90aWZ5KCQxLCAkMilcIiwgW3RoaXMuY2hhbm5lbE5hbWUsIGVuY29kZWRdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMucGVyc2lzdGVuY2UucHJvdmlzaW9uKSB7XG4gICAgICAgIHRoaXMucHJvdmlzaW9uaW5nID8/PSBwcm92aXNpb25NZXNzYWdlQnVzU2NoZW1hKHRoaXMucG9vbCwgdGhpcy5wZXJzaXN0ZW5jZSk7XG4gICAgICAgIGF3YWl0IHRoaXMucHJvdmlzaW9uaW5nO1xuICAgICAgfVxuICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wb29sLmNvbm5lY3QoKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkJFR0lOXCIpO1xuICAgICAgICBhd2FpdCBwZXJzaXN0ZWROb3RpZnkoXG4gICAgICAgICAgY2xpZW50LFxuICAgICAgICAgIHRoaXMuY2hhbm5lbE5hbWUsXG4gICAgICAgICAgdG9waWMsXG4gICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICBlbmNvZGVkLFxuICAgICAgICAgIHRoaXMucGVyc2lzdGVuY2UsXG4gICAgICAgICAgaW5wdXQuc2NvcGUgPz8gdGhpcy5wZXJzaXN0ZW5jZS5zY29wZSxcbiAgICAgICAgICBpbnB1dC50dGwgPz8gdGhpcy5wZXJzaXN0ZW5jZS50dGwsXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIkNPTU1JVFwiKTtcbiAgICAgIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcIlJPTExCQUNLXCIpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgIHRocm93IGNhdXNlO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgY2xpZW50LnJlbGVhc2UoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH1cblxuICBhc3luYyBoaXN0b3J5PFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWU+KFxuICAgIHRvcGljOiBzdHJpbmcsXG4gICAgb3B0aW9uczogeyBhZnRlcj86IHN0cmluZzsgbGltaXQ/OiBudW1iZXI7IHNjb3BlPzogVG9waWNQZXJzaXN0ZW5jZVNjb3BlIH0gPSB7fSxcbiAgKTogUHJvbWlzZTxUb3BpY0hpc3RvcnlQYWdlPFRCb2R5Pj4ge1xuICAgIGlmICghdGhpcy5wZXJzaXN0ZW5jZSkgdGhyb3cgbmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIHBlcnNpc3RlbmNlIGlzIGRpc2FibGVkXCIpO1xuICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlLnByb3Zpc2lvbikge1xuICAgICAgdGhpcy5wcm92aXNpb25pbmcgPz89IHByb3Zpc2lvbk1lc3NhZ2VCdXNTY2hlbWEodGhpcy5wb29sLCB0aGlzLnBlcnNpc3RlbmNlKTtcbiAgICAgIGF3YWl0IHRoaXMucHJvdmlzaW9uaW5nO1xuICAgIH1cbiAgICByZXR1cm4gaGlzdG9yeTxUQm9keT4odGhpcy5wb29sLCB0aGlzLmNoYW5uZWxOYW1lLCB0b3BpYywgdGhpcy5wZXJzaXN0ZW5jZSwgb3B0aW9ucyk7XG4gIH1cblxuICBhc3luYyBjbGVhbnVwRXhwaXJlZChcbiAgICBvcHRpb25zOiB7IHNjb3BlPzogVG9waWNQZXJzaXN0ZW5jZVNjb3BlOyBsaW1pdD86IG51bWJlciB9ID0ge30sXG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgaWYgKCF0aGlzLnBlcnNpc3RlbmNlKSB0aHJvdyBuZXcgRXJyb3IoXCJQb3N0Z3JlcyB0b3BpYyBidXMgcGVyc2lzdGVuY2UgaXMgZGlzYWJsZWRcIik7XG4gICAgcmV0dXJuIGNsZWFudXBFeHBpcmVkKFxuICAgICAgdGhpcy5wb29sLFxuICAgICAgdGhpcy5wZXJzaXN0ZW5jZSxcbiAgICAgIG9wdGlvbnMuc2NvcGUgPz8gdGhpcy5wZXJzaXN0ZW5jZS5zY29wZSxcbiAgICAgIG9wdGlvbnMubGltaXQsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJzY3JpYmUgdG8gYHRvcGljYCwgcmV0dXJuaW5nIHRoZSBmdW5jdGlvbiB0aGF0IHVuc3Vic2NyaWJlcy5cbiAgICpcbiAgICogQ29ubmVjdHMgb24gZmlyc3QgdXNlLiBTZXZlcmFsIGxpc3RlbmVycyBtYXkgc2hhcmUgYSB0b3BpYzsgZWFjaCBpcyBjYWxsZWRcbiAgICogb25jZSBwZXIgbWVzc2FnZS4gT25seSBtZXNzYWdlcyBwdWJsaXNoZWQgQUZURVIgdGhpcyByZXNvbHZlcyBhcnJpdmUsIHNvXG4gICAqIHN1YnNjcmliZSBiZWZvcmUgdHJpZ2dlcmluZyB3aGF0ZXZlciB5b3UgZXhwZWN0IHRvIG9ic2VydmUuXG4gICAqXG4gICAqIFRoZSByZXR1cm5lZCBmdW5jdGlvbiByZW1vdmVzIGp1c3QgdGhpcyBsaXN0ZW5lciBhbmQgaXMgc2FmZSB0byBjYWxsIHR3aWNlLlxuICAgKiBUaGUgY29ubmVjdGlvbiBzdGF5cyBvcGVuIG9uY2UgdGhlIGxhc3QgbGlzdGVuZXIgbGVhdmVzIC0ge0BsaW5rIGNsb3NlfVxuICAgKiByZWxlYXNlcyBpdCAtIHNvIGEgYnVzIHRoYXQgc3Vic2NyaWJlcyBhbmQgdW5zdWJzY3JpYmVzIHBlciByZXF1ZXN0IGRvZXMgbm90XG4gICAqIGNodXJuIGNvbm5lY3Rpb25zLlxuICAgKi9cbiAgYXN5bmMgbGlzdGVuPFRCb2R5IGV4dGVuZHMgU2VyaWFsaXphYmxlVmFsdWU+KFxuICAgIHRvcGljOiBzdHJpbmcsXG4gICAgbGlzdGVuZXI6IFRvcGljTGlzdGVuZXI8VEJvZHk+LFxuICApOiBQcm9taXNlPCgpID0+IFByb21pc2U8dm9pZD4+IHtcbiAgICBpZiAoIXRvcGljLnRyaW0oKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRvcGljIG11c3Qgbm90IGJlIGVtcHR5XCIpO1xuICAgIGF3YWl0IHRoaXMuc3RhcnQoKTtcbiAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmxpc3RlbmVycy5nZXQodG9waWMpID8/IG5ldyBTZXQ8VG9waWNMaXN0ZW5lcj4oKTtcbiAgICBsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyIGFzIFRvcGljTGlzdGVuZXIpO1xuICAgIHRoaXMubGlzdGVuZXJzLnNldCh0b3BpYywgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgbGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lciBhcyBUb3BpY0xpc3RlbmVyKTtcbiAgICAgIGlmIChsaXN0ZW5lcnMuc2l6ZSA9PT0gMCkgdGhpcy5saXN0ZW5lcnMuZGVsZXRlKHRvcGljKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHRoZSBhdXRvbWF0aWMgaGFsZiBvZiBhIG1lc3NhZ2UncyBtZXRhZGF0YS5cbiAgICpcbiAgICogUHJlY2VkZW5jZSwgd2Vha2VzdCBmaXJzdDogbWFjaGluZS9wcm9jZXNzIGNvbnRleHQsIHRoZW4gQXBwS2l0IHNlbmRlclxuICAgKiBpZGVudGl0eSwgdGhlbiB0aGlzIGJ1cydzIGNvbmZpZ3VyZWQgbWV0YWRhdGEuIFRoZSBjYWxsZXIncyBwZXItbWVzc2FnZVxuICAgKiBtZXRhZGF0YSBpcyBsYXllcmVkIG92ZXIgdGhlIHJlc3VsdCBpbiB7QGxpbmsgYnJvYWRjYXN0fSwgc28gdGhlIG1vc3Qgc3BlY2lmaWNcbiAgICogc291cmNlIGFsd2F5cyB3aW5zIGFuZCBub3RoaW5nIGhlcmUgY2FuIG92ZXJ3cml0ZSBhbiBleHBsaWNpdCBrZXkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlc29sdmVNZXRhZGF0YSgpOiBQcm9taXNlPFRvcGljTWV0YWRhdGE+IHtcbiAgICBjb25zdCBzZW5kZXIgPSBhd2FpdCBzZW5kZXJNZXRhZGF0YSgpO1xuICAgIGNvbnN0IGNvbmZpZ3VyZWQgPVxuICAgICAgdHlwZW9mIHRoaXMubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIiA/IGF3YWl0IHRoaXMubWV0YWRhdGEoKSA6ICh0aGlzLm1ldGFkYXRhID8/IHt9KTtcbiAgICByZXR1cm4geyAuLi5tYWNoaW5lTWV0YWRhdGEoKSwgLi4uc2VuZGVyLCAuLi5jb25maWd1cmVkIH07XG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZSB0aGUgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gYW5kIHN0b3AgZGVsaXZlcmluZyBtZXNzYWdlcy4gSWRlbXBvdGVudC5cbiAgICpcbiAgICogQ2FuY2VscyBhbnkgcGVuZGluZyByZWNvbm5lY3QsIGRyb3BzIGFsbCBsaXN0ZW5lcnMsIHRoZW4gYFVOTElTVEVOYHMgYW5kXG4gICAqIHJldHVybnMgdGhlIGNsaWVudCB0byB0aGUgcG9vbC4gQSBmYWlsZWQgYFVOTElTVEVOYCBpcyByZXBvcnRlZCB0byB0aGUgcG9vbCBhc1xuICAgKiBhIHJlbGVhc2UgZXJyb3Igc28gdGhlIGNvbm5lY3Rpb24gaXMgRElTQ0FSREVEIHJhdGhlciB0aGFuIGhhbmRlZCB0byB0aGUgbmV4dFxuICAgKiBjYWxsZXIgc3RpbGwgc3Vic2NyaWJlZCB0byB0aGUgY2hhbm5lbC4gRG9lcyBub3QgdGhyb3c7IHRoZSBidXMgc3RheXMgY2xvc2VkLlxuICAgKi9cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSByZXR1cm47XG4gICAgdGhpcy5jbG9zZWQgPSB0cnVlO1xuICAgIHRoaXMucmVjb25uZWN0QWJvcnQuYWJvcnQobmV3IEVycm9yKFwiUG9zdGdyZXMgdG9waWMgYnVzIGlzIGNsb3NlZFwiKSk7XG4gICAgYXdhaXQgdGhpcy5zdGFydGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBhd2FpdCB0aGlzLnJlY29ubmVjdGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudDtcbiAgICB0aGlzLmNsaWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxpc3RlbmVycy5jbGVhcigpO1xuICAgIGlmICghY2xpZW50KSByZXR1cm47XG4gICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICBjbGllbnQucmVtb3ZlTGlzdGVuZXIoXCJlcnJvclwiLCB0aGlzLmhhbmRsZUNsaWVudEVycm9yKTtcbiAgICBsZXQgcmVsZWFzZUVycm9yOiBFcnJvciB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KGBVTkxJU1RFTiAke3F1b3RlSWRlbnRpZmllcih0aGlzLmNoYW5uZWxOYW1lKX1gKTtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgcmVsZWFzZUVycm9yID0gZXJyb3JVdGlscy50b0Vycm9yKGNhdXNlKTtcbiAgICB9XG4gICAgY2xpZW50LnJlbGVhc2UocmVsZWFzZUVycm9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBvdXQgb25lIGNsaWVudCwgYXR0YWNoIHRoZSBoYW5kbGVycywgYW5kIGBMSVNURU5gLlxuICAgKlxuICAgKiBUaGUgaGFuZGxlcnMgYXJlIGF0dGFjaGVkIEJFRk9SRSB0aGUgYExJU1RFTmAgcm91bmQgdHJpcCBzbyBhIG5vdGlmaWNhdGlvbiBvclxuICAgKiBlcnJvciBhcnJpdmluZyBtaWQtc2V0dXAgaXMgbm90IG1pc3NlZC4gQW55IGZhaWx1cmUgLSBpbmNsdWRpbmcgdGhlIGJ1cyBiZWluZ1xuICAgKiBjbG9zZWQgd2hpbGUgdGhlIGNvbm5lY3Qgd2FzIGluIGZsaWdodCAtIGRldGFjaGVzIHRoZSBoYW5kbGVycyBhbmQgcmVsZWFzZXNcbiAgICogdGhlIGNsaWVudCBhcyBlcnJvcmVkLCBzbyBhIGhhbGYtY29uZmlndXJlZCBjb25uZWN0aW9uIG5ldmVyIHJldHVybnMgdG8gdGhlXG4gICAqIHBvb2wuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wb29sLmNvbm5lY3QoKTtcbiAgICB0cnkge1xuICAgICAgY2xpZW50Lm9uKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICAgIGNsaWVudC5vbihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KGBMSVNURU4gJHtxdW90ZUlkZW50aWZpZXIodGhpcy5jaGFubmVsTmFtZSl9YCk7XG4gICAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihcIlBvc3RncmVzIHRvcGljIGJ1cyBpcyBjbG9zZWRcIik7XG4gICAgICB0aGlzLmNsaWVudCA9IGNsaWVudDtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKFwibm90aWZpY2F0aW9uXCIsIHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKTtcbiAgICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgICAgY2xpZW50LnJlbGVhc2UoZXJyb3JVdGlscy50b0Vycm9yKGNhdXNlKSk7XG4gICAgICB0aHJvdyBjYXVzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUm91dGUgb25lIGluYm91bmQgbm90aWZpY2F0aW9uIHRvIHRoZSB0b3BpYydzIGxpc3RlbmVycy5cbiAgICpcbiAgICogSWdub3JlcyBvdGhlciBjaGFubmVscyBhbmQgdW5kZWNvZGFibGUgcGF5bG9hZHMgLSB0aGUgY2hhbm5lbCBpcyBzaGFyZWQsIHNvXG4gICAqIGJvdGggYXJlIG9yZGluYXJ5IHRyYWZmaWMuIExpc3RlbmVycyBhcmUgaW52b2tlZCBjb25jdXJyZW50bHkgYW5kIHRoZWlyXG4gICAqIHJlamVjdGlvbnMgZ28gdG8gYG9uRXJyb3JgLCBrZWVwaW5nIG9uZSBzbG93IG9yIGJyb2tlbiBzdWJzY3JpYmVyIGZyb21cbiAgICogc3RhbGxpbmcgdGhlIG5vdGlmaWNhdGlvbiBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVOb3RpZmljYXRpb24gPSAobm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb24pOiB2b2lkID0+IHtcbiAgICBpZiAobm90aWZpY2F0aW9uLmNoYW5uZWwgIT09IHRoaXMuY2hhbm5lbE5hbWUpIHJldHVybjtcbiAgICBjb25zdCBtZXNzYWdlID0gZGVjb2RlKG5vdGlmaWNhdGlvbi5wYXlsb2FkKTtcbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgdGhpcy5kZWxpdmVyKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBgcGF5bG9hZDogXCJwb2ludGVyXCJgIGNhcnJpZXMgb25seSByb3V0aW5nIGFuZCBpZGVudGl0eSwgc28gdGhlIGVudmVsb3BlIGhhc1xuICAgIC8vIHRvIGJlIHJlYWQgYmFjayBiZWZvcmUgYW55dGhpbmcgY2FuIGJlIGRlbGl2ZXJlZC4gT25seSBhdHRlbXB0ZWQgd2hlbiB0aGlzXG4gICAgLy8gYnVzIGlzIGNvbmZpZ3VyZWQgZm9yIHBlcnNpc3RlbmNlOyBvdGhlcndpc2UgdGhlIHBheWxvYWQgaXMgZm9yZWlnbiB0cmFmZmljXG4gICAgLy8gb24gYSBzaGFyZWQgY2hhbm5lbCBhbmQgaWdub3JlZCBhcyBiZWZvcmUuXG4gICAgY29uc3QgcG9pbnRlciA9IHRoaXMucGVyc2lzdGVuY2UgPyBkZWNvZGVQb2ludGVyKG5vdGlmaWNhdGlvbi5wYXlsb2FkKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIXBvaW50ZXIpIHJldHVybjtcbiAgICBpZiAoIXRoaXMubGlzdGVuZXJzLmhhcyhwb2ludGVyLnRvcGljKSkgcmV0dXJuO1xuICAgIHJlYWRQb2ludGVyKHRoaXMucG9vbCwgdGhpcy5jaGFubmVsTmFtZSwgcG9pbnRlciwgdGhpcy5wZXJzaXN0ZW5jZSEpXG4gICAgICAudGhlbigoc3RvcmVkKSA9PiB7XG4gICAgICAgIGlmIChzdG9yZWQpIHRoaXMuZGVsaXZlcihzdG9yZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCh0aGlzLm9uRXJyb3IpO1xuICB9O1xuXG4gIC8qKiBIYW5kIG9uZSBkZWNvZGVkIG1lc3NhZ2UgdG8gdGhlIHRvcGljJ3MgbGlzdGVuZXJzLiAqL1xuICBwcml2YXRlIGRlbGl2ZXIobWVzc2FnZTogVG9waWNNZXNzYWdlKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBsaXN0ZW5lciBvZiB0aGlzLmxpc3RlbmVycy5nZXQobWVzc2FnZS50b3BpYykgPz8gW10pIHtcbiAgICAgIFByb21pc2UucmVzb2x2ZShsaXN0ZW5lcihtZXNzYWdlKSkuY2F0Y2godGhpcy5vbkVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBub3RpZmljYXRpb24gY29ubmVjdGlvbiBkeWluZywgd2hpY2ggYHBnYCByZXBvcnRzIGFzIGFuIGBlcnJvcmBcbiAgICogZXZlbnQgcmF0aGVyIHRoYW4gYSByZWplY3RlZCBxdWVyeS5cbiAgICpcbiAgICogVGhlIGNsaWVudCBpcyB1bnVzYWJsZSBhdCB0aGlzIHBvaW50LCBzbyBpdCBpcyBkZXRhY2hlZCBhbmQgcmVsZWFzZWQgYXNcbiAgICogZXJyb3JlZCAod2hpY2ggZGlzY2FyZHMgaXQpIGJlZm9yZSBhbnl0aGluZyBlbHNlLiBSZWNvbm5lY3Rpb24gb25seSBzdGFydHNcbiAgICogd2hlbiB0aGVyZSBpcyBzdGlsbCBzb21lb25lIHRvIGRlbGl2ZXIgdG8sIHNvIGFuIGlkbGUgb3IgY2xvc2luZyBidXMgZG9lcyBub3RcbiAgICogaG9sZCBhIGNvbm5lY3Rpb24gb3BlbiBjaGFzaW5nIGEgY2hhbm5lbCBub2JvZHkgcmVhZHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZUNsaWVudEVycm9yID0gKGNhdXNlOiBFcnJvcik6IHZvaWQgPT4ge1xuICAgIHRoaXMub25FcnJvcihjYXVzZSk7XG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnQ7XG4gICAgaWYgKCFjbGllbnQpIHJldHVybjtcbiAgICB0aGlzLmNsaWVudCA9IHVuZGVmaW5lZDtcbiAgICBjbGllbnQucmVtb3ZlTGlzdGVuZXIoXCJub3RpZmljYXRpb25cIiwgdGhpcy5oYW5kbGVOb3RpZmljYXRpb24pO1xuICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsIHRoaXMuaGFuZGxlQ2xpZW50RXJyb3IpO1xuICAgIGNsaWVudC5yZWxlYXNlKGNhdXNlKTtcbiAgICBpZiAodGhpcy5jbG9zZWQgfHwgdGhpcy5saXN0ZW5lcnMuc2l6ZSA9PT0gMCkgcmV0dXJuO1xuICAgIHRoaXMucmVjb25uZWN0aW5nID8/PSB0aGlzLnJlY29ubmVjdCgpLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgdGhpcy5yZWNvbm5lY3RpbmcgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlLWVzdGFibGlzaCB0aGUgbm90aWZpY2F0aW9uIGNvbm5lY3Rpb24gd2l0aCBib3VuZGVkIGV4cG9uZW50aWFsIGJhY2tvZmYuXG4gICAqXG4gICAqIFRoZSBmaXJzdCBhdHRlbXB0IGlzIGltbWVkaWF0ZSwgc2luY2UgdGhlIGNvbW1vbiBjYXNlIGlzIGEgc2luZ2xlIGRyb3BwZWRcbiAgICogY29ubmVjdGlvbiB0aGF0IHJlY29ubmVjdHMgYXQgb25jZTsgc3Vic2VxdWVudCBkZWxheXMgZG91YmxlIGZyb20gMjUwbXMgdXAgdG9cbiAgICogNXMgYW5kIHN0YXkgdGhlcmUuIFJldHJpZXMgaW5kZWZpbml0ZWx5IHJhdGhlciB0aGFuIGdpdmluZyB1cCwgYmVjYXVzZSBhIFBvc3RncmVzIHJlc3RhcnRcbiAgICogb3IgYSByb3RhdGVkIExha2ViYXNlIGNyZWRlbnRpYWwgaXMgYSByZWNvdmVyYWJsZSBvdXRhZ2UgYW5kIGEgc2lsZW50bHkgZGVhZFxuICAgKiBsaXN0ZW5lciBpcyB3b3JzZSB0aGFuIGEgbm9pc3kgb25lLiBTdG9wcyB3aGVuIHRoZSBidXMgY2xvc2VzIG9yIHRoZSBsYXN0XG4gICAqIGxpc3RlbmVyIGxlYXZlcywgYW5kIHJlcG9ydHMgZXZlcnkgZmFpbGVkIGF0dGVtcHQgdGhyb3VnaCBgb25FcnJvcmAuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgZGVsYXkgPSAwO1xuICAgIHdoaWxlICghdGhpcy5jbG9zZWQgJiYgdGhpcy5saXN0ZW5lcnMuc2l6ZSA+IDApIHtcbiAgICAgIGlmIChkZWxheSA+IDApIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBhc3luY1V0aWxzLnNsZWVwKGRlbGF5LCB0aGlzLnJlY29ubmVjdEFib3J0LnNpZ25hbCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zdGFydCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgICBpZiAodGhpcy5jbG9zZWQpIHJldHVybjtcbiAgICAgICAgdGhpcy5vbkVycm9yKGNhdXNlKTtcbiAgICAgICAgZGVsYXkgPSBkZWxheSA9PT0gMCA/IE1JTl9SRUNPTk5FQ1RfREVMQVlfTVMgOiBNYXRoLm1pbihkZWxheSAqIDIsIE1BWF9SRUNPTk5FQ1RfREVMQVlfTVMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/advisory-lock.ts","../src/persistence.ts","../src/topic-bus.ts","../index.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/advisory-lock.ts","../src/identity.ts","../src/persistence.ts","../src/topic-bus.ts","../index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -20,8 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@databricks/appkit": "0.81.0",
|
|
23
|
-
"@dbx-tools/test-polyglot": "^0.9.
|
|
24
|
-
"@types/bun": "1.3.14",
|
|
23
|
+
"@dbx-tools/test-polyglot": "^0.9.36",
|
|
25
24
|
"@types/node": "^24.6.0",
|
|
26
25
|
"@types/pg": "^8",
|
|
27
26
|
"typescript": "^5.9.3"
|
|
@@ -30,7 +29,8 @@
|
|
|
30
29
|
"@databricks/appkit": "0.81.0"
|
|
31
30
|
},
|
|
32
31
|
"dependencies": {
|
|
33
|
-
"@dbx-tools/
|
|
32
|
+
"@dbx-tools/lakebase": "^0.9.36",
|
|
33
|
+
"@dbx-tools/shared-core": "^0.9.36",
|
|
34
34
|
"pg": "^8.22.0"
|
|
35
35
|
},
|
|
36
36
|
"main": "./lib/index.js",
|
|
@@ -44,22 +44,60 @@
|
|
|
44
44
|
"types": "./lib/index.d.ts",
|
|
45
45
|
"default": "./lib/index.js"
|
|
46
46
|
},
|
|
47
|
+
"./advisory-lock": {
|
|
48
|
+
"types": "./lib/src/advisory-lock.d.ts",
|
|
49
|
+
"default": "./lib/src/advisory-lock.js"
|
|
50
|
+
},
|
|
51
|
+
"./identity": {
|
|
52
|
+
"types": "./lib/src/identity.d.ts",
|
|
53
|
+
"default": "./lib/src/identity.js"
|
|
54
|
+
},
|
|
55
|
+
"./persistence": {
|
|
56
|
+
"types": "./lib/src/persistence.d.ts",
|
|
57
|
+
"default": "./lib/src/persistence.js"
|
|
58
|
+
},
|
|
59
|
+
"./topic-bus": {
|
|
60
|
+
"types": "./lib/src/topic-bus.d.ts",
|
|
61
|
+
"default": "./lib/src/topic-bus.js"
|
|
62
|
+
},
|
|
47
63
|
"./package.json": "./package.json"
|
|
48
64
|
}
|
|
49
65
|
},
|
|
50
|
-
"version": "0.9.
|
|
66
|
+
"version": "0.9.36",
|
|
51
67
|
"types": "./lib/index.d.ts",
|
|
68
|
+
"dbxToolsConfig": {
|
|
69
|
+
"tags": [
|
|
70
|
+
"node"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
52
73
|
"type": "module",
|
|
53
74
|
"exports": {
|
|
54
75
|
".": {
|
|
55
76
|
"types": "./lib/index.d.ts",
|
|
56
77
|
"default": "./lib/index.js"
|
|
57
78
|
},
|
|
79
|
+
"./advisory-lock": {
|
|
80
|
+
"types": "./lib/src/advisory-lock.d.ts",
|
|
81
|
+
"default": "./lib/src/advisory-lock.js"
|
|
82
|
+
},
|
|
83
|
+
"./identity": {
|
|
84
|
+
"types": "./lib/src/identity.d.ts",
|
|
85
|
+
"default": "./lib/src/identity.js"
|
|
86
|
+
},
|
|
87
|
+
"./persistence": {
|
|
88
|
+
"types": "./lib/src/persistence.d.ts",
|
|
89
|
+
"default": "./lib/src/persistence.js"
|
|
90
|
+
},
|
|
91
|
+
"./topic-bus": {
|
|
92
|
+
"types": "./lib/src/topic-bus.d.ts",
|
|
93
|
+
"default": "./lib/src/topic-bus.js"
|
|
94
|
+
},
|
|
58
95
|
"./package.json": "./package.json"
|
|
59
96
|
},
|
|
60
97
|
"files": [
|
|
61
98
|
"index.ts",
|
|
62
99
|
"src",
|
|
100
|
+
"exports.ts",
|
|
63
101
|
"lib"
|
|
64
102
|
],
|
|
65
103
|
"peerDependenciesMeta": {
|
|
@@ -67,10 +105,5 @@
|
|
|
67
105
|
"optional": true
|
|
68
106
|
}
|
|
69
107
|
},
|
|
70
|
-
"dbxToolsConfig": {
|
|
71
|
-
"tags": [
|
|
72
|
-
"node"
|
|
73
|
-
]
|
|
74
|
-
},
|
|
75
108
|
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"bunx projen\"."
|
|
76
109
|
}
|
package/src/advisory-lock.ts
CHANGED
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { createHash } from "node:crypto";
|
|
12
|
-
import { object } from "@dbx-tools/shared-core";
|
|
13
11
|
import type { Pool, PoolClient, QueryResult, QueryResultRow } from "pg";
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
import { advisoryLockId } from "./identity.ts";
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* What names a lock. Anything reducible to a stable identity: a string, an id, a
|
|
@@ -38,27 +36,6 @@ export interface PgQueryable {
|
|
|
38
36
|
|
|
39
37
|
type UnlockRow = QueryResultRow & { unlocked: boolean };
|
|
40
38
|
|
|
41
|
-
/**
|
|
42
|
-
* Convert an arbitrary structured key into PostgreSQL's signed 64-bit advisory
|
|
43
|
-
* lock namespace. A bigint is preserved directly so callers can interoperate
|
|
44
|
-
* with another implementation that publishes its lock ID.
|
|
45
|
-
*
|
|
46
|
-
* Everything else is canonicalized with `object.toStableKey` and hashed, so key
|
|
47
|
-
* order in an object does not matter while a `1` and a `"1"` stay different locks.
|
|
48
|
-
* A cycle, a non-finite number, or a function/symbol key throws `TypeError`
|
|
49
|
-
* rather than yielding an identity two callers could disagree about.
|
|
50
|
-
*/
|
|
51
|
-
export function advisoryLockId(key: AdvisoryLockKey): bigint {
|
|
52
|
-
if (typeof key === "bigint") return BigInt.asIntN(SIGNED_BIGINT_BITS, key);
|
|
53
|
-
const parts = object.toOneOrMany(key);
|
|
54
|
-
const digest = createHash("sha256");
|
|
55
|
-
parts.forEach((part, index) => {
|
|
56
|
-
if (index > 0) digest.update(Buffer.from([0]));
|
|
57
|
-
digest.update(object.toStableKey(part), "utf8");
|
|
58
|
-
});
|
|
59
|
-
return digest.digest().readBigInt64BE(0);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
39
|
async function acquire(client: PgQueryable, id: bigint, transaction: boolean): Promise<void> {
|
|
63
40
|
const fn = transaction ? "pg_advisory_xact_lock" : "pg_advisory_lock";
|
|
64
41
|
await client.query(`SELECT ${fn}($1::bigint)`, [id.toString()]);
|
|
@@ -85,7 +62,7 @@ export async function withAdvisoryLock<T>(
|
|
|
85
62
|
key: AdvisoryLockKey,
|
|
86
63
|
fn: (client: PoolClient) => Promise<T> | T,
|
|
87
64
|
): Promise<T> {
|
|
88
|
-
const id = advisoryLockId(key);
|
|
65
|
+
const id = BigInt(advisoryLockId(key));
|
|
89
66
|
const client = await pool.connect();
|
|
90
67
|
let acquired = false;
|
|
91
68
|
let failed = false;
|
|
@@ -127,7 +104,7 @@ export async function withAdvisoryTransactionLock<T>(
|
|
|
127
104
|
key: AdvisoryLockKey,
|
|
128
105
|
fn: (client: PoolClient) => Promise<T> | T,
|
|
129
106
|
): Promise<T> {
|
|
130
|
-
const id = advisoryLockId(key);
|
|
107
|
+
const id = BigInt(advisoryLockId(key));
|
|
131
108
|
const client = await pool.connect();
|
|
132
109
|
let releaseError: Error | undefined;
|
|
133
110
|
try {
|
package/src/identity.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-runtime Postgres lock and channel identity policy.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
LakebaseConnectionInputs,
|
|
11
|
+
parseAddress as parseLakebaseAddress,
|
|
12
|
+
parseResourcePath as parseLakebaseResourcePath,
|
|
13
|
+
parseSslMode as parseLakebaseSslMode,
|
|
14
|
+
SslMode,
|
|
15
|
+
} from "@dbx-tools/lakebase/address";
|
|
16
|
+
import * as hash from "@dbx-tools/shared-core/hash";
|
|
17
|
+
import * as object from "@dbx-tools/shared-core/object";
|
|
18
|
+
import * as stringUtils from "@dbx-tools/shared-core/string-utils";
|
|
19
|
+
|
|
20
|
+
const SIGNED_BIGINT_BITS = 64;
|
|
21
|
+
const MAX_CHANNEL_LENGTH = 63;
|
|
22
|
+
const CHANNEL_HASH_LENGTH = 6;
|
|
23
|
+
const CHANNEL_FALLBACK = "bus";
|
|
24
|
+
|
|
25
|
+
/** Convert a structured key into a JSON-safe signed 64-bit lock identifier. */
|
|
26
|
+
export function advisoryLockId(key: unknown, explicit = false): string {
|
|
27
|
+
return resolveAdvisoryLockId(explicit ? BigInt(String(key)) : key).toString();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveAdvisoryLockId(key: unknown): bigint {
|
|
31
|
+
if (typeof key === "bigint") return BigInt.asIntN(SIGNED_BIGINT_BITS, key);
|
|
32
|
+
const parts = object.toOneOrMany(key);
|
|
33
|
+
const digest = createHash("sha256");
|
|
34
|
+
parts.forEach((part, index) => {
|
|
35
|
+
if (index > 0) digest.update(Buffer.from([0]));
|
|
36
|
+
digest.update(object.toStableKey(part), "utf8");
|
|
37
|
+
});
|
|
38
|
+
return digest.digest().readBigInt64BE(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Derive a legal deterministic Postgres channel name from structured input. */
|
|
42
|
+
export function channelName(value: unknown): string {
|
|
43
|
+
const parts = object.toOneOrMany(value);
|
|
44
|
+
const suffix = hash.fnvHashWithOptions(
|
|
45
|
+
{ length: CHANNEL_HASH_LENGTH },
|
|
46
|
+
parts.map((part) => object.toStableKey(part)).join("\u0000"),
|
|
47
|
+
);
|
|
48
|
+
const labelled = parts.filter((part) => {
|
|
49
|
+
const type = typeof part;
|
|
50
|
+
return type === "string" || type === "number" || type === "boolean" || type === "bigint";
|
|
51
|
+
});
|
|
52
|
+
const body = stringUtils
|
|
53
|
+
.toIdentifierWithOptions({ delimiter: "_" }, ...labelled)
|
|
54
|
+
.slice(0, MAX_CHANNEL_LENGTH - suffix.length - 1)
|
|
55
|
+
.replace(/_+$/, "");
|
|
56
|
+
const prefix = /^[A-Za-z_]/.test(body) ? body : `${CHANNEL_FALLBACK}_${body}`;
|
|
57
|
+
return `${prefix}_${suffix}`.replace(/_+/g, "_");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Parse a PostgreSQL URL, Lakebase resource path, hostname, or project ID. */
|
|
61
|
+
export function parseAddress(input: string | null | undefined): LakebaseConnectionInputs {
|
|
62
|
+
return parseLakebaseAddress(input);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Parse a canonical Lakebase project, branch, endpoint, or database path. */
|
|
66
|
+
export function parseResourcePath(input: string | null | undefined): LakebaseConnectionInputs {
|
|
67
|
+
return parseLakebaseResourcePath(input);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Parse a supported PostgreSQL SSL mode. */
|
|
71
|
+
export function parseSslMode(input: string | null | undefined): SslMode | undefined {
|
|
72
|
+
return parseLakebaseSslMode(input);
|
|
73
|
+
}
|
package/src/persistence.ts
CHANGED
|
@@ -122,6 +122,8 @@ function after(value: string | undefined, scope: TopicPersistenceScope): string
|
|
|
122
122
|
}
|
|
123
123
|
return decoded[1];
|
|
124
124
|
}
|
|
125
|
+
|
|
126
|
+
/** Convert a persistence TTL to milliseconds, preserving disabled retention. */
|
|
125
127
|
export function ttlMilliseconds(value: DurationInput | false): number | null {
|
|
126
128
|
if (value === false) return null;
|
|
127
129
|
const milliseconds = object.toDuration(value);
|
|
@@ -131,6 +133,7 @@ export function ttlMilliseconds(value: DurationInput | false): number | null {
|
|
|
131
133
|
return milliseconds;
|
|
132
134
|
}
|
|
133
135
|
|
|
136
|
+
/** Delete one bounded batch of expired persisted topic messages. */
|
|
134
137
|
export async function cleanupExpired(
|
|
135
138
|
queryable: PgQueryable,
|
|
136
139
|
options: ResolvedTopicBusPersistenceOptions,
|
|
@@ -149,6 +152,8 @@ type HistoryRow = QueryResultRow & {
|
|
|
149
152
|
expires_at: Date | string | null;
|
|
150
153
|
envelope: TopicMessage;
|
|
151
154
|
};
|
|
155
|
+
|
|
156
|
+
/** Read a cursor-paginated page of persisted topic history. */
|
|
152
157
|
export async function history<TBody extends object.SerializableValue>(
|
|
153
158
|
queryable: PgQueryable,
|
|
154
159
|
channel: string,
|
|
@@ -174,6 +179,7 @@ export async function history<TBody extends object.SerializableValue>(
|
|
|
174
179
|
};
|
|
175
180
|
}
|
|
176
181
|
|
|
182
|
+
/** Persist a topic message and notify listeners in one transaction. */
|
|
177
183
|
export async function persistedNotify(
|
|
178
184
|
client: PgQueryable,
|
|
179
185
|
channel: string,
|
package/src/topic-bus.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { asyncUtils, errorUtils, hash, json, object, stringUtils } from "@dbx-to
|
|
|
29
29
|
import type { Notification, PoolClient } from "pg";
|
|
30
30
|
|
|
31
31
|
import type { PgPoolLike, PgQueryable } from "./advisory-lock.ts";
|
|
32
|
+
import { channelName } from "./identity.ts";
|
|
32
33
|
import {
|
|
33
34
|
cleanupExpired,
|
|
34
35
|
decodePointer,
|
|
@@ -52,16 +53,6 @@ type SerializableValue = object.SerializableValue;
|
|
|
52
53
|
|
|
53
54
|
/** Channel parts used when a caller names no channel of its own. */
|
|
54
55
|
const DEFAULT_CHANNEL = "dbx_tools_topic_bus";
|
|
55
|
-
/**
|
|
56
|
-
* `NAMEDATALEN - 1`. Postgres TRUNCATES a longer channel name rather than
|
|
57
|
-
* rejecting it, which would split publishers and listeners onto different
|
|
58
|
-
* channels while every call looked like it succeeded.
|
|
59
|
-
*/
|
|
60
|
-
const MAX_CHANNEL_LENGTH = 63;
|
|
61
|
-
/** Base-32 chars of the channel's identity suffix. Max 7 - the digest is 32 bits. */
|
|
62
|
-
const CHANNEL_HASH_LENGTH = 6;
|
|
63
|
-
/** Body used when the parts tokenize to nothing, or lead with a digit. */
|
|
64
|
-
const CHANNEL_FALLBACK = "bus";
|
|
65
56
|
/**
|
|
66
57
|
* Encoded-envelope ceiling. PostgreSQL caps a `NOTIFY` payload at 8000 bytes and
|
|
67
58
|
* fails the statement past that, so the bus rejects the message first with a size
|
|
@@ -277,60 +268,6 @@ async function senderMetadata(): Promise<TopicMetadata> {
|
|
|
277
268
|
}
|
|
278
269
|
}
|
|
279
270
|
|
|
280
|
-
/**
|
|
281
|
-
* Derive a legal Postgres channel name from whatever a caller used to identify
|
|
282
|
-
* the channel.
|
|
283
|
-
*
|
|
284
|
-
* Callers think in terms of what the channel IS - an app name, a tenant id, a
|
|
285
|
-
* `[env, feature]` pair, a config object - and none of those are identifiers.
|
|
286
|
-
* Rejecting them pushed the sanitizing onto every call site, which is how two
|
|
287
|
-
* services end up disagreeing about whether the channel is `my-app`, `my_app`,
|
|
288
|
-
* or `myApp` and silently never hear each other.
|
|
289
|
-
*
|
|
290
|
-
* The parts are tokenized and joined into an identifier, then a short hash of the
|
|
291
|
-
* ORIGINAL parts is appended. The hash is what makes the mapping trustworthy:
|
|
292
|
-
* tokenizing alone is lossy, so `my-app` and `my_app` and `myApp` would collapse
|
|
293
|
-
* onto one channel, and a name long enough to hit `NAMEDATALEN` would collide
|
|
294
|
-
* with anything sharing its leading tokens. With the suffix, the readable part
|
|
295
|
-
* stays readable and distinct inputs stay distinct.
|
|
296
|
-
*
|
|
297
|
-
* Deterministic across processes and runs, which is the whole point - two
|
|
298
|
-
* services given the same parts must land on the same channel without
|
|
299
|
-
* coordinating. Hash inputs are structure-aware, so `["a", "b"]` and `["a_b"]`
|
|
300
|
-
* differ, and object key order does not.
|
|
301
|
-
*/
|
|
302
|
-
export function channelName(value: unknown): string {
|
|
303
|
-
const parts = object.toOneOrMany(value);
|
|
304
|
-
// Hash the CANONICAL form, the same rule `advisoryLockId` uses, so structure and
|
|
305
|
-
// types decide identity: `["a","b"]` differs from `["ab"]`, `1` from `"1"`, and
|
|
306
|
-
// object key order does not matter. Hashing the raw parts would instead lean on
|
|
307
|
-
// the hash module's canonicalizer, which folds every `Date` onto one token.
|
|
308
|
-
const suffix = hash.fnvHashWithOptions(
|
|
309
|
-
{ length: CHANNEL_HASH_LENGTH },
|
|
310
|
-
parts.map((part) => object.toStableKey(part)).join("\u0000"),
|
|
311
|
-
);
|
|
312
|
-
// Only parts that stringify to something a reader recognizes contribute to the
|
|
313
|
-
// readable half. An object would tokenize from `String(value)` as
|
|
314
|
-
// `object_object`, which is noise - it still shapes the hash, so identity is
|
|
315
|
-
// unaffected.
|
|
316
|
-
const labelled = parts.filter((part) => {
|
|
317
|
-
const type = typeof part;
|
|
318
|
-
return type === "string" || type === "number" || type === "boolean" || type === "bigint";
|
|
319
|
-
});
|
|
320
|
-
// Truncate rather than cap through the tokenizer: `trim` would DROP a single
|
|
321
|
-
// token longer than the budget, turning one long name into the bare fallback and
|
|
322
|
-
// making every long name look alike. The hash still separates them, but the
|
|
323
|
-
// channel is unreadable in a log.
|
|
324
|
-
const body = stringUtils
|
|
325
|
-
.toIdentifierWithOptions({ delimiter: "_" }, ...labelled)
|
|
326
|
-
.slice(0, MAX_CHANNEL_LENGTH - suffix.length - 1)
|
|
327
|
-
.replace(/_+$/, "");
|
|
328
|
-
// An identifier cannot start with a digit and the hash alphabet is
|
|
329
|
-
// digit-leading, so a numeric or empty body needs a letter in front.
|
|
330
|
-
const prefix = /^[A-Za-z_]/.test(body) ? body : `${CHANNEL_FALLBACK}_${body}`;
|
|
331
|
-
return `${prefix}_${suffix}`.replace(/_+/g, "_");
|
|
332
|
-
}
|
|
333
|
-
|
|
334
271
|
/** Quote a validated channel for `LISTEN`/`UNLISTEN`, which take no parameters. */
|
|
335
272
|
function quoteIdentifier(value: string): string {
|
|
336
273
|
return `"${value.replaceAll('"', '""')}"`;
|