diff --git a/packages/rivetkit/fixtures/driver-test-suite/actor-onstatechange.ts b/packages/rivetkit/fixtures/driver-test-suite/actor-onstatechange.ts new file mode 100644 index 000000000..f953270f3 --- /dev/null +++ b/packages/rivetkit/fixtures/driver-test-suite/actor-onstatechange.ts @@ -0,0 +1,44 @@ +import { actor } from "rivetkit"; + +export const onStateChangeActor = actor({ + onAuth: () => {}, + state: { + value: 0, + changeCount: 0, + }, + actions: { + // Action that modifies state - should trigger onStateChange + setValue: (c, newValue: number) => { + c.state.value = newValue; + return c.state.value; + }, + // Action that modifies state multiple times - should trigger onStateChange for each change + incrementMultiple: (c, times: number) => { + for (let i = 0; i < times; i++) { + c.state.value++; + } + return c.state.value; + }, + // Action that doesn't modify state - should NOT trigger onStateChange + getValue: (c) => { + return c.state.value; + }, + // Action that reads and returns without modifying - should NOT trigger onStateChange + getDoubled: (c) => { + const doubled = c.state.value * 2; + return doubled; + }, + // Get the count of how many times onStateChange was called + getChangeCount: (c) => { + return c.state.changeCount; + }, + // Reset change counter for testing + resetChangeCount: (c) => { + c.state.changeCount = 0; + }, + }, + // Track onStateChange calls + onStateChange: (c) => { + c.state.changeCount++; + }, +}); diff --git a/packages/rivetkit/fixtures/driver-test-suite/registry.bundled_wseq4k79db.mjs b/packages/rivetkit/fixtures/driver-test-suite/registry.bundled_wseq4k79db.mjs new file mode 100644 index 000000000..94cc923df --- /dev/null +++ b/packages/rivetkit/fixtures/driver-test-suite/registry.bundled_wseq4k79db.mjs @@ -0,0 +1,12036 @@ +// src/actor/connection.ts +import * as cbor2 from "cbor-x"; + +// src/common/versioned-data.ts +var VersionedDataHandler = class { + constructor(config4) { + this.config = config4; + } + serializeWithEmbeddedVersion(data) { + const versioned = { + version: this.config.currentVersion, + data: this.config.serializeVersion(data) + }; + return this.embedVersion(versioned); + } + deserializeWithEmbeddedVersion(bytes) { + const versioned = this.extractVersion(bytes); + return this.deserialize(versioned.data, versioned.version); + } + serialize(data, version) { + return this.config.serializeVersion(data); + } + deserialize(bytes, version) { + if (version === this.config.currentVersion) { + return this.config.deserializeVersion(bytes); + } + if (version > this.config.currentVersion) { + throw new Error( + `Cannot decode data from version ${version}, current version is ${this.config.currentVersion}` + ); + } + let currentData = this.config.deserializeVersion(bytes); + let currentVersion = version; + while (currentVersion < this.config.currentVersion) { + const migration = this.config.migrations.get(currentVersion); + if (!migration) { + throw new Error( + `No migration found from version ${currentVersion} to ${currentVersion + 1}` + ); + } + currentData = migration(currentData); + currentVersion++; + } + return currentData; + } + embedVersion(data) { + const versionBytes = new Uint8Array(4); + new DataView(versionBytes.buffer).setUint32(0, data.version, true); + const result = new Uint8Array(versionBytes.length + data.data.length); + result.set(versionBytes); + result.set(data.data, versionBytes.length); + return result; + } + extractVersion(bytes) { + if (bytes.length < 4) { + throw new Error("Invalid versioned data: too short"); + } + const version = new DataView(bytes.buffer, bytes.byteOffset).getUint32( + 0, + true + ); + const data = bytes.slice(4); + return { version, data }; + } +}; +function createVersionedDataHandler(config4) { + return new VersionedDataHandler(config4); +} + +// dist/schemas/client-protocol/v1.ts +import * as bare from "@bare-ts/lib"; +var config = /* @__PURE__ */ bare.Config({}); +function readInit(bc) { + return { + actorId: bare.readString(bc), + connectionId: bare.readString(bc), + connectionToken: bare.readString(bc) + }; +} +function writeInit(bc, x) { + bare.writeString(bc, x.actorId); + bare.writeString(bc, x.connectionId); + bare.writeString(bc, x.connectionToken); +} +function read0(bc) { + return bare.readBool(bc) ? bare.readData(bc) : null; +} +function write0(bc, x) { + bare.writeBool(bc, x !== null); + if (x !== null) { + bare.writeData(bc, x); + } +} +function read1(bc) { + return bare.readBool(bc) ? bare.readUint(bc) : null; +} +function write1(bc, x) { + bare.writeBool(bc, x !== null); + if (x !== null) { + bare.writeUint(bc, x); + } +} +function readError(bc) { + return { + code: bare.readString(bc), + message: bare.readString(bc), + metadata: read0(bc), + actionId: read1(bc) + }; +} +function writeError(bc, x) { + bare.writeString(bc, x.code); + bare.writeString(bc, x.message); + write0(bc, x.metadata); + write1(bc, x.actionId); +} +function readActionResponse(bc) { + return { + id: bare.readUint(bc), + output: bare.readData(bc) + }; +} +function writeActionResponse(bc, x) { + bare.writeUint(bc, x.id); + bare.writeData(bc, x.output); +} +function readEvent(bc) { + return { + name: bare.readString(bc), + args: bare.readData(bc) + }; +} +function writeEvent(bc, x) { + bare.writeString(bc, x.name); + bare.writeData(bc, x.args); +} +function readToClientBody(bc) { + const offset = bc.offset; + const tag = bare.readU8(bc); + switch (tag) { + case 0: + return { tag: "Init", val: readInit(bc) }; + case 1: + return { tag: "Error", val: readError(bc) }; + case 2: + return { tag: "ActionResponse", val: readActionResponse(bc) }; + case 3: + return { tag: "Event", val: readEvent(bc) }; + default: { + bc.offset = offset; + throw new bare.BareError(offset, "invalid tag"); + } + } +} +function writeToClientBody(bc, x) { + switch (x.tag) { + case "Init": { + bare.writeU8(bc, 0); + writeInit(bc, x.val); + break; + } + case "Error": { + bare.writeU8(bc, 1); + writeError(bc, x.val); + break; + } + case "ActionResponse": { + bare.writeU8(bc, 2); + writeActionResponse(bc, x.val); + break; + } + case "Event": { + bare.writeU8(bc, 3); + writeEvent(bc, x.val); + break; + } + } +} +function readToClient(bc) { + return { + body: readToClientBody(bc) + }; +} +function writeToClient(bc, x) { + writeToClientBody(bc, x.body); +} +function encodeToClient(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeToClient(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeToClient(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readToClient(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readActionRequest(bc) { + return { + id: bare.readUint(bc), + name: bare.readString(bc), + args: bare.readData(bc) + }; +} +function writeActionRequest(bc, x) { + bare.writeUint(bc, x.id); + bare.writeString(bc, x.name); + bare.writeData(bc, x.args); +} +function readSubscriptionRequest(bc) { + return { + eventName: bare.readString(bc), + subscribe: bare.readBool(bc) + }; +} +function writeSubscriptionRequest(bc, x) { + bare.writeString(bc, x.eventName); + bare.writeBool(bc, x.subscribe); +} +function readToServerBody(bc) { + const offset = bc.offset; + const tag = bare.readU8(bc); + switch (tag) { + case 0: + return { tag: "ActionRequest", val: readActionRequest(bc) }; + case 1: + return { tag: "SubscriptionRequest", val: readSubscriptionRequest(bc) }; + default: { + bc.offset = offset; + throw new bare.BareError(offset, "invalid tag"); + } + } +} +function writeToServerBody(bc, x) { + switch (x.tag) { + case "ActionRequest": { + bare.writeU8(bc, 0); + writeActionRequest(bc, x.val); + break; + } + case "SubscriptionRequest": { + bare.writeU8(bc, 1); + writeSubscriptionRequest(bc, x.val); + break; + } + } +} +function readToServer(bc) { + return { + body: readToServerBody(bc) + }; +} +function writeToServer(bc, x) { + writeToServerBody(bc, x.body); +} +function encodeToServer(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeToServer(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeToServer(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readToServer(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readHttpActionRequest(bc) { + return { + args: bare.readData(bc) + }; +} +function writeHttpActionRequest(bc, x) { + bare.writeData(bc, x.args); +} +function encodeHttpActionRequest(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeHttpActionRequest(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeHttpActionRequest(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readHttpActionRequest(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readHttpActionResponse(bc) { + return { + output: bare.readData(bc) + }; +} +function writeHttpActionResponse(bc, x) { + bare.writeData(bc, x.output); +} +function encodeHttpActionResponse(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeHttpActionResponse(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeHttpActionResponse(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readHttpActionResponse(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readHttpResponseError(bc) { + return { + code: bare.readString(bc), + message: bare.readString(bc), + metadata: read0(bc) + }; +} +function writeHttpResponseError(bc, x) { + bare.writeString(bc, x.code); + bare.writeString(bc, x.message); + write0(bc, x.metadata); +} +function encodeHttpResponseError(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeHttpResponseError(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeHttpResponseError(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readHttpResponseError(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readHttpResolveResponse(bc) { + return { + actorId: bare.readString(bc) + }; +} +function writeHttpResolveResponse(bc, x) { + bare.writeString(bc, x.actorId); +} +function encodeHttpResolveResponse(x) { + const bc = new bare.ByteCursor( + new Uint8Array(config.initialBufferLength), + config + ); + writeHttpResolveResponse(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeHttpResolveResponse(bytes) { + const bc = new bare.ByteCursor(bytes, config); + const result = readHttpResolveResponse(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare.BareError(bc.offset, "remaining bytes"); + } + return result; +} + +// src/schemas/client-protocol/versioned.ts +var CURRENT_VERSION = 1; +var migrations = /* @__PURE__ */ new Map(); +var TO_SERVER_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeToServer(data), + deserializeVersion: (bytes) => decodeToServer(bytes) +}); +var TO_CLIENT_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeToClient(data), + deserializeVersion: (bytes) => decodeToClient(bytes) +}); +var HTTP_ACTION_REQUEST_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeHttpActionRequest(data), + deserializeVersion: (bytes) => decodeHttpActionRequest(bytes) +}); +var HTTP_ACTION_RESPONSE_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeHttpActionResponse(data), + deserializeVersion: (bytes) => decodeHttpActionResponse(bytes) +}); +var HTTP_RESPONSE_ERROR_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeHttpResponseError(data), + deserializeVersion: (bytes) => decodeHttpResponseError(bytes) +}); +var HTTP_RESOLVE_REQUEST_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (_) => new Uint8Array(), + deserializeVersion: (bytes) => null +}); +var HTTP_RESOLVE_RESPONSE_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION, + migrations, + serializeVersion: (data) => encodeHttpResolveResponse(data), + deserializeVersion: (bytes) => decodeHttpResolveResponse(bytes) +}); + +// src/actor/errors.ts +var INTERNAL_ERROR_CODE = "internal_error"; +var INTERNAL_ERROR_DESCRIPTION = "Internal error. Read the server logs for more details."; +var USER_ERROR_CODE = "user_error"; +var ActorError = class extends Error { + constructor(code, message, opts) { + super(message, { cause: opts?.cause }); + this.code = code; + this.public = opts?.public ?? false; + this.metadata = opts?.metadata; + if (opts?.public) { + this.statusCode = 400; + } + } + __type = "ActorError"; + public; + metadata; + statusCode = 500; + static isActorError(error) { + return typeof error === "object" && error.__type === "ActorError"; + } + toString() { + return this.message; + } + /** + * Serialize error for HTTP response + */ + serializeForHttp() { + return { + type: this.code, + message: this.message, + metadata: this.metadata + }; + } +}; +var InternalError = class extends ActorError { + constructor(message) { + super(INTERNAL_ERROR_CODE, message); + } +}; +var Unreachable = class extends InternalError { + constructor(x) { + super(`Unreachable case: ${x}`); + } +}; +var StateNotEnabled = class extends ActorError { + constructor() { + super( + "state_not_enabled", + "State not enabled. Must implement `createState` or `state` to use state. (https://www.rivet.gg/docs/actors/state/#initializing-state)" + ); + } +}; +var ConnStateNotEnabled = class extends ActorError { + constructor() { + super( + "conn_state_not_enabled", + "Connection state not enabled. Must implement `createConnectionState` or `connectionState` to use connection state. (https://www.rivet.gg/docs/actors/connections/#connection-state)" + ); + } +}; +var VarsNotEnabled = class extends ActorError { + constructor() { + super( + "vars_not_enabled", + "Variables not enabled. Must implement `createVars` or `vars` to use state. (https://www.rivet.gg/docs/actors/ephemeral-variables/#initializing-variables)" + ); + } +}; +var ActionTimedOut = class extends ActorError { + constructor() { + super( + "action_timed_out", + "Action timed out. This can be increased with: `actor({ options: { action: { timeout: ... } } })`", + { public: true } + ); + } +}; +var ActionNotFound = class extends ActorError { + constructor(name) { + super( + "action_not_found", + `Action '${name}' not found. Validate the action exists on your actor.`, + { public: true } + ); + } +}; +var InvalidEncoding = class extends ActorError { + constructor(format) { + super( + "invalid_encoding", + `Invalid encoding \`${format}\`. (https://www.rivet.gg/docs/actors/clients/#actor-client)`, + { + public: true + } + ); + } +}; +var ConnNotFound = class extends ActorError { + constructor(id) { + super("conn_not_found", `Connection not found for ID: ${id}`, { + public: true + }); + } +}; +var IncorrectConnToken = class extends ActorError { + constructor() { + super("incorrect_conn_token", "Incorrect connection token.", { + public: true + }); + } +}; +var MessageTooLong = class extends ActorError { + constructor() { + super( + "message_too_long", + "Message too long. This can be configured with: `registry.runServer({ maxIncomingMessageSize: ... })`", + { public: true } + ); + } +}; +var MalformedMessage = class extends ActorError { + constructor(cause) { + super("malformed_message", `Malformed message: ${cause}`, { + public: true, + cause + }); + } +}; +var InvalidStateType = class extends ActorError { + constructor(opts) { + let msg = ""; + if (opts?.path) { + msg += `Attempted to set invalid state at path \`${opts.path}\`.`; + } else { + msg += "Attempted to set invalid state."; + } + msg += " Valid types include: null, undefined, boolean, string, number, BigInt, Date, RegExp, Error, typed arrays (Uint8Array, Int8Array, Float32Array, etc.), Map, Set, Array, and plain objects. (https://www.rivet.gg/docs/actors/state/#limitations)"; + super("invalid_state_type", msg); + } +}; +var Unsupported = class extends ActorError { + constructor(feature) { + super("unsupported", `Unsupported feature: ${feature}`); + } +}; +var UserError = class extends ActorError { + /** + * Constructs a new UserError instance. + * + * @param message - The error message to be displayed. + * @param opts - Optional parameters for the error, including a machine-readable code and additional metadata. + */ + constructor(message, opts) { + super(opts?.code ?? USER_ERROR_CODE, message, { + public: true, + metadata: opts?.metadata + }); + } +}; +var InvalidQueryJSON = class extends ActorError { + constructor(error) { + super("invalid_query_json", `Invalid query JSON: ${error}`, { + public: true, + cause: error + }); + } +}; +var InvalidRequest = class extends ActorError { + constructor(error) { + super("invalid_request", `Invalid request: ${error}`, { + public: true, + cause: error + }); + } +}; +var ActorNotFound = class extends ActorError { + constructor(identifier) { + super( + "actor_not_found", + identifier ? `Actor not found: ${identifier} (https://www.rivet.gg/docs/actors/clients/#actor-client)` : "Actor not found (https://www.rivet.gg/docs/actors/clients/#actor-client)", + { public: true } + ); + } +}; +var ActorAlreadyExists = class extends ActorError { + constructor(name, key) { + super( + "actor_already_exists", + `Actor already exists with name '${name}' and key '${JSON.stringify(key)}' (https://www.rivet.gg/docs/actors/clients/#actor-client)`, + { public: true } + ); + } +}; +var ProxyError = class extends ActorError { + constructor(operation, error) { + super( + "proxy_error", + `Error proxying ${operation}, this is likely an internal error: ${error}`, + { + public: true, + cause: error + } + ); + } +}; +var InvalidParams = class extends ActorError { + constructor(message) { + super("invalid_params", message, { public: true }); + } +}; +var Forbidden = class extends ActorError { + constructor(message, opts) { + super( + "forbidden", + message ?? "Forbidden. Access denied. (https://www.rivet.gg/docs/actors/authentication/)", + { + public: true, + metadata: opts?.metadata + } + ); + this.statusCode = 403; + } +}; +var DatabaseNotEnabled = class extends ActorError { + constructor() { + super( + "database_not_enabled", + "Database not enabled. Must implement `database` to use database." + ); + } +}; +var FetchHandlerNotDefined = class extends ActorError { + constructor() { + super( + "fetch_handler_not_defined", + "Raw HTTP handler not defined. Actor must implement `onFetch` to handle raw HTTP requests. (https://www.rivet.gg/docs/actors/fetch-and-websocket-handler/)", + { public: true } + ); + this.statusCode = 404; + } +}; +var InvalidFetchResponse = class extends ActorError { + constructor() { + super( + "invalid_fetch_response", + "Actor's onFetch handler must return a Response object. Returning void/undefined is not allowed. (https://www.rivet.gg/docs/actors/fetch-and-websocket-handler/)", + { public: true } + ); + this.statusCode = 500; + } +}; + +// src/common/utils.ts +function assertUnreachable(x) { + throw new Error(`Unreachable case: ${x}`); +} +function isCborSerializable(value, onInvalid, currentPath = "") { + if (value === null || value === void 0) { + return true; + } + if (typeof value === "number") { + if (!Number.isFinite(value)) { + onInvalid?.(currentPath); + return false; + } + return true; + } + if (typeof value === "boolean" || typeof value === "string") { + return true; + } + if (typeof value === "bigint") { + return true; + } + if (value instanceof Date) { + return true; + } + if (value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Uint16Array || value instanceof Uint32Array || value instanceof BigUint64Array || value instanceof Int8Array || value instanceof Int16Array || value instanceof Int32Array || value instanceof BigInt64Array || value instanceof Float32Array || value instanceof Float64Array) { + return true; + } + if (value instanceof Map) { + for (const [key, val] of value.entries()) { + const keyPath = currentPath ? `${currentPath}.key(${String(key)})` : `key(${String(key)})`; + const valPath = currentPath ? `${currentPath}.value(${String(key)})` : `value(${String(key)})`; + if (!isCborSerializable(key, onInvalid, keyPath) || !isCborSerializable(val, onInvalid, valPath)) { + return false; + } + } + return true; + } + if (value instanceof Set) { + let index = 0; + for (const item of value.values()) { + const itemPath = currentPath ? `${currentPath}.set[${index}]` : `set[${index}]`; + if (!isCborSerializable(item, onInvalid, itemPath)) { + return false; + } + index++; + } + return true; + } + if (value instanceof RegExp) { + return true; + } + if (value instanceof Error) { + return true; + } + if (Array.isArray(value)) { + for (let i = 0; i < value.length; i++) { + const itemPath = currentPath ? `${currentPath}[${i}]` : `[${i}]`; + if (!isCborSerializable(value[i], onInvalid, itemPath)) { + return false; + } + } + return true; + } + if (typeof value === "object") { + const proto = Object.getPrototypeOf(value); + if (proto !== null && proto !== Object.prototype) { + const protoConstructor = value.constructor; + if (protoConstructor && typeof protoConstructor.name === "string") { + } + } + for (const key in value) { + const propPath = currentPath ? `${currentPath}.${key}` : key; + if (!isCborSerializable( + value[key], + onInvalid, + propPath + )) { + return false; + } + } + return true; + } + onInvalid?.(currentPath); + return false; +} +function deconstructError(error, logger10, extraLog, exposeInternalError = false) { + let statusCode; + let public_; + let code; + let message; + let metadata; + if (ActorError.isActorError(error) && error.public) { + statusCode = "statusCode" in error && error.statusCode ? error.statusCode : 400; + public_ = true; + code = error.code; + message = getErrorMessage(error); + metadata = error.metadata; + logger10.info("public error", { + code, + message, + issues: "https://github.com/rivet-gg/rivetkit/issues", + support: "https://rivet.gg/discord", + ...extraLog + }); + } else if (exposeInternalError) { + if (ActorError.isActorError(error)) { + statusCode = 500; + public_ = false; + code = error.code; + message = getErrorMessage(error); + metadata = error.metadata; + logger10.info("internal error", { + code, + message, + issues: "https://github.com/rivet-gg/rivetkit/issues", + support: "https://rivet.gg/discord", + ...extraLog + }); + } else { + statusCode = 500; + public_ = false; + code = INTERNAL_ERROR_CODE; + message = getErrorMessage(error); + logger10.info("internal error", { + code, + message, + issues: "https://github.com/rivet-gg/rivetkit/issues", + support: "https://rivet.gg/discord", + ...extraLog + }); + } + } else { + statusCode = 500; + public_ = false; + code = INTERNAL_ERROR_CODE; + message = INTERNAL_ERROR_DESCRIPTION; + metadata = { + //url: `https://hub.rivet.gg/projects/${actorMetadata.project.slug}/environments/${actorMetadata.environment.slug}/actors?actorId=${actorMetadata.actor.id}`, + }; + logger10.warn("internal error", { + error: getErrorMessage(error), + stack: error?.stack, + issues: "https://github.com/rivet-gg/rivetkit/issues", + support: "https://rivet.gg/discord", + ...extraLog + }); + } + return { + __type: "ActorError", + statusCode, + public: public_, + code, + message, + metadata + }; +} +function stringifyError(error) { + if (error instanceof Error) { + if (typeof process !== "undefined" && getEnvUniversal("_RIVETKIT_ERROR_STACK") === "1") { + return `${error.name}: ${error.message}${error.stack ? ` +${error.stack}` : ""}`; + } else { + return `${error.name}: ${error.message}`; + } + } else if (typeof error === "string") { + return error; + } else if (typeof error === "object" && error !== null) { + try { + return `${JSON.stringify(error)}`; + } catch { + return "[cannot stringify error]"; + } + } else { + return `Unknown error: ${getErrorMessage(error)}`; + } +} +function getErrorMessage(err) { + if (err && typeof err === "object" && "message" in err && typeof err.message === "string") { + return err.message; + } else { + return String(err); + } +} +function noopNext() { + return async () => { + }; +} + +// package.json +var package_default = { + name: "rivetkit", + version: "2.0.2", + license: "Apache-2.0", + keywords: [ + "rivetkit", + "stateful", + "serverless", + "actors", + "agents", + "realtime", + "websocket", + "actors", + "framework" + ], + files: [ + "dist", + "src", + "deno.json", + "bun.json", + "package.json" + ], + type: "module", + exports: { + ".": { + import: { + types: "./dist/tsup/mod.d.ts", + default: "./dist/tsup/mod.js" + }, + require: { + types: "./dist/tsup/mod.d.cts", + default: "./dist/tsup/mod.cjs" + } + }, + "./client": { + import: { + types: "./dist/tsup/client/mod.d.ts", + default: "./dist/tsup/client/mod.js" + }, + require: { + types: "./dist/tsup/client/mod.d.cts", + default: "./dist/tsup/client/mod.cjs" + } + }, + "./log": { + import: { + types: "./dist/tsup/common/log.d.ts", + default: "./dist/tsup/common/log.js" + }, + require: { + types: "./dist/tsup/common/log.d.cts", + default: "./dist/tsup/common/log.cjs" + } + }, + "./errors": { + import: { + types: "./dist/tsup/actor/errors.d.ts", + default: "./dist/tsup/actor/errors.js" + }, + require: { + types: "./dist/tsup/actor/errors.d.cts", + default: "./dist/tsup/actor/errors.cjs" + } + }, + "./utils": { + import: { + types: "./dist/tsup/utils.d.ts", + default: "./dist/tsup/utils.js" + }, + require: { + types: "./dist/tsup/utils.d.cts", + default: "./dist/tsup/utils.cjs" + } + }, + "./driver-helpers": { + import: { + types: "./dist/tsup/driver-helpers/mod.d.ts", + default: "./dist/tsup/driver-helpers/mod.js" + }, + require: { + types: "./dist/tsup/driver-helpers/mod.d.cts", + default: "./dist/tsup/driver-helpers/mod.cjs" + } + }, + "./driver-helpers/websocket": { + import: { + types: "./dist/tsup/common/websocket.d.ts", + default: "./dist/tsup/common/websocket.js" + }, + require: { + types: "./dist/tsup/common/websocket.d.cts", + default: "./dist/tsup/common/websocket.cjs" + } + }, + "./driver-test-suite": { + import: { + types: "./dist/tsup/driver-test-suite/mod.d.ts", + default: "./dist/tsup/driver-test-suite/mod.js" + }, + require: { + types: "./dist/tsup/driver-test-suite/mod.d.cts", + default: "./dist/tsup/driver-test-suite/mod.cjs" + } + }, + "./topologies/coordinate": { + import: { + types: "./dist/tsup/topologies/coordinate/mod.d.ts", + default: "./dist/tsup/topologies/coordinate/mod.js" + }, + require: { + types: "./dist/tsup/topologies/coordinate/mod.d.cts", + default: "./dist/tsup/topologies/coordinate/mod.cjs" + } + }, + "./topologies/partition": { + import: { + types: "./dist/tsup/topologies/partition/mod.d.ts", + default: "./dist/tsup/topologies/partition/mod.js" + }, + require: { + types: "./dist/tsup/topologies/partition/mod.d.cts", + default: "./dist/tsup/topologies/partition/mod.cjs" + } + }, + "./test": { + import: { + types: "./dist/tsup/test/mod.d.ts", + default: "./dist/tsup/test/mod.js" + }, + require: { + types: "./dist/tsup/test/mod.d.cts", + default: "./dist/tsup/test/mod.cjs" + } + }, + "./inspector": { + import: { + types: "./dist/tsup/inspector/mod.d.ts", + default: "./dist/tsup/inspector/mod.js" + }, + require: { + types: "./dist/tsup/inspector/mod.d.cts", + default: "./dist/tsup/inspector/mod.cjs" + } + } + }, + engines: { + node: ">=22.0.0" + }, + sideEffects: false, + scripts: { + dev: "pnpm build --watch", + build: "tsup src/mod.ts src/client/mod.ts src/common/log.ts src/common/websocket.ts src/actor/errors.ts src/topologies/coordinate/mod.ts src/topologies/partition/mod.ts src/utils.ts src/driver-helpers/mod.ts src/driver-test-suite/mod.ts src/test/mod.ts src/inspector/mod.ts", + "build:schema": "./scripts/compile-bare.ts compile schemas/client-protocol/v1.bare -o dist/schemas/client-protocol/v1.ts && ./scripts/compile-bare.ts compile schemas/file-system-driver/v1.bare -o dist/schemas/file-system-driver/v1.ts && ./scripts/compile-bare.ts compile schemas/actor-persist/v1.bare -o dist/schemas/actor-persist/v1.ts", + "check-types": "tsc --noEmit", + test: "vitest run", + "test:watch": "vitest", + "dump-openapi": "tsx scripts/dump-openapi.ts" + }, + dependencies: { + "@bare-ts/lib": "~0.3.0", + "@hono/standard-validator": "^0.1.3", + "@hono/zod-openapi": "^0.19.10", + "@rivetkit/engine-runner": "https://pkg.pr.new/rivet-gg/engine/@rivetkit/engine-runner@664a377", + "@rivetkit/fast-json-patch": "^3.1.2", + "cbor-x": "^1.6.0", + hono: "^4.7.0", + invariant: "^2.2.4", + nanoevents: "^9.1.0", + "on-change": "^5.0.1", + "p-retry": "^6.2.1", + zod: "^3.25.76" + }, + devDependencies: { + "@bare-ts/tools": "^0.13.0", + "@hono/node-server": "^1.18.2", + "@hono/node-ws": "^1.1.1", + "@rivet-gg/actor-core": "^25.1.0", + "@types/invariant": "^2", + "@types/node": "^22.13.1", + "@types/ws": "^8", + "@vitest/ui": "3.1.1", + "bundle-require": "^5.1.0", + eventsource: "^3.0.5", + tsup: "^8.4.0", + tsx: "^4.19.4", + typescript: "^5.7.3", + vitest: "^3.1.1", + ws: "^8.18.1" + }, + peerDependencies: { + "@hono/node-server": "^1.14.0", + "@hono/node-ws": "^1.1.1", + eventsource: "^3.0.5", + ws: "^8.0.0" + }, + peerDependenciesMeta: { + "@hono/node-server": { + optional: true + }, + "@hono/node-ws": { + optional: true + }, + eventsource: { + optional: true + }, + ws: { + optional: true + } + }, + stableVersion: "0.8.0" +}; + +// src/utils.ts +var VERSION = package_default.version; +var _userAgent; +function httpUserAgent() { + if (_userAgent !== void 0) { + return _userAgent; + } + let userAgent = `RivetKit/${VERSION}`; + const navigatorObj = typeof navigator !== "undefined" ? navigator : void 0; + if (navigatorObj?.userAgent) userAgent += ` ${navigatorObj.userAgent}`; + _userAgent = userAgent; + return userAgent; +} +function getEnvUniversal(key) { + if (typeof Deno !== "undefined") { + return Deno.env.get(key); + } else if (typeof process !== "undefined") { + return process.env[key]; + } +} +var TIMEOUT_MAX = 2147483647; +function setLongTimeout(listener, after) { + let timeout; + function start(remaining) { + if (remaining <= TIMEOUT_MAX) { + timeout = setTimeout(listener, remaining); + } else { + timeout = setTimeout(() => { + start(remaining - TIMEOUT_MAX); + }, TIMEOUT_MAX); + } + } + start(after); + return { + abort: () => { + if (timeout !== void 0) clearTimeout(timeout); + } + }; +} +var SinglePromiseQueue = class { + /** Next operation to execute in the queue. If attempting to enqueue another op, it will override the existing op. */ + #queuedOp; + /** The currently running promise of #drainLoop. Do not await this, instead await `pending` to await the current cycle. */ + runningDrainLoop; + /** Pending resolver fro the currently queued entry. */ + #pending; + /** Queue the next operation and return a promise that resolves when it flushes. */ + enqueue(op) { + this.#queuedOp = op; + if (!this.#pending) { + this.#pending = Promise.withResolvers(); + } + const waitForThisCycle = this.#pending.promise; + if (!this.runningDrainLoop) { + this.runningDrainLoop = this.#drainLoop(); + } + return waitForThisCycle; + } + /** Drain queued operations sequentially until there is nothing left. */ + async #drainLoop() { + try { + while (this.#queuedOp) { + const resolver = this.#pending; + this.#pending = void 0; + const op = this.#queuedOp; + this.#queuedOp = void 0; + try { + await op(); + } catch { + } + resolver?.resolve(); + } + } finally { + this.runningDrainLoop = void 0; + } + } +}; +function bufferToArrayBuffer(buf) { + return buf.buffer.slice( + buf.byteOffset, + buf.byteOffset + buf.byteLength + ); +} + +// src/common/log-levels.ts +var LogLevels = { + TRACE: 0, + DEBUG: 1, + INFO: 2, + WARN: 3, + ERROR: 4, + CRITICAL: 5 +}; +var LevelNameMap = { + 0: "TRACE", + 1: "DEBUG", + 2: "INFO", + 3: "WARN", + 4: "ERROR", + 5: "CRITICAL" +}; + +// src/common/logfmt.ts +var LOG_LEVEL_COLORS = { + [LogLevels.CRITICAL]: "\x1B[31m", + // Red + [LogLevels.ERROR]: "\x1B[31m", + // Red + [LogLevels.WARN]: "\x1B[33m", + // Yellow + [LogLevels.INFO]: "\x1B[32m", + // Green + [LogLevels.DEBUG]: "\x1B[36m", + // Cyan + [LogLevels.TRACE]: "\x1B[36m" + // Cyan +}; +var RESET_COLOR = "\x1B[0m"; +function stringify(...data) { + let line = ""; + for (let i = 0; i < data.length; i++) { + const [key, valueRaw] = data[i]; + let isNull = false; + let valueString; + if (valueRaw == null) { + isNull = true; + valueString = ""; + } else { + valueString = valueRaw.toString(); + } + if (valueString.length > 512 && key !== "msg" && key !== "error") + valueString = `${valueString.slice(0, 512)}...`; + const needsQuoting = valueString.indexOf(" ") > -1 || valueString.indexOf("=") > -1; + const needsEscaping = valueString.indexOf('"') > -1 || valueString.indexOf("\\") > -1; + valueString = valueString.replace(/\n/g, "\\n"); + if (needsEscaping) valueString = valueString.replace(/["\\]/g, "\\$&"); + if (needsQuoting || needsEscaping) valueString = `"${valueString}"`; + if (valueString === "" && !isNull) valueString = '""'; + if (LOGGER_CONFIG.enableColor) { + let color = "\x1B[2m"; + if (key === "level") { + const level = LogLevels[valueString]; + const levelColor = LOG_LEVEL_COLORS[level]; + if (levelColor) { + color = levelColor; + } + } else if (key === "msg") { + color = "\x1B[32m"; + } else if (key === "trace") { + color = "\x1B[34m"; + } + line += `\x1B[0m\x1B[1m${key}\x1B[0m\x1B[2m=\x1B[0m${color}${valueString}${RESET_COLOR}`; + } else { + line += `${key}=${valueString}`; + } + if (i !== data.length - 1) { + line += " "; + } + } + return line; +} +function formatTimestamp(date) { + const year = date.getUTCFullYear(); + const month = String(date.getUTCMonth() + 1).padStart(2, "0"); + const day = String(date.getUTCDate()).padStart(2, "0"); + const hours = String(date.getUTCHours()).padStart(2, "0"); + const minutes = String(date.getUTCMinutes()).padStart(2, "0"); + const seconds = String(date.getUTCSeconds()).padStart(2, "0"); + const milliseconds = String(date.getUTCMilliseconds()).padStart(3, "0"); + return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}Z`; +} +function castToLogValue(v) { + if (typeof v === "string" || typeof v === "number" || typeof v === "bigint" || typeof v === "boolean" || v === null || v === void 0) { + return v; + } + if (v instanceof Error) { + return String(v); + } + try { + return JSON.stringify(v); + } catch { + return "[cannot stringify]"; + } +} +var LOGGER_CONFIG = { + enableColor: false, + enableSpreadObject: false, + enableErrorStack: false +}; + +// src/common/log.ts +var Logger = class { + name; + level; + constructor(name, level) { + this.name = name; + this.level = level; + } + log(level, message, ...args) { + const record = { + msg: message, + args, + level, + loggerName: this.name, + datetime: /* @__PURE__ */ new Date(), + levelName: LevelNameMap[level] + }; + if (this.#shouldLog(level)) { + this.#logRecord(record); + } + } + #shouldLog(level) { + return level >= LogLevels[this.level]; + } + #logRecord(record) { + console.log(formatter(record)); + } + trace(message, ...args) { + this.log(LogLevels.TRACE, message, ...args); + } + debug(message, ...args) { + this.log(LogLevels.DEBUG, message, ...args); + } + info(message, ...args) { + this.log(LogLevels.INFO, message, ...args); + } + warn(message, ...args) { + this.log(LogLevels.WARN, message, ...args); + } + error(message, ...args) { + this.log(LogLevels.ERROR, message, ...args); + } + critical(message, ...args) { + this.log(LogLevels.CRITICAL, message, ...args); + } +}; +var loggers = {}; +function getLogger(name = "default") { + const defaultLogLevelEnv = getEnvUniversal( + "_LOG_LEVEL" + ); + const defaultLogLevel = defaultLogLevelEnv ?? "INFO"; + if (!loggers[name]) { + loggers[name] = new Logger(name, defaultLogLevel); + } + return loggers[name]; +} +function formatter(log) { + const args = []; + for (let i = 0; i < log.args.length; i++) { + const logArg = log.args[i]; + if (logArg && typeof logArg === "object") { + for (const k in logArg) { + const v = logArg[k]; + pushArg(k, v, args); + } + } else { + pushArg(`arg${i}`, logArg, args); + } + } + const logTs = getEnvUniversal("_LOG_TIMESTAMP") === "1"; + const logTarget = getEnvUniversal("_LOG_TARGET") === "1"; + return stringify( + ...logTs ? [["ts", formatTimestamp(/* @__PURE__ */ new Date())]] : [], + ["level", LevelNameMap[log.level]], + ...logTarget ? [["target", log.loggerName]] : [], + ["msg", log.msg], + ...args + ); +} +function pushArg(k, v, args) { + args.push([k, castToLogValue(v)]); +} + +// src/actor/log.ts +var RUNTIME_LOGGER_NAME = "actor-runtime"; +var ACTOR_LOGGER_NAME = "actor"; +function logger() { + return getLogger(RUNTIME_LOGGER_NAME); +} +function instanceLogger() { + return getLogger(ACTOR_LOGGER_NAME); +} + +// src/actor/protocol/serde.ts +import { z } from "zod"; + +// src/serde.ts +import * as cbor from "cbor-x"; +import invariant from "invariant"; +function encodingIsBinary(encoding) { + if (encoding === "json") { + return false; + } else if (encoding === "cbor" || encoding === "bare") { + return true; + } else { + assertUnreachable(encoding); + } +} +function contentTypeForEncoding(encoding) { + if (encoding === "json") { + return "application/json"; + } else if (encoding === "cbor" || encoding === "bare") { + return "application/octet-stream"; + } else { + assertUnreachable(encoding); + } +} +function serializeWithEncoding(encoding, value, versionedDataHandler) { + if (encoding === "json") { + return jsonStringifyCompat(value); + } else if (encoding === "cbor") { + return cbor.encode(value); + } else if (encoding === "bare") { + return versionedDataHandler.serializeWithEmbeddedVersion(value); + } else { + assertUnreachable(encoding); + } +} +function deserializeWithEncoding(encoding, buffer, versionedDataHandler) { + if (encoding === "json") { + if (typeof buffer === "string") { + return JSON.parse(buffer); + } else { + const decoder = new TextDecoder("utf-8"); + const jsonString = decoder.decode(buffer); + return JSON.parse(jsonString); + } + } else if (encoding === "cbor") { + invariant( + typeof buffer !== "string", + "buffer cannot be string for cbor encoding" + ); + return cbor.decode(buffer); + } else if (encoding === "bare") { + invariant( + typeof buffer !== "string", + "buffer cannot be string for bare encoding" + ); + return versionedDataHandler.deserializeWithEmbeddedVersion(buffer); + } else { + assertUnreachable(encoding); + } +} + +// src/actor/utils.ts +function assertUnreachable2(x) { + logger().error("unreachable", { value: `${x}`, stack: new Error().stack }); + throw new Unreachable(x); +} +var DeadlineError = class extends Error { + constructor() { + super("Promise did not complete before deadline."); + } +}; +function deadline(promise, timeout) { + const controller = new AbortController(); + const signal = controller.signal; + const timeoutId = setTimeout(() => controller.abort(), timeout); + return Promise.race([ + promise, + new Promise((_, reject) => { + signal.addEventListener("abort", () => reject(new DeadlineError())); + }) + ]).finally(() => { + clearTimeout(timeoutId); + }); +} +function generateSecureToken(length = 32) { + const array = new Uint8Array(length); + crypto.getRandomValues(array); + return btoa(String.fromCharCode(...array)); +} +function generateRandomString(length = 32) { + const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + result += characters[randomIndex]; + } + return result; +} + +// src/actor/protocol/serde.ts +var EncodingSchema = z.enum(["json", "cbor", "bare"]); +var CachedSerializer = class { + #data; + #cache = /* @__PURE__ */ new Map(); + #versionedDataHandler; + constructor(data, versionedDataHandler) { + this.#data = data; + this.#versionedDataHandler = versionedDataHandler; + } + get rawData() { + return this.#data; + } + serialize(encoding) { + const cached = this.#cache.get(encoding); + if (cached) { + return cached; + } else { + const serialized = serializeWithEncoding( + encoding, + this.#data, + this.#versionedDataHandler + ); + this.#cache.set(encoding, serialized); + return serialized; + } + } +}; +function base64EncodeUint8Array(uint8Array) { + let binary = ""; + const len = uint8Array.byteLength; + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(uint8Array[i]); + } + return btoa(binary); +} +function base64EncodeArrayBuffer(arrayBuffer) { + const uint8Array = new Uint8Array(arrayBuffer); + return base64EncodeUint8Array(uint8Array); +} +function encodeDataToString(message) { + if (typeof message === "string") { + return message; + } else if (message instanceof ArrayBuffer) { + return base64EncodeArrayBuffer(message); + } else if (message instanceof Uint8Array) { + return base64EncodeUint8Array(message); + } else { + assertUnreachable2(message); + } +} +function jsonStringifyCompat(input) { + return JSON.stringify( + input, + (_key, value) => typeof value === "bigint" ? value.toString() : value + ); +} + +// src/actor/connection.ts +function generateConnId() { + return crypto.randomUUID(); +} +function generateConnToken() { + return generateSecureToken(32); +} +var CONNECTION_DRIVER_WEBSOCKET = "webSocket"; +var CONNECTION_DRIVER_SSE = "sse"; +var CONNECTION_DRIVER_HTTP = "http"; +var CONNECTION_CHECK_LIVENESS_SYMBOL = Symbol("checkLiveness"); +var Conn = class { + subscriptions = /* @__PURE__ */ new Set(); + #stateEnabled; + // TODO: Remove this cyclical reference + #actor; + #status = "connected"; + /** + * The proxied state that notifies of changes automatically. + * + * Any data that should be stored indefinitely should be held within this object. + */ + __persist; + /** + * Driver used to manage realtime connection communication. + * + * @protected + */ + #driver; + get params() { + return this.__persist.params; + } + get auth() { + return this.__persist.authData; + } + get driver() { + return this.__persist.connDriver; + } + get _stateEnabled() { + return this.#stateEnabled; + } + /** + * Gets the current state of the connection. + * + * Throws an error if the state is not enabled. + */ + get state() { + this.#validateStateEnabled(); + if (!this.__persist.state) throw new Error("state should exists"); + return this.__persist.state; + } + /** + * Sets the state of the connection. + * + * Throws an error if the state is not enabled. + */ + set state(value) { + this.#validateStateEnabled(); + this.__persist.state = value; + } + /** + * Unique identifier for the connection. + */ + get id() { + return this.__persist.connId; + } + /** + * Token used to authenticate this request. + */ + get _token() { + return this.__persist.token; + } + /** + * Status of the connection. + */ + get status() { + return this.#status; + } + /** + * Timestamp of the last time the connection was seen, i.e. the last time the connection was active and checked for liveness. + */ + get lastSeen() { + return this.__persist.lastSeen; + } + /** + * Initializes a new instance of the Connection class. + * + * This should only be constructed by {@link Actor}. + * + * @protected + */ + constructor(actor2, persist, driver, stateEnabled) { + this.#actor = actor2; + this.__persist = persist; + this.#driver = driver; + this.#stateEnabled = stateEnabled; + } + #validateStateEnabled() { + if (!this.#stateEnabled) { + throw new ConnStateNotEnabled(); + } + } + /** + * Sends a WebSocket message to the client. + * + * @param message - The message to send. + * + * @protected + */ + _sendMessage(message) { + this.#driver.sendMessage?.( + this.#actor, + this, + this.__persist.connDriverState, + message + ); + } + /** + * Sends an event with arguments to the client. + * + * @param eventName - The name of the event. + * @param args - The arguments for the event. + * @see {@link https://rivet.gg/docs/events|Events Documentation} + */ + send(eventName, ...args) { + this.#actor.inspector.emitter.emit("eventFired", { + type: "event", + eventName, + args, + connId: this.id + }); + this._sendMessage( + new CachedSerializer( + { + body: { + tag: "Event", + val: { + name: eventName, + args: bufferToArrayBuffer(cbor2.encode(args)) + } + } + }, + TO_CLIENT_VERSIONED + ) + ); + } + /** + * Disconnects the client with an optional reason. + * + * @param reason - The reason for disconnection. + */ + async disconnect(reason) { + this.#status = "reconnecting"; + await this.#driver.disconnect( + this.#actor, + this, + this.__persist.connDriverState, + reason + ); + } + /** + * This method checks the connection's liveness by querying the driver for its ready state. + * If the connection is not closed, it updates the last liveness timestamp and returns `true`. + * Otherwise, it returns `false`. + * @internal + */ + [CONNECTION_CHECK_LIVENESS_SYMBOL]() { + const readyState = this.#driver.getConnectionReadyState(this.#actor, this); + const isConnectionClosed = readyState === 3 /* CLOSED */ || readyState === 2 /* CLOSING */ || readyState === void 0; + const newLastSeen = Date.now(); + const newStatus = isConnectionClosed ? "reconnecting" : "connected"; + logger().debug("liveness probe for connection", { + connId: this.id, + actorId: this.#actor.id, + readyState, + status: this.#status, + newStatus, + lastSeen: this.__persist.lastSeen, + currentTs: newLastSeen + }); + if (!isConnectionClosed) { + this.__persist.lastSeen = newLastSeen; + } + this.#status = newStatus; + return { + status: this.#status, + lastSeen: this.__persist.lastSeen + }; + } +}; + +// src/actor/config.ts +import { z as z2 } from "zod"; +var ActorConfigSchema = z2.object({ + onAuth: z2.function().optional(), + onCreate: z2.function().optional(), + onStart: z2.function().optional(), + onStop: z2.function().optional(), + onStateChange: z2.function().optional(), + onBeforeConnect: z2.function().optional(), + onConnect: z2.function().optional(), + onDisconnect: z2.function().optional(), + onBeforeActionResponse: z2.function().optional(), + onFetch: z2.function().optional(), + onWebSocket: z2.function().optional(), + actions: z2.record(z2.function()).default({}), + state: z2.any().optional(), + createState: z2.function().optional(), + connState: z2.any().optional(), + createConnState: z2.function().optional(), + vars: z2.any().optional(), + db: z2.any().optional(), + createVars: z2.function().optional(), + options: z2.object({ + createVarsTimeout: z2.number().positive().default(5e3), + createConnStateTimeout: z2.number().positive().default(5e3), + onConnectTimeout: z2.number().positive().default(5e3), + // This must be less than ACTOR_STOP_THRESHOLD_MS + onStopTimeout: z2.number().positive().default(5e3), + stateSaveInterval: z2.number().positive().default(1e4), + actionTimeout: z2.number().positive().default(6e4), + // Max time to wait for waitUntil background promises during shutdown + waitUntilTimeout: z2.number().positive().default(15e3), + connectionLivenessTimeout: z2.number().positive().default(2500), + connectionLivenessInterval: z2.number().positive().default(5e3), + noSleep: z2.boolean().default(false), + sleepTimeout: z2.number().positive().default(3e4) + }).strict().default({}) +}).strict().refine( + (data) => !(data.state !== void 0 && data.createState !== void 0), + { + message: "Cannot define both 'state' and 'createState'", + path: ["state"] + } +).refine( + (data) => !(data.connState !== void 0 && data.createConnState !== void 0), + { + message: "Cannot define both 'connState' and 'createConnState'", + path: ["connState"] + } +).refine( + (data) => !(data.vars !== void 0 && data.createVars !== void 0), + { + message: "Cannot define both 'vars' and 'createVars'", + path: ["vars"] + } +); + +// src/actor/instance.ts +import * as cbor5 from "cbor-x"; +import invariant2 from "invariant"; +import onChange from "on-change"; + +// src/inspector/actor.ts +import { sValidator } from "@hono/standard-validator"; +import jsonPatch from "@rivetkit/fast-json-patch"; +import { Hono } from "hono"; +import { streamSSE as streamSSE2 } from "hono/streaming"; +import { createNanoEvents } from "nanoevents"; +import z6 from "zod/v4"; + +// src/inspector/protocol/common.ts +import z5 from "zod/v4"; + +// src/manager/protocol/query.ts +import { z as z4 } from "zod"; + +// src/actor/router-endpoints.ts +import * as cbor4 from "cbor-x"; +import { streamSSE } from "hono/streaming"; + +// src/actor/action.ts +var ActionContext = class { + /** + * Should not be called directly. + * + * @param actorContext - The actor context + * @param conn - The connection associated with the action + */ + constructor(actorContext, conn) { + this.conn = conn; + this.#actorContext = actorContext; + } + #actorContext; + /** + * Get the actor state + */ + get state() { + return this.#actorContext.state; + } + /** + * Get the actor variables + */ + get vars() { + return this.#actorContext.vars; + } + /** + * Broadcasts an event to all connected clients. + */ + broadcast(name, ...args) { + this.#actorContext.broadcast(name, ...args); + } + /** + * Gets the logger instance. + */ + get log() { + return this.#actorContext.log; + } + /** + * Gets actor ID. + */ + get actorId() { + return this.#actorContext.actorId; + } + /** + * Gets the actor name. + */ + get name() { + return this.#actorContext.name; + } + /** + * Gets the actor key. + */ + get key() { + return this.#actorContext.key; + } + /** + * Gets the region. + */ + get region() { + return this.#actorContext.region; + } + /** + * Gets the scheduler. + */ + get schedule() { + return this.#actorContext.schedule; + } + /** + * Gets the map of connections. + */ + get conns() { + return this.#actorContext.conns; + } + /** + * Returns the client for the given registry. + */ + client() { + return this.#actorContext.client(); + } + /** + * @experimental + */ + get db() { + return this.#actorContext.db; + } + /** + * Forces the state to get saved. + */ + async saveState(opts) { + return this.#actorContext.saveState(opts); + } + /** + * Prevents the actor from sleeping until promise is complete. + */ + waitUntil(promise) { + this.#actorContext.waitUntil(promise); + } + /** + * AbortSignal that fires when the actor is stopping. + */ + get abortSignal() { + return this.#actorContext.abortSignal; + } + /** + * Forces the actor to sleep. + * + * Not supported on all drivers. + * + * @experimental + */ + sleep() { + this.#actorContext.sleep(); + } +}; + +// src/manager/log.ts +var LOGGER_NAME = "actor-manager"; +function logger2() { + return getLogger(LOGGER_NAME); +} + +// src/manager/hono-websocket-adapter.ts +var HonoWebSocketAdapter = class { + // WebSocket readyState values + CONNECTING = 0; + OPEN = 1; + CLOSING = 2; + CLOSED = 3; + #ws; + #readyState = 1; + // Start as OPEN since WSContext is already connected + #eventListeners = /* @__PURE__ */ new Map(); + #closeCode; + #closeReason; + constructor(ws) { + this.#ws = ws; + this.#readyState = this.OPEN; + setTimeout(() => { + this.#fireEvent("open", { type: "open", target: this }); + }, 0); + } + get readyState() { + return this.#readyState; + } + get binaryType() { + return "arraybuffer"; + } + set binaryType(value) { + } + get bufferedAmount() { + return 0; + } + get extensions() { + return ""; + } + get protocol() { + return ""; + } + get url() { + return ""; + } + send(data) { + if (this.readyState !== this.OPEN) { + throw new Error("WebSocket is not open"); + } + try { + logger2().debug("bridge sending data", { + dataType: typeof data, + isString: typeof data === "string", + isArrayBuffer: data instanceof ArrayBuffer, + dataStr: typeof data === "string" ? data.substring(0, 100) : "" + }); + if (typeof data === "string") { + this.#ws.send(data); + } else if (data instanceof ArrayBuffer) { + this.#ws.send(data); + } else if (ArrayBuffer.isView(data)) { + const buffer = data.buffer.slice( + data.byteOffset, + data.byteOffset + data.byteLength + ); + if (buffer instanceof SharedArrayBuffer) { + const arrayBuffer = new ArrayBuffer(buffer.byteLength); + new Uint8Array(arrayBuffer).set(new Uint8Array(buffer)); + this.#ws.send(arrayBuffer); + } else { + this.#ws.send(buffer); + } + } else if (data instanceof Blob) { + data.arrayBuffer().then((buffer) => { + this.#ws.send(buffer); + }).catch((error) => { + logger2().error("failed to convert blob to arraybuffer", { error }); + this.#fireEvent("error", { type: "error", target: this, error }); + }); + } else { + logger2().warn("unsupported data type, converting to string", { + dataType: typeof data, + data + }); + this.#ws.send(String(data)); + } + } catch (error) { + logger2().error("error sending websocket data", { error }); + this.#fireEvent("error", { type: "error", target: this, error }); + throw error; + } + } + close(code = 1e3, reason = "") { + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return; + } + this.#readyState = this.CLOSING; + this.#closeCode = code; + this.#closeReason = reason; + try { + this.#ws.close(code, reason); + this.#readyState = this.CLOSED; + this.#fireEvent("close", { + type: "close", + target: this, + code, + reason, + wasClean: code === 1e3 + }); + } catch (error) { + logger2().error("error closing websocket", { error }); + this.#readyState = this.CLOSED; + this.#fireEvent("close", { + type: "close", + target: this, + code: 1006, + reason: "Abnormal closure", + wasClean: false + }); + } + } + addEventListener(type, listener) { + if (!this.#eventListeners.has(type)) { + this.#eventListeners.set(type, /* @__PURE__ */ new Set()); + } + this.#eventListeners.get(type).add(listener); + } + removeEventListener(type, listener) { + const listeners = this.#eventListeners.get(type); + if (listeners) { + listeners.delete(listener); + } + } + dispatchEvent(event) { + const listeners = this.#eventListeners.get(event.type); + if (listeners) { + for (const listener of listeners) { + try { + listener(event); + } catch (error) { + logger2().error(`error in ${event.type} event listener`, { error }); + } + } + } + return true; + } + // Internal method to handle incoming messages from WSContext + _handleMessage(data) { + let messageData; + if (typeof data === "string") { + messageData = data; + } else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) { + messageData = data; + } else if (data && typeof data === "object" && "data" in data) { + messageData = data.data; + } else { + messageData = String(data); + } + logger2().debug("bridge handling message", { + dataType: typeof messageData, + isArrayBuffer: messageData instanceof ArrayBuffer, + dataStr: typeof messageData === "string" ? messageData : "" + }); + this.#fireEvent("message", { + type: "message", + target: this, + data: messageData + }); + } + // Internal method to handle close from WSContext + _handleClose(code, reason) { + this.#ws.close(1e3, "hack_force_close"); + if (this.readyState === this.CLOSED) return; + this.#readyState = this.CLOSED; + this.#closeCode = code; + this.#closeReason = reason; + this.#fireEvent("close", { + type: "close", + target: this, + code, + reason, + wasClean: code === 1e3 + }); + } + // Internal method to handle errors from WSContext + _handleError(error) { + this.#fireEvent("error", { + type: "error", + target: this, + error + }); + } + #fireEvent(type, event) { + const listeners = this.#eventListeners.get(type); + if (listeners) { + for (const listener of listeners) { + try { + listener(event); + } catch (error) { + logger2().error(`error in ${type} event listener`, { error }); + } + } + } + switch (type) { + case "open": + if (this.#onopen) { + try { + this.#onopen(event); + } catch (error) { + logger2().error("error in onopen handler", { error }); + } + } + break; + case "close": + if (this.#onclose) { + try { + this.#onclose(event); + } catch (error) { + logger2().error("error in onclose handler", { error }); + } + } + break; + case "error": + if (this.#onerror) { + try { + this.#onerror(event); + } catch (error) { + logger2().error("error in onerror handler", { error }); + } + } + break; + case "message": + if (this.#onmessage) { + try { + this.#onmessage(event); + } catch (error) { + logger2().error("error in onmessage handler", { error }); + } + } + break; + } + } + // Event handler properties with getters/setters + #onopen = null; + #onclose = null; + #onerror = null; + #onmessage = null; + get onopen() { + return this.#onopen; + } + set onopen(handler) { + this.#onopen = handler; + } + get onclose() { + return this.#onclose; + } + set onclose(handler) { + this.#onclose = handler; + } + get onerror() { + return this.#onerror; + } + set onerror(handler) { + this.#onerror = handler; + } + get onmessage() { + return this.#onmessage; + } + set onmessage(handler) { + this.#onmessage = handler; + } +}; + +// src/actor/protocol/old.ts +import * as cbor3 from "cbor-x"; +import { z as z3 } from "zod"; +var TransportSchema = z3.enum(["websocket", "sse"]); +function getValueLength(value) { + if (typeof value === "string") { + return value.length; + } else if (value instanceof Blob) { + return value.size; + } else if (value instanceof ArrayBuffer || value instanceof SharedArrayBuffer || value instanceof Uint8Array) { + return value.byteLength; + } else { + assertUnreachable(value); + } +} +async function inputDataToBuffer(data) { + if (typeof data === "string") { + return data; + } else if (data instanceof Blob) { + const arrayBuffer = await data.arrayBuffer(); + return new Uint8Array(arrayBuffer); + } else if (data instanceof Uint8Array) { + return data; + } else if (data instanceof ArrayBuffer || data instanceof SharedArrayBuffer) { + return new Uint8Array(data); + } else { + throw new MalformedMessage(); + } +} +async function parseMessage(value, opts) { + const length = getValueLength(value); + if (length > opts.maxIncomingMessageSize) { + throw new MessageTooLong(); + } + const buffer = await inputDataToBuffer(value); + return deserializeWithEncoding(opts.encoding, buffer, TO_SERVER_VERSIONED); +} +async function processMessage(message, actor2, conn, handler) { + let actionId; + let actionName; + try { + if (message.body.tag === "ActionRequest") { + if (handler.onExecuteAction === void 0) { + throw new Unsupported("Action"); + } + const { id, name, args: argsRaw } = message.body.val; + actionId = id; + actionName = name; + const args = cbor3.decode(new Uint8Array(argsRaw)); + logger().debug("processing action request", { + actionId: id, + actionName: name + }); + const ctx = new ActionContext( + actor2.actorContext, + conn + ); + const output = await handler.onExecuteAction(ctx, name, args); + logger().debug("sending action response", { + actionId: id, + actionName: name, + outputType: typeof output, + isPromise: output instanceof Promise + }); + conn._sendMessage( + new CachedSerializer( + { + body: { + tag: "ActionResponse", + val: { + id, + output: bufferToArrayBuffer(cbor3.encode(output)) + } + } + }, + TO_CLIENT_VERSIONED + ) + ); + logger().debug("action response sent", { id, name }); + } else if (message.body.tag === "SubscriptionRequest") { + if (handler.onSubscribe === void 0 || handler.onUnsubscribe === void 0) { + throw new Unsupported("Subscriptions"); + } + const { eventName, subscribe } = message.body.val; + logger().debug("processing subscription request", { + eventName, + subscribe + }); + if (subscribe) { + await handler.onSubscribe(eventName, conn); + } else { + await handler.onUnsubscribe(eventName, conn); + } + logger().debug("subscription request completed", { + eventName, + subscribe + }); + } else { + assertUnreachable(message.body); + } + } catch (error) { + const { code, message: message2, metadata } = deconstructError(error, logger(), { + connectionId: conn.id, + actionId, + actionName + }); + logger().debug("sending error response", { + actionId, + actionName, + code, + message: message2 + }); + conn._sendMessage( + new CachedSerializer( + { + body: { + tag: "Error", + val: { + code, + message: message2, + metadata: bufferToArrayBuffer(cbor3.encode(metadata)), + actionId: actionId ?? null + } + } + }, + TO_CLIENT_VERSIONED + ) + ); + logger().debug("error response sent", { actionId, actionName }); + } +} + +// src/actor/router-endpoints.ts +async function handleWebSocketConnect(req, runConfig, actorDriver, actorId, encoding, parameters, authData) { + const exposeInternalError = req ? getRequestExposeInternalError(req) : false; + const { + promise: handlersPromise, + resolve: handlersResolve, + reject: handlersReject + } = Promise.withResolvers(); + let actor2; + try { + actor2 = await actorDriver.loadActor(actorId); + } catch (error) { + return { + onOpen: (_evt, ws) => { + const { code } = deconstructError( + error, + logger(), + { + wsEvent: "open" + }, + exposeInternalError + ); + ws.close(1011, code); + }, + onMessage: (_evt, ws) => { + ws.close(1011, "Actor not loaded"); + }, + onClose: (_event, _ws) => { + }, + onError: (_error) => { + } + }; + } + return { + onOpen: (_evt, ws) => { + logger().debug("websocket open"); + (async () => { + try { + const connId = generateConnId(); + const connToken = generateConnToken(); + const connState = await actor2.prepareConn(parameters, req); + const connGlobalState = actorDriver.getGenericConnGlobalState(actorId); + connGlobalState.websockets.set(connId, ws); + logger().debug("registered websocket for conn", { + actorId, + totalCount: connGlobalState.websockets.size + }); + const conn = await actor2.createConn( + connId, + connToken, + parameters, + connState, + CONNECTION_DRIVER_WEBSOCKET, + { encoding }, + authData + ); + handlersResolve({ conn, actor: actor2, connId }); + } catch (error) { + handlersReject(error); + const { code } = deconstructError( + error, + logger(), + { + wsEvent: "open" + }, + exposeInternalError + ); + ws.close(1011, code); + } + })(); + }, + onMessage: (evt, ws) => { + handlersPromise.then(({ conn, actor: actor3 }) => { + logger().debug("received message"); + const value = evt.data.valueOf(); + parseMessage(value, { + encoding, + maxIncomingMessageSize: runConfig.maxIncomingMessageSize + }).then((message) => { + actor3.processMessage(message, conn).catch((error) => { + const { code } = deconstructError( + error, + logger(), + { + wsEvent: "message" + }, + exposeInternalError + ); + ws.close(1011, code); + }); + }).catch((error) => { + const { code } = deconstructError( + error, + logger(), + { + wsEvent: "message" + }, + exposeInternalError + ); + ws.close(1011, code); + }); + }).catch((error) => { + const { code } = deconstructError( + error, + logger(), + { + wsEvent: "message" + }, + exposeInternalError + ); + ws.close(1011, code); + }); + }, + onClose: (event, ws) => { + if (event.wasClean) { + logger().info("websocket closed", { + code: event.code, + reason: event.reason, + wasClean: event.wasClean + }); + } else { + logger().warn("websocket closed", { + code: event.code, + reason: event.reason, + wasClean: event.wasClean + }); + } + ws.close(1e3, "hack_force_close"); + handlersPromise.then(({ conn, actor: actor3, connId }) => { + const connGlobalState = actorDriver.getGenericConnGlobalState(actorId); + const didDelete = connGlobalState.websockets.delete(connId); + if (didDelete) { + logger().info("removing websocket for conn", { + totalCount: connGlobalState.websockets.size + }); + } else { + logger().warn("websocket does not exist for conn", { + actorId, + totalCount: connGlobalState.websockets.size + }); + } + actor3.__removeConn(conn); + }).catch((error) => { + deconstructError( + error, + logger(), + { wsEvent: "close" }, + exposeInternalError + ); + }); + }, + onError: (_error) => { + try { + logger().warn("websocket error"); + } catch (error) { + deconstructError( + error, + logger(), + { wsEvent: "error" }, + exposeInternalError + ); + } + } + }; +} +async function handleSseConnect(c, _runConfig, actorDriver, actorId, authData) { + const encoding = getRequestEncoding(c.req); + const parameters = getRequestConnParams(c.req); + return streamSSE(c, async (stream) => { + let actor2; + let connId; + let connToken; + let connState; + let conn; + try { + actor2 = await actorDriver.loadActor(actorId); + connId = generateConnId(); + connToken = generateConnToken(); + connState = await actor2.prepareConn(parameters, c.req.raw); + logger().debug("sse open"); + actorDriver.getGenericConnGlobalState(actorId).sseStreams.set(connId, stream); + conn = await actor2.createConn( + connId, + connToken, + parameters, + connState, + CONNECTION_DRIVER_SSE, + { encoding }, + authData + ); + const abortResolver = Promise.withResolvers(); + stream.onAbort(async () => { + try { + logger().debug("sse stream aborted"); + if (connId) { + actorDriver.getGenericConnGlobalState(actorId).sseStreams.delete(connId); + } + if (conn && actor2) { + actor2.__removeConn(conn); + } + abortResolver.resolve(void 0); + } catch (error) { + logger().error("error closing sse connection", { error }); + abortResolver.resolve(void 0); + } + }); + try { + c.executionCtx.waitUntil(abortResolver.promise); + } catch { + } + await abortResolver.promise; + } catch (error) { + logger().error("error in sse connection", { error }); + if (connId !== void 0) { + actorDriver.getGenericConnGlobalState(actorId).sseStreams.delete(connId); + } + if (conn && actor2 !== void 0) { + actor2.__removeConn(conn); + } + stream.close(); + } + }); +} +async function handleAction(c, _runConfig, actorDriver, actionName, actorId, authData) { + const encoding = getRequestEncoding(c.req); + const parameters = getRequestConnParams(c.req); + logger().debug("handling action", { actionName, encoding }); + const arrayBuffer = await c.req.arrayBuffer(); + const request = deserializeWithEncoding( + encoding, + new Uint8Array(arrayBuffer), + HTTP_ACTION_REQUEST_VERSIONED + ); + const actionArgs = cbor4.decode(new Uint8Array(request.args)); + let actor2; + let conn; + let output; + try { + actor2 = await actorDriver.loadActor(actorId); + const connState = await actor2.prepareConn(parameters, c.req.raw); + conn = await actor2.createConn( + generateConnId(), + generateConnToken(), + parameters, + connState, + CONNECTION_DRIVER_HTTP, + {}, + authData + ); + const ctx = new ActionContext(actor2.actorContext, conn); + output = await actor2.executeAction(ctx, actionName, actionArgs); + } finally { + if (conn) { + actor2?.__removeConn(conn); + } + } + const responseData = { + output: bufferToArrayBuffer(cbor4.encode(output)) + }; + const serialized = serializeWithEncoding( + encoding, + responseData, + HTTP_ACTION_RESPONSE_VERSIONED + ); + return c.body(serialized, 200, { + "Content-Type": contentTypeForEncoding(encoding) + }); +} +async function handleConnectionMessage(c, _runConfig, actorDriver, connId, connToken, actorId) { + const encoding = getRequestEncoding(c.req); + const arrayBuffer = await c.req.arrayBuffer(); + const message = deserializeWithEncoding( + encoding, + new Uint8Array(arrayBuffer), + TO_SERVER_VERSIONED + ); + const actor2 = await actorDriver.loadActor(actorId); + const conn = actor2.conns.get(connId); + if (!conn) { + throw new ConnNotFound(connId); + } + if (conn._token !== connToken) { + throw new IncorrectConnToken(); + } + await actor2.processMessage(message, conn); + return c.json({}); +} +async function handleRawWebSocketHandler(req, path3, actorDriver, actorId, authData) { + const actor2 = await actorDriver.loadActor(actorId); + return { + onOpen: (_evt, ws) => { + const adapter = new HonoWebSocketAdapter(ws); + ws.__adapter = adapter; + const url = new URL(path3, "http://actor"); + const pathname = url.pathname.replace(/^\/raw\/websocket/, "") || "/"; + const normalizedPath = pathname + url.search; + let newRequest; + if (req) { + newRequest = new Request(`http://actor${normalizedPath}`, req); + } else { + newRequest = new Request(`http://actor${normalizedPath}`, { + method: "GET" + }); + } + logger().debug("rewriting websocket url", { + from: path3, + to: newRequest.url + }); + actor2.handleWebSocket(adapter, { + request: newRequest, + auth: authData + }); + }, + onMessage: (event, ws) => { + const adapter = ws.__adapter; + if (adapter) { + adapter._handleMessage(event); + } + }, + onClose: (evt, ws) => { + const adapter = ws.__adapter; + if (adapter) { + adapter._handleClose(evt?.code || 1006, evt?.reason || ""); + } + }, + onError: (error, ws) => { + const adapter = ws.__adapter; + if (adapter) { + adapter._handleError(error); + } + } + }; +} +function getRequestEncoding(req) { + const encodingParam = req.header(HEADER_ENCODING); + if (!encodingParam) { + throw new InvalidEncoding("undefined"); + } + const result = EncodingSchema.safeParse(encodingParam); + if (!result.success) { + throw new InvalidEncoding(encodingParam); + } + return result.data; +} +function getRequestExposeInternalError(req) { + const param = req.headers.get(HEADER_EXPOSE_INTERNAL_ERROR); + if (!param) { + return false; + } + return param === "true"; +} +function getRequestQuery(c) { + const queryParam = c.req.header(HEADER_ACTOR_QUERY); + if (!queryParam) { + logger().error("missing query parameter"); + throw new InvalidRequest("missing query"); + } + try { + const parsed = JSON.parse(queryParam); + return parsed; + } catch (error) { + logger().error("invalid query json", { error }); + throw new InvalidQueryJSON(error); + } +} +var HEADER_ACTOR_QUERY = "X-RivetKit-Query"; +var HEADER_ENCODING = "X-RivetKit-Encoding"; +var HEADER_EXPOSE_INTERNAL_ERROR = "X-RivetKit-Expose-Internal-Error"; +var HEADER_CONN_PARAMS = "X-RivetKit-Conn-Params"; +var HEADER_AUTH_DATA = "X-RivetKit-Auth-Data"; +var HEADER_ACTOR_ID = "X-RivetKit-Actor"; +var HEADER_CONN_ID = "X-RivetKit-Conn"; +var HEADER_CONN_TOKEN = "X-RivetKit-Conn-Token"; +var ALLOWED_PUBLIC_HEADERS = [ + "Content-Type", + "User-Agent", + HEADER_ACTOR_QUERY, + HEADER_ENCODING, + HEADER_CONN_PARAMS, + HEADER_ACTOR_ID, + HEADER_CONN_ID, + HEADER_CONN_TOKEN +]; +function getRequestConnParams(req) { + const paramsParam = req.header(HEADER_CONN_PARAMS); + if (!paramsParam) { + return null; + } + try { + return JSON.parse(paramsParam); + } catch (err) { + throw new InvalidParams( + `Invalid params JSON: ${stringifyError(err)}` + ); + } +} + +// src/manager/protocol/query.ts +var MAX_ACTOR_KEY_SIZE = 128; +var ActorKeySchema = z4.array(z4.string().max(MAX_ACTOR_KEY_SIZE)); +var CreateRequestSchema = z4.object({ + name: z4.string(), + key: ActorKeySchema, + input: z4.unknown().optional(), + region: z4.string().optional() +}); +var GetForKeyRequestSchema = z4.object({ + name: z4.string(), + key: ActorKeySchema +}); +var GetOrCreateRequestSchema = z4.object({ + name: z4.string(), + key: ActorKeySchema, + input: z4.unknown().optional(), + region: z4.string().optional() +}); +var ActorQuerySchema = z4.union([ + z4.object({ + getForId: z4.object({ + name: z4.string(), + actorId: z4.string() + }) + }), + z4.object({ + getForKey: GetForKeyRequestSchema + }), + z4.object({ + getOrCreateForKey: GetOrCreateRequestSchema + }), + z4.object({ + create: CreateRequestSchema + }) +]); +var ConnectRequestSchema = z4.object({ + query: ActorQuerySchema.describe(HEADER_ACTOR_QUERY), + encoding: EncodingSchema.describe(HEADER_ENCODING), + connParams: z4.string().optional().describe(HEADER_CONN_PARAMS) +}); +var ConnectWebSocketRequestSchema = z4.object({ + query: ActorQuerySchema.describe("query"), + encoding: EncodingSchema.describe("encoding"), + connParams: z4.unknown().optional().describe("conn_params") +}); +var ConnMessageRequestSchema = z4.object({ + actorId: z4.string().describe(HEADER_ACTOR_ID), + connId: z4.string().describe(HEADER_CONN_ID), + encoding: EncodingSchema.describe(HEADER_ENCODING), + connToken: z4.string().describe(HEADER_CONN_TOKEN) +}); +var ResolveRequestSchema = z4.object({ + query: ActorQuerySchema.describe(HEADER_ACTOR_QUERY), + connParams: z4.string().optional().describe(HEADER_CONN_PARAMS) +}); + +// src/inspector/protocol/common.ts +var ActorId = z5.string().brand("ActorId"); +var ActorFeature = /* @__PURE__ */ ((ActorFeature2) => { + ActorFeature2["Logs"] = "logs"; + ActorFeature2["Config"] = "config"; + ActorFeature2["Connections"] = "connections"; + ActorFeature2["State"] = "state"; + ActorFeature2["Console"] = "console"; + ActorFeature2["Runtime"] = "runtime"; + ActorFeature2["Metrics"] = "metrics"; + ActorFeature2["EventsMonitoring"] = "events-monitoring"; + ActorFeature2["Database"] = "database"; + return ActorFeature2; +})(ActorFeature || {}); +var ActorLogEntry = z5.object({ + level: z5.string(), + message: z5.string(), + timestamp: z5.string(), + metadata: z5.record(z5.string(), z5.any()).optional() +}); +var ActorSchema = z5.object({ + id: ActorId, + name: z5.string(), + key: z5.array(z5.string()), + tags: z5.record(z5.string(), z5.string()).optional(), + region: z5.string().optional(), + createdAt: z5.string().optional(), + startedAt: z5.string().optional(), + destroyedAt: z5.string().optional(), + features: z5.array(z5.enum(ActorFeature)).optional() +}); +var OperationSchema = z5.discriminatedUnion("op", [ + z5.object({ + op: z5.literal("remove"), + path: z5.string() + }), + z5.object({ + op: z5.literal("add"), + path: z5.string(), + value: z5.unknown() + }), + z5.object({ + op: z5.literal("replace"), + path: z5.string(), + value: z5.unknown() + }), + z5.object({ + op: z5.literal("move"), + path: z5.string(), + from: z5.string() + }), + z5.object({ + op: z5.literal("copy"), + path: z5.string(), + from: z5.string() + }), + z5.object({ + op: z5.literal("test"), + path: z5.string(), + value: z5.unknown() + }) +]); +var PatchSchema = z5.array(OperationSchema); +var ConnectionSchema = z5.object({ + params: z5.record(z5.string(), z5.any()).optional(), + id: z5.string(), + stateEnabled: z5.boolean().optional(), + state: z5.any().optional(), + auth: z5.record(z5.string(), z5.any()).optional() +}); +var RealtimeEventSchema = z5.discriminatedUnion("type", [ + z5.object({ + type: z5.literal("action"), + name: z5.string(), + args: z5.array(z5.any()), + connId: z5.string() + }), + z5.object({ + type: z5.literal("broadcast"), + eventName: z5.string(), + args: z5.array(z5.any()) + }), + z5.object({ + type: z5.literal("subscribe"), + eventName: z5.string(), + connId: z5.string() + }), + z5.object({ + type: z5.literal("unsubscribe"), + eventName: z5.string(), + connId: z5.string() + }), + z5.object({ + type: z5.literal("event"), + eventName: z5.string(), + args: z5.array(z5.any()), + connId: z5.string() + }) +]); +var RecordedRealtimeEventSchema = RealtimeEventSchema.and( + z5.object({ + id: z5.string(), + timestamp: z5.number() + }) +); +var DatabaseQuerySchema = z5.object({ + sql: z5.string(), + args: z5.array(z5.string().or(z5.number())) +}); +var TableSchema = z5.object({ + schema: z5.string(), + name: z5.string(), + type: z5.enum(["table", "view"]) +}); +var TablesSchema = z5.array(TableSchema); +var ColumnSchema = z5.object({ + cid: z5.number(), + name: z5.string(), + type: z5.string().toLowerCase().transform((val) => { + return z5.enum(["integer", "text", "real", "blob", "numeric", "serial"]).parse(val); + }), + notnull: z5.coerce.boolean(), + dflt_value: z5.string().nullable(), + pk: z5.coerce.boolean().nullable() +}); +var ColumnsSchema = z5.array(ColumnSchema); +var ForeignKeySchema = z5.object({ + id: z5.number(), + table: z5.string(), + from: z5.string(), + to: z5.string() +}); +var ForeignKeysSchema = z5.array(ForeignKeySchema); +var BuildSchema = z5.object({ + name: z5.string(), + createdAt: z5.string().optional(), + tags: z5.record(z5.string(), z5.string()).optional() +}); +var BuildsSchema = z5.array(BuildSchema); +var CreateActorSchema = z5.object({ + name: z5.string(), + // FIXME: Replace with ActorKeySchema when ready + key: z5.array(z5.string().max(MAX_ACTOR_KEY_SIZE)), + input: z5.any() +}); + +// src/inspector/actor.ts +function createActorInspectorRouter() { + return new Hono().get("/ping", (c) => { + return c.json({ message: "pong" }, 200); + }).get("/state", async (c) => { + if (await c.var.inspector.accessors.isStateEnabled()) { + return c.json( + { + enabled: true, + state: await c.var.inspector.accessors.getState() + }, + 200 + ); + } + return c.json({ enabled: false, state: null }, 200); + }).patch( + "/state", + sValidator( + "json", + z6.object({ patch: PatchSchema }).or(z6.object({ replace: z6.any() })) + ), + async (c) => { + if (!await c.var.inspector.accessors.isStateEnabled()) { + return c.json({ enabled: false }, 200); + } + const body = c.req.valid("json"); + if ("replace" in body) { + await c.var.inspector.accessors.setState(body.replace); + return c.json( + { + enabled: true, + state: await c.var.inspector.accessors.getState() + }, + 200 + ); + } + const state = await c.var.inspector.accessors.getState(); + const { newDocument: newState } = jsonPatch.applyPatch( + state, + body.patch + ); + await c.var.inspector.accessors.setState(newState); + return c.json( + { enabled: true, state: await c.var.inspector.accessors.getState() }, + 200 + ); + } + ).get("/state/stream", async (c) => { + if (!await c.var.inspector.accessors.isStateEnabled()) { + return c.json({ enabled: false }, 200); + } + let id = 0; + let unsub; + return streamSSE2( + c, + async (stream) => { + unsub = c.var.inspector.emitter.on("stateUpdated", async (state) => { + stream.writeSSE({ + data: JSON.stringify(state) || "", + event: "state-update", + id: String(id++) + }); + }); + const { promise } = Promise.withResolvers(); + return promise; + }, + async () => { + unsub?.(); + } + ); + }).get("/connections", async (c) => { + const connections = await c.var.inspector.accessors.getConnections(); + return c.json({ connections }, 200); + }).get("/connections/stream", async (c) => { + let id = 0; + let unsub; + return streamSSE2( + c, + async (stream) => { + unsub = c.var.inspector.emitter.on("connectionUpdated", async () => { + stream.writeSSE({ + data: JSON.stringify( + await c.var.inspector.accessors.getConnections() + ), + event: "connection-update", + id: String(id++) + }); + }); + const { promise } = Promise.withResolvers(); + return promise; + }, + async () => { + unsub?.(); + } + ); + }).get("/events", async (c) => { + const events = c.var.inspector.lastRealtimeEvents; + return c.json({ events }, 200); + }).post("/events/clear", async (c) => { + c.var.inspector.lastRealtimeEvents.length = 0; + return c.json({ message: "Events cleared" }, 200); + }).get("/events/stream", async (c) => { + let id = 0; + let unsub; + return streamSSE2( + c, + async (stream) => { + unsub = c.var.inspector.emitter.on("eventFired", () => { + stream.writeSSE({ + data: JSON.stringify(c.var.inspector.lastRealtimeEvents), + event: "realtime-event", + id: String(id++) + }); + }); + const { promise } = Promise.withResolvers(); + return promise; + }, + async () => { + unsub?.(); + } + ); + }).get("/rpcs", async (c) => { + const rpcs = await c.var.inspector.accessors.getRpcs(); + return c.json({ rpcs }, 200); + }).get("/db", async (c) => { + if (!await c.var.inspector.accessors.isDbEnabled()) { + return c.json({ enabled: false, db: null }, 200); + } + const db = await c.var.inspector.accessors.getDb(); + const rows = await db.execute(`PRAGMA table_list`); + const tables = TablesSchema.parse(rows).filter( + (table) => table.schema !== "temp" && !table.name.startsWith("sqlite_") + ); + const tablesInfo = await Promise.all( + tables.map((table) => db.execute(`PRAGMA table_info(${table.name})`)) + ); + const columns = tablesInfo.map((def) => ColumnsSchema.parse(def)); + const foreignKeysList = await Promise.all( + tables.map( + (table) => db.execute(`PRAGMA foreign_key_list(${table.name})`) + ) + ); + const foreignKeys = foreignKeysList.map( + (def) => ForeignKeysSchema.parse(def) + ); + const countInfo = await Promise.all( + tables.map( + (table) => db.execute(`SELECT COUNT(*) as count FROM ${table.name}`) + ) + ); + const counts = countInfo.map((def) => { + return def[0].count || 0; + }); + return c.json( + { + enabled: true, + db: tablesInfo.map((_, index) => { + return { + table: tables[index], + columns: columns[index], + foreignKeys: foreignKeys[index], + records: counts[index] + }; + }) + }, + 200 + ); + }).post( + "/db", + sValidator( + "json", + z6.object({ query: z6.string(), params: z6.array(z6.any()).optional() }) + ), + async (c) => { + if (!await c.var.inspector.accessors.isDbEnabled()) { + return c.json({ enabled: false }, 200); + } + const db = await c.var.inspector.accessors.getDb(); + try { + const result = await db.execute( + c.req.valid("json").query, + ...c.req.valid("json").params || [] + ); + return c.json({ result }, 200); + } catch (error) { + c; + return c.json({ error: error.message }, 500); + } + } + ); +} +var ActorInspector = class { + accessors; + emitter = createNanoEvents(); + #lastRealtimeEvents = []; + get lastRealtimeEvents() { + return this.#lastRealtimeEvents; + } + constructor(accessors) { + this.accessors = accessors(); + this.emitter.on("eventFired", (event) => { + this.#lastRealtimeEvents.push({ + id: crypto.randomUUID(), + timestamp: Date.now(), + ...event + }); + if (this.#lastRealtimeEvents.length > 100) { + this.#lastRealtimeEvents = this.#lastRealtimeEvents.slice(-100); + } + }); + } +}; + +// dist/schemas/actor-persist/v1.ts +import * as bare2 from "@bare-ts/lib"; +var config2 = /* @__PURE__ */ bare2.Config({}); +function readPersistedSubscription(bc) { + return { + eventName: bare2.readString(bc) + }; +} +function writePersistedSubscription(bc, x) { + bare2.writeString(bc, x.eventName); +} +function read02(bc) { + return bare2.readBool(bc) ? bare2.readData(bc) : null; +} +function write02(bc, x) { + bare2.writeBool(bc, x !== null); + if (x !== null) { + bare2.writeData(bc, x); + } +} +function read12(bc) { + const len = bare2.readUintSafe(bc); + if (len === 0) { + return []; + } + const result = [readPersistedSubscription(bc)]; + for (let i = 1; i < len; i++) { + result[i] = readPersistedSubscription(bc); + } + return result; +} +function write12(bc, x) { + bare2.writeUintSafe(bc, x.length); + for (let i = 0; i < x.length; i++) { + writePersistedSubscription(bc, x[i]); + } +} +function readPersistedConnection(bc) { + return { + id: bare2.readString(bc), + token: bare2.readString(bc), + driver: bare2.readString(bc), + driverState: bare2.readData(bc), + parameters: bare2.readData(bc), + state: bare2.readData(bc), + auth: read02(bc), + subscriptions: read12(bc), + lastSeen: bare2.readU64(bc) + }; +} +function writePersistedConnection(bc, x) { + bare2.writeString(bc, x.id); + bare2.writeString(bc, x.token); + bare2.writeString(bc, x.driver); + bare2.writeData(bc, x.driverState); + bare2.writeData(bc, x.parameters); + bare2.writeData(bc, x.state); + write02(bc, x.auth); + write12(bc, x.subscriptions); + bare2.writeU64(bc, x.lastSeen); +} +function readGenericPersistedScheduleEvent(bc) { + return { + action: bare2.readString(bc), + args: read02(bc) + }; +} +function writeGenericPersistedScheduleEvent(bc, x) { + bare2.writeString(bc, x.action); + write02(bc, x.args); +} +function readPersistedScheduleEventKind(bc) { + const offset = bc.offset; + const tag = bare2.readU8(bc); + switch (tag) { + case 0: + return { tag: "GenericPersistedScheduleEvent", val: readGenericPersistedScheduleEvent(bc) }; + default: { + bc.offset = offset; + throw new bare2.BareError(offset, "invalid tag"); + } + } +} +function writePersistedScheduleEventKind(bc, x) { + switch (x.tag) { + case "GenericPersistedScheduleEvent": { + bare2.writeU8(bc, 0); + writeGenericPersistedScheduleEvent(bc, x.val); + break; + } + } +} +function readPersistedScheduleEvent(bc) { + return { + eventId: bare2.readString(bc), + timestamp: bare2.readU64(bc), + kind: readPersistedScheduleEventKind(bc) + }; +} +function writePersistedScheduleEvent(bc, x) { + bare2.writeString(bc, x.eventId); + bare2.writeU64(bc, x.timestamp); + writePersistedScheduleEventKind(bc, x.kind); +} +function read2(bc) { + const len = bare2.readUintSafe(bc); + if (len === 0) { + return []; + } + const result = [readPersistedConnection(bc)]; + for (let i = 1; i < len; i++) { + result[i] = readPersistedConnection(bc); + } + return result; +} +function write2(bc, x) { + bare2.writeUintSafe(bc, x.length); + for (let i = 0; i < x.length; i++) { + writePersistedConnection(bc, x[i]); + } +} +function read3(bc) { + const len = bare2.readUintSafe(bc); + if (len === 0) { + return []; + } + const result = [readPersistedScheduleEvent(bc)]; + for (let i = 1; i < len; i++) { + result[i] = readPersistedScheduleEvent(bc); + } + return result; +} +function write3(bc, x) { + bare2.writeUintSafe(bc, x.length); + for (let i = 0; i < x.length; i++) { + writePersistedScheduleEvent(bc, x[i]); + } +} +function readPersistedActor(bc) { + return { + input: read02(bc), + hasInitialized: bare2.readBool(bc), + state: bare2.readData(bc), + connections: read2(bc), + scheduledEvents: read3(bc) + }; +} +function writePersistedActor(bc, x) { + write02(bc, x.input); + bare2.writeBool(bc, x.hasInitialized); + bare2.writeData(bc, x.state); + write2(bc, x.connections); + write3(bc, x.scheduledEvents); +} +function encodePersistedActor(x) { + const bc = new bare2.ByteCursor( + new Uint8Array(config2.initialBufferLength), + config2 + ); + writePersistedActor(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodePersistedActor(bytes) { + const bc = new bare2.ByteCursor(bytes, config2); + const result = readPersistedActor(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare2.BareError(bc.offset, "remaining bytes"); + } + return result; +} + +// src/schemas/actor-persist/versioned.ts +var CURRENT_VERSION2 = 1; +var migrations2 = /* @__PURE__ */ new Map(); +var PERSISTED_ACTOR_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION2, + migrations: migrations2, + serializeVersion: (data) => encodePersistedActor(data), + deserializeVersion: (bytes) => decodePersistedActor(bytes) +}); + +// src/actor/context.ts +var ActorContext = class { + #actor; + constructor(actor2) { + this.#actor = actor2; + } + /** + * Get the actor state + */ + get state() { + return this.#actor.state; + } + /** + * Get the actor variables + */ + get vars() { + return this.#actor.vars; + } + /** + * Broadcasts an event to all connected clients. + * @param name - The name of the event. + * @param args - The arguments to send with the event. + */ + broadcast(name, ...args) { + this.#actor._broadcast(name, ...args); + return; + } + /** + * Gets the logger instance. + */ + get log() { + return this.#actor.log; + } + /** + * Gets actor ID. + */ + get actorId() { + return this.#actor.id; + } + /** + * Gets the actor name. + */ + get name() { + return this.#actor.name; + } + /** + * Gets the actor key. + */ + get key() { + return this.#actor.key; + } + /** + * Gets the region. + */ + get region() { + return this.#actor.region; + } + /** + * Gets the scheduler. + */ + get schedule() { + return this.#actor.schedule; + } + /** + * Gets the map of connections. + */ + get conns() { + return this.#actor.conns; + } + /** + * Returns the client for the given registry. + */ + client() { + return this.#actor.inlineClient; + } + /** + * Gets the database. + * @experimental + * @throws {DatabaseNotEnabled} If the database is not enabled. + */ + get db() { + return this.#actor.db; + } + /** + * Forces the state to get saved. + * + * @param opts - Options for saving the state. + */ + async saveState(opts) { + return this.#actor.saveState(opts); + } + /** + * Prevents the actor from sleeping until promise is complete. + */ + waitUntil(promise) { + this.#actor._waitUntil(promise); + } + /** + * AbortSignal that fires when the actor is stopping. + */ + get abortSignal() { + return this.#actor.abortSignal; + } + /** + * Forces the actor to sleep. + * + * Not supported on all drivers. + * + * @experimental + */ + sleep() { + this.#actor._sleep(); + } +}; + +// src/actor/schedule.ts +var Schedule = class { + #actor; + constructor(actor2) { + this.#actor = actor2; + } + async after(duration, fn, ...args) { + await this.#actor.scheduleEvent(Date.now() + duration, fn, args); + } + async at(timestamp, fn, ...args) { + await this.#actor.scheduleEvent(timestamp, fn, args); + } +}; + +// src/actor/instance.ts +var ActorInstance = class { + // Shared actor context for this instance + actorContext; + #sleepCalled = false; + #stopCalled = false; + get isStopping() { + return this.#stopCalled || this.#sleepCalled; + } + #persistChanged = false; + #isInOnStateChange = false; + /** + * The proxied state that notifies of changes automatically. + * + * Any data that should be stored indefinitely should be held within this object. + */ + #persist; + /** Raw state without the proxy wrapper */ + #persistRaw; + #persistWriteQueue = new SinglePromiseQueue(); + #alarmWriteQueue = new SinglePromiseQueue(); + #lastSaveTime = 0; + #pendingSaveTimeout; + #vars; + #backgroundPromises = []; + #abortController = new AbortController(); + #config; + #connectionDrivers; + #actorDriver; + #inlineClient; + #actorId; + #name; + #key; + #region; + #ready = false; + #connections = /* @__PURE__ */ new Map(); + #subscriptionIndex = /* @__PURE__ */ new Map(); + #checkConnLivenessInterval; + #sleepTimeout; + // Track active raw requests so sleep logic can account for them + #activeRawFetchCount = 0; + #activeRawWebSockets = /* @__PURE__ */ new Set(); + #schedule; + #db; + #inspector = new ActorInspector(() => { + return { + isDbEnabled: async () => { + return this.#db !== void 0; + }, + getDb: async () => { + return this.db; + }, + isStateEnabled: async () => { + return this.stateEnabled; + }, + getState: async () => { + this.#validateStateEnabled(); + return this.#persistRaw.state; + }, + getRpcs: async () => { + return Object.keys(this.#config.actions); + }, + getConnections: async () => { + return Array.from(this.#connections.entries()).map(([id, conn]) => ({ + id, + stateEnabled: conn._stateEnabled, + params: conn.params, + state: conn._stateEnabled ? conn.state : void 0, + auth: conn.auth + })); + }, + setState: async (state) => { + this.#validateStateEnabled(); + this.#persist.state = { ...state }; + await this.saveState({ immediate: true }); + } + }; + }); + get id() { + return this.#actorId; + } + get inlineClient() { + return this.#inlineClient; + } + get inspector() { + return this.#inspector; + } + get #sleepingSupported() { + return this.#actorDriver.sleep !== void 0; + } + /** + * This constructor should never be used directly. + * + * Constructed in {@link ActorInstance.start}. + * + * @private + */ + constructor(config4) { + this.#config = config4; + this.actorContext = new ActorContext(this); + } + async start(connectionDrivers, actorDriver, inlineClient, actorId, name, key, region) { + this.#connectionDrivers = connectionDrivers; + this.#actorDriver = actorDriver; + this.#inlineClient = inlineClient; + this.#actorId = actorId; + this.#name = name; + this.#key = key; + this.#region = region; + this.#schedule = new Schedule(this); + await this.#initialize(); + if (this.#varsEnabled) { + let vars; + if ("createVars" in this.#config) { + const dataOrPromise = this.#config.createVars( + this.actorContext, + this.#actorDriver.getContext(this.#actorId) + ); + if (dataOrPromise instanceof Promise) { + vars = await deadline( + dataOrPromise, + this.#config.options.createVarsTimeout + ); + } else { + vars = dataOrPromise; + } + } else if ("vars" in this.#config) { + vars = structuredClone(this.#config.vars); + } else { + throw new Error("Could not variables from 'createVars' or 'vars'"); + } + this.#vars = vars; + } + logger().info("actor starting"); + if (this.#config.onStart) { + const result = this.#config.onStart(this.actorContext); + if (result instanceof Promise) { + await result; + } + } + if ("db" in this.#config && this.#config.db) { + const client = await this.#config.db.createClient({ + getDatabase: () => actorDriver.getDatabase(this.#actorId) + }); + logger().info("database migration starting"); + await this.#config.db.onMigrate?.(client); + logger().info("database migration complete"); + this.#db = client; + } + if (this.#persist.scheduledEvents.length > 0) { + await this.#queueSetAlarm(this.#persist.scheduledEvents[0].timestamp); + } + logger().info("actor ready"); + this.#ready = true; + this.#resetSleepTimer(); + this.#checkConnLivenessInterval = setInterval( + this.#checkConnectionsLiveness.bind(this), + this.#config.options.connectionLivenessInterval + ); + this.#checkConnectionsLiveness(); + } + async #scheduleEventInner(newEvent) { + this.actorContext.log.info("scheduling event", newEvent); + const insertIndex = this.#persist.scheduledEvents.findIndex( + (x) => x.timestamp > newEvent.timestamp + ); + if (insertIndex === -1) { + this.#persist.scheduledEvents.push(newEvent); + } else { + this.#persist.scheduledEvents.splice(insertIndex, 0, newEvent); + } + if (insertIndex === 0 || this.#persist.scheduledEvents.length === 1) { + this.actorContext.log.info("setting alarm", { + timestamp: newEvent.timestamp, + eventCount: this.#persist.scheduledEvents.length + }); + await this.#queueSetAlarm(newEvent.timestamp); + } + } + async _onAlarm() { + const now = Date.now(); + this.actorContext.log.debug("alarm triggered", { + now, + events: this.#persist.scheduledEvents.length + }); + this.#resetSleepTimer(); + const runIndex = this.#persist.scheduledEvents.findIndex( + (x) => x.timestamp <= now + ); + if (runIndex === -1) { + logger().warn("no events are due yet, time may have broken"); + if (this.#persist.scheduledEvents.length > 0) { + const nextTs = this.#persist.scheduledEvents[0].timestamp; + this.actorContext.log.warn( + "alarm fired early, rescheduling for next event", + { + now, + nextTs, + delta: nextTs - now + } + ); + await this.#queueSetAlarm(nextTs); + } + this.actorContext.log.debug("no events to run", { now }); + return; + } + const scheduleEvents = this.#persist.scheduledEvents.splice( + 0, + runIndex + 1 + ); + this.actorContext.log.debug("running events", { + count: scheduleEvents.length + }); + if (this.#persist.scheduledEvents.length > 0) { + const nextTs = this.#persist.scheduledEvents[0].timestamp; + this.actorContext.log.info("setting next alarm", { + nextTs, + remainingEvents: this.#persist.scheduledEvents.length + }); + await this.#queueSetAlarm(nextTs); + } + for (const event of scheduleEvents) { + try { + this.actorContext.log.info("running action for event", { + event: event.eventId, + timestamp: event.timestamp, + action: event.kind.generic.actionName + }); + const fn = this.#config.actions[event.kind.generic.actionName]; + if (!fn) + throw new Error( + `Missing action for alarm ${event.kind.generic.actionName}` + ); + if (typeof fn !== "function") + throw new Error( + `Alarm function lookup for ${event.kind.generic.actionName} returned ${typeof fn}` + ); + try { + const args = event.kind.generic.args ? cbor5.decode(new Uint8Array(event.kind.generic.args)) : []; + await fn.call(void 0, this.actorContext, ...args); + } catch (error) { + this.actorContext.log.error("error while running event", { + error: stringifyError(error), + event: event.eventId, + timestamp: event.timestamp, + action: event.kind.generic.actionName + }); + } + } catch (error) { + this.actorContext.log.error("internal error while running event", { + error: stringifyError(error), + ...event + }); + } + } + } + async scheduleEvent(timestamp, action, args) { + return this.#scheduleEventInner({ + eventId: crypto.randomUUID(), + timestamp, + kind: { + generic: { + actionName: action, + args: bufferToArrayBuffer(cbor5.encode(args)) + } + } + }); + } + get stateEnabled() { + return "createState" in this.#config || "state" in this.#config; + } + #validateStateEnabled() { + if (!this.stateEnabled) { + throw new StateNotEnabled(); + } + } + get #connStateEnabled() { + return "createConnState" in this.#config || "connState" in this.#config; + } + get #varsEnabled() { + return "createVars" in this.#config || "vars" in this.#config; + } + #validateVarsEnabled() { + if (!this.#varsEnabled) { + throw new VarsNotEnabled(); + } + } + /** Promise used to wait for a save to complete. This is required since you cannot await `#saveStateThrottled`. */ + #onPersistSavedPromise; + /** Throttled save state method. Used to write to KV at a reasonable cadence. */ + #savePersistThrottled() { + const now = Date.now(); + const timeSinceLastSave = now - this.#lastSaveTime; + const saveInterval = this.#config.options.stateSaveInterval; + if (timeSinceLastSave < saveInterval) { + if (this.#pendingSaveTimeout === void 0) { + this.#pendingSaveTimeout = setTimeout(() => { + this.#pendingSaveTimeout = void 0; + this.#savePersistInner(); + }, saveInterval - timeSinceLastSave); + } + } else { + this.#savePersistInner(); + } + } + /** Saves the state to KV. You probably want to use #saveStateThrottled instead except for a few edge cases. */ + async #savePersistInner() { + try { + this.#lastSaveTime = Date.now(); + if (this.#persistChanged) { + const finished = this.#persistWriteQueue.enqueue(async () => { + logger().debug("saving persist"); + this.#persistChanged = false; + const bareData = this.#convertToBarePersisted(this.#persistRaw); + await this.#actorDriver.writePersistedData( + this.#actorId, + PERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(bareData) + ); + logger().debug("persist saved"); + }); + await finished; + } + this.#onPersistSavedPromise?.resolve(); + } catch (error) { + this.#onPersistSavedPromise?.reject(error); + throw error; + } + } + async #queueSetAlarm(timestamp) { + await this.#alarmWriteQueue.enqueue(async () => { + await this.#actorDriver.setAlarm(this, timestamp); + }); + } + /** + * Creates proxy for `#persist` that handles automatically flagging when state needs to be updated. + */ + #setPersist(target) { + this.#persistRaw = target; + if (target === null || typeof target !== "object") { + let invalidPath = ""; + if (!isCborSerializable( + target, + (path3) => { + invalidPath = path3; + }, + "" + )) { + throw new InvalidStateType({ path: invalidPath }); + } + return target; + } + if (this.#persist) { + onChange.unsubscribe(this.#persist); + } + this.#persist = onChange( + target, + // biome-ignore lint/suspicious/noExplicitAny: Don't know types in proxy + (path3, value, _previousValue, _applyData) => { + if (path3 !== "state" && !path3.startsWith("state.")) { + return; + } + let invalidPath = ""; + if (!isCborSerializable( + value, + (invalidPathPart) => { + invalidPath = invalidPathPart; + }, + "" + )) { + throw new InvalidStateType({ + path: path3 + (invalidPath ? `.${invalidPath}` : "") + }); + } + this.#persistChanged = true; + this.inspector.emitter.emit("stateUpdated", this.#persist.state); + if (this.#config.onStateChange && this.#ready && !this.#isInOnStateChange) { + try { + this.#isInOnStateChange = true; + this.#config.onStateChange( + this.actorContext, + this.#persistRaw.state + ); + } catch (error) { + logger().error("error in `_onStateChange`", { + error: stringifyError(error) + }); + } finally { + this.#isInOnStateChange = false; + } + } + }, + { ignoreDetached: true } + ); + } + async #initialize() { + const persistDataBuffer = await this.#actorDriver.readPersistedData( + this.#actorId + ); + invariant2( + persistDataBuffer !== void 0, + "persist data has not been set, it should be set when initialized" + ); + const bareData = PERSISTED_ACTOR_VERSIONED.deserializeWithEmbeddedVersion( + persistDataBuffer + ); + const persistData = this.#convertFromBarePersisted(bareData); + if (persistData.hasInitiated) { + logger().info("actor restoring", { + connections: persistData.connections.length + }); + this.#setPersist(persistData); + for (const connPersist of this.#persist.connections) { + const driver = this.__getConnDriver(connPersist.connDriver); + const conn = new Conn( + this, + connPersist, + driver, + this.#connStateEnabled + ); + this.#connections.set(conn.id, conn); + for (const sub of connPersist.subscriptions) { + this.#addSubscription(sub.eventName, conn, true); + } + } + } else { + logger().info("actor creating"); + let stateData; + if (this.stateEnabled) { + logger().info("actor state initializing"); + if ("createState" in this.#config) { + this.#config.createState; + stateData = await this.#config.createState( + this.actorContext, + persistData.input + ); + } else if ("state" in this.#config) { + stateData = structuredClone(this.#config.state); + } else { + throw new Error("Both 'createState' or 'state' were not defined"); + } + } else { + logger().debug("state not enabled"); + } + persistData.state = stateData; + persistData.hasInitiated = true; + logger().debug("writing state"); + const bareData2 = this.#convertToBarePersisted(persistData); + await this.#actorDriver.writePersistedData( + this.#actorId, + PERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(bareData2) + ); + this.#setPersist(persistData); + if (this.#config.onCreate) { + await this.#config.onCreate(this.actorContext, persistData.input); + } + } + } + __getConnForId(id) { + return this.#connections.get(id); + } + /** + * Removes a connection and cleans up its resources. + */ + __removeConn(conn) { + if (!conn) { + logger().warn("`conn` does not exist"); + return; + } + const connIdx = this.#persist.connections.findIndex( + (c) => c.connId === conn.id + ); + if (connIdx !== -1) { + this.#persist.connections.splice(connIdx, 1); + this.saveState({ immediate: true, allowStoppingState: true }); + } else { + logger().warn("could not find persisted connection to remove", { + connId: conn.id + }); + } + this.#connections.delete(conn.id); + for (const eventName of [...conn.subscriptions.values()]) { + this.#removeSubscription(eventName, conn, true); + } + this.inspector.emitter.emit("connectionUpdated"); + if (this.#config.onDisconnect) { + try { + const result = this.#config.onDisconnect(this.actorContext, conn); + if (result instanceof Promise) { + result.catch((error) => { + logger().error("error in `onDisconnect`", { + error: stringifyError(error) + }); + }); + } + } catch (error) { + logger().error("error in `onDisconnect`", { + error: stringifyError(error) + }); + } + } + this.#resetSleepTimer(); + } + async prepareConn(params, request) { + let connState; + const onBeforeConnectOpts = { + request + }; + if (this.#config.onBeforeConnect) { + await this.#config.onBeforeConnect( + this.actorContext, + onBeforeConnectOpts, + params + ); + } + if (this.#connStateEnabled) { + if ("createConnState" in this.#config) { + const dataOrPromise = this.#config.createConnState( + this.actorContext, + onBeforeConnectOpts, + params + ); + if (dataOrPromise instanceof Promise) { + connState = await deadline( + dataOrPromise, + this.#config.options.createConnStateTimeout + ); + } else { + connState = dataOrPromise; + } + } else if ("connState" in this.#config) { + connState = structuredClone(this.#config.connState); + } else { + throw new Error( + "Could not create connection state from 'createConnState' or 'connState'" + ); + } + } + return connState; + } + __getConnDriver(driverId) { + const driver = this.#connectionDrivers[driverId]; + if (!driver) throw new Error(`No connection driver: ${driverId}`); + return driver; + } + /** + * Called after establishing a connection handshake. + */ + async createConn(connectionId, connectionToken, params, state, driverId, driverState, authData) { + this.#assertReady(); + if (this.#connections.has(connectionId)) { + throw new Error(`Connection already exists: ${connectionId}`); + } + const driver = this.__getConnDriver(driverId); + const persist = { + connId: connectionId, + token: connectionToken, + connDriver: driverId, + connDriverState: driverState, + params, + state, + authData, + lastSeen: Date.now(), + subscriptions: [] + }; + const conn = new Conn( + this, + persist, + driver, + this.#connStateEnabled + ); + this.#connections.set(conn.id, conn); + this.#resetSleepTimer(); + this.#persist.connections.push(persist); + this.saveState({ immediate: true }); + if (this.#config.onConnect) { + try { + const result = this.#config.onConnect(this.actorContext, conn); + if (result instanceof Promise) { + deadline(result, this.#config.options.onConnectTimeout).catch( + (error) => { + logger().error("error in `onConnect`, closing socket", { + error + }); + conn?.disconnect("`onConnect` failed"); + } + ); + } + } catch (error) { + logger().error("error in `onConnect`", { + error: stringifyError(error) + }); + conn?.disconnect("`onConnect` failed"); + } + } + this.inspector.emitter.emit("connectionUpdated"); + conn._sendMessage( + new CachedSerializer( + { + body: { + tag: "Init", + val: { + actorId: this.id, + connectionId: conn.id, + connectionToken: conn._token + } + } + }, + TO_CLIENT_VERSIONED + ) + ); + return conn; + } + // MARK: Messages + async processMessage(message, conn) { + await processMessage(message, this, conn, { + onExecuteAction: async (ctx, name, args) => { + this.inspector.emitter.emit("eventFired", { + type: "action", + name, + args, + connId: conn.id + }); + return await this.executeAction(ctx, name, args); + }, + onSubscribe: async (eventName, conn2) => { + this.inspector.emitter.emit("eventFired", { + type: "subscribe", + eventName, + connId: conn2.id + }); + this.#addSubscription(eventName, conn2, false); + }, + onUnsubscribe: async (eventName, conn2) => { + this.inspector.emitter.emit("eventFired", { + type: "unsubscribe", + eventName, + connId: conn2.id + }); + this.#removeSubscription(eventName, conn2, false); + } + }); + } + // MARK: Events + #addSubscription(eventName, connection, fromPersist) { + if (connection.subscriptions.has(eventName)) { + logger().debug("connection already has subscription", { eventName }); + return; + } + if (!fromPersist) { + connection.__persist.subscriptions.push({ eventName }); + this.saveState({ immediate: true }); + } + connection.subscriptions.add(eventName); + let subscribers = this.#subscriptionIndex.get(eventName); + if (!subscribers) { + subscribers = /* @__PURE__ */ new Set(); + this.#subscriptionIndex.set(eventName, subscribers); + } + subscribers.add(connection); + } + #removeSubscription(eventName, connection, fromRemoveConn) { + if (!connection.subscriptions.has(eventName)) { + logger().warn("connection does not have subscription", { eventName }); + return; + } + if (!fromRemoveConn) { + connection.subscriptions.delete(eventName); + const subIdx = connection.__persist.subscriptions.findIndex( + (s) => s.eventName === eventName + ); + if (subIdx !== -1) { + connection.__persist.subscriptions.splice(subIdx, 1); + } else { + logger().warn("subscription does not exist with name", { eventName }); + } + this.saveState({ immediate: true }); + } + const subscribers = this.#subscriptionIndex.get(eventName); + if (subscribers) { + subscribers.delete(connection); + if (subscribers.size === 0) { + this.#subscriptionIndex.delete(eventName); + } + } + } + #assertReady(allowStoppingState = false) { + if (!this.#ready) throw new InternalError("Actor not ready"); + if (!allowStoppingState && this.#sleepCalled) + throw new InternalError("Actor is going to sleep"); + if (!allowStoppingState && this.#stopCalled) + throw new InternalError("Actor is stopping"); + } + /** + * Check the liveness of all connections. + * Sets up a recurring check based on the configured interval. + */ + #checkConnectionsLiveness() { + logger().debug("checking connections liveness"); + for (const conn of this.#connections.values()) { + const liveness = conn[CONNECTION_CHECK_LIVENESS_SYMBOL](); + if (liveness.status === "connected") { + logger().debug("connection is alive", { connId: conn.id }); + } else { + const lastSeen = liveness.lastSeen; + const sinceLastSeen = Date.now() - lastSeen; + if (sinceLastSeen < this.#config.options.connectionLivenessTimeout) { + logger().debug("connection might be alive, will check later", { + connId: conn.id, + lastSeen, + sinceLastSeen + }); + continue; + } + logger().warn("connection is dead, removing", { + connId: conn.id, + lastSeen + }); + this.__removeConn(conn); + } + } + } + /** + * Check if the actor is ready to handle requests. + */ + isReady() { + return this.#ready; + } + /** + * Execute an action call from a client. + * + * This method handles: + * 1. Validating the action name + * 2. Executing the action function + * 3. Processing the result through onBeforeActionResponse (if configured) + * 4. Handling timeouts and errors + * 5. Saving state changes + * + * @param ctx The action context + * @param actionName The name of the action being called + * @param args The arguments passed to the action + * @returns The result of the action call + * @throws {ActionNotFound} If the action doesn't exist + * @throws {ActionTimedOut} If the action times out + * @internal + */ + async executeAction(ctx, actionName, args) { + invariant2(this.#ready, "executing action before ready"); + if (!(actionName in this.#config.actions)) { + logger().warn("action does not exist", { actionName }); + throw new ActionNotFound(actionName); + } + const actionFunction = this.#config.actions[actionName]; + if (typeof actionFunction !== "function") { + logger().warn("action is not a function", { + actionName, + type: typeof actionFunction + }); + throw new ActionNotFound(actionName); + } + try { + logger().debug("executing action", { actionName, args }); + const outputOrPromise = actionFunction.call(void 0, ctx, ...args); + let output; + if (outputOrPromise instanceof Promise) { + logger().debug("awaiting async action", { actionName }); + output = await deadline( + outputOrPromise, + this.#config.options.actionTimeout + ); + logger().debug("async action completed", { actionName }); + } else { + output = outputOrPromise; + } + if (this.#config.onBeforeActionResponse) { + try { + const processedOutput = this.#config.onBeforeActionResponse( + this.actorContext, + actionName, + args, + output + ); + if (processedOutput instanceof Promise) { + logger().debug("awaiting onBeforeActionResponse", { + actionName + }); + output = await processedOutput; + logger().debug("onBeforeActionResponse completed", { + actionName + }); + } else { + output = processedOutput; + } + } catch (error) { + logger().error("error in `onBeforeActionResponse`", { + error: stringifyError(error) + }); + } + } + logger().debug("action completed", { + actionName, + outputType: typeof output, + isPromise: output instanceof Promise + }); + return output; + } catch (error) { + if (error instanceof DeadlineError) { + throw new ActionTimedOut(); + } + logger().error("action error", { + actionName, + error: stringifyError(error) + }); + throw error; + } finally { + this.#savePersistThrottled(); + } + } + /** + * Returns a list of action methods available on this actor. + */ + get actions() { + return Object.keys(this.#config.actions); + } + /** + * Handles raw HTTP requests to the actor. + */ + async handleFetch(request, opts) { + this.#assertReady(); + if (!this.#config.onFetch) { + throw new FetchHandlerNotDefined(); + } + this.#activeRawFetchCount++; + this.#resetSleepTimer(); + try { + const response = await this.#config.onFetch( + this.actorContext, + request, + opts + ); + if (!response) { + throw new InvalidFetchResponse(); + } + return response; + } catch (error) { + logger().error("onFetch error", { + error: stringifyError(error) + }); + throw error; + } finally { + this.#activeRawFetchCount = Math.max(0, this.#activeRawFetchCount - 1); + this.#resetSleepTimer(); + this.#savePersistThrottled(); + } + } + /** + * Handles raw WebSocket connections to the actor. + */ + async handleWebSocket(websocket, opts) { + this.#assertReady(); + if (!this.#config.onWebSocket) { + throw new InternalError("onWebSocket handler not defined"); + } + try { + const stateBeforeHandler = this.#persistChanged; + this.#activeRawWebSockets.add(websocket); + this.#resetSleepTimer(); + const onSocketClosed = () => { + try { + websocket.removeEventListener("close", onSocketClosed); + websocket.removeEventListener("error", onSocketClosed); + } catch { + } + this.#activeRawWebSockets.delete(websocket); + this.#resetSleepTimer(); + }; + try { + websocket.addEventListener("close", onSocketClosed); + websocket.addEventListener("error", onSocketClosed); + } catch { + } + await this.#config.onWebSocket(this.actorContext, websocket, opts); + if (this.#persistChanged && !stateBeforeHandler) { + await this.saveState({ immediate: true }); + } + } catch (error) { + logger().error("onWebSocket error", { + error: stringifyError(error) + }); + throw error; + } finally { + this.#savePersistThrottled(); + } + } + // MARK: Lifecycle hooks + // MARK: Exposed methods + /** + * Gets the logger instance. + */ + get log() { + return instanceLogger(); + } + /** + * Gets the name. + */ + get name() { + return this.#name; + } + /** + * Gets the key. + */ + get key() { + return this.#key; + } + /** + * Gets the region. + */ + get region() { + return this.#region; + } + /** + * Gets the scheduler. + */ + get schedule() { + return this.#schedule; + } + /** + * Gets the map of connections. + */ + get conns() { + return this.#connections; + } + /** + * Gets the current state. + * + * Changing properties of this value will automatically be persisted. + */ + get state() { + this.#validateStateEnabled(); + return this.#persist.state; + } + /** + * Gets the database. + * @experimental + * @throws {DatabaseNotEnabled} If the database is not enabled. + */ + get db() { + if (!this.#db) { + throw new DatabaseNotEnabled(); + } + return this.#db; + } + /** + * Sets the current state. + * + * This property will automatically be persisted. + */ + set state(value) { + this.#validateStateEnabled(); + this.#persist.state = value; + } + get vars() { + this.#validateVarsEnabled(); + invariant2(this.#vars !== void 0, "vars not enabled"); + return this.#vars; + } + /** + * Broadcasts an event to all connected clients. + * @param name - The name of the event. + * @param args - The arguments to send with the event. + */ + _broadcast(name, ...args) { + this.#assertReady(); + this.inspector.emitter.emit("eventFired", { + type: "broadcast", + eventName: name, + args + }); + const subscriptions = this.#subscriptionIndex.get(name); + if (!subscriptions) return; + const toClientSerializer = new CachedSerializer( + { + body: { + tag: "Event", + val: { + name, + args: bufferToArrayBuffer(cbor5.encode(args)) + } + } + }, + TO_CLIENT_VERSIONED + ); + for (const connection of subscriptions) { + connection._sendMessage(toClientSerializer); + } + } + /** + * Prevents the actor from sleeping until promise is complete. + * + * This allows the actor runtime to ensure that a promise completes while + * returning from an action request early. + * + * @param promise - The promise to run in the background. + */ + _waitUntil(promise) { + this.#assertReady(); + const nonfailablePromise = promise.then(() => { + logger().debug("wait until promise complete"); + }).catch((error) => { + logger().error("wait until promise failed", { + error: stringifyError(error) + }); + }); + this.#backgroundPromises.push(nonfailablePromise); + } + /** + * Forces the state to get saved. + * + * This is helpful if running a long task that may fail later or when + * running a background job that updates the state. + * + * @param opts - Options for saving the state. + */ + async saveState(opts) { + this.#assertReady(opts.allowStoppingState); + if (this.#persistChanged) { + if (opts.immediate) { + await this.#savePersistInner(); + } else { + if (!this.#onPersistSavedPromise) { + this.#onPersistSavedPromise = Promise.withResolvers(); + } + this.#savePersistThrottled(); + await this.#onPersistSavedPromise.promise; + } + } + } + // MARK: Sleep + /** + * Reset timer from the last actor interaction that allows it to be put to sleep. + * + * This should be called any time a sleep-related event happens: + * - Connection opens (will clear timer) + * - Connection closes (will schedule timer if there are no open connections) + * - Alarm triggers (will reset timer) + * + * We don't need to call this on events like individual action calls, since there will always be a connection open for these. + **/ + #resetSleepTimer() { + if (this.#config.options.noSleep || !this.#sleepingSupported) return; + const canSleep = this.#canSleep(); + logger().debug("resetting sleep timer", { + canSleep, + existingTimeout: !!this.#sleepTimeout + }); + if (this.#sleepTimeout) { + clearTimeout(this.#sleepTimeout); + this.#sleepTimeout = void 0; + } + if (this.#sleepCalled) return; + if (canSleep) { + this.#sleepTimeout = setTimeout(() => { + this._sleep().catch((error) => { + logger().error("error during sleep", { + error: stringifyError(error) + }); + }); + }, this.#config.options.sleepTimeout); + } + } + /** If this actor can be put in a sleeping state. */ + #canSleep() { + if (!this.#ready) return false; + for (const conn of this.#connections.values()) { + if (conn.status === "connected") return false; + } + if (this.#activeRawFetchCount > 0) return false; + if (this.#activeRawWebSockets.size > 0) return false; + return true; + } + /** Puts an actor to sleep. This should just start the sleep sequence, most shutdown logic should be in _stop (which is called by the ActorDriver when sleeping). */ + async _sleep() { + const sleep2 = this.#actorDriver.sleep?.bind( + this.#actorDriver, + this.#actorId + ); + invariant2(this.#sleepingSupported, "sleeping not supported"); + invariant2(sleep2, "no sleep on driver"); + if (this.#sleepCalled) { + logger().warn("already sleeping actor"); + return; + } + this.#sleepCalled = true; + logger().info("actor sleeping"); + setImmediate(async () => { + await sleep2(); + }); + } + // MARK: Stop + async _stop() { + if (this.#stopCalled) { + logger().warn("already stopping actor"); + return; + } + this.#stopCalled = true; + logger().info("actor stopping"); + try { + this.#abortController.abort(); + } catch { + } + if (this.#config.onStop) { + try { + logger().debug("calling onStop"); + const result = this.#config.onStop(this.actorContext); + if (result instanceof Promise) { + await deadline(result, this.#config.options.onStopTimeout); + } + logger().debug("onStop completed"); + } catch (error) { + if (error instanceof DeadlineError) { + logger().error("onStop timed out"); + } else { + logger().error("error in onStop", { + error: stringifyError(error) + }); + } + } + } + const promises = []; + for (const connection of this.#connections.values()) { + promises.push(connection.disconnect()); + } + await this.#waitBackgroundPromises(this.#config.options.waitUntilTimeout); + if (this.#pendingSaveTimeout) clearTimeout(this.#pendingSaveTimeout); + if (this.#sleepTimeout) clearTimeout(this.#sleepTimeout); + if (this.#checkConnLivenessInterval) + clearInterval(this.#checkConnLivenessInterval); + await this.saveState({ immediate: true, allowStoppingState: true }); + const res = Promise.race([ + Promise.all(promises).then(() => false), + new Promise( + (res2) => globalThis.setTimeout(() => res2(true), 1500) + ) + ]); + if (await res) { + logger().warn( + "timed out waiting for connections to close, shutting down anyway" + ); + } + if (this.#persistWriteQueue.runningDrainLoop) + await this.#persistWriteQueue.runningDrainLoop; + if (this.#alarmWriteQueue.runningDrainLoop) + await this.#alarmWriteQueue.runningDrainLoop; + } + /** Abort signal that fires when the actor is stopping. */ + get abortSignal() { + return this.#abortController.signal; + } + /** Wait for background waitUntil promises with a timeout. */ + async #waitBackgroundPromises(timeoutMs) { + const pending = this.#backgroundPromises; + if (pending.length === 0) { + logger().debug("no background promises"); + return; + } + const timedOut = await Promise.race([ + Promise.allSettled(pending).then(() => false), + new Promise( + (resolve) => setTimeout(() => resolve(true), timeoutMs) + ) + ]); + if (timedOut) { + logger().error( + "timed out waiting for background tasks, background promises may have leaked", + { + count: pending.length, + timeoutMs + } + ); + } else { + logger().debug("background promises finished"); + } + } + // MARK: BARE Conversion Helpers + #convertToBarePersisted(persist) { + return { + input: persist.input !== void 0 ? bufferToArrayBuffer(cbor5.encode(persist.input)) : null, + hasInitialized: persist.hasInitiated, + state: bufferToArrayBuffer(cbor5.encode(persist.state)), + connections: persist.connections.map((conn) => ({ + id: conn.connId, + token: conn.token, + driver: conn.connDriver, + driverState: bufferToArrayBuffer( + cbor5.encode(conn.connDriverState || {}) + ), + parameters: bufferToArrayBuffer(cbor5.encode(conn.params || {})), + state: bufferToArrayBuffer(cbor5.encode(conn.state || {})), + auth: conn.authData !== void 0 ? bufferToArrayBuffer(cbor5.encode(conn.authData)) : null, + subscriptions: conn.subscriptions.map((sub) => ({ + eventName: sub.eventName + })), + lastSeen: BigInt(conn.lastSeen) + })), + scheduledEvents: persist.scheduledEvents.map((event) => ({ + eventId: event.eventId, + timestamp: BigInt(event.timestamp), + kind: { + tag: "GenericPersistedScheduleEvent", + val: { + action: event.kind.generic.actionName, + args: event.kind.generic.args ?? null + } + } + })) + }; + } + #convertFromBarePersisted(bareData) { + return { + input: bareData.input ? cbor5.decode(new Uint8Array(bareData.input)) : void 0, + hasInitiated: bareData.hasInitialized, + state: cbor5.decode(new Uint8Array(bareData.state)), + connections: bareData.connections.map((conn) => ({ + connId: conn.id, + token: conn.token, + connDriver: conn.driver, + connDriverState: cbor5.decode(new Uint8Array(conn.driverState)), + params: cbor5.decode(new Uint8Array(conn.parameters)), + state: cbor5.decode(new Uint8Array(conn.state)), + authData: conn.auth ? cbor5.decode(new Uint8Array(conn.auth)) : void 0, + subscriptions: conn.subscriptions.map((sub) => ({ + eventName: sub.eventName + })), + lastSeen: Number(conn.lastSeen) + })), + scheduledEvents: bareData.scheduledEvents.map((event) => ({ + eventId: event.eventId, + timestamp: Number(event.timestamp), + kind: { + generic: { + actionName: event.kind.val.action, + args: event.kind.val.args + } + } + })) + }; + } +}; + +// src/actor/definition.ts +var ActorDefinition = class { + #config; + constructor(config4) { + this.#config = config4; + } + get config() { + return this.#config; + } + instantiate() { + return new ActorInstance(this.#config); + } +}; +function lookupInRegistry(registryConfig, name) { + const definition = registryConfig.use[name]; + if (!definition) throw new Error(`no actor in registry for name ${name}`); + return definition; +} + +// src/actor/generic-conn-driver.ts +var GenericConnGlobalState = class { + websockets = /* @__PURE__ */ new Map(); + sseStreams = /* @__PURE__ */ new Map(); +}; +function createGenericConnDrivers(globalState) { + return { + [CONNECTION_DRIVER_WEBSOCKET]: createGenericWebSocketDriver(globalState), + [CONNECTION_DRIVER_SSE]: createGenericSseDriver(globalState), + [CONNECTION_DRIVER_HTTP]: createGenericHttpDriver() + }; +} +function createGenericWebSocketDriver(globalState) { + return { + sendMessage: (actor2, conn, state, message) => { + const ws = globalState.websockets.get(conn.id); + if (!ws) { + logger().warn("missing ws for sendMessage", { + actorId: actor2.id, + connId: conn.id, + totalCount: globalState.websockets.size + }); + return; + } + const serialized = message.serialize(state.encoding); + logger().debug("sending websocket message", { + encoding: state.encoding, + dataType: typeof serialized, + isUint8Array: serialized instanceof Uint8Array, + isArrayBuffer: serialized instanceof ArrayBuffer, + dataLength: serialized.byteLength || serialized.length + }); + if (serialized instanceof Uint8Array) { + const buffer = serialized.buffer.slice( + serialized.byteOffset, + serialized.byteOffset + serialized.byteLength + ); + if (buffer instanceof SharedArrayBuffer) { + const arrayBuffer = new ArrayBuffer(buffer.byteLength); + new Uint8Array(arrayBuffer).set(new Uint8Array(buffer)); + logger().debug("converted SharedArrayBuffer to ArrayBuffer", { + byteLength: arrayBuffer.byteLength + }); + ws.send(arrayBuffer); + } else { + logger().debug("sending ArrayBuffer", { + byteLength: buffer.byteLength + }); + ws.send(buffer); + } + } else { + logger().debug("sending string data", { + length: serialized.length + }); + ws.send(serialized); + } + }, + disconnect: async (actor2, conn, _state, reason) => { + const ws = globalState.websockets.get(conn.id); + if (!ws) { + logger().warn("missing ws for disconnect", { + actorId: actor2.id, + connId: conn.id, + totalCount: globalState.websockets.size + }); + return; + } + const raw = ws.raw; + if (!raw) { + logger().warn("ws.raw does not exist"); + return; + } + const { promise, resolve } = Promise.withResolvers(); + raw.addEventListener("close", () => resolve()); + ws.close(1e3, reason); + await promise; + }, + getConnectionReadyState: (_actor, conn) => { + const ws = globalState.websockets.get(conn.id); + if (!ws) { + logger().warn("missing ws for getConnectionReadyState", { + connId: conn.id + }); + return void 0; + } + const raw = ws.raw; + return raw.readyState; + } + }; +} +function createGenericSseDriver(globalState) { + return { + sendMessage: (_actor, conn, state, message) => { + const stream = globalState.sseStreams.get(conn.id); + if (!stream) { + logger().warn("missing sse stream for sendMessage", { + connId: conn.id + }); + return; + } + stream.writeSSE({ + data: encodeDataToString(message.serialize(state.encoding)) + }); + }, + disconnect: async (_actor, conn, _state, _reason) => { + const stream = globalState.sseStreams.get(conn.id); + if (!stream) { + logger().warn("missing sse stream for disconnect", { connId: conn.id }); + return; + } + stream.close(); + }, + getConnectionReadyState: (_actor, conn) => { + const stream = globalState.sseStreams.get(conn.id); + if (!stream) { + logger().warn("missing sse stream for getConnectionReadyState", { + connId: conn.id + }); + return void 0; + } + if (stream.aborted || stream.closed) { + return 3 /* CLOSED */; + } + return 1 /* OPEN */; + } + }; +} +function createGenericHttpDriver() { + return { + getConnectionReadyState(_actor, _conn) { + return 1 /* OPEN */; + }, + disconnect: async () => { + } + }; +} + +// src/actor/router.ts +import { Hono as Hono2 } from "hono"; +import invariant3 from "invariant"; + +// src/common/router.ts +import * as cbor6 from "cbor-x"; +function logger3() { + return getLogger("router"); +} +function loggerMiddleware(logger10) { + return async (c, next) => { + const method = c.req.method; + const path3 = c.req.path; + const startTime = Date.now(); + await next(); + const duration = Date.now() - startTime; + logger10.debug("http request", { + method, + path: path3, + status: c.res.status, + dt: `${duration}ms`, + reqSize: c.req.header("content-length"), + resSize: c.res.headers.get("content-length"), + userAgent: c.req.header("user-agent") + }); + }; +} +function handleRouteNotFound(c) { + return c.text("Not Found (RivetKit)", 404); +} +function handleRouteError(opts, error, c) { + const exposeInternalError = opts.enableExposeInternalError && getRequestExposeInternalError(c.req.raw); + const { statusCode, code, message, metadata } = deconstructError( + error, + logger3(), + { + method: c.req.method, + path: c.req.path + }, + exposeInternalError + ); + let encoding; + try { + encoding = getRequestEncoding(c.req); + } catch (err) { + logger3().debug("failed to extract encoding", { + error: stringifyError(err) + }); + encoding = "json"; + } + const output = serializeWithEncoding( + encoding, + { + code, + message, + metadata: bufferToArrayBuffer(cbor6.encode(metadata)) + }, + HTTP_RESPONSE_ERROR_VERSIONED + ); + return c.body(output, { status: statusCode }); +} + +// src/inspector/utils.ts +import crypto2 from "node:crypto"; +import { createMiddleware } from "hono/factory"; + +// src/inspector/log.ts +function inspectorLogger() { + return getLogger("inspector"); +} + +// src/inspector/utils.ts +function compareSecrets(providedSecret, validSecret) { + if (providedSecret.length !== validSecret.length) { + return false; + } + const encoder = new TextEncoder(); + const a = encoder.encode(providedSecret); + const b = encoder.encode(validSecret); + if (a.byteLength !== b.byteLength) { + return false; + } + if (!crypto2.timingSafeEqual(a, b)) { + return false; + } + return true; +} +var secureInspector = (runConfig) => createMiddleware(async (c, next) => { + if (!runConfig.inspector.enabled) { + return c.text("Inspector is not enabled", 503); + } + const userToken = c.req.header("Authorization")?.replace("Bearer ", ""); + if (!userToken) { + return c.text("Unauthorized", 401); + } + const inspectorToken = runConfig.inspector.token?.(); + if (!inspectorToken) { + return c.text("Unauthorized", 401); + } + const isValid = compareSecrets(userToken, inspectorToken); + if (!isValid) { + return c.text("Unauthorized", 401); + } + await next(); +}); +function getInspectorUrl(runConfig) { + if (!runConfig?.inspector?.enabled) { + return "disabled"; + } + const accessToken = runConfig?.inspector?.token?.(); + if (!accessToken) { + inspectorLogger().warn( + "Inspector Token is not set, but Inspector is enabled. Please set it in the run configuration `inspector.token` or via `RIVETKIT_INSPECTOR_TOKEN` environment variable. Inspector will not be accessible." + ); + return "disabled"; + } + const url = new URL("https://studio.rivet.gg"); + url.searchParams.set("t", accessToken); + if (runConfig?.inspector?.defaultEndpoint) { + url.searchParams.set("u", runConfig.inspector.defaultEndpoint); + } + return url.href; +} + +// src/actor/router.ts +var PATH_CONNECT_WEBSOCKET = "/connect/websocket"; +var PATH_RAW_WEBSOCKET_PREFIX = "/raw/websocket/"; +function createActorRouter(runConfig, actorDriver) { + const router = new Hono2({ strict: false }); + router.use("*", loggerMiddleware(logger())); + router.get("/", (c) => { + return c.text( + "This is an RivetKit actor.\n\nLearn more at https://rivetkit.org" + ); + }); + router.get("/health", (c) => { + return c.text("ok"); + }); + router.get(PATH_CONNECT_WEBSOCKET, async (c) => { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + if (upgradeWebSocket) { + return upgradeWebSocket(async (c2) => { + const encodingRaw = c2.req.header(HEADER_ENCODING); + const connParamsRaw = c2.req.header(HEADER_CONN_PARAMS); + const authDataRaw = c2.req.header(HEADER_AUTH_DATA); + const encoding = EncodingSchema.parse(encodingRaw); + const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : void 0; + const authData = authDataRaw ? JSON.parse(authDataRaw) : void 0; + return await handleWebSocketConnect( + c2.req.raw, + runConfig, + actorDriver, + c2.env.actorId, + encoding, + connParams, + authData + ); + })(c, noopNext()); + } else { + return c.text( + "WebSockets are not enabled for this driver. Use SSE instead.", + 400 + ); + } + }); + router.get("/connect/sse", async (c) => { + const authDataRaw = c.req.header(HEADER_AUTH_DATA); + let authData; + if (authDataRaw) { + authData = JSON.parse(authDataRaw); + } + return handleSseConnect(c, runConfig, actorDriver, c.env.actorId, authData); + }); + router.post("/action/:action", async (c) => { + const actionName = c.req.param("action"); + const authDataRaw = c.req.header(HEADER_AUTH_DATA); + let authData; + if (authDataRaw) { + authData = JSON.parse(authDataRaw); + } + return handleAction( + c, + runConfig, + actorDriver, + actionName, + c.env.actorId, + authData + ); + }); + router.post("/connections/message", async (c) => { + const connId = c.req.header(HEADER_CONN_ID); + const connToken = c.req.header(HEADER_CONN_TOKEN); + if (!connId || !connToken) { + throw new Error("Missing required parameters"); + } + return handleConnectionMessage( + c, + runConfig, + actorDriver, + connId, + connToken, + c.env.actorId + ); + }); + router.all("/raw/http/*", async (c) => { + const authDataRaw = c.req.header(HEADER_AUTH_DATA); + let authData; + if (authDataRaw) { + authData = JSON.parse(authDataRaw); + } + const actor2 = await actorDriver.loadActor(c.env.actorId); + const url = new URL(c.req.url); + const originalPath = url.pathname.replace(/^\/raw\/http/, "") || "/"; + const correctedUrl = new URL(originalPath + url.search, url.origin); + const correctedRequest = new Request(correctedUrl, { + method: c.req.method, + headers: c.req.raw.headers, + body: c.req.raw.body + }); + logger().debug("rewriting http url", { + from: c.req.url, + to: correctedRequest.url + }); + const response = await actor2.handleFetch(correctedRequest, { + auth: authData + }); + if (!response) { + throw new InternalError("handleFetch returned void unexpectedly"); + } + return response; + }); + router.get(`${PATH_RAW_WEBSOCKET_PREFIX}*`, async (c) => { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + if (upgradeWebSocket) { + return upgradeWebSocket(async (c2) => { + const encodingRaw = c2.req.header(HEADER_ENCODING); + const connParamsRaw = c2.req.header(HEADER_CONN_PARAMS); + const authDataRaw = c2.req.header(HEADER_AUTH_DATA); + const encoding = EncodingSchema.parse(encodingRaw); + const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : void 0; + const authData = authDataRaw ? JSON.parse(authDataRaw) : void 0; + const url = new URL(c2.req.url); + const pathWithQuery = c2.req.path + url.search; + logger().debug("actor router raw websocket", { + path: c2.req.path, + url: c2.req.url, + search: url.search, + pathWithQuery + }); + return await handleRawWebSocketHandler( + c2.req.raw, + pathWithQuery, + actorDriver, + c2.env.actorId, + authData + ); + })(c, noopNext()); + } else { + return c.text( + "WebSockets are not enabled for this driver. Use SSE instead.", + 400 + ); + } + }); + if (runConfig.inspector.enabled) { + router.route( + "/inspect", + new Hono2().use(secureInspector(runConfig), async (c, next) => { + const inspector = (await actorDriver.loadActor(c.env.actorId)).inspector; + invariant3(inspector, "inspector not supported on this platform"); + c.set("inspector", inspector); + await next(); + }).route("/", createActorInspectorRouter()) + ); + } + router.notFound(handleRouteNotFound); + router.onError( + handleRouteError.bind(void 0, { + // All headers to this endpoint are considered secure, so we can enable the expose internal error header for requests from the internal client + enableExposeInternalError: true + }) + ); + return router; +} + +// src/actor/mod.ts +function actor(input) { + const config4 = ActorConfigSchema.parse(input); + return new ActorDefinition(config4); +} + +// src/client/actor-conn.ts +import * as cbor8 from "cbor-x"; +import invariant5 from "invariant"; +import pRetry from "p-retry"; + +// src/client/errors.ts +var ActorClientError = class extends Error { +}; +var InternalError2 = class extends ActorClientError { +}; +var ActorError2 = class extends ActorClientError { + constructor(code, message, metadata) { + super(message); + this.code = code; + this.metadata = metadata; + } + __type = "ActorError"; +}; +var HttpRequestError = class extends ActorClientError { + constructor(message, opts) { + super(`HTTP request error: ${message}`, { cause: opts?.cause }); + } +}; +var ActorConnDisposed = class extends ActorClientError { + constructor() { + super("Attempting to interact with a disposed actor connection."); + } +}; + +// src/client/log.ts +var LOGGER_NAME2 = "actor-client"; +function logger4() { + return getLogger(LOGGER_NAME2); +} + +// src/client/utils.ts +import * as cbor7 from "cbor-x"; +import invariant4 from "invariant"; +function messageLength(message) { + if (message instanceof Blob) { + return message.size; + } + if (message instanceof ArrayBuffer) { + return message.byteLength; + } + if (message instanceof Uint8Array) { + return message.byteLength; + } + if (typeof message === "string") { + return message.length; + } + assertUnreachable(message); +} +async function sendHttpRequest(opts) { + logger4().debug("sending http request", { + url: opts.url, + encoding: opts.encoding + }); + let contentType; + let bodyData; + if (opts.method === "POST" || opts.method === "PUT") { + invariant4(opts.body !== void 0, "missing body"); + contentType = contentTypeForEncoding(opts.encoding); + bodyData = serializeWithEncoding( + opts.encoding, + opts.body, + opts.requestVersionedDataHandler + ); + } + let response; + try { + response = await (opts.customFetch ?? fetch)( + new Request(opts.url, { + method: opts.method, + headers: { + ...opts.headers, + ...contentType ? { + "Content-Type": contentType + } : {}, + "User-Agent": httpUserAgent() + }, + body: bodyData, + credentials: "include", + signal: opts.signal + }) + ); + } catch (error) { + throw new HttpRequestError(`Request failed: ${error}`, { + cause: error + }); + } + if (!response.ok) { + const bufferResponse = await response.arrayBuffer(); + let responseData; + try { + responseData = deserializeWithEncoding( + opts.encoding, + new Uint8Array(bufferResponse), + HTTP_RESPONSE_ERROR_VERSIONED + ); + } catch (error) { + const textResponse = new TextDecoder("utf-8", { fatal: false }).decode( + bufferResponse + ); + throw new HttpRequestError( + `${response.statusText} (${response.status}): +${textResponse}` + ); + } + throw new ActorError2( + responseData.code, + responseData.message, + responseData.metadata ? cbor7.decode(new Uint8Array(responseData.metadata)) : void 0 + ); + } + if (opts.skipParseResponse) { + return void 0; + } + try { + const buffer = new Uint8Array(await response.arrayBuffer()); + return deserializeWithEncoding( + opts.encoding, + buffer, + opts.responseVersionedDataHandler + ); + } catch (error) { + throw new HttpRequestError(`Failed to parse response: ${error}`, { + cause: error + }); + } +} + +// src/client/actor-conn.ts +var CONNECT_SYMBOL = Symbol("connect"); +var ActorConnRaw = class { + #disposed = false; + /* Will be aborted on dispose. */ + #abortController = new AbortController(); + /** If attempting to connect. Helpful for knowing if in a retry loop when reconnecting. */ + #connecting = false; + // These will only be set on SSE driver + #actorId; + #connectionId; + #connectionToken; + #transport; + #messageQueue = []; + #actionsInFlight = /* @__PURE__ */ new Map(); + // biome-ignore lint/suspicious/noExplicitAny: Unknown subscription type + #eventSubscriptions = /* @__PURE__ */ new Map(); + #errorHandlers = /* @__PURE__ */ new Set(); + #actionIdCounter = 0; + /** + * Interval that keeps the NodeJS process alive if this is the only thing running. + * + * See ttps://github.com/nodejs/node/issues/22088 + */ + #keepNodeAliveInterval; + /** Promise used to indicate the socket has connected successfully. This will be rejected if the connection fails. */ + #onOpenPromise; + #client; + #driver; + #params; + #encodingKind; + #actorQuery; + // TODO: ws message queue + /** + * Do not call this directly. + * + * Creates an instance of ActorConnRaw. + * + * @protected + */ + constructor(client, driver, params, encodingKind, actorQuery) { + this.#client = client; + this.#driver = driver; + this.#params = params; + this.#encodingKind = encodingKind; + this.#actorQuery = actorQuery; + this.#keepNodeAliveInterval = setInterval(() => 6e4); + } + /** + * Call a raw action connection. See {@link ActorConn} for type-safe action calls. + * + * @see {@link ActorConn} + * @template Args - The type of arguments to pass to the action function. + * @template Response - The type of the response returned by the action function. + * @param {string} name - The name of the action function to call. + * @param {...Args} args - The arguments to pass to the action function. + * @returns {Promise} - A promise that resolves to the response of the action function. + */ + async action(opts) { + logger4().debug("action", { name: opts.name, args: opts.args }); + const actionId = this.#actionIdCounter; + this.#actionIdCounter += 1; + const { promise, resolve, reject } = Promise.withResolvers(); + this.#actionsInFlight.set(actionId, { name: opts.name, resolve, reject }); + this.#sendMessage({ + body: { + tag: "ActionRequest", + val: { + id: BigInt(actionId), + name: opts.name, + args: bufferToArrayBuffer(cbor8.encode(opts.args)) + } + } + }); + const { id: responseId, output } = await promise; + if (responseId !== BigInt(actionId)) + throw new Error( + `Request ID ${actionId} does not match response ID ${responseId}` + ); + return cbor8.decode(new Uint8Array(output)); + } + /** + * Do not call this directly. + enc + * Establishes a connection to the server using the specified endpoint & encoding & driver. + * + * @protected + */ + [CONNECT_SYMBOL]() { + this.#connectWithRetry(); + } + async #connectWithRetry() { + this.#connecting = true; + try { + await pRetry(this.#connectAndWait.bind(this), { + forever: true, + minTimeout: 250, + maxTimeout: 3e4, + onFailedAttempt: (error) => { + logger4().warn("failed to reconnect", { + attempt: error.attemptNumber, + error: stringifyError(error) + }); + }, + // Cancel retry if aborted + signal: this.#abortController.signal + }); + } catch (err) { + if (err.name === "AbortError") { + logger4().info("connection retry aborted"); + return; + } else { + throw err; + } + } + this.#connecting = false; + } + async #connectAndWait() { + try { + if (this.#onOpenPromise) + throw new Error("#onOpenPromise already defined"); + this.#onOpenPromise = Promise.withResolvers(); + if (this.#client[TRANSPORT_SYMBOL] === "websocket") { + await this.#connectWebSocket(); + } else if (this.#client[TRANSPORT_SYMBOL] === "sse") { + await this.#connectSse(); + } else { + assertUnreachable(this.#client[TRANSPORT_SYMBOL]); + } + await this.#onOpenPromise.promise; + } finally { + this.#onOpenPromise = void 0; + } + } + async #connectWebSocket({ signal } = {}) { + const ws = await this.#driver.connectWebSocket( + void 0, + this.#actorQuery, + this.#encodingKind, + this.#params, + signal ? { signal } : void 0 + ); + this.#transport = { websocket: ws }; + ws.addEventListener("open", () => { + logger4().debug("websocket open"); + }); + ws.addEventListener("message", async (ev) => { + this.#handleOnMessage(ev.data); + }); + ws.addEventListener("close", (ev) => { + this.#handleOnClose(ev); + }); + ws.addEventListener("error", (_ev) => { + this.#handleOnError(); + }); + } + async #connectSse({ signal } = {}) { + const eventSource = await this.#driver.connectSse( + void 0, + this.#actorQuery, + this.#encodingKind, + this.#params, + signal ? { signal } : void 0 + ); + this.#transport = { sse: eventSource }; + eventSource.onopen = () => { + logger4().debug("eventsource open"); + }; + eventSource.onmessage = (ev) => { + this.#handleOnMessage(ev.data); + }; + eventSource.onerror = (_ev) => { + if (eventSource.readyState === eventSource.CLOSED) { + this.#handleOnClose(new Event("error")); + } else { + this.#handleOnError(); + } + }; + } + /** Called by the onopen event from drivers. */ + #handleOnOpen() { + logger4().debug("socket open", { + messageQueueLength: this.#messageQueue.length + }); + if (this.#onOpenPromise) { + this.#onOpenPromise.resolve(void 0); + } else { + logger4().warn("#onOpenPromise is undefined"); + } + for (const eventName of this.#eventSubscriptions.keys()) { + this.#sendSubscription(eventName, true); + } + const queue = this.#messageQueue; + this.#messageQueue = []; + for (const msg of queue) { + this.#sendMessage(msg); + } + } + /** Called by the onmessage event from drivers. */ + async #handleOnMessage(data) { + logger4().trace("received message", { + dataType: typeof data, + isBlob: data instanceof Blob, + isArrayBuffer: data instanceof ArrayBuffer + }); + const response = await this.#parseMessage(data); + logger4().trace( + "parsed message", + getEnvUniversal("_RIVETKIT_LOG_MESSAGE") ? { + message: jsonStringifyCompat(response).substring(0, 100) + "..." + } : {} + ); + if (response.body.tag === "Init") { + this.#actorId = response.body.val.actorId; + this.#connectionId = response.body.val.connectionId; + this.#connectionToken = response.body.val.connectionToken; + logger4().trace("received init message", { + actorId: this.#actorId, + connectionId: this.#connectionId + }); + this.#handleOnOpen(); + } else if (response.body.tag === "Error") { + const { code, message, metadata, actionId } = response.body.val; + if (actionId) { + const inFlight = this.#takeActionInFlight(Number(actionId)); + logger4().warn("action error", { + actionId, + actionName: inFlight?.name, + code, + message, + metadata + }); + inFlight.reject(new ActorError2(code, message, metadata)); + } else { + logger4().warn("connection error", { + code, + message, + metadata + }); + const actorError = new ActorError2(code, message, metadata); + if (this.#onOpenPromise) { + this.#onOpenPromise.reject(actorError); + } + for (const [id, inFlight] of this.#actionsInFlight.entries()) { + inFlight.reject(actorError); + this.#actionsInFlight.delete(id); + } + this.#dispatchActorError(actorError); + } + } else if (response.body.tag === "ActionResponse") { + const { id: actionId } = response.body.val; + logger4().trace("received action response", { + actionId + }); + const inFlight = this.#takeActionInFlight(Number(actionId)); + logger4().trace("resolving action promise", { + actionId, + actionName: inFlight?.name + }); + inFlight.resolve(response.body.val); + } else if (response.body.tag === "Event") { + logger4().trace("received event", { name: response.body.val.name }); + this.#dispatchEvent(response.body.val); + } else { + assertUnreachable(response.body); + } + } + /** Called by the onclose event from drivers. */ + #handleOnClose(event) { + if (this.#onOpenPromise) { + this.#onOpenPromise.reject(new Error("Closed")); + } + const closeEvent = event; + if (closeEvent.wasClean) { + logger4().info("socket closed", { + code: closeEvent.code, + reason: closeEvent.reason, + wasClean: closeEvent.wasClean + }); + } else { + logger4().warn("socket closed", { + code: closeEvent.code, + reason: closeEvent.reason, + wasClean: closeEvent.wasClean + }); + } + this.#transport = void 0; + if (!this.#disposed && !this.#connecting) { + this.#connectWithRetry(); + } + } + /** Called by the onerror event from drivers. */ + #handleOnError() { + if (this.#disposed) return; + logger4().warn("socket error"); + } + #takeActionInFlight(id) { + const inFlight = this.#actionsInFlight.get(id); + if (!inFlight) { + throw new InternalError2(`No in flight response for ${id}`); + } + this.#actionsInFlight.delete(id); + return inFlight; + } + #dispatchEvent(event) { + const { name, args: argsRaw } = event; + const args = cbor8.decode(new Uint8Array(argsRaw)); + const listeners = this.#eventSubscriptions.get(name); + if (!listeners) return; + for (const listener of [...listeners]) { + listener.callback(...args); + if (listener.once) { + listeners.delete(listener); + } + } + if (listeners.size === 0) { + this.#eventSubscriptions.delete(name); + } + } + #dispatchActorError(error) { + for (const handler of [...this.#errorHandlers]) { + try { + handler(error); + } catch (err) { + logger4().error("Error in connection error handler", { + error: stringifyError(err) + }); + } + } + } + #addEventSubscription(eventName, callback, once) { + const listener = { + callback, + once + }; + let subscriptionSet = this.#eventSubscriptions.get(eventName); + if (subscriptionSet === void 0) { + subscriptionSet = /* @__PURE__ */ new Set(); + this.#eventSubscriptions.set(eventName, subscriptionSet); + this.#sendSubscription(eventName, true); + } + subscriptionSet.add(listener); + return () => { + const listeners = this.#eventSubscriptions.get(eventName); + if (listeners) { + listeners.delete(listener); + if (listeners.size === 0) { + this.#eventSubscriptions.delete(eventName); + this.#sendSubscription(eventName, false); + } + } + }; + } + /** + * Subscribes to an event that will happen repeatedly. + * + * @template Args - The type of arguments the event callback will receive. + * @param {string} eventName - The name of the event to subscribe to. + * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered. + * @returns {EventUnsubscribe} - A function to unsubscribe from the event. + * @see {@link https://rivet.gg/docs/events|Events Documentation} + */ + on(eventName, callback) { + return this.#addEventSubscription(eventName, callback, false); + } + /** + * Subscribes to an event that will be triggered only once. + * + * @template Args - The type of arguments the event callback will receive. + * @param {string} eventName - The name of the event to subscribe to. + * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered. + * @returns {EventUnsubscribe} - A function to unsubscribe from the event. + * @see {@link https://rivet.gg/docs/events|Events Documentation} + */ + once(eventName, callback) { + return this.#addEventSubscription(eventName, callback, true); + } + /** + * Subscribes to connection errors. + * + * @param {ActorErrorCallback} callback - The callback function to execute when a connection error occurs. + * @returns {() => void} - A function to unsubscribe from the error handler. + */ + onError(callback) { + this.#errorHandlers.add(callback); + return () => { + this.#errorHandlers.delete(callback); + }; + } + #sendMessage(message, opts) { + if (this.#disposed) { + throw new ActorConnDisposed(); + } + let queueMessage = false; + if (!this.#transport) { + queueMessage = true; + } else if ("websocket" in this.#transport) { + if (this.#transport.websocket.readyState === 1) { + try { + const messageSerialized = serializeWithEncoding( + this.#encodingKind, + message, + TO_SERVER_VERSIONED + ); + this.#transport.websocket.send(messageSerialized); + logger4().trace("sent websocket message", { + len: messageLength(messageSerialized) + }); + } catch (error) { + logger4().warn("failed to send message, added to queue", { + error + }); + queueMessage = true; + } + } else { + queueMessage = true; + } + } else if ("sse" in this.#transport) { + if (this.#transport.sse.readyState === 1) { + this.#sendHttpMessage(message, opts); + } else { + queueMessage = true; + } + } else { + assertUnreachable(this.#transport); + } + if (!opts?.ephemeral && queueMessage) { + this.#messageQueue.push(message); + logger4().debug("queued connection message"); + } + } + async #sendHttpMessage(message, opts) { + try { + if (!this.#actorId || !this.#connectionId || !this.#connectionToken) + throw new InternalError2("Missing connection ID or token."); + logger4().trace( + "sent http message", + getEnvUniversal("_RIVETKIT_LOG_MESSAGE") ? { + message: jsonStringifyCompat(message).substring(0, 100) + "..." + } : {} + ); + await this.#driver.sendHttpMessage( + void 0, + this.#actorId, + this.#encodingKind, + this.#connectionId, + this.#connectionToken, + message, + opts?.signal ? { signal: opts.signal } : void 0 + ); + } catch (error) { + logger4().warn("failed to send message, added to queue", { + error + }); + if (!opts?.ephemeral) { + this.#messageQueue.unshift(message); + } + } + } + async #parseMessage(data) { + invariant5(this.#transport, "transport must be defined"); + if (encodingIsBinary(this.#encodingKind) && "sse" in this.#transport) { + if (typeof data === "string") { + const binaryString = atob(data); + data = new Uint8Array( + [...binaryString].map((char) => char.charCodeAt(0)) + ); + } else { + throw new InternalError2( + `Expected data to be a string for SSE, got ${data}.` + ); + } + } + const buffer = await inputDataToBuffer(data); + return deserializeWithEncoding( + this.#encodingKind, + buffer, + TO_CLIENT_VERSIONED + ); + } + /** + * Disconnects from the actor. + * + * @returns {Promise} A promise that resolves when the socket is gracefully closed. + */ + async dispose() { + if (this.#disposed) { + logger4().warn("connection already disconnected"); + return; + } + this.#disposed = true; + logger4().debug("disposing actor conn"); + clearInterval(this.#keepNodeAliveInterval); + this.#abortController.abort(); + this.#client[ACTOR_CONNS_SYMBOL].delete(this); + if (!this.#transport) { + } else if ("websocket" in this.#transport) { + const ws = this.#transport.websocket; + if (ws.readyState === 2 || ws.readyState === 3) { + logger4().debug("ws already closed or closing"); + } else { + const { promise, resolve } = Promise.withResolvers(); + ws.addEventListener("close", () => { + logger4().debug("ws closed"); + resolve(void 0); + }); + ws.close(); + await promise; + } + } else if ("sse" in this.#transport) { + this.#transport.sse.close(); + } else { + assertUnreachable(this.#transport); + } + this.#transport = void 0; + } + #sendSubscription(eventName, subscribe) { + this.#sendMessage( + { + body: { + tag: "SubscriptionRequest", + val: { + eventName, + subscribe + } + } + }, + { ephemeral: true } + ); + } +}; + +// src/client/actor-handle.ts +import invariant6 from "invariant"; + +// src/client/raw-utils.ts +async function rawHttpFetch(driver, actorQuery, params, input, init) { + let path3; + let mergedInit = init || {}; + if (typeof input === "string") { + path3 = input; + } else if (input instanceof URL) { + path3 = input.pathname + input.search; + } else if (input instanceof Request) { + const url = new URL(input.url); + path3 = url.pathname + url.search; + const requestHeaders = new Headers(input.headers); + const initHeaders = new Headers(init?.headers || {}); + const mergedHeaders = new Headers(requestHeaders); + for (const [key, value] of initHeaders) { + mergedHeaders.set(key, value); + } + mergedInit = { + method: input.method, + body: input.body, + mode: input.mode, + credentials: input.credentials, + redirect: input.redirect, + referrer: input.referrer, + referrerPolicy: input.referrerPolicy, + integrity: input.integrity, + keepalive: input.keepalive, + signal: input.signal, + ...mergedInit, + // init overrides Request properties + headers: mergedHeaders + // headers must be set after spread to ensure proper merge + }; + if (mergedInit.body) { + mergedInit.duplex = "half"; + } + } else { + throw new TypeError("Invalid input type for fetch"); + } + return await driver.rawHttpRequest( + void 0, + actorQuery, + // Force JSON so it's readable by the user + "json", + params, + path3, + mergedInit, + void 0 + ); +} +async function rawWebSocket(driver, actorQuery, params, path3, protocols) { + return await driver.rawWebSocket( + void 0, + actorQuery, + // Force JSON so it's readable by the user + "json", + params, + path3 || "", + protocols, + void 0 + ); +} + +// src/client/actor-handle.ts +var ActorHandleRaw = class { + #client; + #driver; + #encodingKind; + #actorQuery; + #params; + /** + * Do not call this directly. + * + * Creates an instance of ActorHandleRaw. + * + * @protected + */ + constructor(client, driver, params, encodingKind, actorQuery) { + this.#client = client; + this.#driver = driver; + this.#encodingKind = encodingKind; + this.#actorQuery = actorQuery; + this.#params = params; + } + /** + * Call a raw action. This method sends an HTTP request to invoke the named action. + * + * @see {@link ActorHandle} + * @template Args - The type of arguments to pass to the action function. + * @template Response - The type of the response returned by the action function. + */ + async action(opts) { + return await this.#driver.action( + void 0, + this.#actorQuery, + this.#encodingKind, + this.#params, + opts.name, + opts.args, + { signal: opts.signal } + ); + } + /** + * Establishes a persistent connection to the actor. + * + * @template AD The actor class that this connection is for. + * @returns {ActorConn} A connection to the actor. + */ + connect() { + logger4().debug("establishing connection from handle", { + query: this.#actorQuery + }); + const conn = new ActorConnRaw( + this.#client, + this.#driver, + this.#params, + this.#encodingKind, + this.#actorQuery + ); + return this.#client[CREATE_ACTOR_CONN_PROXY]( + conn + ); + } + /** + * Makes a raw HTTP request to the actor. + * + * @param input - The URL, path, or Request object + * @param init - Standard fetch RequestInit options + * @returns Promise - The raw HTTP response + */ + async fetch(input, init) { + return rawHttpFetch( + this.#driver, + this.#actorQuery, + this.#params, + input, + init + ); + } + /** + * Creates a raw WebSocket connection to the actor. + * + * @param path - The path for the WebSocket connection (e.g., "stream") + * @param protocols - Optional WebSocket subprotocols + * @returns WebSocket - A raw WebSocket connection + */ + async websocket(path3, protocols) { + return rawWebSocket( + this.#driver, + this.#actorQuery, + this.#params, + path3, + protocols + ); + } + /** + * Resolves the actor to get its unique actor ID + * + * @returns {Promise} - A promise that resolves to the actor's ID + */ + async resolve({ signal } = {}) { + if ("getForKey" in this.#actorQuery || "getOrCreateForKey" in this.#actorQuery) { + let name; + if ("getForKey" in this.#actorQuery) { + name = this.#actorQuery.getForKey.name; + } else if ("getOrCreateForKey" in this.#actorQuery) { + name = this.#actorQuery.getOrCreateForKey.name; + } else { + assertUnreachable2(this.#actorQuery); + } + const actorId = await this.#driver.resolveActorId( + void 0, + this.#actorQuery, + this.#encodingKind, + this.#params, + signal ? { signal } : void 0 + ); + this.#actorQuery = { getForId: { actorId, name } }; + return actorId; + } else if ("getForId" in this.#actorQuery) { + return this.#actorQuery.getForId.actorId; + } else if ("create" in this.#actorQuery) { + invariant6(false, "actorQuery cannot be create"); + } else { + assertUnreachable2(this.#actorQuery); + } + } +}; + +// src/client/client.ts +var ACTOR_CONNS_SYMBOL = Symbol("actorConns"); +var CREATE_ACTOR_CONN_PROXY = Symbol("createActorConnProxy"); +var TRANSPORT_SYMBOL = Symbol("transport"); +var ClientRaw = class { + #disposed = false; + [ACTOR_CONNS_SYMBOL] = /* @__PURE__ */ new Set(); + #driver; + #encodingKind; + [TRANSPORT_SYMBOL]; + /** + * Creates an instance of Client. + * + * @param {string} managerEndpoint - The manager endpoint. See {@link https://rivet.gg/docs/setup|Initial Setup} for instructions on getting the manager endpoint. + * @param {ClientOptions} [opts] - Options for configuring the client. + * @see {@link https://rivet.gg/docs/setup|Initial Setup} + */ + constructor(driver, opts) { + this.#driver = driver; + this.#encodingKind = opts?.encoding ?? "bare"; + this[TRANSPORT_SYMBOL] = opts?.transport ?? "websocket"; + } + /** + * Gets a stateless handle to a actor by its ID. + * + * @template AD The actor class that this handle is for. + * @param {string} name - The name of the actor. + * @param {string} actorId - The ID of the actor. + * @param {GetWithIdOptions} [opts] - Options for getting the actor. + * @returns {ActorHandle} - A handle to the actor. + */ + getForId(name, actorId, opts) { + logger4().debug("get handle to actor with id", { + name, + actorId, + params: opts?.params + }); + const actorQuery = { + getForId: { + name, + actorId + } + }; + const handle = this.#createHandle(opts?.params, actorQuery); + return createActorProxy(handle); + } + /** + * Gets a stateless handle to a actor by its key, but does not create the actor if it doesn't exist. + * + * @template AD The actor class that this handle is for. + * @param {string} name - The name of the actor. + * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings. + * @param {GetWithIdOptions} [opts] - Options for getting the actor. + * @returns {ActorHandle} - A handle to the actor. + */ + get(name, key, opts) { + const keyArray = typeof key === "string" ? [key] : key || []; + logger4().debug("get handle to actor", { + name, + key: keyArray, + parameters: opts?.params + }); + const actorQuery = { + getForKey: { + name, + key: keyArray + } + }; + const handle = this.#createHandle(opts?.params, actorQuery); + return createActorProxy(handle); + } + /** + * Gets a stateless handle to a actor by its key, creating it if necessary. + * + * @template AD The actor class that this handle is for. + * @param {string} name - The name of the actor. + * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings. + * @param {GetOptions} [opts] - Options for getting the actor. + * @returns {ActorHandle} - A handle to the actor. + */ + getOrCreate(name, key, opts) { + const keyArray = typeof key === "string" ? [key] : key || []; + logger4().debug("get or create handle to actor", { + name, + key: keyArray, + parameters: opts?.params, + createInRegion: opts?.createInRegion + }); + const actorQuery = { + getOrCreateForKey: { + name, + key: keyArray, + input: opts?.createWithInput, + region: opts?.createInRegion + } + }; + const handle = this.#createHandle(opts?.params, actorQuery); + return createActorProxy(handle); + } + /** + * Creates a new actor with the provided key and returns a stateless handle to it. + * Resolves the actor ID and returns a handle with getForId query. + * + * @template AD The actor class that this handle is for. + * @param {string} name - The name of the actor. + * @param {string | string[]} key - The key to identify the actor. Can be a single string or an array of strings. + * @param {CreateOptions} [opts] - Options for creating the actor (excluding name and key). + * @returns {Promise>} - A promise that resolves to a handle to the actor. + */ + async create(name, key, opts) { + const keyArray = typeof key === "string" ? [key] : key || []; + const createQuery = { + create: { + ...opts, + // Do these last to override `opts` + name, + key: keyArray + } + }; + logger4().debug("create actor handle", { + name, + key: keyArray, + parameters: opts?.params, + create: createQuery.create + }); + const actorId = await this.#driver.resolveActorId( + void 0, + createQuery, + this.#encodingKind, + opts?.params, + opts?.signal ? { signal: opts.signal } : void 0 + ); + logger4().debug("created actor with ID", { + name, + key: keyArray, + actorId + }); + const getForIdQuery = { + getForId: { + name, + actorId + } + }; + const handle = this.#createHandle(opts?.params, getForIdQuery); + const proxy = createActorProxy(handle); + return proxy; + } + #createHandle(params, actorQuery) { + return new ActorHandleRaw( + this, + this.#driver, + params, + this.#encodingKind, + actorQuery + ); + } + [CREATE_ACTOR_CONN_PROXY](conn) { + this[ACTOR_CONNS_SYMBOL].add(conn); + conn[CONNECT_SYMBOL](); + return createActorProxy(conn); + } + /** + * Disconnects from all actors. + * + * @returns {Promise} A promise that resolves when all connections are closed. + */ + async dispose() { + if (this.#disposed) { + logger4().warn("client already disconnected"); + return; + } + this.#disposed = true; + logger4().debug("disposing client"); + const disposePromises = []; + for (const conn of this[ACTOR_CONNS_SYMBOL].values()) { + disposePromises.push(conn.dispose()); + } + await Promise.all(disposePromises); + } +}; +function createClientWithDriver(driver, opts) { + const client = new ClientRaw(driver, opts); + return new Proxy(client, { + get: (target, prop, receiver) => { + if (typeof prop === "symbol" || prop in target) { + const value = Reflect.get(target, prop, receiver); + if (typeof value === "function") { + return value.bind(target); + } + return value; + } + if (typeof prop === "string") { + return { + // Handle methods (stateless action) + get: (key, opts2) => { + return target.get( + prop, + key, + opts2 + ); + }, + getOrCreate: (key, opts2) => { + return target.getOrCreate(prop, key, opts2); + }, + getForId: (actorId, opts2) => { + return target.getForId( + prop, + actorId, + opts2 + ); + }, + create: async (key, opts2 = {}) => { + return await target.create(prop, key, opts2); + } + }; + } + return void 0; + } + }); +} +function createActorProxy(handle) { + const methodCache = /* @__PURE__ */ new Map(); + return new Proxy(handle, { + get(target, prop, receiver) { + if (typeof prop === "symbol") { + return Reflect.get(target, prop, receiver); + } + if (prop === "constructor" || prop in target) { + const value = Reflect.get(target, prop, receiver); + if (typeof value === "function") { + return value.bind(target); + } + return value; + } + if (typeof prop === "string") { + if (prop === "then") return void 0; + let method = methodCache.get(prop); + if (!method) { + method = (...args) => target.action({ name: prop, args }); + methodCache.set(prop, method); + } + return method; + } + }, + // Support for 'in' operator + has(target, prop) { + if (typeof prop === "string") { + return true; + } + return Reflect.has(target, prop); + }, + // Support instanceof checks + getPrototypeOf(target) { + return Reflect.getPrototypeOf(target); + }, + // Prevent property enumeration of non-existent action methods + ownKeys(target) { + return Reflect.ownKeys(target); + }, + // Support proper property descriptors + getOwnPropertyDescriptor(target, prop) { + const targetDescriptor = Reflect.getOwnPropertyDescriptor(target, prop); + if (targetDescriptor) { + return targetDescriptor; + } + if (typeof prop === "string") { + return { + configurable: true, + enumerable: false, + writable: false, + value: (...args) => target.action({ name: prop, args }) + }; + } + return void 0; + } + }); +} + +// src/common/inline-websocket-adapter2.ts +import { WSContext } from "hono/ws"; +var LOGGER_NAME3 = "fake-event-source2"; +function logger5() { + return getLogger(LOGGER_NAME3); +} +var InlineWebSocketAdapter2 = class { + // WebSocket readyState values + CONNECTING = 0; + OPEN = 1; + CLOSING = 2; + CLOSED = 3; + // Private properties + #handler; + #wsContext; + #readyState = 0; + // Start in CONNECTING state + #queuedMessages = []; + // Event buffering is needed since events can be fired + // before JavaScript has a chance to add event listeners (e.g. within the same tick) + #bufferedEvents = []; + // Event listeners with buffering + #eventListeners = /* @__PURE__ */ new Map(); + constructor(handler) { + this.#handler = handler; + this.#wsContext = new WSContext({ + raw: this, + send: (data) => { + logger5().debug("WSContext.send called"); + this.#handleMessage(data); + }, + close: (code, reason) => { + logger5().debug("WSContext.close called", { code, reason }); + this.#handleClose(code || 1e3, reason || ""); + }, + // Set readyState to 1 (OPEN) since handlers expect an open connection + readyState: 1 + }); + this.#initialize(); + } + get readyState() { + return this.#readyState; + } + get binaryType() { + return "arraybuffer"; + } + set binaryType(value) { + } + get bufferedAmount() { + return 0; + } + get extensions() { + return ""; + } + get protocol() { + return ""; + } + get url() { + return ""; + } + send(data) { + logger5().debug("send called", { readyState: this.readyState }); + if (this.readyState !== this.OPEN) { + const error = new Error("WebSocket is not open"); + logger5().warn("cannot send message, websocket not open", { + readyState: this.readyState, + dataType: typeof data, + dataLength: typeof data === "string" ? data.length : "binary", + error + }); + this.#fireError(error); + return; + } + this.#handler.onMessage({ data }, this.#wsContext); + } + /** + * Closes the connection + */ + close(code = 1e3, reason = "") { + if (this.readyState === this.CLOSED || this.readyState === this.CLOSING) { + return; + } + logger5().debug("closing fake websocket", { code, reason }); + this.#readyState = this.CLOSING; + try { + this.#handler.onClose({ code, reason, wasClean: true }, this.#wsContext); + } catch (err) { + logger5().error("error closing websocket", { error: err }); + } finally { + this.#readyState = this.CLOSED; + const closeEvent = { + type: "close", + wasClean: code === 1e3, + code, + reason, + target: this, + currentTarget: this + }; + this.#fireClose(closeEvent); + } + } + /** + * Initialize the connection with the handler + */ + async #initialize() { + try { + logger5().debug("fake websocket initializing"); + logger5().debug("calling handler.onOpen with WSContext"); + this.#handler.onOpen(void 0, this.#wsContext); + this.#readyState = this.OPEN; + logger5().debug("fake websocket initialized and now OPEN"); + this.#fireOpen(); + if (this.#queuedMessages.length > 0) { + if (this.readyState !== this.OPEN) { + logger5().warn("socket no longer open, dropping queued messages"); + return; + } + logger5().debug( + `now processing ${this.#queuedMessages.length} queued messages` + ); + const messagesToProcess = [...this.#queuedMessages]; + this.#queuedMessages = []; + for (const message of messagesToProcess) { + logger5().debug("processing queued message"); + this.#handleMessage(message); + } + } + } catch (err) { + logger5().error("error opening fake websocket", { + error: err, + errorMessage: err instanceof Error ? err.message : String(err), + stack: err instanceof Error ? err.stack : void 0 + }); + this.#fireError(err); + this.close(1011, "Internal error during initialization"); + } + } + /** + * Handle messages received from the server via the WSContext + */ + #handleMessage(data) { + if (this.readyState !== this.OPEN) { + logger5().debug("message received before socket is OPEN, queuing", { + readyState: this.readyState, + dataType: typeof data, + dataLength: typeof data === "string" ? data.length : data instanceof ArrayBuffer ? data.byteLength : data instanceof Uint8Array ? data.byteLength : "unknown" + }); + this.#queuedMessages.push(data); + return; + } + logger5().debug("fake websocket received message from server", { + dataType: typeof data, + dataLength: typeof data === "string" ? data.length : data instanceof ArrayBuffer ? data.byteLength : data instanceof Uint8Array ? data.byteLength : "unknown" + }); + const event = { + type: "message", + data, + target: this, + currentTarget: this + }; + this.#dispatchEvent("message", event); + } + #handleClose(code, reason) { + if (this.readyState === this.CLOSED) return; + this.#readyState = this.CLOSED; + const event = { + type: "close", + code, + reason, + wasClean: code === 1e3, + target: this, + currentTarget: this + }; + this.#dispatchEvent("close", event); + } + addEventListener(type, listener) { + if (!this.#eventListeners.has(type)) { + this.#eventListeners.set(type, []); + } + this.#eventListeners.get(type).push(listener); + this.#flushBufferedEvents(type); + } + removeEventListener(type, listener) { + const listeners = this.#eventListeners.get(type); + if (listeners) { + const index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + } + } + #dispatchEvent(type, event) { + const listeners = this.#eventListeners.get(type); + if (listeners && listeners.length > 0) { + logger5().debug( + `dispatching ${type} event to ${listeners.length} listeners` + ); + for (const listener of listeners) { + try { + listener(event); + } catch (err) { + logger5().error(`error in ${type} event listener`, { error: err }); + } + } + } else { + logger5().debug(`no ${type} listeners registered, buffering event`); + this.#bufferedEvents.push({ type, event }); + } + switch (type) { + case "open": + if (this.#onopen) { + try { + this.#onopen(event); + } catch (error) { + logger5().error("error in onopen handler", { error }); + } + } + break; + case "close": + if (this.#onclose) { + try { + this.#onclose(event); + } catch (error) { + logger5().error("error in onclose handler", { error }); + } + } + break; + case "error": + if (this.#onerror) { + try { + this.#onerror(event); + } catch (error) { + logger5().error("error in onerror handler", { error }); + } + } + break; + case "message": + if (this.#onmessage) { + try { + this.#onmessage(event); + } catch (error) { + logger5().error("error in onmessage handler", { error }); + } + } + break; + } + } + dispatchEvent(event) { + this.#dispatchEvent(event.type, event); + return true; + } + #flushBufferedEvents(type) { + const eventsToFlush = this.#bufferedEvents.filter( + (buffered) => buffered.type === type + ); + this.#bufferedEvents = this.#bufferedEvents.filter( + (buffered) => buffered.type !== type + ); + for (const { event } of eventsToFlush) { + this.#dispatchEvent(type, event); + } + } + #fireOpen() { + try { + const event = { + type: "open", + target: this, + currentTarget: this + }; + this.#dispatchEvent("open", event); + } catch (err) { + logger5().error("error in open event", { error: err }); + } + } + #fireClose(event) { + try { + this.#dispatchEvent("close", event); + } catch (err) { + logger5().error("error in close event", { error: err }); + } + } + #fireError(error) { + try { + const event = { + type: "error", + target: this, + currentTarget: this, + error, + message: error instanceof Error ? error.message : String(error) + }; + this.#dispatchEvent("error", event); + } catch (err) { + logger5().error("error in error event", { error: err }); + } + logger5().error("websocket error", { error }); + } + // Event handler properties with getters/setters + #onopen = null; + #onclose = null; + #onerror = null; + #onmessage = null; + get onopen() { + return this.#onopen; + } + set onopen(handler) { + this.#onopen = handler; + } + get onclose() { + return this.#onclose; + } + set onclose(handler) { + this.#onclose = handler; + } + get onerror() { + return this.#onerror; + } + set onerror(handler) { + this.#onerror = handler; + } + get onmessage() { + return this.#onmessage; + } + set onmessage(handler) { + this.#onmessage = handler; + } +}; + +// src/drivers/engine/actor-driver.ts +import { Runner } from "@rivetkit/engine-runner"; +import * as cbor10 from "cbor-x"; +import { WSContext as WSContext2 } from "hono/ws"; +import invariant7 from "invariant"; + +// src/registry/run-config.ts +import { z as z8 } from "zod"; + +// src/inspector/config.ts +import { z as z7 } from "zod"; +var defaultTokenFn = () => { + const envToken = getEnvUniversal("RIVETKIT_INSPECTOR_TOKEN"); + if (envToken) { + return envToken; + } + return ""; +}; +var defaultEnabled = () => { + return getEnvUniversal("NODE_ENV") !== "production" || !getEnvUniversal("RIVETKIT_INSPECTOR_DISABLE"); +}; +var defaultInspectorOrigins = [ + "http://localhost:43708", + "https://studio.rivet.gg" +]; +var defaultCors = { + origin: (origin) => { + if (defaultInspectorOrigins.includes(origin) || origin.startsWith("https://") && origin.endsWith("rivet-gg.vercel.app")) { + return origin; + } else { + return null; + } + }, + allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], + allowHeaders: [ + "Content-Type", + "Authorization", + HEADER_ACTOR_QUERY, + "last-event-id" + ], + maxAge: 3600, + credentials: true +}; +var InspectorConfigSchema = z7.object({ + enabled: z7.boolean().optional().default(defaultEnabled), + /** CORS configuration for the router. Uses Hono's CORS middleware options. */ + cors: z7.custom().optional().default(() => defaultCors), + /** + * Token used to access the Inspector. + */ + token: z7.function().returns(z7.string()).optional().default(() => defaultTokenFn), + /** + * Default RivetKit server endpoint for Rivet Inspector to connect to. This should be the same endpoint as what you use for your Rivet client to connect to RivetKit. + * + * This is a convenience property just for printing out the inspector URL. + */ + defaultEndpoint: z7.string().optional() +}).optional().default(() => ({ + enabled: defaultEnabled(), + token: defaultTokenFn, + cors: defaultCors +})); + +// src/registry/run-config.ts +var DriverConfigSchema = z8.object({ + /** Machine-readable name to identify this driver by. */ + name: z8.string(), + manager: z8.custom(), + actor: z8.custom() +}); +var RunConfigSchema = z8.object({ + driver: DriverConfigSchema.optional(), + /** Endpoint to connect to the Rivet engine. Can be configured via RIVET_ENGINE env var. */ + engine: z8.string().optional(), + // This is a function to allow for lazy configuration of upgradeWebSocket on the + // fly. This is required since the dependencies that profie upgradeWebSocket + // (specifically Node.js) can sometimes only be specified after the router is + // created or must be imported async using `await import(...)` + getUpgradeWebSocket: z8.custom().optional(), + role: z8.enum(["all", "server", "runner"]).optional().default("all"), + /** CORS configuration for the router. Uses Hono's CORS middleware options. */ + cors: z8.custom().optional(), + maxIncomingMessageSize: z8.number().optional().default(65536), + inspector: InspectorConfigSchema, + /** + * Base path for the router. This is used to prefix all routes. + * For example, if the base path is `/api`, then the route `/actors` will be + * available at `/api/actors`. + */ + basePath: z8.string().optional().default("/") +}).default({}); + +// src/driver-helpers/utils.ts +import * as cbor9 from "cbor-x"; +function serializeEmptyPersistData(input) { + const persistData = { + input: input !== void 0 ? bufferToArrayBuffer(cbor9.encode(input)) : null, + hasInitialized: false, + state: bufferToArrayBuffer(cbor9.encode(void 0)), + connections: [], + scheduledEvents: [] + }; + return PERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(persistData); +} + +// src/drivers/engine/keys.ts +var EMPTY_KEY = "/"; +var KEY_SEPARATOR = "/"; +function serializeActorKey(key) { + if (key.length === 0) { + return EMPTY_KEY; + } + const escapedParts = key.map((part) => { + if (part === "") { + return "\\0"; + } + let escaped = part.replace(/\\/g, "\\\\"); + escaped = escaped.replace(/\//g, `\\${KEY_SEPARATOR}`); + return escaped; + }); + return escapedParts.join(KEY_SEPARATOR); +} +function deserializeActorKey(keyString) { + if (keyString === void 0 || keyString === null || keyString === EMPTY_KEY) { + return []; + } + const parts = []; + let currentPart = ""; + let escaping = false; + let isEmptyStringMarker = false; + for (let i = 0; i < keyString.length; i++) { + const char = keyString[i]; + if (escaping) { + if (char === "0") { + isEmptyStringMarker = true; + } else { + currentPart += char; + } + escaping = false; + } else if (char === "\\") { + escaping = true; + } else if (char === KEY_SEPARATOR) { + if (isEmptyStringMarker) { + parts.push(""); + isEmptyStringMarker = false; + } else { + parts.push(currentPart); + } + currentPart = ""; + } else { + currentPart += char; + } + } + if (escaping) { + parts.push(currentPart + "\\"); + } else if (isEmptyStringMarker) { + parts.push(""); + } else if (currentPart !== "" || parts.length > 0) { + parts.push(currentPart); + } + return parts; +} + +// src/drivers/engine/kv.ts +var KEYS = { + PERSIST_DATA: Uint8Array.from([1, 1]) +}; + +// src/drivers/engine/log.ts +var LOGGER_NAME4 = "driver-engine"; +function logger6() { + return getLogger(LOGGER_NAME4); +} + +// src/drivers/engine/actor-driver.ts +var EngineActorDriver = class { + #registryConfig; + #runConfig; + #managerDriver; + #inlineClient; + #config; + #runner; + #actors = /* @__PURE__ */ new Map(); + #actorRouter; + #version = 1; + // Version for the runner protocol + constructor(registryConfig, runConfig, managerDriver, inlineClient, config4) { + this.#registryConfig = registryConfig; + this.#runConfig = runConfig; + this.#managerDriver = managerDriver; + this.#inlineClient = inlineClient; + this.#config = config4; + this.#actorRouter = createActorRouter(runConfig, this); + let hasDisconnected = false; + const runnerConfig = { + version: this.#version, + endpoint: config4.endpoint, + pegboardEndpoint: config4.pegboardEndpoint, + namespace: config4.namespace, + totalSlots: config4.totalSlots, + runnerName: config4.runnerName, + runnerKey: config4.runnerKey, + metadata: { + inspectorToken: this.#runConfig.inspector.token() + }, + prepopulateActorNames: Object.fromEntries( + Object.keys(this.#registryConfig.use).map((name) => [ + name, + { metadata: {} } + ]) + ), + onConnected: () => { + if (hasDisconnected) { + logger6().info("runner reconnected", { + namespace: this.#config.namespace, + runnerName: this.#config.runnerName + }); + } else { + logger6().debug("runner connected", { + namespace: this.#config.namespace, + runnerName: this.#config.runnerName + }); + } + }, + onDisconnected: () => { + logger6().warn("runner disconnected", { + namespace: this.#config.namespace, + runnerName: this.#config.runnerName + }); + hasDisconnected = true; + }, + fetch: this.#runnerFetch.bind(this), + websocket: this.#runnerWebSocket.bind(this), + onActorStart: this.#runnerOnActorStart.bind(this), + onActorStop: this.#runnerOnActorStop.bind(this) + }; + this.#runner = new Runner(runnerConfig); + this.#runner.start(); + logger6().debug("engine runner started", { + endpoint: config4.endpoint, + namespace: config4.namespace, + runnerName: config4.runnerName + }); + } + async #loadActorHandler(actorId) { + const handler = this.#actors.get(actorId); + if (!handler) throw new Error(`Actor handler does not exist ${actorId}`); + if (handler.actorStartPromise) await handler.actorStartPromise.promise; + if (!handler.actor) throw new Error("Actor should be loaded"); + return handler; + } + async loadActor(actorId) { + const handler = await this.#loadActorHandler(actorId); + if (!handler.actor) throw new Error(`Actor ${actorId} failed to load`); + return handler.actor; + } + getGenericConnGlobalState(actorId) { + const handler = this.#actors.get(actorId); + if (!handler) { + throw new Error(`Actor ${actorId} not loaded`); + } + return handler.genericConnGlobalState; + } + getContext(actorId) { + return {}; + } + async readPersistedData(actorId) { + const handler = this.#actors.get(actorId); + if (!handler) throw new Error(`Actor ${actorId} not loaded`); + if (handler.persistedData) return handler.persistedData; + const [value] = await this.#runner.kvGet(actorId, [KEYS.PERSIST_DATA]); + if (value !== null) { + handler.persistedData = value; + return value; + } else { + return void 0; + } + } + async writePersistedData(actorId, data) { + const handler = this.#actors.get(actorId); + if (!handler) throw new Error(`Actor ${actorId} not loaded`); + handler.persistedData = data; + await this.#runner.kvPut(actorId, [[KEYS.PERSIST_DATA, data]]); + } + async setAlarm(actor2, timestamp) { + } + async getDatabase(_actorId) { + return void 0; + } + // Runner lifecycle callbacks + async #runnerOnActorStart(actorId, generation, config4) { + logger6().debug("runner actor starting", { + actorId, + name: config4.name, + key: config4.key, + generation + }); + let input; + if (config4.input) { + input = cbor10.decode(config4.input); + } + let handler = this.#actors.get(actorId); + if (!handler) { + handler = { + genericConnGlobalState: new GenericConnGlobalState(), + actorStartPromise: Promise.withResolvers(), + persistedData: serializeEmptyPersistData(input) + }; + this.#actors.set(actorId, handler); + } + const name = config4.name; + invariant7(config4.key, "actor should have a key"); + const key = deserializeActorKey(config4.key); + const definition = lookupInRegistry( + this.#registryConfig, + config4.name + // TODO: Remove cast + ); + handler.actor = definition.instantiate(); + const connDrivers = createGenericConnDrivers( + handler.genericConnGlobalState + ); + await handler.actor.start( + connDrivers, + this, + this.#inlineClient, + actorId, + name, + key, + "unknown" + // TODO: Add regions + ); + handler.actorStartPromise?.resolve(); + handler.actorStartPromise = void 0; + logger6().debug("runner actor started", { actorId, name, key }); + } + async #runnerOnActorStop(actorId, generation) { + logger6().debug("runner actor stopping", { actorId, generation }); + const handler = this.#actors.get(actorId); + if (handler?.actor) { + await handler.actor._stop(); + this.#actors.delete(actorId); + } + logger6().debug("runner actor stopped", { actorId }); + } + async #runnerFetch(actorId, request) { + logger6().debug("runner fetch", { + actorId, + url: request.url, + method: request.method + }); + return await this.#actorRouter.fetch(request, { actorId }); + } + async #runnerWebSocket(actorId, websocketRaw, request) { + const websocket = websocketRaw; + logger6().debug("runner websocket", { actorId, url: request.url }); + const url = new URL(request.url); + const encodingRaw = request.headers.get(HEADER_ENCODING); + const connParamsRaw = request.headers.get(HEADER_CONN_PARAMS); + const authDataRaw = request.headers.get(HEADER_AUTH_DATA); + const encoding = EncodingSchema.parse(encodingRaw); + const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : void 0; + const authData = authDataRaw ? JSON.parse(authDataRaw) : void 0; + let wsHandlerPromise; + if (url.pathname === PATH_CONNECT_WEBSOCKET) { + wsHandlerPromise = handleWebSocketConnect( + request, + this.#runConfig, + this, + actorId, + encoding, + connParams, + authData + ); + } else if (url.pathname.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) { + wsHandlerPromise = handleRawWebSocketHandler( + request, + url.pathname + url.search, + this, + actorId, + authData + ); + } else { + throw new Error(`Unreachable path: ${url.pathname}`); + } + const wsContext = new WSContext2(websocket); + wsHandlerPromise.catch((err) => { + logger6().error("building websocket handlers errored", { err }); + wsContext.close(1011, `${err}`); + }); + if (websocket.readyState === 1) { + wsHandlerPromise.then((x) => x.onOpen?.(new Event("open"), wsContext)); + } else { + websocket.addEventListener("open", (event) => { + wsHandlerPromise.then((x) => x.onOpen?.(event, wsContext)); + }); + } + websocket.addEventListener("message", (event) => { + wsHandlerPromise.then((x) => x.onMessage?.(event, wsContext)); + }); + websocket.addEventListener("close", (event) => { + wsHandlerPromise.then((x) => x.onClose?.(event, wsContext)); + }); + websocket.addEventListener("error", (event) => { + wsHandlerPromise.then((x) => x.onError?.(event, wsContext)); + }); + } + async sleep(actorId) { + this.#runner.sleepActor(actorId); + } + async shutdown(immediate) { + logger6().info("stopping engine actor driver"); + await this.#runner.shutdown(immediate); + } +}; + +// src/drivers/engine/config.ts +import { z as z9 } from "zod"; +var ConfigSchema = z9.object({ + app: z9.custom().optional(), + endpoint: z9.string().default( + () => getEnvUniversal("RIVET_ENGINE") ?? "http://localhost:7080" + ), + pegboardEndpoint: z9.string().optional(), + namespace: z9.string().default(() => getEnvUniversal("RIVET_NAMESPACE") ?? "default"), + runnerName: z9.string().default(() => getEnvUniversal("RIVET_RUNNER") ?? "rivetkit"), + // TODO: Automatically attempt ot determine key by common env vars (e.g. k8s pod name) + runnerKey: z9.string().default( + () => getEnvUniversal("RIVET_RUNNER_KEY") ?? crypto.randomUUID() + ), + totalSlots: z9.number().default(1e5), + addresses: z9.record( + z9.object({ + host: z9.string(), + port: z9.number() + }) + ).default({ main: { host: "127.0.0.1", port: 5051 } }) +}).default({}); + +// src/drivers/engine/manager-driver.ts +import * as cbor11 from "cbor-x"; +import invariant8 from "invariant"; + +// src/common/websocket.ts +var webSocketPromise = null; +async function importWebSocket() { + if (webSocketPromise !== null) { + return webSocketPromise; + } + webSocketPromise = (async () => { + let _WebSocket; + if (typeof WebSocket !== "undefined") { + _WebSocket = WebSocket; + logger4().debug("using native websocket"); + } else { + try { + const ws = await import("ws"); + _WebSocket = ws.default; + logger4().debug("using websocket from npm"); + } catch { + _WebSocket = class MockWebSocket { + constructor() { + throw new Error( + 'WebSocket support requires installing the "ws" peer dependency.' + ); + } + }; + logger4().debug("using mock websocket"); + } + } + return _WebSocket; + })(); + return webSocketPromise; +} + +// src/drivers/engine/api-utils.ts +var EngineApiError = class extends Error { + constructor(group, code, message) { + super(message || `Engine API error: ${group}/${code}`); + this.group = group; + this.code = code; + this.name = "EngineApiError"; + } +}; +async function apiCall(endpoint, namespace, method, path3, body) { + const url = `${endpoint}${path3}${path3.includes("?") ? "&" : "?"}namespace=${encodeURIComponent(namespace)}`; + const options = { + method, + headers: { + "Content-Type": "application/json" + } + }; + if (body !== void 0 && method !== "GET") { + options.body = JSON.stringify(body); + } + logger6().debug("making api call", { method, url }); + const response = await fetch(url, options); + if (!response.ok) { + const errorText = await response.text(); + logger6().error("api call failed", { + status: response.status, + statusText: response.statusText, + error: errorText, + method, + path: path3 + }); + try { + const errorData = JSON.parse(errorText); + if (errorData.kind === "error" && errorData.group && errorData.code) { + throw new EngineApiError( + errorData.group, + errorData.code, + errorData.message + ); + } + } catch (parseError) { + } + throw new Error( + `API call failed: ${response.status} ${response.statusText}` + ); + } + return response.json(); +} + +// src/drivers/engine/api-endpoints.ts +async function getActor(config4, actorId) { + return apiCall( + config4.endpoint, + config4.namespace, + "GET", + `/actors/${encodeURIComponent(actorId)}` + ); +} +async function getActorById(config4, name, key) { + const serializedKey = serializeActorKey(key); + return apiCall( + config4.endpoint, + config4.namespace, + "GET", + `/actors/by-id?name=${encodeURIComponent(name)}&key=${encodeURIComponent(serializedKey)}` + ); +} +async function getOrCreateActorById(config4, request) { + return apiCall( + config4.endpoint, + config4.namespace, + "PUT", + `/actors/by-id`, + request + ); +} +async function createActor(config4, request) { + return apiCall( + config4.endpoint, + config4.namespace, + "POST", + `/actors`, + request + ); +} +async function destroyActor(config4, actorId) { + return apiCall( + config4.endpoint, + config4.namespace, + "DELETE", + `/actors/${encodeURIComponent(actorId)}` + ); +} + +// src/drivers/engine/ws-proxy.ts +async function createWebSocketProxy(c, targetUrl, headers) { + const WebSocket2 = await importWebSocket(); + for (const [k, v] of c.req.raw.headers.entries()) { + if (!k.startsWith("sec-") && k !== "connection" && k !== "upgrade") { + headers[k] = v; + } + } + const state = {}; + return { + onOpen: async (event, clientWs) => { + logger6().debug("client websocket connected", { targetUrl }); + if (clientWs.readyState !== 1) { + logger6().warn("client websocket not open on connection", { + targetUrl, + readyState: clientWs.readyState + }); + return; + } + const targetWs = new WebSocket2(targetUrl, { headers }); + state.targetWs = targetWs; + state.connectPromise = new Promise((resolve, reject) => { + targetWs.addEventListener("open", () => { + logger6().debug("target websocket connected", { targetUrl }); + if (clientWs.readyState !== 1) { + logger6().warn("client websocket closed before target connected", { + targetUrl, + clientReadyState: clientWs.readyState + }); + targetWs.close(1001, "Client disconnected"); + reject(new Error("Client disconnected")); + return; + } + resolve(); + }); + targetWs.addEventListener("error", (error) => { + logger6().warn("target websocket error during connection", { + targetUrl + }); + reject(error); + }); + }); + state.targetWs.addEventListener("message", (event2) => { + if (typeof event2.data === "string" || event2.data instanceof ArrayBuffer) { + clientWs.send(event2.data); + } else if (event2.data instanceof Blob) { + event2.data.arrayBuffer().then((buffer) => { + clientWs.send(buffer); + }); + } + }); + state.targetWs.addEventListener("close", (event2) => { + logger6().debug("target websocket closed", { + targetUrl, + code: event2.code, + reason: event2.reason + }); + closeWebSocketIfOpen(clientWs, event2.code, event2.reason); + }); + state.targetWs.addEventListener("error", (error) => { + logger6().error("target websocket error", { targetUrl, error }); + closeWebSocketIfOpen(clientWs, 1011, "Target WebSocket error"); + }); + }, + onMessage: async (event, clientWs) => { + if (!state.targetWs || !state.connectPromise) { + logger6().error("websocket state not initialized", { targetUrl }); + return; + } + try { + await state.connectPromise; + if (state.targetWs.readyState === WebSocket2.OPEN) { + state.targetWs.send(event.data); + } else { + logger6().warn("target websocket not open", { + targetUrl, + readyState: state.targetWs.readyState + }); + } + } catch (error) { + logger6().error("failed to connect to target websocket", { + targetUrl, + error + }); + closeWebSocketIfOpen(clientWs, 1011, "Failed to connect to target"); + } + }, + onClose: (event, clientWs) => { + logger6().debug("client websocket closed", { + targetUrl, + code: event.code, + reason: event.reason, + wasClean: event.wasClean + }); + if (state.targetWs) { + if (state.targetWs.readyState === WebSocket2.OPEN || state.targetWs.readyState === WebSocket2.CONNECTING) { + state.targetWs.close(1e3, event.reason || "Client disconnected"); + } + } + }, + onError: (event, clientWs) => { + logger6().error("client websocket error", { targetUrl, event }); + if (state.targetWs) { + if (state.targetWs.readyState === WebSocket2.OPEN) { + state.targetWs.close(1011, "Client WebSocket error"); + } else if (state.targetWs.readyState === WebSocket2.CONNECTING) { + state.targetWs.close(); + } + } + } + }; +} +function closeWebSocketIfOpen(ws, code, reason) { + if (ws.readyState === 1) { + ws.close(code, reason); + } else if ("close" in ws && ws.readyState === WebSocket.OPEN) { + ws.close(code, reason); + } +} + +// src/drivers/engine/manager-driver.ts +var EngineManagerDriver = class { + #config; + #runConfig; + #importWebSocketPromise; + constructor(config4, runConfig) { + this.#config = config4; + this.#runConfig = runConfig; + if (!this.#runConfig.inspector.token()) { + const token = generateRandomString(); + this.#runConfig.inspector.token = () => token; + } + this.#importWebSocketPromise = importWebSocket(); + } + async sendRequest(actorId, actorRequest) { + logger6().debug("sending request to actor via guard", { + actorId, + method: actorRequest.method, + url: actorRequest.url + }); + return this.#forwardHttpRequest(actorRequest, actorId); + } + async openWebSocket(path3, actorId, encoding, params) { + const WebSocket2 = await this.#importWebSocketPromise; + const guardUrl = `${this.#config.endpoint}${path3}`; + logger6().debug("opening websocket to actor via guard", { + actorId, + path: path3, + guardUrl + }); + const ws = new WebSocket2(guardUrl, { + headers: buildGuardHeadersForWebSocket(actorId, encoding, params) + }); + logger6().debug("websocket connection opened", { actorId }); + return ws; + } + async proxyRequest(_c, actorRequest, actorId) { + logger6().debug("forwarding request to actor via guard", { + actorId, + method: actorRequest.method, + url: actorRequest.url, + hasBody: !!actorRequest.body + }); + return this.#forwardHttpRequest(actorRequest, actorId); + } + async proxyWebSocket(c, path3, actorId, encoding, params, authData) { + const upgradeWebSocket = this.#runConfig.getUpgradeWebSocket?.(); + invariant8(upgradeWebSocket, "missing getUpgradeWebSocket"); + const guardUrl = `${this.#config.endpoint}${path3}`; + const wsGuardUrl = guardUrl.replace("http://", "ws://"); + logger6().debug("forwarding websocket to actor via guard", { + actorId, + path: path3, + guardUrl + }); + const headers = buildGuardHeadersForWebSocket( + actorId, + encoding, + params, + authData + ); + const args = await createWebSocketProxy(c, wsGuardUrl, headers); + return await upgradeWebSocket(() => args)(c, noopNext()); + } + extraStartupLog() { + return { + engine: this.#config.endpoint, + namespace: this.#config.namespace, + runner: this.#config.runnerName, + address: Object.values(this.#config.addresses).map((v) => `${v.host}:${v.port}`).join(", ") + }; + } + async getForId({ + c, + name, + actorId + }) { + try { + const response = await getActor(this.#config, actorId); + if (response.actor.name !== name) { + logger6().debug("actor name mismatch from api", { + actorId, + apiName: response.actor.name, + requestedName: name + }); + return void 0; + } + const keyRaw = response.actor.key; + invariant8(keyRaw, `actor ${actorId} should have key`); + const key = deserializeActorKey(keyRaw); + return { + actorId, + name, + key + }; + } catch (error) { + if (error instanceof EngineApiError && error.group === "actor" && error.code === "not_found") { + return void 0; + } + throw error; + } + } + async getWithKey({ + c, + name, + key + }) { + logger6().debug("getWithKey: searching for actor", { name, key }); + try { + const response = await getActorById(this.#config, name, key); + if (!response.actor_id) { + return void 0; + } + const actorId = response.actor_id; + logger6().debug("getWithKey: found actor via api", { + actorId, + name, + key + }); + return { + actorId, + name, + key + }; + } catch (error) { + if (error instanceof EngineApiError && error.group === "actor" && error.code === "not_found") { + return void 0; + } + throw error; + } + } + async getOrCreateWithKey(input) { + const { c, name, key, input: actorInput, region } = input; + logger6().info( + "getOrCreateWithKey: getting or creating actor via engine api", + { + name, + key + } + ); + const response = await getOrCreateActorById(this.#config, { + name, + key: serializeActorKey(key), + runner_name_selector: this.#config.runnerName, + input: input ? cbor11.encode(actorInput).toString("base64") : void 0, + crash_policy: "sleep" + }); + const actorId = response.actor_id; + logger6().info("getOrCreateWithKey: actor ready", { + actorId, + name, + key, + created: response.created + }); + return { + actorId, + name, + key + }; + } + async createActor({ + c, + name, + key, + input + }) { + const existingActor = await this.getWithKey({ c, name, key }); + if (existingActor) { + throw new ActorAlreadyExists(name, key); + } + logger6().info("creating actor via engine api", { name, key }); + const result = await createActor(this.#config, { + name, + runner_name_selector: this.#config.runnerName, + key: serializeActorKey(key), + input: input ? cbor11.encode(input).toString("base64") : null, + crash_policy: "sleep" + }); + const actorId = result.actor.actor_id; + logger6().info("actor created", { actorId, name, key }); + return { + actorId, + name, + key + }; + } + async destroyActor(actorId) { + logger6().info("destroying actor via engine api", { actorId }); + await destroyActor(this.#config, actorId); + logger6().info("actor destroyed", { actorId }); + } + async #forwardHttpRequest(actorRequest, actorId) { + const url = new URL(actorRequest.url); + const guardUrl = `${this.#config.endpoint}${url.pathname}${url.search}`; + let bodyToSend = null; + const guardHeaders = buildGuardHeadersForHttp(actorRequest, actorId); + if (actorRequest.body && actorRequest.method !== "GET" && actorRequest.method !== "HEAD") { + if (actorRequest.bodyUsed) { + throw new Error("Request body has already been consumed"); + } + const clonedRequest = actorRequest.clone(); + bodyToSend = await clonedRequest.arrayBuffer(); + guardHeaders.delete("transfer-encoding"); + guardHeaders.set( + "content-length", + String(bodyToSend.byteLength) + ); + } + const guardRequest = new Request(guardUrl, { + method: actorRequest.method, + headers: guardHeaders, + body: bodyToSend + }); + return mutableResponse(await fetch(guardRequest)); + } +}; +function mutableResponse(fetchRes) { + return new Response(fetchRes.body, fetchRes); +} +function buildGuardHeadersForHttp(actorRequest, actorId) { + const headers = new Headers(); + for (const [key, value] of actorRequest.headers.entries()) { + headers.set(key, value); + } + headers.set("x-rivet-target", "actor"); + headers.set("x-rivet-actor", actorId); + headers.set("x-rivet-port", "main"); + return headers; +} +function buildGuardHeadersForWebSocket(actorId, encoding, params, authData) { + const headers = {}; + headers["x-rivet-target"] = "actor"; + headers["x-rivet-actor"] = actorId; + headers["x-rivet-port"] = "main"; + headers[HEADER_EXPOSE_INTERNAL_ERROR] = "true"; + headers[HEADER_ENCODING] = encoding; + if (params) { + headers[HEADER_CONN_PARAMS] = JSON.stringify(params); + } + if (authData) { + headers[HEADER_AUTH_DATA] = JSON.stringify(authData); + } + return headers; +} + +// src/drivers/engine/mod.ts +function createEngineDriver(inputConfig) { + const config4 = ConfigSchema.parse(inputConfig); + return { + name: "engine", + manager: (_registryConfig, runConfig) => { + return new EngineManagerDriver(config4, runConfig); + }, + actor: (registryConfig, runConfig, managerDriver, inlineClient) => { + return new EngineActorDriver( + registryConfig, + runConfig, + managerDriver, + inlineClient, + config4 + ); + } + }; +} + +// src/drivers/file-system/actor.ts +var FileSystemActorDriver = class { + #registryConfig; + #runConfig; + #managerDriver; + #inlineClient; + #state; + constructor(registryConfig, runConfig, managerDriver, inlineClient, state) { + this.#registryConfig = registryConfig; + this.#runConfig = runConfig; + this.#managerDriver = managerDriver; + this.#inlineClient = inlineClient; + this.#state = state; + } + async loadActor(actorId) { + return this.#state.startActor( + this.#registryConfig, + this.#runConfig, + this.#inlineClient, + this, + actorId + ); + } + getGenericConnGlobalState(actorId) { + return this.#state.getActorOrError(actorId).genericConnGlobalState; + } + /** + * Get the current storage directory path + */ + get storagePath() { + return this.#state.storagePath; + } + getContext(_actorId) { + return {}; + } + async readPersistedData(actorId) { + return new Uint8Array( + (await this.#state.loadActorStateOrError(actorId)).persistedData + ); + } + async writePersistedData(actorId, data) { + const state = await this.#state.loadActorStateOrError(actorId); + await this.#state.writeActor(actorId, { + ...state, + persistedData: bufferToArrayBuffer(data) + }); + } + async setAlarm(actor2, timestamp) { + await this.#state.setActorAlarm(actor2.id, timestamp); + } + getDatabase(actorId) { + return this.#state.createDatabase(actorId); + } + sleep(actorId) { + return this.#state.sleepActor(actorId); + } +}; + +// src/drivers/file-system/global-state.ts +import * as crypto4 from "node:crypto"; +import * as fsSync2 from "node:fs"; +import * as fs2 from "node:fs/promises"; +import * as path2 from "node:path"; +import invariant9 from "invariant"; + +// dist/schemas/file-system-driver/v1.ts +import * as bare3 from "@bare-ts/lib"; +var config3 = /* @__PURE__ */ bare3.Config({}); +function read03(bc) { + const len = bare3.readUintSafe(bc); + if (len === 0) { + return []; + } + const result = [bare3.readString(bc)]; + for (let i = 1; i < len; i++) { + result[i] = bare3.readString(bc); + } + return result; +} +function write03(bc, x) { + bare3.writeUintSafe(bc, x.length); + for (let i = 0; i < x.length; i++) { + bare3.writeString(bc, x[i]); + } +} +function readActorState(bc) { + return { + actorId: bare3.readString(bc), + name: bare3.readString(bc), + key: read03(bc), + persistedData: bare3.readData(bc), + createdAt: bare3.readU64(bc) + }; +} +function writeActorState(bc, x) { + bare3.writeString(bc, x.actorId); + bare3.writeString(bc, x.name); + write03(bc, x.key); + bare3.writeData(bc, x.persistedData); + bare3.writeU64(bc, x.createdAt); +} +function encodeActorState(x) { + const bc = new bare3.ByteCursor( + new Uint8Array(config3.initialBufferLength), + config3 + ); + writeActorState(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeActorState(bytes) { + const bc = new bare3.ByteCursor(bytes, config3); + const result = readActorState(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare3.BareError(bc.offset, "remaining bytes"); + } + return result; +} +function readActorAlarm(bc) { + return { + actorId: bare3.readString(bc), + timestamp: bare3.readUint(bc) + }; +} +function writeActorAlarm(bc, x) { + bare3.writeString(bc, x.actorId); + bare3.writeUint(bc, x.timestamp); +} +function encodeActorAlarm(x) { + const bc = new bare3.ByteCursor( + new Uint8Array(config3.initialBufferLength), + config3 + ); + writeActorAlarm(bc, x); + return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset); +} +function decodeActorAlarm(bytes) { + const bc = new bare3.ByteCursor(bytes, config3); + const result = readActorAlarm(bc); + if (bc.offset < bc.view.byteLength) { + throw new bare3.BareError(bc.offset, "remaining bytes"); + } + return result; +} + +// src/schemas/file-system-driver/versioned.ts +var CURRENT_VERSION3 = 1; +var migrations3 = /* @__PURE__ */ new Map(); +var ACTOR_STATE_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION3, + migrations: migrations3, + serializeVersion: (data) => encodeActorState(data), + deserializeVersion: (bytes) => decodeActorState(bytes) +}); +var ACTOR_ALARM_VERSIONED = createVersionedDataHandler({ + currentVersion: CURRENT_VERSION3, + migrations: migrations3, + serializeVersion: (data) => encodeActorAlarm(data), + deserializeVersion: (bytes) => decodeActorAlarm(bytes) +}); + +// src/drivers/file-system/log.ts +var LOGGER_NAME5 = "driver-fs"; +function logger7() { + return getLogger(LOGGER_NAME5); +} + +// src/drivers/file-system/utils.ts +import * as crypto3 from "node:crypto"; +import * as fsSync from "node:fs"; +import * as fs from "node:fs/promises"; +import * as os from "node:os"; +import * as path from "node:path"; +function generateActorId(name, key) { + const jsonString = JSON.stringify([name, key]); + const hash = crypto3.createHash("sha256").update(jsonString).digest("hex").substring(0, 16); + return hash; +} +function createHashForPath(dirPath) { + const normalizedPath = path.normalize(dirPath); + const lastComponent = path.basename(normalizedPath); + const hash = crypto3.createHash("sha256").update(normalizedPath).digest("hex").substring(0, 8); + return `${lastComponent}-${hash}`; +} +function getStoragePath(customPath) { + const dataPath = getDataPath("rivetkit"); + const pathToHash = customPath || process.cwd(); + const dirHash = createHashForPath(pathToHash); + return path.join(dataPath, dirHash); +} +async function pathExists(path3) { + try { + await fs.access(path3); + return true; + } catch { + return false; + } +} +async function ensureDirectoryExists(directoryPath) { + if (!await pathExists(directoryPath)) { + await fs.mkdir(directoryPath, { recursive: true }); + } +} +function ensureDirectoryExistsSync(directoryPath) { + if (!fsSync.existsSync(directoryPath)) { + fsSync.mkdirSync(directoryPath, { recursive: true }); + } +} +function getDataPath(appName) { + const platform = process.platform; + const homeDir = os.homedir(); + switch (platform) { + case "win32": + return path.join( + process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"), + appName + ); + case "darwin": + return path.join(homeDir, "Library", "Application Support", appName); + default: + return path.join( + process.env.XDG_DATA_HOME || path.join(homeDir, ".local", "share"), + appName + ); + } +} + +// src/drivers/file-system/global-state.ts +var FileSystemGlobalState = class { + #storagePath; + #stateDir; + #dbsDir; + #alarmsDir; + #persist; + #actors = /* @__PURE__ */ new Map(); + #actorCountOnStartup = 0; + #runnerParams; + get storagePath() { + return this.#storagePath; + } + get actorCountOnStartup() { + return this.#actorCountOnStartup; + } + constructor(persist = true, customPath) { + this.#persist = persist; + this.#storagePath = persist ? getStoragePath(customPath) : "/tmp"; + this.#stateDir = path2.join(this.#storagePath, "state"); + this.#dbsDir = path2.join(this.#storagePath, "databases"); + this.#alarmsDir = path2.join(this.#storagePath, "alarms"); + if (this.#persist) { + ensureDirectoryExistsSync(this.#stateDir); + ensureDirectoryExistsSync(this.#dbsDir); + ensureDirectoryExistsSync(this.#alarmsDir); + try { + const actorIds = fsSync2.readdirSync(this.#stateDir); + this.#actorCountOnStartup = actorIds.length; + } catch (error) { + logger7().error("failed to count actors", { error }); + } + logger7().debug("file system driver ready", { + dir: this.#storagePath, + actorCount: this.#actorCountOnStartup + }); + try { + this.#cleanupTempFilesSync(); + } catch (err) { + logger7().error("failed to cleanup temp files", { error: err }); + } + } else { + logger7().debug("memory driver ready"); + } + } + getActorStatePath(actorId) { + return path2.join(this.#stateDir, actorId); + } + getActorDbPath(actorId) { + return path2.join(this.#dbsDir, `${actorId}.db`); + } + getActorAlarmPath(actorId) { + return path2.join(this.#alarmsDir, actorId); + } + async *getActorsIterator(params) { + let actorIds = Array.from(this.#actors.keys()).sort(); + if (fsSync2.existsSync(this.#stateDir)) { + actorIds = fsSync2.readdirSync(this.#stateDir).filter((id) => !id.includes(".tmp")).sort(); + } + const startIndex = params.cursor ? actorIds.indexOf(params.cursor) + 1 : 0; + for (let i = startIndex; i < actorIds.length; i++) { + const actorId = actorIds[i]; + if (!actorId) { + continue; + } + try { + const state = await this.loadActorStateOrError(actorId); + yield state; + } catch (error) { + logger7().error("failed to load actor state", { actorId, error }); + } + } + } + /** + * Ensures an entry exists for this actor. + * + * Used for #createActor and #loadActor. + */ + #upsertEntry(actorId) { + let entry = this.#actors.get(actorId); + if (entry) { + return entry; + } + entry = { + id: actorId, + genericConnGlobalState: new GenericConnGlobalState(), + removed: false + }; + this.#actors.set(actorId, entry); + return entry; + } + /** + * Creates a new actor and writes to file system. + */ + async createActor(actorId, name, key, input) { + if (this.#actors.has(actorId)) { + throw new ActorAlreadyExists(name, key); + } + const entry = this.#upsertEntry(actorId); + entry.state = { + actorId, + name, + key, + createdAt: BigInt(Date.now()), + persistedData: bufferToArrayBuffer(serializeEmptyPersistData(input)) + }; + await this.writeActor(actorId, entry.state); + return entry; + } + /** + * Loads the actor from disk or returns the existing actor entry. This will return an entry even if the actor does not actually exist. + */ + async loadActor(actorId) { + const entry = this.#upsertEntry(actorId); + if (entry.state) { + return entry; + } + if (!this.#persist) { + return entry; + } + if (entry.loadPromise) { + await entry.loadPromise; + return entry; + } + entry.loadPromise = this.loadActorState(entry); + return entry.loadPromise; + } + async loadActorState(entry) { + const stateFilePath = this.getActorStatePath(entry.id); + try { + const stateData = await fs2.readFile(stateFilePath); + entry.state = ACTOR_STATE_VERSIONED.deserializeWithEmbeddedVersion( + new Uint8Array(stateData) + ); + return entry; + } catch (innerError) { + if (innerError.code === "ENOENT") { + entry.loadPromise = void 0; + return entry; + } + const error = new Error(`Failed to load actor state: ${innerError}`); + throw error; + } + } + async loadOrCreateActor(actorId, name, key, input) { + const entry = await this.loadActor(actorId); + if (!entry.state) { + entry.state = { + actorId, + name, + key, + createdAt: BigInt(Date.now()), + persistedData: bufferToArrayBuffer(serializeEmptyPersistData(input)) + }; + await this.writeActor(actorId, entry.state); + } + return entry; + } + async sleepActor(actorId) { + invariant9( + this.#persist, + "cannot sleep actor with memory driver, must use file system driver" + ); + const actor2 = this.#actors.get(actorId); + invariant9(actor2, `tried to sleep ${actorId}, does not exist`); + if (actor2.loadPromise) await actor2.loadPromise.catch(); + if (actor2.startPromise?.promise) await actor2.startPromise.promise.catch(); + actor2.removed = true; + invariant9(actor2.actor, "actor should be loaded"); + await actor2.actor._stop(); + this.#actors.delete(actorId); + } + /** + * Save actor state to disk. + */ + async writeActor(actorId, state) { + if (!this.#persist) { + return; + } + const entry = this.#actors.get(actorId); + invariant9(entry, "actor entry does not exist"); + await this.#performWrite(actorId, state); + } + async setActorAlarm(actorId, timestamp) { + const entry = this.#actors.get(actorId); + invariant9(entry, "actor entry does not exist"); + if (this.#persist) { + const alarmPath = this.getActorAlarmPath(actorId); + const tempPath = `${alarmPath}.tmp.${crypto4.randomUUID()}`; + try { + await ensureDirectoryExists(path2.dirname(alarmPath)); + const alarmData = { + actorId, + timestamp: BigInt(timestamp) + }; + const data = ACTOR_ALARM_VERSIONED.serializeWithEmbeddedVersion(alarmData); + await fs2.writeFile(tempPath, data); + await fs2.rename(tempPath, alarmPath); + } catch (error) { + try { + await fs2.unlink(tempPath); + } catch { + } + logger7().error("failed to write alarm", { actorId, error }); + throw new Error(`Failed to write alarm: ${error}`); + } + } + this.#scheduleAlarmTimeout(actorId, timestamp); + } + /** + * Perform the actual write operation with atomic writes + */ + async #performWrite(actorId, state) { + const dataPath = this.getActorStatePath(actorId); + const tempPath = `${dataPath}.tmp.${crypto4.randomUUID()}`; + try { + await ensureDirectoryExists(path2.dirname(dataPath)); + const bareState = { + actorId: state.actorId, + name: state.name, + key: state.key, + createdAt: state.createdAt, + persistedData: state.persistedData + }; + const serializedState = ACTOR_STATE_VERSIONED.serializeWithEmbeddedVersion(bareState); + await fs2.writeFile(tempPath, serializedState); + await fs2.rename(tempPath, dataPath); + } catch (error) { + try { + await fs2.unlink(tempPath); + } catch { + } + logger7().error("failed to save actor state", { actorId, error }); + throw new Error(`Failed to save actor state: ${error}`); + } + } + /** + * Call this method after the actor driver has been initiated. + * + * This will trigger all initial alarms from the file system. + * + * This needs to be sync since DriverConfig.actor is sync + */ + onRunnerStart(registryConfig, runConfig, inlineClient, actorDriver) { + if (this.#runnerParams) { + logger7().warn("already called onRunnerStart"); + return; + } + this.#runnerParams = { + registryConfig, + runConfig, + inlineClient, + actorDriver + }; + try { + this.#loadAlarmsSync(); + } catch (err) { + logger7().error("failed to load alarms on startup", { error: err }); + } + } + async startActor(registryConfig, runConfig, inlineClient, actorDriver, actorId) { + const entry = await this.loadActor(actorId); + if (!entry.state) { + throw new Error(`Actor does exist and cannot be started: ${actorId}`); + } + if (entry.startPromise) { + await entry.startPromise.promise; + invariant9(entry.actor, "actor should have loaded"); + return entry.actor; + } + if (entry.actor) { + return entry.actor; + } + entry.startPromise = Promise.withResolvers(); + try { + const definition = lookupInRegistry(registryConfig, entry.state.name); + entry.actor = definition.instantiate(); + const connDrivers = createGenericConnDrivers( + entry.genericConnGlobalState + ); + await entry.actor.start( + connDrivers, + actorDriver, + inlineClient, + actorId, + entry.state.name, + entry.state.key, + "unknown" + ); + entry.startPromise.resolve(); + entry.startPromise = void 0; + return entry.actor; + } catch (innerError) { + const error = new Error( + `Failed to start actor ${actorId}: ${innerError}`, + { cause: innerError } + ); + entry.startPromise?.reject(error); + entry.startPromise = void 0; + throw error; + } + } + async loadActorStateOrError(actorId) { + const state = (await this.loadActor(actorId)).state; + if (!state) throw new Error(`Actor does not exist: ${actorId}`); + return state; + } + getActorOrError(actorId) { + const entry = this.#actors.get(actorId); + if (!entry) throw new Error(`No entry for actor: ${actorId}`); + return entry; + } + async createDatabase(actorId) { + return this.getActorDbPath(actorId); + } + /** + * Load all persisted alarms from disk and schedule their timers. + */ + #loadAlarmsSync() { + try { + const files = fsSync2.existsSync(this.#alarmsDir) ? fsSync2.readdirSync(this.#alarmsDir) : []; + for (const file of files) { + if (file.includes(".tmp.")) continue; + const fullPath = path2.join(this.#alarmsDir, file); + try { + const buf = fsSync2.readFileSync(fullPath); + const alarmData = ACTOR_ALARM_VERSIONED.deserializeWithEmbeddedVersion( + new Uint8Array(buf) + ); + const timestamp = Number(alarmData.timestamp); + if (Number.isFinite(timestamp)) { + this.#scheduleAlarmTimeout(alarmData.actorId, timestamp); + } else { + logger7().debug("invalid alarm file contents", { file }); + } + } catch (err) { + logger7().error("failed to read alarm file", { + file, + error: stringifyError(err) + }); + } + } + } catch (err) { + logger7().error("failed to list alarms directory", { error: err }); + } + } + /** + * Schedule an alarm timer for an actor without writing to disk. + */ + #scheduleAlarmTimeout(actorId, timestamp) { + const entry = this.#upsertEntry(actorId); + if (entry.alarmTimestamp !== void 0 && timestamp >= entry.alarmTimestamp) { + logger7().debug("skipping alarm schedule (later than existing)", { + actorId, + timestamp, + current: entry.alarmTimestamp + }); + return; + } + logger7().debug("scheduling alarm", { actorId, timestamp }); + entry.alarmTimeout?.abort(); + entry.alarmTimestamp = timestamp; + const delay = Math.max(0, timestamp - Date.now()); + entry.alarmTimeout = setLongTimeout(async () => { + entry.alarmTimestamp = void 0; + if (this.#persist) { + try { + await fs2.unlink(this.getActorAlarmPath(actorId)); + } catch (err) { + if (err?.code !== "ENOENT") { + logger7().debug("failed to remove alarm file", { + actorId, + error: stringifyError(err) + }); + } + } + } + try { + logger7().debug("triggering alarm", { actorId, timestamp }); + const loaded = await this.loadActor(actorId); + if (!loaded.state) throw new Error(`Actor does not exist: ${actorId}`); + const runnerParams = this.#runnerParams; + invariant9(runnerParams, "missing runner params"); + if (!loaded.actor) { + await this.startActor( + runnerParams.registryConfig, + runnerParams.runConfig, + runnerParams.inlineClient, + runnerParams.actorDriver, + actorId + ); + } + invariant9(loaded.actor, "actor should be loaded after wake"); + await loaded.actor._onAlarm(); + } catch (err) { + logger7().error("failed to handle alarm", { + actorId, + error: stringifyError(err) + }); + } + }, delay); + } + getOrCreateInspectorAccessToken() { + const tokenPath = path2.join(this.#storagePath, "inspector-token"); + if (fsSync2.existsSync(tokenPath)) { + return fsSync2.readFileSync(tokenPath, "utf-8"); + } + const newToken = generateRandomString(); + fsSync2.writeFileSync(tokenPath, newToken); + return newToken; + } + /** + * Cleanup stale temp files on startup (synchronous) + */ + #cleanupTempFilesSync() { + try { + const files = fsSync2.readdirSync(this.#stateDir); + const tempFiles = files.filter((f) => f.includes(".tmp.")); + const oneHourAgo = Date.now() - 36e5; + for (const tempFile of tempFiles) { + try { + const fullPath = path2.join(this.#stateDir, tempFile); + const stat = fsSync2.statSync(fullPath); + if (stat.mtimeMs < oneHourAgo) { + fsSync2.unlinkSync(fullPath); + logger7().info("cleaned up stale temp file", { file: tempFile }); + } + } catch (err) { + logger7().debug("failed to cleanup temp file", { + file: tempFile, + error: err + }); + } + } + } catch (err) { + logger7().error("failed to read actors directory for cleanup", { + error: err + }); + } + } +}; + +// src/drivers/file-system/manager.ts +import invariant11 from "invariant"; + +// src/inline-client-driver/mod.ts +import * as cbor12 from "cbor-x"; +import invariant10 from "invariant"; +import onChange2 from "on-change"; + +// src/common/eventsource.ts +var eventSourcePromise = null; +async function importEventSource() { + if (eventSourcePromise !== null) { + return eventSourcePromise; + } + eventSourcePromise = (async () => { + let _EventSource; + try { + const es = await import("eventsource"); + _EventSource = es.EventSource; + logger4().debug("using eventsource from npm"); + } catch (err) { + _EventSource = class MockEventSource { + constructor() { + throw new Error( + 'EventSource support requires installing the "eventsource" peer dependency.' + ); + } + }; + logger4().debug("using mock eventsource"); + } + return _EventSource; + })(); + return eventSourcePromise; +} + +// src/inline-client-driver/log.ts +var LOGGER_NAME6 = "inline-client-driver"; +function logger8() { + return getLogger(LOGGER_NAME6); +} + +// src/inline-client-driver/mod.ts +function createInlineClientDriver(managerDriver) { + const driver = { + action: async (c, actorQuery, encoding, params, actionName, args, opts) => { + try { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("found actor for action", { actorId }); + invariant10(actorId, "Missing actor ID"); + logger8().debug("handling action", { actionName, encoding }); + const responseData = await sendHttpRequest({ + url: `http://actor/action/${encodeURIComponent(actionName)}`, + method: "POST", + headers: { + [HEADER_ENCODING]: encoding, + ...params !== void 0 ? { [HEADER_CONN_PARAMS]: JSON.stringify(params) } : {}, + [HEADER_EXPOSE_INTERNAL_ERROR]: "true" + }, + body: { + args: bufferToArrayBuffer(cbor12.encode(args)) + }, + encoding, + customFetch: managerDriver.sendRequest.bind(managerDriver, actorId), + signal: opts?.signal, + requestVersionedDataHandler: HTTP_ACTION_REQUEST_VERSIONED, + responseVersionedDataHandler: HTTP_ACTION_RESPONSE_VERSIONED + }); + return cbor12.decode(new Uint8Array(responseData.output)); + } catch (err) { + const { code, message, metadata } = deconstructError( + err, + logger8(), + {}, + true + ); + const x = new ActorError2(code, message, metadata); + throw new ActorError2(code, message, metadata); + } + }, + resolveActorId: async (c, actorQuery, _encodingKind) => { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("resolved actor", { actorId }); + invariant10(actorId, "missing actor ID"); + return actorId; + }, + connectWebSocket: async (c, actorQuery, encodingKind, params) => { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("found actor for action", { actorId }); + invariant10(actorId, "Missing actor ID"); + logger8().debug("opening websocket", { actorId, encoding: encodingKind }); + const ws = await managerDriver.openWebSocket( + PATH_CONNECT_WEBSOCKET, + actorId, + encodingKind, + params + ); + return ws; + }, + connectSse: async (c, actorQuery, encodingKind, params) => { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("found actor for sse connection", { actorId }); + invariant10(actorId, "Missing actor ID"); + logger8().debug("opening sse connection", { + actorId, + encoding: encodingKind + }); + const EventSourceClass = await importEventSource(); + const eventSource = new EventSourceClass("http://actor/connect/sse", { + fetch: (input, init) => { + return fetch(input, { + ...init, + headers: { + ...init?.headers, + "User-Agent": httpUserAgent(), + [HEADER_ENCODING]: encodingKind, + ...params !== void 0 ? { [HEADER_CONN_PARAMS]: JSON.stringify(params) } : {}, + [HEADER_EXPOSE_INTERNAL_ERROR]: "true" + } + }); + } + }); + return eventSource; + }, + sendHttpMessage: async (c, actorId, encoding, connectionId, connectionToken, message) => { + logger8().debug("sending http message", { actorId, connectionId }); + await sendHttpRequest({ + url: "http://actor/connections/message", + method: "POST", + headers: { + [HEADER_ENCODING]: encoding, + [HEADER_CONN_ID]: connectionId, + [HEADER_CONN_TOKEN]: connectionToken, + [HEADER_EXPOSE_INTERNAL_ERROR]: "true" + }, + body: message, + encoding, + skipParseResponse: true, + customFetch: managerDriver.sendRequest.bind(managerDriver, actorId), + requestVersionedDataHandler: TO_SERVER_VERSIONED, + responseVersionedDataHandler: TO_CLIENT_VERSIONED + }); + }, + rawHttpRequest: async (c, actorQuery, encoding, params, path3, init) => { + try { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("found actor for raw http", { actorId }); + invariant10(actorId, "Missing actor ID"); + const normalizedPath = path3.startsWith("/") ? path3.slice(1) : path3; + const url = new URL(`http://actor/raw/http/${normalizedPath}`); + const proxyRequestHeaders = new Headers(init.headers); + if (params) { + proxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params)); + } + const proxyRequest = new Request(url, { + ...init, + headers: proxyRequestHeaders + }); + return await managerDriver.sendRequest(actorId, proxyRequest); + } catch (err) { + const { code, message, metadata } = deconstructError( + err, + logger8(), + {}, + true + ); + throw new ActorError2(code, message, metadata); + } + }, + rawWebSocket: async (c, actorQuery, encoding, params, path3, protocols) => { + const { actorId } = await queryActor(c, actorQuery, managerDriver); + logger8().debug("found actor for action", { actorId }); + invariant10(actorId, "Missing actor ID"); + const normalizedPath = path3.startsWith("/") ? path3.slice(1) : path3; + logger8().debug("opening websocket", { + actorId, + encoding, + path: normalizedPath + }); + const ws = await managerDriver.openWebSocket( + `${PATH_RAW_WEBSOCKET_PREFIX}${normalizedPath}`, + actorId, + encoding, + params + ); + return ws; + } + }; + return driver; +} +async function queryActor(c, query, driver) { + logger8().debug("querying actor", { query }); + let actorOutput; + if ("getForId" in query) { + const output = await driver.getForId({ + c, + name: query.getForId.name, + actorId: query.getForId.actorId + }); + if (!output) throw new ActorNotFound(query.getForId.actorId); + actorOutput = output; + } else if ("getForKey" in query) { + const existingActor = await driver.getWithKey({ + c, + name: query.getForKey.name, + key: query.getForKey.key + }); + if (!existingActor) { + throw new ActorNotFound( + `${query.getForKey.name}:${JSON.stringify(query.getForKey.key)}` + ); + } + actorOutput = existingActor; + } else if ("getOrCreateForKey" in query) { + const getOrCreateOutput = await driver.getOrCreateWithKey({ + c, + name: query.getOrCreateForKey.name, + key: query.getOrCreateForKey.key, + input: query.getOrCreateForKey.input, + region: query.getOrCreateForKey.region + }); + actorOutput = { + actorId: getOrCreateOutput.actorId + }; + } else if ("create" in query) { + const createOutput = await driver.createActor({ + c, + name: query.create.name, + key: query.create.key, + input: query.create.input, + region: query.create.region + }); + actorOutput = { + actorId: createOutput.actorId + }; + } else { + throw new InvalidRequest("Invalid query format"); + } + logger8().debug("actor query result", { + actorId: actorOutput.actorId + }); + return { actorId: actorOutput.actorId }; +} + +// src/inspector/manager.ts +import { sValidator as sValidator2 } from "@hono/standard-validator"; +import { Hono as Hono3 } from "hono"; +function createManagerInspectorRouter() { + return new Hono3().get("/ping", (c) => { + return c.json({ message: "pong" }, 200); + }).get("/actors", async (c) => { + const limit = Number.parseInt(c.req.query("limit") ?? "") || void 0; + const cursor = c.req.query("cursor") || void 0; + if (!limit || limit && limit <= 0) { + return c.json("Invalid limit", 400); + } + try { + const actors = await c.var.inspector.accessors.getAllActors({ + limit, + cursor + }); + return c.json(actors, 200); + } catch (error) { + inspectorLogger().error("Failed to fetch actors", error); + return c.json("Failed to fetch actors", 500); + } + }).post("/actors", sValidator2("json", CreateActorSchema), async (c) => { + const actor2 = await c.var.inspector.accessors.createActor( + c.req.valid("json") + ); + return c.json(actor2, 201); + }).get("/builds", async (c) => { + const builds = await c.var.inspector.accessors.getBuilds(); + return c.json(builds, 200); + }).get("/actor/:id", async (c) => { + const id = c.req.param("id"); + const actor2 = await c.var.inspector.accessors.getActorById(id); + if (!actor2) { + return c.json({ error: "Actor not found" }, 404); + } + return c.json(actor2, 200); + }).get("/bootstrap", async (c) => { + const actors = await c.var.inspector.accessors.getAllActors({ + limit: 10 + }); + return c.json({ actors }, 200); + }); +} +var ManagerInspector = class { + accessors; + constructor(accessors) { + this.accessors = accessors(); + inspectorLogger().debug("Manager Inspector enabled and ready"); + } +}; + +// src/drivers/file-system/manager.ts +var FileSystemManagerDriver = class { + #registryConfig; + #runConfig; + #state; + #driverConfig; + #actorDriver; + #actorRouter; + inspector; + constructor(registryConfig, runConfig, state, driverConfig) { + this.#registryConfig = registryConfig; + this.#runConfig = runConfig; + this.#state = state; + this.#driverConfig = driverConfig; + if (runConfig.inspector.enabled) { + let transformActor2 = function(actorState) { + return { + id: actorState.actorId, + name: actorState.name, + key: actorState.key, + startedAt, + createdAt: new Date(Number(actorState.createdAt)).toISOString(), + features: [ + "state" /* State */, + "connections" /* Connections */, + "console" /* Console */, + "events-monitoring" /* EventsMonitoring */, + "database" /* Database */ + ] + }; + }; + var transformActor = transformActor2; + if (!this.#runConfig.inspector.token()) { + this.#runConfig.inspector.token = () => this.#state.getOrCreateInspectorAccessToken(); + } + const startedAt = (/* @__PURE__ */ new Date()).toISOString(); + this.inspector = new ManagerInspector(() => { + return { + getAllActors: async ({ cursor, limit }) => { + const itr = this.#state.getActorsIterator({ cursor }); + const actors = []; + for await (const actor2 of itr) { + actors.push(transformActor2(actor2)); + if (limit && actors.length >= limit) { + break; + } + } + return actors; + }, + getActorById: async (id) => { + try { + const result = await this.#state.loadActorStateOrError(id); + return transformActor2(result); + } catch { + return null; + } + }, + getBuilds: async () => { + return Object.keys(this.#registryConfig.use).map((name) => ({ + name + })); + }, + createActor: async (input) => { + const { actorId } = await this.createActor(input); + try { + const result = await this.#state.loadActorStateOrError(actorId); + return transformActor2(result); + } catch { + return null; + } + } + }; + }); + } + const inlineClient = createClientWithDriver(createInlineClientDriver(this)); + this.#actorDriver = this.#driverConfig.actor( + registryConfig, + runConfig, + this, + inlineClient + ); + this.#actorRouter = createActorRouter(this.#runConfig, this.#actorDriver); + } + async sendRequest(actorId, actorRequest) { + return await this.#actorRouter.fetch(actorRequest, { + actorId + }); + } + async openWebSocket(path3, actorId, encoding, params) { + if (path3 === PATH_CONNECT_WEBSOCKET) { + const wsHandler = await handleWebSocketConnect( + void 0, + this.#runConfig, + this.#actorDriver, + actorId, + encoding, + params, + void 0 + ); + return new InlineWebSocketAdapter2(wsHandler); + } else if (path3.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) { + const wsHandler = await handleRawWebSocketHandler( + void 0, + path3, + this.#actorDriver, + actorId, + void 0 + ); + return new InlineWebSocketAdapter2(wsHandler); + } else { + throw new Error(`Unreachable path: ${path3}`); + } + } + async proxyRequest(c, actorRequest, actorId) { + return await this.#actorRouter.fetch(actorRequest, { + actorId + }); + } + async proxyWebSocket(c, path3, actorId, encoding, connParams, authData) { + const upgradeWebSocket = this.#runConfig.getUpgradeWebSocket?.(); + invariant11(upgradeWebSocket, "missing getUpgradeWebSocket"); + if (path3 === PATH_CONNECT_WEBSOCKET) { + const wsHandler = await handleWebSocketConnect( + c.req.raw, + this.#runConfig, + this.#actorDriver, + actorId, + encoding, + connParams, + authData + ); + return upgradeWebSocket(() => wsHandler)(c, noopNext()); + } else if (path3.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) { + const wsHandler = await handleRawWebSocketHandler( + c.req.raw, + path3, + this.#actorDriver, + actorId, + authData + ); + return upgradeWebSocket(() => wsHandler)(c, noopNext()); + } else { + throw new Error(`Unreachable path: ${path3}`); + } + } + async getForId({ actorId }) { + const actor2 = await this.#state.loadActor(actorId); + if (!actor2.state) { + return void 0; + } + try { + return { + actorId, + name: actor2.state.name, + key: actor2.state.key + }; + } catch (error) { + logger7().error("failed to read actor state", { actorId, error }); + return void 0; + } + } + async getWithKey({ + name, + key + }) { + const actorId = generateActorId(name, key); + const actor2 = await this.#state.loadActor(actorId); + if (actor2.state) { + return { + actorId, + name, + key + }; + } + return void 0; + } + async getOrCreateWithKey(input) { + const actorId = generateActorId(input.name, input.key); + const actorEntry = await this.#state.loadOrCreateActor( + actorId, + input.name, + input.key, + input.input + ); + invariant11(actorEntry.state, "must have state"); + return { + actorId: actorEntry.state.actorId, + name: actorEntry.state.name, + key: actorEntry.state.key + }; + } + async createActor({ name, key, input }) { + const actorId = generateActorId(name, key); + await this.#state.createActor(actorId, name, key, input); + return { + actorId, + name, + key + }; + } + extraStartupLog() { + return { + instances: this.#state.actorCountOnStartup, + data: this.#state.storagePath + }; + } +}; + +// src/drivers/file-system/mod.ts +function createFileSystemOrMemoryDriver(persist = true, customPath) { + const state = new FileSystemGlobalState(persist, customPath); + const driverConfig = { + name: persist ? "file-system" : "memory", + manager: (registryConfig, runConfig) => new FileSystemManagerDriver( + registryConfig, + runConfig, + state, + driverConfig + ), + actor: (registryConfig, runConfig, managerDriver, inlineClient) => { + const actorDriver = new FileSystemActorDriver( + registryConfig, + runConfig, + managerDriver, + inlineClient, + state + ); + state.onRunnerStart(registryConfig, runConfig, inlineClient, actorDriver); + return actorDriver; + } + }; + return driverConfig; +} + +// src/drivers/default.ts +function chooseDefaultDriver(runConfig) { + const engineEndpoint = runConfig.engine || getEnvUniversal("RIVET_ENGINE"); + if (engineEndpoint && runConfig.driver) { + throw new UserError( + "Cannot specify both 'engine' and 'driver' in configuration" + ); + } + if (runConfig.driver) { + return runConfig.driver; + } + if (engineEndpoint) { + logger().debug("using rivet engine driver", { endpoint: engineEndpoint }); + return createEngineDriver({ endpoint: engineEndpoint }); + } + logger().debug("using default file system driver"); + return createFileSystemOrMemoryDriver(true); +} + +// src/manager/router.ts +import { createRoute, OpenAPIHono } from "@hono/zod-openapi"; +import * as cbor13 from "cbor-x"; +import { + Hono as Hono4 +} from "hono"; +import { cors } from "hono/cors"; +import { streamSSE as streamSSE3 } from "hono/streaming"; +import invariant12 from "invariant"; +import { z as z10 } from "zod"; + +// src/manager/auth.ts +function getIntentsFromQuery(query) { + const intents = /* @__PURE__ */ new Set(); + if ("getForId" in query) { + intents.add("get"); + } else if ("getForKey" in query) { + intents.add("get"); + } else if ("getOrCreateForKey" in query) { + intents.add("get"); + intents.add("create"); + } else if ("create" in query) { + intents.add("create"); + } + return intents; +} +async function getActorNameFromQuery(c, driver, query) { + if ("getForId" in query) { + const output = await driver.getForId({ + c, + name: query.getForId.name, + actorId: query.getForId.actorId + }); + if (!output) throw new ActorNotFound(query.getForId.actorId); + return output.name; + } else if ("getForKey" in query) { + return query.getForKey.name; + } else if ("getOrCreateForKey" in query) { + return query.getOrCreateForKey.name; + } else if ("create" in query) { + return query.create.name; + } else { + throw new InvalidRequest("Invalid query format"); + } +} +async function authenticateRequest(c, actorDefinition, intents, params) { + if (!("onAuth" in actorDefinition.config)) { + throw new Forbidden( + "Actor requires authentication but no onAuth handler is defined (https://rivet.gg/docs/actors/authentication/). Provide an empty handler to disable auth: `onAuth: () => {}`" + ); + } + try { + const dataOrPromise = actorDefinition.config.onAuth( + { + request: c.req.raw, + intents + }, + params + ); + if (dataOrPromise instanceof Promise) { + return await dataOrPromise; + } else { + return dataOrPromise; + } + } catch (error) { + logger2().info("authentication error", { error: stringifyError(error) }); + throw error; + } +} +async function authenticateEndpoint(c, driver, registryConfig, query, additionalIntents, params) { + const intents = getIntentsFromQuery(query); + for (const intent of additionalIntents) { + intents.add(intent); + } + const actorName = await getActorNameFromQuery(c, driver, query); + const actorDefinition = registryConfig.use[actorName]; + if (!actorDefinition) { + throw new ActorNotFound(actorName); + } + return await authenticateRequest(c, actorDefinition, intents, params); +} + +// src/manager/router.ts +function parseWebSocketProtocols(protocols) { + let queryRaw; + let encodingRaw; + let connParamsRaw; + if (protocols) { + const protocolList = protocols.split(",").map((p) => p.trim()); + for (const protocol of protocolList) { + if (protocol.startsWith("query.")) { + queryRaw = decodeURIComponent(protocol.substring("query.".length)); + } else if (protocol.startsWith("encoding.")) { + encodingRaw = protocol.substring("encoding.".length); + } else if (protocol.startsWith("conn_params.")) { + connParamsRaw = decodeURIComponent( + protocol.substring("conn_params.".length) + ); + } + } + } + return { queryRaw, encodingRaw, connParamsRaw }; +} +var OPENAPI_ENCODING = z10.string().openapi({ + description: "The encoding format to use for the response (json, cbor)", + example: "json" +}); +var OPENAPI_ACTOR_QUERY = z10.string().openapi({ + description: "Actor query information" +}); +var OPENAPI_CONN_PARAMS = z10.string().openapi({ + description: "Connection parameters" +}); +var OPENAPI_ACTOR_ID = z10.string().openapi({ + description: "Actor ID (used in some endpoints)", + example: "actor-123456" +}); +var OPENAPI_CONN_ID = z10.string().openapi({ + description: "Connection ID", + example: "conn-123456" +}); +var OPENAPI_CONN_TOKEN = z10.string().openapi({ + description: "Connection token" +}); +function buildOpenApiResponses(schema, validateBody) { + return { + 200: { + description: "Success", + content: validateBody ? { + "application/json": { + schema + } + } : {} + }, + 400: { + description: "User error" + }, + 500: { + description: "Internal error" + } + }; +} +function createManagerRouter(registryConfig, runConfig, inlineClientDriver, managerDriver, validateBody) { + const router = new OpenAPIHono({ strict: false }).basePath( + runConfig.basePath + ); + router.use("*", loggerMiddleware(logger2())); + if (runConfig.cors || runConfig.inspector?.cors) { + router.use("*", async (c, next) => { + const path3 = c.req.path; + if (path3.endsWith("/actors/connect/websocket") || path3.includes("/actors/raw/websocket/") || // inspectors implement their own CORS handling + path3.endsWith("/inspect") || path3.endsWith("/actors/inspect")) { + return next(); + } + return cors({ + ...runConfig.cors ?? {}, + ...runConfig.inspector?.cors ?? {}, + origin: (origin, c2) => { + const inspectorOrigin = runConfig.inspector?.cors?.origin; + if (inspectorOrigin !== void 0) { + if (typeof inspectorOrigin === "function") { + const allowed = inspectorOrigin(origin, c2); + if (allowed) return allowed; + } else if (Array.isArray(inspectorOrigin)) { + return inspectorOrigin.includes(origin) ? origin : void 0; + } else { + return inspectorOrigin; + } + } + if (runConfig.cors?.origin !== void 0) { + if (typeof runConfig.cors.origin === "function") { + const allowed = runConfig.cors.origin(origin, c2); + if (allowed) return allowed; + } else { + return runConfig.cors.origin; + } + } + return null; + }, + allowMethods: (origin, c2) => { + const inspectorMethods = runConfig.inspector?.cors?.allowMethods; + if (inspectorMethods) { + if (typeof inspectorMethods === "function") { + return inspectorMethods(origin, c2); + } + return inspectorMethods; + } + if (runConfig.cors?.allowMethods) { + if (typeof runConfig.cors.allowMethods === "function") { + return runConfig.cors.allowMethods(origin, c2); + } + return runConfig.cors.allowMethods; + } + return []; + }, + allowHeaders: [ + ...runConfig.cors?.allowHeaders ?? [], + ...runConfig.inspector?.cors?.allowHeaders ?? [], + ...ALLOWED_PUBLIC_HEADERS, + "Content-Type", + "User-Agent" + ], + credentials: runConfig.cors?.credentials ?? runConfig.inspector?.cors?.credentials ?? true + })(c, next); + }); + } + router.get("/", (c) => { + return c.text( + "This is an RivetKit registry.\n\nLearn more at https://rivetkit.org" + ); + }); + { + const ResolveQuerySchema = z10.object({ + query: z10.any().openapi({ + example: { getForId: { actorId: "actor-123" } } + }) + }).openapi("ResolveQuery"); + const ResolveResponseSchema = z10.object({ + i: z10.string().openapi({ + example: "actor-123" + }) + }).openapi("ResolveResponse"); + const resolveRoute = createRoute({ + method: "post", + path: "/actors/resolve", + request: { + body: { + content: validateBody ? { + "application/json": { + schema: ResolveQuerySchema + } + } : {} + }, + headers: z10.object({ + [HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY + }) + }, + responses: buildOpenApiResponses(ResolveResponseSchema, validateBody) + }); + router.openapi( + resolveRoute, + (c) => handleResolveRequest(c, registryConfig, managerDriver) + ); + } + { + router.use("*", (c, next) => { + if (c.req.path.endsWith("/actors/connect/websocket")) { + return handleWebSocketConnectRequest( + c, + registryConfig, + runConfig, + managerDriver + ); + } + return next(); + }); + const wsRoute = createRoute({ + method: "get", + path: "/actors/connect/websocket", + responses: { + 101: { + description: "WebSocket upgrade" + } + } + }); + router.openapi(wsRoute, () => { + throw new Error("Should be unreachable"); + }); + } + { + const sseRoute = createRoute({ + method: "get", + path: "/actors/connect/sse", + request: { + headers: z10.object({ + [HEADER_ENCODING]: OPENAPI_ENCODING, + [HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY, + [HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional() + }) + }, + responses: { + 200: { + description: "SSE stream", + content: { + "text/event-stream": { + schema: z10.unknown() + } + } + } + } + }); + router.openapi( + sseRoute, + (c) => handleSseConnectRequest(c, registryConfig, runConfig, managerDriver) + ); + } + { + const ActionParamsSchema = z10.object({ + action: z10.string().openapi({ + param: { + name: "action", + in: "path" + }, + example: "myAction" + }) + }).openapi("ActionParams"); + const ActionRequestSchema = z10.object({ + query: z10.any().openapi({ + example: { getForId: { actorId: "actor-123" } } + }), + body: z10.any().optional().openapi({ + example: { param1: "value1", param2: 123 } + }) + }).openapi("ActionRequest"); + const ActionResponseSchema = z10.any().openapi("ActionResponse"); + const actionRoute = createRoute({ + method: "post", + path: "/actors/actions/{action}", + request: { + params: ActionParamsSchema, + body: { + content: validateBody ? { + "application/json": { + schema: ActionRequestSchema + } + } : {} + }, + headers: z10.object({ + [HEADER_ENCODING]: OPENAPI_ENCODING, + [HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional() + }) + }, + responses: buildOpenApiResponses(ActionResponseSchema, validateBody) + }); + router.openapi( + actionRoute, + (c) => handleActionRequest(c, registryConfig, runConfig, managerDriver) + ); + } + { + const ConnectionMessageRequestSchema = z10.object({ + message: z10.any().openapi({ + example: { type: "message", content: "Hello, actor!" } + }) + }).openapi("ConnectionMessageRequest"); + const ConnectionMessageResponseSchema = z10.any().openapi("ConnectionMessageResponse"); + const messageRoute = createRoute({ + method: "post", + path: "/actors/message", + request: { + body: { + content: validateBody ? { + "application/json": { + schema: ConnectionMessageRequestSchema + } + } : {} + }, + headers: z10.object({ + [HEADER_ACTOR_ID]: OPENAPI_ACTOR_ID, + [HEADER_CONN_ID]: OPENAPI_CONN_ID, + [HEADER_ENCODING]: OPENAPI_ENCODING, + [HEADER_CONN_TOKEN]: OPENAPI_CONN_TOKEN + }) + }, + responses: buildOpenApiResponses( + ConnectionMessageResponseSchema, + validateBody + ) + }); + router.openapi( + messageRoute, + (c) => handleMessageRequest(c, registryConfig, runConfig, managerDriver) + ); + } + { + const RawHttpRequestBodySchema = z10.any().optional().openapi({ + description: "Raw request body (can be any content type)" + }); + const RawHttpResponseSchema = z10.any().openapi({ + description: "Raw response from actor's onFetch handler" + }); + const rawHttpRouteConfig = { + path: "/actors/raw/http/*", + request: { + headers: z10.object({ + [HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY.optional(), + [HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional() + }), + body: { + content: { + "*/*": { + schema: RawHttpRequestBodySchema + } + } + } + }, + responses: { + 200: { + description: "Success - response from actor's onFetch handler", + content: { + "*/*": { + schema: RawHttpResponseSchema + } + } + }, + 404: { + description: "Actor does not have an onFetch handler" + }, + 500: { + description: "Internal server error or invalid response from actor" + } + } + }; + const httpMethods = [ + "get", + "post", + "put", + "delete", + "patch", + "head", + "options" + ]; + for (const method of httpMethods) { + const route = createRoute({ + method, + ...rawHttpRouteConfig + }); + router.openapi(route, async (c) => { + return handleRawHttpRequest( + c, + registryConfig, + runConfig, + managerDriver + ); + }); + } + } + { + router.use("*", async (c, next) => { + if (c.req.path.includes("/raw/websocket/")) { + return handleRawWebSocketRequest( + c, + registryConfig, + runConfig, + managerDriver + ); + } + return next(); + }); + const rawWebSocketRoute = createRoute({ + method: "get", + path: "/actors/raw/websocket/*", + request: {}, + responses: { + 101: { + description: "WebSocket upgrade successful" + }, + 400: { + description: "WebSockets not enabled or invalid request" + }, + 404: { + description: "Actor does not have an onWebSocket handler" + } + } + }); + router.openapi(rawWebSocketRoute, () => { + throw new Error("Should be unreachable"); + }); + } + if (runConfig.inspector?.enabled) { + router.route( + "/actors/inspect", + new Hono4().use( + cors(runConfig.inspector.cors), + secureInspector(runConfig), + universalActorProxy({ + registryConfig, + runConfig, + driver: managerDriver + }) + ).all( + "/", + (c) => ( + // this should be handled by the actor proxy, but just in case + c.text("Unreachable.", 404) + ) + ) + ); + router.route( + "/inspect", + new Hono4().use( + cors(runConfig.inspector.cors), + secureInspector(runConfig), + async (c, next) => { + const inspector = managerDriver.inspector; + invariant12(inspector, "inspector not supported on this platform"); + c.set("inspector", inspector); + await next(); + } + ).route("/", createManagerInspectorRouter()) + ); + } + if (registryConfig.test.enabled) { + router.post(".test/inline-driver/call", async (c) => { + const buffer = await c.req.arrayBuffer(); + const { encoding, transport, method, args } = cbor13.decode(new Uint8Array(buffer)); + logger2().debug("received inline request", { + encoding, + transport, + method, + args + }); + let response; + try { + const output = await inlineClientDriver[method]( + ...args + ); + response = { ok: output }; + } catch (rawErr) { + const err = deconstructError(rawErr, logger2(), {}, true); + response = { err }; + } + return c.body(cbor13.encode(response)); + }); + router.get(".test/inline-driver/connect-websocket", async (c) => { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + invariant12(upgradeWebSocket, "websockets not supported on this platform"); + return upgradeWebSocket(async (c2) => { + const { + actorQuery: actorQueryRaw, + params: paramsRaw, + encodingKind + } = c2.req.query(); + const actorQuery = JSON.parse(actorQueryRaw); + const params = paramsRaw !== void 0 ? JSON.parse(paramsRaw) : void 0; + logger2().debug("received test inline driver websocket", { + actorQuery, + params, + encodingKind + }); + const clientWsPromise = inlineClientDriver.connectWebSocket( + void 0, + actorQuery, + encodingKind, + params, + void 0 + ); + return await createTestWebSocketProxy(clientWsPromise, "standard"); + })(c, noopNext()); + }); + router.get(".test/inline-driver/raw-websocket", async (c) => { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + invariant12(upgradeWebSocket, "websockets not supported on this platform"); + return upgradeWebSocket(async (c2) => { + const { + actorQuery: actorQueryRaw, + params: paramsRaw, + encodingKind, + path: path3, + protocols: protocolsRaw + } = c2.req.query(); + const actorQuery = JSON.parse(actorQueryRaw); + const params = paramsRaw !== void 0 ? JSON.parse(paramsRaw) : void 0; + const protocols = protocolsRaw !== void 0 ? JSON.parse(protocolsRaw) : void 0; + logger2().debug("received test inline driver raw websocket", { + actorQuery, + params, + encodingKind, + path: path3, + protocols + }); + logger2().debug("calling inlineClientDriver.rawWebSocket"); + const clientWsPromise = inlineClientDriver.rawWebSocket( + void 0, + actorQuery, + encodingKind, + params, + path3, + protocols, + void 0 + ); + logger2().debug("calling createTestWebSocketProxy"); + return await createTestWebSocketProxy(clientWsPromise, "raw"); + })(c, noopNext()); + }); + router.all(".test/inline-driver/raw-http/*", async (c) => { + const actorQueryHeader = c.req.header(HEADER_ACTOR_QUERY); + const paramsHeader = c.req.header(HEADER_CONN_PARAMS); + const encodingHeader = c.req.header(HEADER_ENCODING); + if (!actorQueryHeader || !encodingHeader) { + return c.text("Missing required headers", 400); + } + const actorQuery = JSON.parse(actorQueryHeader); + const params = paramsHeader ? JSON.parse(paramsHeader) : void 0; + const encoding = encodingHeader; + const fullPath = c.req.path; + const pathOnly = fullPath.split("/.test/inline-driver/raw-http/")[1] || ""; + const url = new URL(c.req.url); + const pathWithQuery = pathOnly + url.search; + logger2().debug("received test inline driver raw http", { + actorQuery, + params, + encoding, + path: pathWithQuery, + method: c.req.method + }); + try { + const response = await inlineClientDriver.rawHttpRequest( + void 0, + actorQuery, + encoding, + params, + pathWithQuery, + { + method: c.req.method, + headers: c.req.raw.headers, + body: c.req.raw.body + }, + void 0 + ); + return response; + } catch (error) { + logger2().error("error in test inline raw http", { + error: stringifyError(error) + }); + const err = deconstructError(error, logger2(), {}, true); + return c.json( + { + error: { + code: err.code, + message: err.message, + metadata: err.metadata + } + }, + err.statusCode + ); + } + }); + } + managerDriver.modifyManagerRouter?.( + registryConfig, + router + ); + const mountedRouter = new Hono4(); + mountedRouter.route("/", router); + mountedRouter.route("/registry", router); + mountedRouter.notFound(handleRouteNotFound); + mountedRouter.onError(handleRouteError.bind(void 0, {})); + return { router: mountedRouter, openapi: router }; +} +async function queryActor2(c, query, driver) { + logger2().debug("querying actor", { query }); + let actorOutput; + if ("getForId" in query) { + const output = await driver.getForId({ + c, + name: query.getForId.name, + actorId: query.getForId.actorId + }); + if (!output) throw new ActorNotFound(query.getForId.actorId); + actorOutput = output; + } else if ("getForKey" in query) { + const existingActor = await driver.getWithKey({ + c, + name: query.getForKey.name, + key: query.getForKey.key + }); + if (!existingActor) { + throw new ActorNotFound( + `${query.getForKey.name}:${JSON.stringify(query.getForKey.key)}` + ); + } + actorOutput = existingActor; + } else if ("getOrCreateForKey" in query) { + const getOrCreateOutput = await driver.getOrCreateWithKey({ + c, + name: query.getOrCreateForKey.name, + key: query.getOrCreateForKey.key, + input: query.getOrCreateForKey.input, + region: query.getOrCreateForKey.region + }); + actorOutput = { + actorId: getOrCreateOutput.actorId + }; + } else if ("create" in query) { + const createOutput = await driver.createActor({ + c, + name: query.create.name, + key: query.create.key, + input: query.create.input, + region: query.create.region + }); + actorOutput = { + actorId: createOutput.actorId + }; + } else { + throw new InvalidRequest("Invalid query format"); + } + logger2().debug("actor query result", { + actorId: actorOutput.actorId + }); + return { actorId: actorOutput.actorId }; +} +async function createTestWebSocketProxy(clientWsPromise, connectionType) { + let clientWs = null; + try { + logger2().debug("awaiting client websocket promise"); + const ws = await clientWsPromise; + clientWs = ws; + logger2().debug("client websocket promise resolved", { + constructor: ws?.constructor.name + }); + await new Promise((resolve, reject) => { + const onOpen = () => { + logger2().debug("test websocket connection opened"); + resolve(); + }; + const onError = (error) => { + logger2().error("test websocket connection failed", { error }); + reject( + new Error(`Failed to open WebSocket: ${error.message || error}`) + ); + }; + ws.addEventListener("open", onOpen); + ws.addEventListener("error", onError); + }); + } catch (error) { + logger2().error( + `failed to establish client ${connectionType} websocket connection`, + { error } + ); + return { + onOpen: (_evt, serverWs) => { + serverWs.close(1011, "Failed to establish connection"); + }, + onMessage: () => { + }, + onError: () => { + }, + onClose: () => { + } + }; + } + return { + onOpen: (_evt, serverWs) => { + logger2().debug(`test ${connectionType} websocket connection opened`); + logger2().debug("clientWs info", { + constructor: clientWs.constructor.name, + hasAddEventListener: typeof clientWs.addEventListener === "function", + readyState: clientWs.readyState + }); + clientWs.addEventListener("message", (clientEvt) => { + logger2().debug( + `test ${connectionType} websocket connection message from client`, + { + dataType: typeof clientEvt.data, + isBlob: clientEvt.data instanceof Blob, + isArrayBuffer: clientEvt.data instanceof ArrayBuffer, + dataConstructor: clientEvt.data?.constructor?.name, + dataStr: typeof clientEvt.data === "string" ? clientEvt.data.substring(0, 100) : void 0 + } + ); + if (serverWs.readyState === 1) { + if (clientEvt.data instanceof Blob) { + clientEvt.data.arrayBuffer().then((buffer) => { + logger2().debug( + "converted client blob to arraybuffer, sending to server", + { + bufferSize: buffer.byteLength + } + ); + serverWs.send(buffer); + }).catch((error) => { + logger2().error("failed to convert blob to arraybuffer", { + error + }); + }); + } else { + logger2().debug("sending client data directly to server", { + dataType: typeof clientEvt.data, + dataLength: typeof clientEvt.data === "string" ? clientEvt.data.length : void 0 + }); + serverWs.send(clientEvt.data); + } + } + }); + clientWs.addEventListener("close", (clientEvt) => { + logger2().debug(`test ${connectionType} websocket connection closed`); + if (serverWs.readyState !== 3) { + serverWs.close(clientEvt.code, clientEvt.reason); + } + }); + clientWs.addEventListener("error", () => { + logger2().debug(`test ${connectionType} websocket connection error`); + if (serverWs.readyState !== 3) { + serverWs.close(1011, "Error in client websocket"); + } + }); + }, + onMessage: (evt) => { + logger2().debug("received message from server", { + dataType: typeof evt.data, + isBlob: evt.data instanceof Blob, + isArrayBuffer: evt.data instanceof ArrayBuffer, + dataConstructor: evt.data?.constructor?.name, + dataStr: typeof evt.data === "string" ? evt.data.substring(0, 100) : void 0 + }); + if (clientWs.readyState === 1) { + if (evt.data instanceof Blob) { + evt.data.arrayBuffer().then((buffer) => { + logger2().debug("converted blob to arraybuffer, sending", { + bufferSize: buffer.byteLength + }); + clientWs.send(buffer); + }).catch((error) => { + logger2().error("failed to convert blob to arraybuffer", { + error + }); + }); + } else { + logger2().debug("sending data directly", { + dataType: typeof evt.data, + dataLength: typeof evt.data === "string" ? evt.data.length : void 0 + }); + clientWs.send(evt.data); + } + } + }, + onClose: (event, serverWs) => { + logger2().debug(`server ${connectionType} websocket closed`, { + wasClean: event.wasClean, + code: event.code, + reason: event.reason + }); + serverWs.close(1e3, "hack_force_close"); + if (clientWs && clientWs.readyState !== clientWs.CLOSED && clientWs.readyState !== clientWs.CLOSING) { + clientWs.close(1e3, event.reason); + } + }, + onError: (error) => { + logger2().error(`error in server ${connectionType} websocket`, { error }); + if (clientWs && clientWs.readyState !== clientWs.CLOSED && clientWs.readyState !== clientWs.CLOSING) { + clientWs.close(1011, "Error in server websocket"); + } + } + }; +} +async function handleSseConnectRequest(c, registryConfig, _runConfig, driver) { + let encoding; + try { + encoding = getRequestEncoding(c.req); + logger2().debug("sse connection request received", { encoding }); + const params = ConnectRequestSchema.safeParse({ + query: getRequestQuery(c), + encoding: c.req.header(HEADER_ENCODING), + connParams: c.req.header(HEADER_CONN_PARAMS) + }); + if (!params.success) { + logger2().error("invalid connection parameters", { + error: params.error + }); + throw new InvalidRequest(params.error); + } + const query = params.data.query; + const connParams = params.data.connParams ? JSON.parse(params.data.connParams) : void 0; + const authData = await authenticateEndpoint( + c, + driver, + registryConfig, + query, + ["connect"], + connParams + ); + const { actorId } = await queryActor2(c, query, driver); + invariant12(actorId, "Missing actor ID"); + logger2().debug("sse connection to actor", { actorId }); + logger2().debug("using custom proxy mode for sse connection"); + const url = new URL("http://actor/connect/sse"); + const proxyRequestHeaderes = new Headers(); + proxyRequestHeaderes.set(HEADER_ENCODING, params.data.encoding); + if (params.data.connParams) { + proxyRequestHeaderes.set(HEADER_CONN_PARAMS, params.data.connParams); + } + if (authData) { + proxyRequestHeaderes.set(HEADER_AUTH_DATA, JSON.stringify(authData)); + } + const proxyRequest = new Request(url, { headers: proxyRequestHeaderes }); + return await driver.proxyRequest(c, proxyRequest, actorId); + } catch (error) { + const { code, message, metadata } = deconstructError(error, logger2(), { + sseEvent: "setup" + }); + return streamSSE3(c, async (stream) => { + try { + if (encoding) { + const errorMsg = { + body: { + tag: "Error", + val: { + code, + message, + metadata: bufferToArrayBuffer(cbor13.encode(metadata)), + actionId: null + } + } + }; + const serialized = serializeWithEncoding( + encoding, + errorMsg, + TO_CLIENT_VERSIONED + ); + await stream.writeSSE({ + data: typeof serialized === "string" ? serialized : Buffer.from(serialized).toString("base64") + }); + } else { + await stream.writeSSE({ + data: code, + event: "error" + }); + } + } catch (serializeError) { + logger2().error("failed to send error to sse client", { + error: serializeError + }); + await stream.writeSSE({ + data: "internal error during error handling", + event: "error" + }); + } + }); + } +} +async function handleWebSocketConnectRequest(c, registryConfig, runConfig, driver) { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + if (!upgradeWebSocket) { + return c.text( + "WebSockets are not enabled for this driver. Use SSE instead.", + 400 + ); + } + let encoding; + try { + logger2().debug("websocket connection request received"); + const protocols = c.req.header("sec-websocket-protocol"); + const { queryRaw, encodingRaw, connParamsRaw } = parseWebSocketProtocols(protocols); + let queryUnvalidated; + try { + queryUnvalidated = JSON.parse(queryRaw); + } catch (error) { + logger2().error("invalid query json", { error }); + throw new InvalidQueryJSON(error); + } + let connParamsUnvalidated = null; + try { + if (connParamsRaw) { + connParamsUnvalidated = JSON.parse(connParamsRaw); + } + } catch (error) { + logger2().error("invalid conn params", { error }); + throw new InvalidParams( + `Invalid params JSON: ${stringifyError(error)}` + ); + } + const params = ConnectWebSocketRequestSchema.safeParse({ + query: queryUnvalidated, + encoding: encodingRaw, + connParams: connParamsUnvalidated + }); + if (!params.success) { + logger2().error("invalid connection parameters", { + error: params.error + }); + throw new InvalidRequest(params.error); + } + encoding = params.data.encoding; + const authData = await authenticateEndpoint( + c, + driver, + registryConfig, + params.data.query, + ["connect"], + connParamsRaw + ); + const { actorId } = await queryActor2(c, params.data.query, driver); + logger2().debug("found actor for websocket connection", { + actorId + }); + invariant12(actorId, "missing actor id"); + return await driver.proxyWebSocket( + c, + PATH_CONNECT_WEBSOCKET, + actorId, + params.data.encoding, + params.data.connParams, + authData + ); + } catch (error) { + const { code, message, metadata } = deconstructError(error, logger2(), { + wsEvent: "setup" + }); + return await upgradeWebSocket(() => ({ + onOpen: (_evt, ws) => { + if (encoding) { + try { + const errorMsg = { + body: { + tag: "Error", + val: { + code, + message, + metadata: bufferToArrayBuffer(cbor13.encode(metadata)), + actionId: null + } + } + }; + const serialized = serializeWithEncoding( + encoding, + errorMsg, + TO_CLIENT_VERSIONED + ); + ws.send(serialized); + ws.close(1011, code); + } catch (serializeError) { + logger2().error("failed to send error to websocket client", { + error: serializeError + }); + ws.close(1011, "internal error during error handling"); + } + } else { + ws.close(1011, code); + } + } + }))(c, noopNext()); + } +} +async function handleMessageRequest(c, _registryConfig, _runConfig, driver) { + logger2().debug("connection message request received"); + try { + const params = ConnMessageRequestSchema.safeParse({ + actorId: c.req.header(HEADER_ACTOR_ID), + connId: c.req.header(HEADER_CONN_ID), + encoding: c.req.header(HEADER_ENCODING), + connToken: c.req.header(HEADER_CONN_TOKEN) + }); + if (!params.success) { + logger2().error("invalid connection parameters", { + error: params.error + }); + throw new InvalidRequest(params.error); + } + const { actorId, connId, encoding, connToken } = params.data; + const url = new URL("http://actor/connections/message"); + const proxyRequestHeaders = new Headers(); + proxyRequestHeaders.set(HEADER_ENCODING, encoding); + proxyRequestHeaders.set(HEADER_CONN_ID, connId); + proxyRequestHeaders.set(HEADER_CONN_TOKEN, connToken); + const proxyRequest = new Request(url, { + method: "POST", + body: c.req.raw.body, + duplex: "half", + headers: proxyRequestHeaders + }); + return await driver.proxyRequest(c, proxyRequest, actorId); + } catch (error) { + logger2().error("error proxying connection message", { error }); + if (!ActorError.isActorError(error)) { + throw new ProxyError("connection message", error); + } else { + throw error; + } + } +} +async function handleActionRequest(c, registryConfig, _runConfig, driver) { + try { + const actionName = c.req.param("action"); + logger2().debug("action call received", { actionName }); + const params = ConnectRequestSchema.safeParse({ + query: getRequestQuery(c), + encoding: c.req.header(HEADER_ENCODING), + connParams: c.req.header(HEADER_CONN_PARAMS) + }); + if (!params.success) { + logger2().error("invalid connection parameters", { + error: params.error + }); + throw new InvalidRequest(params.error); + } + const connParams = params.data.connParams ? JSON.parse(params.data.connParams) : void 0; + const authData = await authenticateEndpoint( + c, + driver, + registryConfig, + params.data.query, + ["action"], + connParams + ); + const { actorId } = await queryActor2(c, params.data.query, driver); + logger2().debug("found actor for action", { actorId }); + invariant12(actorId, "Missing actor ID"); + const url = new URL( + `http://actor/action/${encodeURIComponent(actionName)}` + ); + const proxyRequestHeaders = new Headers(); + proxyRequestHeaders.set(HEADER_ENCODING, params.data.encoding); + if (params.data.connParams) { + proxyRequestHeaders.set(HEADER_CONN_PARAMS, params.data.connParams); + } + if (authData) { + proxyRequestHeaders.set(HEADER_AUTH_DATA, JSON.stringify(authData)); + } + const proxyRequest = new Request(url, { + method: "POST", + body: c.req.raw.body, + headers: proxyRequestHeaders + }); + return await driver.proxyRequest(c, proxyRequest, actorId); + } catch (error) { + logger2().error("error in action handler", { error: stringifyError(error) }); + if (!ActorError.isActorError(error)) { + throw new ProxyError("Action call", error); + } else { + throw error; + } + } +} +async function handleResolveRequest(c, registryConfig, driver) { + const encoding = getRequestEncoding(c.req); + logger2().debug("resolve request encoding", { encoding }); + const params = ResolveRequestSchema.safeParse({ + query: getRequestQuery(c), + connParams: c.req.header(HEADER_CONN_PARAMS) + }); + if (!params.success) { + logger2().error("invalid connection parameters", { + error: params.error + }); + throw new InvalidRequest(params.error); + } + const connParams = params.data.connParams ? JSON.parse(params.data.connParams) : void 0; + const query = params.data.query; + await authenticateEndpoint(c, driver, registryConfig, query, [], connParams); + const { actorId } = await queryActor2(c, query, driver); + logger2().debug("resolved actor", { actorId }); + invariant12(actorId, "Missing actor ID"); + const response = { + actorId + }; + const serialized = serializeWithEncoding( + encoding, + response, + HTTP_RESOLVE_RESPONSE_VERSIONED + ); + return c.body(serialized); +} +async function handleRawHttpRequest(c, registryConfig, _runConfig, driver) { + try { + const subpath = c.req.path.split("/raw/http/")[1] || ""; + logger2().debug("raw http request received", { subpath }); + const queryHeader = c.req.header(HEADER_ACTOR_QUERY); + if (!queryHeader) { + throw new InvalidRequest("Missing actor query header"); + } + const query = JSON.parse(queryHeader); + const connParamsHeader = c.req.header(HEADER_CONN_PARAMS); + const connParams = connParamsHeader ? JSON.parse(connParamsHeader) : void 0; + const authData = await authenticateEndpoint( + c, + driver, + registryConfig, + query, + ["action"], + connParams + ); + const { actorId } = await queryActor2(c, query, driver); + logger2().debug("found actor for raw http", { actorId }); + invariant12(actorId, "Missing actor ID"); + const originalUrl = new URL(c.req.url); + const url = new URL( + `http://actor/raw/http/${subpath}${originalUrl.search}` + ); + logger2().debug("rewriting http url", { + from: c.req.url, + to: url + }); + const proxyRequestHeaders = new Headers(c.req.raw.headers); + if (connParams) { + proxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(connParams)); + } + if (authData) { + proxyRequestHeaders.set(HEADER_AUTH_DATA, JSON.stringify(authData)); + } + const proxyRequest = new Request(url, { + method: c.req.method, + headers: proxyRequestHeaders, + body: c.req.raw.body + }); + return await driver.proxyRequest(c, proxyRequest, actorId); + } catch (error) { + logger2().error("error in raw http handler", { + error: stringifyError(error) + }); + if (!ActorError.isActorError(error)) { + throw new ProxyError("Raw HTTP request", error); + } else { + throw error; + } + } +} +async function handleRawWebSocketRequest(c, registryConfig, runConfig, driver) { + const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); + if (!upgradeWebSocket) { + return c.text("WebSockets are not enabled for this driver.", 400); + } + try { + const subpath = c.req.path.split("/raw/websocket/")[1] || ""; + logger2().debug("raw websocket request received", { subpath }); + const protocols = c.req.header("sec-websocket-protocol"); + const { + queryRaw: queryFromProtocol, + connParamsRaw: connParamsFromProtocol + } = parseWebSocketProtocols(protocols); + if (!queryFromProtocol) { + throw new InvalidRequest("Missing query in WebSocket protocol"); + } + const query = JSON.parse(queryFromProtocol); + let connParams; + if (connParamsFromProtocol) { + connParams = JSON.parse(connParamsFromProtocol); + } + const authData = await authenticateEndpoint( + c, + driver, + registryConfig, + query, + ["action"], + connParams + ); + const { actorId } = await queryActor2(c, query, driver); + logger2().debug("found actor for raw websocket", { actorId }); + invariant12(actorId, "Missing actor ID"); + logger2().debug("using custom proxy mode for raw websocket"); + const originalUrl = new URL(c.req.url); + const proxyPath = `${PATH_RAW_WEBSOCKET_PREFIX}${subpath}${originalUrl.search}`; + logger2().debug("manager router proxyWebSocket", { + originalUrl: c.req.url, + subpath, + search: originalUrl.search, + proxyPath + }); + return await driver.proxyWebSocket( + c, + proxyPath, + actorId, + "json", + // Default encoding for raw WebSocket + connParams, + authData + ); + } catch (error) { + const { code } = deconstructError(error, logger2(), { + wsEvent: "setup" + }); + return await upgradeWebSocket(() => ({ + onOpen: (_evt, ws) => { + ws.close(1011, code); + } + }))(c, noopNext()); + } +} +function universalActorProxy({ + registryConfig, + runConfig, + driver +}) { + return async (c, _next) => { + if (c.req.header("upgrade") === "websocket") { + return handleRawWebSocketRequest(c, registryConfig, runConfig, driver); + } else { + const queryHeader = c.req.header(HEADER_ACTOR_QUERY); + if (!queryHeader) { + throw new InvalidRequest("Missing actor query header"); + } + const query = ActorQuerySchema.parse(JSON.parse(queryHeader)); + const { actorId } = await queryActor2(c, query, driver); + const url = new URL(c.req.url); + url.hostname = "actor"; + url.pathname = url.pathname.replace(new RegExp(`^${runConfig.basePath}`, ""), "").replace(/^\/?registry\/actors/, "").replace(/^\/?actors/, ""); + const proxyRequest = new Request(url, { + method: c.req.method, + headers: c.req.raw.headers, + body: c.req.raw.body + }); + return await driver.proxyRequest(c, proxyRequest, actorId); + } + }; +} + +// src/registry/config.ts +import { z as z11 } from "zod"; +var ActorsSchema = z11.record( + z11.string(), + z11.custom() +); +var TestConfigSchema = z11.object({ enabled: z11.boolean() }); +var RegistryConfigSchema = z11.object({ + use: z11.record(z11.string(), z11.custom()), + // TODO: Find a better way of passing around the test config + /** + * Test configuration. + * + * DO NOT MANUALLY ENABLE. THIS IS USED INTERNALLY. + * @internal + **/ + test: TestConfigSchema.optional().default({ enabled: false }) +}); + +// src/registry/log.ts +var LOGGER_NAME7 = "registry"; +function logger9() { + return getLogger(LOGGER_NAME7); +} + +// src/registry/serve.ts +import { Hono as Hono5 } from "hono"; +async function crossPlatformServe(rivetKitRouter, userRouter) { + const app = userRouter ?? new Hono5(); + let serve; + try { + const dep = await import("@hono/node-server"); + serve = dep.serve; + } catch (err) { + logger9().error( + "failed to import @hono/node-server. please run 'npm install @hono/node-server @hono/node-ws'" + ); + process.exit(1); + } + app.route("/registry", rivetKitRouter); + let createNodeWebSocket; + try { + const dep = await import("@hono/node-ws"); + createNodeWebSocket = dep.createNodeWebSocket; + } catch (err) { + logger9().error( + "failed to import @hono/node-ws. please run 'npm install @hono/node-server @hono/node-ws'" + ); + process.exit(1); + } + const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ + app + }); + const port = Number.parseInt( + getEnvUniversal("PORT") ?? getEnvUniversal("PORT_HTTP") ?? "8080" + ); + const server = serve( + { fetch: app.fetch, port }, + () => logger9().info("server listening", { port }) + ); + injectWebSocket(server); + return { upgradeWebSocket }; +} + +// src/registry/mod.ts +var Registry = class { + #config; + get config() { + return this.#config; + } + constructor(config4) { + this.#config = config4; + } + /** + * Runs the registry for a server. + */ + createServer(inputConfig) { + const config4 = RunConfigSchema.parse(inputConfig); + const driver = chooseDefaultDriver(config4); + let upgradeWebSocket; + if (!config4.getUpgradeWebSocket) { + config4.getUpgradeWebSocket = () => upgradeWebSocket; + } + const managerDriver = driver.manager(this.#config, config4); + const clientDriver = createInlineClientDriver(managerDriver); + const { router: hono } = createManagerRouter( + this.#config, + config4, + clientDriver, + managerDriver, + false + ); + const client = createClientWithDriver(clientDriver); + const driverLog = managerDriver.extraStartupLog?.() ?? {}; + logger9().info("rivetkit ready", { + driver: driver.name, + definitions: Object.keys(this.#config.use).length, + ...driverLog + }); + if (config4.inspector?.enabled) { + logger9().info("inspector ready", { + url: getInspectorUrl(config4) + }); + } + if (config4.role === "all" || config4.role === "runner") { + const inlineClient = createClientWithDriver( + createInlineClientDriver(managerDriver) + ); + const _actorDriver = driver.actor( + this.#config, + config4, + managerDriver, + inlineClient + ); + } + return { + client, + hono, + handler: async (req) => await hono.fetch(req), + serve: async (app) => { + const out = await crossPlatformServe(hono, app); + upgradeWebSocket = out.upgradeWebSocket; + } + }; + } + /** + * Runs the registry as a standalone server. + */ + async runServer(inputConfig) { + const { serve } = this.createServer(inputConfig); + serve(); + } +}; +function setup(input) { + const config4 = RegistryConfigSchema.parse(input); + return new Registry(config4); +} + +// fixtures/driver-test-suite/action-inputs.ts +var inputActor = actor({ + onAuth: () => { + }, + createState: (c, input) => { + return { + initialInput: input, + onCreateInput: void 0 + }; + }, + onCreate: (c, input) => { + c.state.onCreateInput = input; + }, + actions: { + getInputs: (c) => { + return { + initialInput: c.state.initialInput, + onCreateInput: c.state.onCreateInput + }; + } + } +}); + +// fixtures/driver-test-suite/action-timeout.ts +var shortTimeoutActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + options: { + actionTimeout: 50 + // 50ms timeout + }, + actions: { + quickAction: async (c) => { + return "quick response"; + }, + slowAction: async (c) => { + await new Promise((resolve) => setTimeout(resolve, 100)); + return "slow response"; + } + } +}); +var longTimeoutActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + options: { + actionTimeout: 200 + // 200ms timeout + }, + actions: { + delayedAction: async (c) => { + await new Promise((resolve) => setTimeout(resolve, 100)); + return "delayed response"; + } + } +}); +var defaultTimeoutActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + actions: { + normalAction: async (c) => { + await new Promise((resolve) => setTimeout(resolve, 50)); + return "normal response"; + } + } +}); +var syncTimeoutActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + options: { + actionTimeout: 50 + // 50ms timeout + }, + actions: { + syncAction: (c) => { + return "sync response"; + } + } +}); + +// fixtures/driver-test-suite/action-types.ts +var syncActionActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + actions: { + // Simple synchronous action that returns a value directly + increment: (c, amount = 1) => { + c.state.value += amount; + return c.state.value; + }, + // Synchronous action that returns an object + getInfo: (c) => { + return { + currentValue: c.state.value, + timestamp: Date.now() + }; + }, + // Synchronous action with no return value (void) + reset: (c) => { + c.state.value = 0; + } + } +}); +var asyncActionActor = actor({ + onAuth: () => { + }, + state: { value: 0, data: null }, + actions: { + // Async action with a delay + delayedIncrement: async (c, amount = 1) => { + await Promise.resolve(); + c.state.value += amount; + return c.state.value; + }, + // Async action that simulates an API call + fetchData: async (c, id) => { + await Promise.resolve(); + const data = { id, timestamp: Date.now() }; + c.state.data = data; + return data; + }, + // Async action with error handling + asyncWithError: async (c, shouldError) => { + await Promise.resolve(); + if (shouldError) { + throw new UserError("Intentional error"); + } + return "Success"; + } + } +}); +var promiseActor = actor({ + onAuth: () => { + }, + state: { results: [] }, + actions: { + // Action that returns a resolved promise + resolvedPromise: (c) => { + return Promise.resolve("resolved value"); + }, + // Action that returns a promise that resolves after a delay + delayedPromise: (c) => { + return new Promise((resolve) => { + c.state.results.push("delayed"); + resolve("delayed value"); + }); + }, + // Action that returns a rejected promise + rejectedPromise: (c) => { + return Promise.reject(new UserError("promised rejection")); + }, + // Action to check the collected results + getResults: (c) => { + return c.state.results; + } + } +}); + +// fixtures/driver-test-suite/actor-onstatechange.ts +var onStateChangeActor = actor({ + onAuth: () => { + }, + state: { + value: 0, + changeCount: 0 + }, + actions: { + // Action that modifies state - should trigger onStateChange + setValue: (c, newValue) => { + c.state.value = newValue; + return c.state.value; + }, + // Action that modifies state multiple times - should trigger onStateChange for each change + incrementMultiple: (c, times) => { + for (let i = 0; i < times; i++) { + c.state.value++; + } + return c.state.value; + }, + // Action that doesn't modify state - should NOT trigger onStateChange + getValue: (c) => { + return c.state.value; + }, + // Action that reads and returns without modifying - should NOT trigger onStateChange + getDoubled: (c) => { + const doubled = c.state.value * 2; + return doubled; + }, + // Get the count of how many times onStateChange was called + getChangeCount: (c) => { + return c.state.changeCount; + }, + // Reset change counter for testing + resetChangeCount: (c) => { + c.state.changeCount = 0; + } + }, + // Track onStateChange calls + onStateChange: (c) => { + c.state.changeCount++; + } +}); + +// fixtures/driver-test-suite/auth.ts +var authActor = actor({ + state: { requests: 0 }, + onAuth: (opts, params) => { + const apiKey = params?.apiKey; + if (!apiKey) { + throw new UserError("API key required", { code: "missing_auth" }); + } + if (apiKey !== "valid-api-key") { + throw new UserError("Invalid API key", { code: "invalid_auth" }); + } + return { userId: "user123", token: apiKey }; + }, + actions: { + getRequests: (c) => { + c.state.requests++; + return c.state.requests; + }, + getUserAuth: (c) => c.conn.auth + } +}); +var intentAuthActor = actor({ + state: { value: 0 }, + onAuth: ({ request, intents }, params) => { + console.log("intents", intents, params); + const role = params.role; + if (intents.has("create") && role !== "admin") { + throw new UserError("Admin role required for create operations", { + code: "insufficient_permissions" + }); + } + if (intents.has("action") && !["admin", "user"].includes(role || "")) { + throw new UserError("User or admin role required for actions", { + code: "insufficient_permissions" + }); + } + return { role, timestamp: Date.now() }; + }, + actions: { + getValue: (c) => c.state.value, + setValue: (c, value) => { + c.state.value = value; + return value; + }, + getAuth: (c) => c.conn.auth + } +}); +var publicActor = actor({ + state: { visitors: 0 }, + onAuth: () => { + return null; + }, + actions: { + visit: (c) => { + c.state.visitors++; + return c.state.visitors; + } + } +}); +var noAuthActor = actor({ + state: { value: 42 }, + actions: { + getValue: (c) => c.state.value + } +}); +var asyncAuthActor = actor({ + state: { count: 0 }, + onAuth: async (opts, params) => { + const token = params?.token; + if (!token) { + throw new UserError("Token required", { code: "missing_token" }); + } + if (token === "invalid") { + throw new UserError("Token is invalid", { code: "invalid_token" }); + } + return { userId: `user-${token}`, validated: true }; + }, + actions: { + increment: (c) => { + c.state.count++; + return c.state.count; + }, + getAuthData: (c) => c.conn.auth + } +}); + +// fixtures/driver-test-suite/conn-liveness.ts +var connLivenessActor = actor({ + onAuth: () => { + }, + state: { + counter: 0, + acceptingConnections: true + }, + options: { + connectionLivenessInterval: 5e3, + connectionLivenessTimeout: 2500 + }, + onConnect: (c, conn) => { + if (!c.state.acceptingConnections) { + conn.disconnect(); + throw new Error("Actor is not accepting connections"); + } + }, + actions: { + getWsConnectionsLiveness: (c) => { + return Array.from(c.conns.values()).filter((conn) => conn.driver === CONNECTION_DRIVER_WEBSOCKET).map((conn) => ({ + id: conn.id, + status: conn.status, + lastSeen: conn.lastSeen + })); + }, + getConnectionId: (c) => { + return c.conn.id; + }, + kill: (c, connId) => { + c.state.acceptingConnections = false; + const conn = c.conns.get(connId); + if (conn) { + conn.disconnect(); + } + }, + getCounter: (c) => { + return c.state.counter; + }, + increment: (c, amount) => { + c.state.counter += amount; + return c.state.counter; + } + } +}); + +// fixtures/driver-test-suite/conn-params.ts +var counterWithParams = actor({ + onAuth: () => { + }, + state: { count: 0, initializers: [] }, + createConnState: (c, opts, params) => { + return { + name: params.name || "anonymous" + }; + }, + onConnect: (c, conn) => { + c.state.initializers.push(conn.state.name); + }, + actions: { + increment: (c, x) => { + c.state.count += x; + c.broadcast("newCount", { + count: c.state.count, + by: c.conn.state.name + }); + return c.state.count; + }, + getInitializers: (c) => { + return c.state.initializers; + } + } +}); + +// fixtures/driver-test-suite/conn-state.ts +var connStateActor = actor({ + onAuth: () => { + }, + state: { + sharedCounter: 0, + disconnectionCount: 0 + }, + // Define connection state + createConnState: (c, opts, params) => { + return { + username: params?.username || "anonymous", + role: params?.role || "user", + counter: 0, + createdAt: Date.now() + }; + }, + // Lifecycle hook when a connection is established + onConnect: (c, conn) => { + c.broadcast("userConnected", { + id: conn.id, + username: "anonymous", + role: "user" + }); + }, + // Lifecycle hook when a connection is closed + onDisconnect: (c, conn) => { + c.state.disconnectionCount += 1; + c.broadcast("userDisconnected", { + id: conn.id + }); + }, + actions: { + // Action to increment the connection's counter + incrementConnCounter: (c, amount = 1) => { + c.conn.state.counter += amount; + }, + // Action to increment the shared counter + incrementSharedCounter: (c, amount = 1) => { + c.state.sharedCounter += amount; + return c.state.sharedCounter; + }, + // Get the connection state + getConnectionState: (c) => { + return { id: c.conn.id, ...c.conn.state }; + }, + // Check all active connections + getConnectionIds: (c) => { + return c.conns.keys().toArray(); + }, + // Get disconnection count + getDisconnectionCount: (c) => { + return c.state.disconnectionCount; + }, + // Get all active connection states + getAllConnectionStates: (c) => { + return c.conns.entries().map(([id, conn]) => ({ id, ...conn.state })).toArray(); + }, + // Send message to a specific connection with matching ID + sendToConnection: (c, targetId, message) => { + if (c.conns.has(targetId)) { + c.conns.get(targetId).send("directMessage", { from: c.conn.id, message }); + return true; + } else { + return false; + } + }, + // Update connection state (simulated for tests) + updateConnection: (c, updates) => { + if (updates.username) c.conn.state.username = updates.username; + if (updates.role) c.conn.state.role = updates.role; + return c.conn.state; + } + } +}); + +// fixtures/driver-test-suite/counter.ts +var counter = actor({ + onAuth: () => { + }, + state: { count: 0 }, + actions: { + increment: (c, x) => { + c.state.count += x; + c.broadcast("newCount", c.state.count); + return c.state.count; + }, + getCount: (c) => { + return c.state.count; + } + } +}); + +// fixtures/driver-test-suite/error-handling.ts +var errorHandlingActor = actor({ + onAuth: () => { + }, + state: { + errorLog: [] + }, + actions: { + // Action that throws a UserError with just a message + throwSimpleError: () => { + throw new UserError("Simple error message"); + }, + // Action that throws a UserError with code and metadata + throwDetailedError: () => { + throw new UserError("Detailed error message", { + code: "detailed_error", + metadata: { + reason: "test", + timestamp: Date.now() + } + }); + }, + // Action that throws an internal error + throwInternalError: () => { + throw new Error("This is an internal error"); + }, + // Action that returns successfully + successfulAction: () => { + return "success"; + }, + // Action that times out (simulated with a long delay) + timeoutAction: async (c) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve("This should not be reached if timeout works"); + }, 1e4); + }); + }, + // Action with configurable delay to test timeout edge cases + delayedAction: async (c, delayMs) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(`Completed after ${delayMs}ms`); + }, delayMs); + }); + }, + // Log an error for inspection + logError: (c, error) => { + c.state.errorLog.push(error); + return c.state.errorLog; + }, + // Get the error log + getErrorLog: (c) => { + return c.state.errorLog; + }, + // Clear the error log + clearErrorLog: (c) => { + c.state.errorLog = []; + return true; + } + }, + options: { + actionTimeout: 500 + // 500ms timeout for actions + } +}); +var customTimeoutActor = actor({ + state: {}, + actions: { + quickAction: async () => { + await new Promise((resolve) => setTimeout(resolve, 50)); + return "Quick action completed"; + }, + slowAction: async () => { + await new Promise((resolve) => setTimeout(resolve, 300)); + return "Slow action completed"; + } + }, + options: { + actionTimeout: 200 + // 200ms timeout + } +}); + +// fixtures/driver-test-suite/inline-client.ts +var inlineClientActor = actor({ + onAuth: () => { + }, + state: { messages: [] }, + actions: { + // Action that uses client to call another actor (stateless) + callCounterIncrement: async (c, amount) => { + const client = c.client(); + const result = await client.counter.getOrCreate(["inline-test"]).increment(amount); + c.state.messages.push( + `Called counter.increment(${amount}), result: ${result}` + ); + return result; + }, + // Action that uses client to get counter state (stateless) + getCounterState: async (c) => { + const client = c.client(); + const count = await client.counter.getOrCreate(["inline-test"]).getCount(); + c.state.messages.push(`Got counter state: ${count}`); + return count; + }, + // Action that uses client with .connect() for stateful communication + connectToCounterAndIncrement: async (c, amount) => { + const client = c.client(); + const handle = client.counter.getOrCreate(["inline-test-stateful"]); + const connection = handle.connect(); + const events = []; + connection.on("newCount", (count) => { + events.push(count); + }); + const result1 = await connection.increment(amount); + const result2 = await connection.increment(amount * 2); + await connection.dispose(); + c.state.messages.push( + `Connected to counter, incremented by ${amount} and ${amount * 2}, results: ${result1}, ${result2}, events: ${JSON.stringify(events)}` + ); + return { result1, result2, events }; + }, + // Get all messages from this actor's state + getMessages: (c) => { + return c.state.messages; + }, + // Clear messages + clearMessages: (c) => { + c.state.messages = []; + } + } +}); + +// fixtures/driver-test-suite/lifecycle.ts +var counterWithLifecycle = actor({ + onAuth: () => { + }, + state: { + count: 0, + events: [] + }, + createConnState: (c, opts, params) => ({ + joinTime: Date.now() + }), + onStart: (c) => { + c.state.events.push("onStart"); + }, + onBeforeConnect: (c, opts, params) => { + if (params?.trackLifecycle) c.state.events.push("onBeforeConnect"); + }, + onConnect: (c, conn) => { + if (conn.params?.trackLifecycle) c.state.events.push("onConnect"); + }, + onDisconnect: (c, conn) => { + if (conn.params?.trackLifecycle) c.state.events.push("onDisconnect"); + }, + actions: { + getEvents: (c) => { + return c.state.events; + }, + increment: (c, x) => { + c.state.count += x; + return c.state.count; + } + } +}); + +// fixtures/driver-test-suite/metadata.ts +var metadataActor = actor({ + onAuth: () => { + }, + state: { + lastMetadata: null, + actorName: "", + // Store tags and region in state for testing since they may not be + // available in the context in all environments + storedTags: {}, + storedRegion: null + }, + onStart: (c) => { + c.state.actorName = c.name; + }, + actions: { + // Set up test tags - this will be called by tests to simulate tags + setupTestTags: (c, tags) => { + c.state.storedTags = tags; + return tags; + }, + // Set up test region - this will be called by tests to simulate region + setupTestRegion: (c, region) => { + c.state.storedRegion = region; + return region; + }, + // Get all available metadata + getMetadata: (c) => { + const metadata = { + name: c.name, + tags: c.state.storedTags, + region: c.state.storedRegion + }; + c.state.lastMetadata = metadata; + return metadata; + }, + // Get the actor name + getActorName: (c) => { + return c.name; + }, + // Get a specific tag by key + getTag: (c, key) => { + return c.state.storedTags[key] || null; + }, + // Get all tags + getTags: (c) => { + return c.state.storedTags; + }, + // Get the region + getRegion: (c) => { + return c.state.storedRegion; + }, + // Get the stored actor name (from onStart) + getStoredActorName: (c) => { + return c.state.actorName; + }, + // Get last retrieved metadata + getLastMetadata: (c) => { + return c.state.lastMetadata; + } + } +}); + +// fixtures/driver-test-suite/raw-http.ts +import { Hono as Hono6 } from "hono"; +var rawHttpActor = actor({ + state: { + requestCount: 0 + }, + onAuth() { + return {}; + }, + onFetch(ctx, request) { + const url = new URL(request.url); + const method = request.method; + ctx.state.requestCount++; + if (url.pathname === "/api/hello") { + return new Response(JSON.stringify({ message: "Hello from actor!" }), { + headers: { "Content-Type": "application/json" } + }); + } + if (url.pathname === "/api/echo" && method === "POST") { + return new Response(request.body, { + headers: request.headers + }); + } + if (url.pathname === "/api/state") { + return new Response( + JSON.stringify({ + requestCount: ctx.state.requestCount + }), + { + headers: { "Content-Type": "application/json" } + } + ); + } + if (url.pathname === "/api/headers") { + const headers = Object.fromEntries(request.headers.entries()); + return new Response(JSON.stringify(headers), { + headers: { "Content-Type": "application/json" } + }); + } + return new Response("Not Found", { status: 404 }); + }, + actions: {} +}); +var rawHttpNoHandlerActor = actor({ + // No onFetch handler - all requests should return 404 + onAuth() { + return {}; + }, + actions: {} +}); +var rawHttpVoidReturnActor = actor({ + onAuth() { + return {}; + }, + onFetch(ctx, request) { + return void 0; + }, + actions: {} +}); +var rawHttpHonoActor = actor({ + onAuth() { + return {}; + }, + createVars() { + const router = new Hono6(); + router.get("/", (c) => c.json({ message: "Welcome to Hono actor!" })); + router.get( + "/users", + (c) => c.json([ + { id: 1, name: "Alice" }, + { id: 2, name: "Bob" } + ]) + ); + router.get("/users/:id", (c) => { + const id = c.req.param("id"); + return c.json({ id: parseInt(id), name: id === "1" ? "Alice" : "Bob" }); + }); + router.post("/users", async (c) => { + const body = await c.req.json(); + return c.json({ id: 3, ...body }, 201); + }); + router.put("/users/:id", async (c) => { + const id = c.req.param("id"); + const body = await c.req.json(); + return c.json({ id: parseInt(id), ...body }); + }); + router.delete("/users/:id", (c) => { + const id = c.req.param("id"); + return c.json({ message: `User ${id} deleted` }); + }); + return { router }; + }, + onFetch(ctx, request) { + return ctx.vars.router.fetch(request); + }, + actions: {} +}); + +// fixtures/driver-test-suite/raw-http-auth.ts +var rawHttpAuthActor = actor({ + state: { + requestCount: 0 + }, + onAuth: (opts, params) => { + const apiKey = params.apiKey; + if (!apiKey) { + throw new UserError("API key required", { code: "missing_auth" }); + } + if (apiKey !== "valid-api-key") { + throw new UserError("Invalid API key", { code: "invalid_auth" }); + } + return { userId: "user123", token: apiKey }; + }, + onFetch(ctx, request) { + const url = new URL(request.url); + ctx.state.requestCount++; + if (url.pathname === "/api/auth-info") { + return new Response( + JSON.stringify({ + message: "Authenticated request", + requestCount: ctx.state.requestCount + }), + { + headers: { "Content-Type": "application/json" } + } + ); + } + if (url.pathname === "/api/protected") { + return new Response( + JSON.stringify({ + message: "This is protected content" + }), + { + headers: { "Content-Type": "application/json" } + } + ); + } + return new Response("Not Found", { status: 404 }); + }, + actions: { + getRequestCount(ctx) { + return ctx.state.requestCount; + }, + getAuthFromConnections(ctx) { + const firstConn = ctx.conns.values().next().value; + return firstConn?.auth; + } + } +}); +var rawHttpNoAuthActor = actor({ + state: { + value: 42 + }, + onFetch(ctx, request) { + return new Response( + JSON.stringify({ + value: ctx.state.value + }), + { + headers: { "Content-Type": "application/json" } + } + ); + }, + actions: { + getValue(ctx) { + return ctx.state.value; + } + } +}); +var rawHttpPublicActor = actor({ + state: { + visitors: 0 + }, + onAuth: () => { + return null; + }, + onFetch(ctx, request) { + ctx.state.visitors++; + return new Response( + JSON.stringify({ + message: "Welcome visitor!", + count: ctx.state.visitors + }), + { + headers: { "Content-Type": "application/json" } + } + ); + }, + actions: { + getVisitorCount(ctx) { + return ctx.state.visitors; + } + } +}); +var rawHttpCustomAuthActor = actor({ + state: { + authorized: 0, + unauthorized: 0 + }, + onAuth: () => { + return {}; + }, + onFetch(ctx, request) { + const authHeader = request.headers.get("Authorization"); + if (!authHeader || !authHeader.startsWith("Bearer ")) { + ctx.state.unauthorized++; + return new Response(JSON.stringify({ error: "Unauthorized" }), { + status: 401, + headers: { "Content-Type": "application/json" } + }); + } + const token = authHeader.substring(7); + if (token !== "custom-token") { + ctx.state.unauthorized++; + return new Response(JSON.stringify({ error: "Invalid token" }), { + status: 403, + headers: { "Content-Type": "application/json" } + }); + } + ctx.state.authorized++; + return new Response( + JSON.stringify({ + message: "Authorized!", + authorized: ctx.state.authorized + }), + { + headers: { "Content-Type": "application/json" } + } + ); + }, + actions: { + getStats(ctx) { + return { + authorized: ctx.state.authorized, + unauthorized: ctx.state.unauthorized + }; + } + } +}); + +// fixtures/driver-test-suite/raw-http-request-properties.ts +var rawHttpRequestPropertiesActor = actor({ + onAuth() { + return {}; + }, + actions: {}, + onFetch(ctx, request) { + const url = new URL(request.url); + const method = request.method; + const headers = Object.fromEntries(request.headers.entries()); + const handleBody = async () => { + if (!request.body) { + return null; + } + const contentType = request.headers.get("content-type") || ""; + try { + if (contentType.includes("application/json")) { + const text = await request.text(); + return text ? JSON.parse(text) : null; + } else { + const text = await request.text(); + return text || null; + } + } catch (error) { + return null; + } + }; + if (method === "HEAD") { + return new Response(null, { + status: 200, + headers: { "Content-Type": "application/json" } + }); + } + return handleBody().then((body) => { + const responseData = { + // URL properties + url: request.url, + pathname: url.pathname, + search: url.search, + searchParams: Object.fromEntries(url.searchParams.entries()), + hash: url.hash, + // Method + method: request.method, + // Headers + headers, + // Body + body, + bodyText: typeof body === "string" ? body : body === null && request.body !== null ? "" : null, + // Additional properties that might be available + // Note: Some properties like cache, credentials, mode, etc. + // might not be available in all environments + cache: request.cache || null, + credentials: request.credentials || null, + mode: request.mode || null, + redirect: request.redirect || null, + referrer: request.referrer || null + }; + return new Response(JSON.stringify(responseData), { + headers: { "Content-Type": "application/json" } + }); + }); + } +}); + +// fixtures/driver-test-suite/raw-websocket.ts +var rawWebSocketActor = actor({ + state: { + connectionCount: 0, + messageCount: 0 + }, + onAuth(params) { + return { connParams: params }; + }, + onWebSocket(ctx, websocket, opts) { + ctx.state.connectionCount = ctx.state.connectionCount + 1; + console.log(`[ACTOR] New connection, count: ${ctx.state.connectionCount}`); + websocket.send( + JSON.stringify({ + type: "welcome", + connectionCount: ctx.state.connectionCount + }) + ); + console.log("[ACTOR] Sent welcome message"); + websocket.addEventListener("message", (event) => { + ctx.state.messageCount = ctx.state.messageCount + 1; + console.log( + `[ACTOR] Message received, total count: ${ctx.state.messageCount}, data:`, + event.data + ); + const data = event.data; + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + if (parsed.type === "ping") { + websocket.send( + JSON.stringify({ + type: "pong", + timestamp: Date.now() + }) + ); + } else if (parsed.type === "getStats") { + console.log( + `[ACTOR] Sending stats - connections: ${ctx.state.connectionCount}, messages: ${ctx.state.messageCount}` + ); + websocket.send( + JSON.stringify({ + type: "stats", + connectionCount: ctx.state.connectionCount, + messageCount: ctx.state.messageCount + }) + ); + } else if (parsed.type === "getAuthData") { + websocket.send( + JSON.stringify({ + type: "authData", + authData: null, + message: "Auth data not available in raw WebSocket handler" + }) + ); + } else if (parsed.type === "getRequestInfo") { + websocket.send( + JSON.stringify({ + type: "requestInfo", + url: opts.request.url, + pathname: new URL(opts.request.url).pathname, + search: new URL(opts.request.url).search + }) + ); + } else { + websocket.send(data); + } + } catch { + websocket.send(data); + } + } else { + websocket.send(data); + } + }); + websocket.addEventListener("close", () => { + ctx.state.connectionCount = ctx.state.connectionCount - 1; + console.log( + `[ACTOR] Connection closed, count: ${ctx.state.connectionCount}` + ); + }); + }, + actions: { + getStats(ctx) { + return { + connectionCount: ctx.state.connectionCount, + messageCount: ctx.state.messageCount + }; + } + } +}); +var rawWebSocketBinaryActor = actor({ + onAuth() { + return {}; + }, + onWebSocket(ctx, websocket, opts) { + websocket.addEventListener("message", (event) => { + const data = event.data; + if (data instanceof ArrayBuffer || data instanceof Uint8Array) { + const bytes = new Uint8Array(data); + const reversed = new Uint8Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + reversed[i] = bytes[bytes.length - 1 - i]; + } + websocket.send(reversed); + } + }); + }, + actions: {} +}); + +// fixtures/driver-test-suite/raw-websocket-auth.ts +var rawWebSocketAuthActor = actor({ + state: { + connectionCount: 0, + messageCount: 0 + }, + onAuth: (opts, params) => { + const apiKey = params.apiKey; + if (!apiKey) { + throw new UserError("API key required", { code: "missing_auth" }); + } + if (apiKey !== "valid-api-key") { + throw new UserError("Invalid API key", { code: "invalid_auth" }); + } + return { userId: "user123", token: apiKey }; + }, + onWebSocket(ctx, websocket) { + ctx.state.connectionCount++; + websocket.send( + JSON.stringify({ + type: "welcome", + message: "Authenticated WebSocket connection", + connectionCount: ctx.state.connectionCount + }) + ); + websocket.addEventListener("message", (event) => { + ctx.state.messageCount++; + const data = event.data; + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + if (parsed.type === "getAuth") { + websocket.send( + JSON.stringify({ + type: "authInfo", + authenticated: true + }) + ); + } else { + websocket.send( + JSON.stringify({ + type: "echo", + original: parsed + }) + ); + } + } catch { + websocket.send(data); + } + } + }); + websocket.addEventListener("close", () => { + ctx.state.connectionCount--; + }); + }, + actions: { + getStats(ctx) { + return { + connectionCount: ctx.state.connectionCount, + messageCount: ctx.state.messageCount + }; + } + } +}); +var rawWebSocketNoAuthActor = actor({ + state: { + connections: 0 + }, + onWebSocket(ctx, websocket) { + ctx.state.connections++; + websocket.send( + JSON.stringify({ + type: "connected", + connections: ctx.state.connections + }) + ); + }, + actions: { + getConnectionCount(ctx) { + return ctx.state.connections; + } + } +}); +var rawWebSocketPublicActor = actor({ + state: { + visitors: 0 + }, + onAuth: () => { + return null; + }, + onWebSocket(ctx, websocket) { + ctx.state.visitors++; + websocket.send( + JSON.stringify({ + type: "welcome", + message: "Public WebSocket connection", + visitorNumber: ctx.state.visitors + }) + ); + websocket.addEventListener("message", (event) => { + websocket.send(event.data); + }); + }, + actions: { + getVisitorCount(ctx) { + return ctx.state.visitors; + } + } +}); +var rawWebSocketCustomAuthActor = actor({ + state: { + authorized: 0, + unauthorized: 0 + }, + onAuth: () => { + return {}; + }, + onWebSocket(ctx, websocket, opts) { + const url = new URL(opts.request.url); + const token = url.searchParams.get("token"); + if (!token || token !== "custom-ws-token") { + ctx.state.unauthorized++; + websocket.send( + JSON.stringify({ + type: "error", + message: "Unauthorized" + }) + ); + websocket.close(1008, "Unauthorized"); + return; + } + ctx.state.authorized++; + websocket.send( + JSON.stringify({ + type: "authorized", + message: "Welcome authenticated user!" + }) + ); + websocket.addEventListener("message", (event) => { + websocket.send( + JSON.stringify({ + type: "echo", + data: event.data, + authenticated: true + }) + ); + }); + }, + actions: { + getStats(ctx) { + return { + authorized: ctx.state.authorized, + unauthorized: ctx.state.unauthorized + }; + } + } +}); + +// fixtures/driver-test-suite/request-access.ts +var requestAccessActor = actor({ + onAuth: () => { + }, + // Allow unauthenticated connections + state: { + // Track request info from different hooks + onBeforeConnectRequest: { + hasRequest: false, + requestUrl: null, + requestMethod: null, + requestHeaders: {} + }, + createConnStateRequest: { + hasRequest: false, + requestUrl: null, + requestMethod: null, + requestHeaders: {} + }, + onFetchRequest: { + hasRequest: false, + requestUrl: null, + requestMethod: null, + requestHeaders: {} + }, + onWebSocketRequest: { + hasRequest: false, + requestUrl: null, + requestMethod: null, + requestHeaders: {} + } + }, + createConnState: (c, { request }, params) => { + return { + trackRequest: params?.trackRequest || false, + requestInfo: params?.trackRequest && request ? { + hasRequest: true, + requestUrl: request.url, + requestMethod: request.method, + requestHeaders: Object.fromEntries(request.headers.entries()) + } : null + }; + }, + onConnect: (c, conn) => { + if (conn.state.requestInfo) { + c.state.createConnStateRequest = conn.state.requestInfo; + } + }, + onBeforeConnect: (c, { request }, params) => { + if (params?.trackRequest) { + if (request) { + c.state.onBeforeConnectRequest.hasRequest = true; + c.state.onBeforeConnectRequest.requestUrl = request.url; + c.state.onBeforeConnectRequest.requestMethod = request.method; + const headers = {}; + request.headers.forEach((value, key) => { + headers[key] = value; + }); + c.state.onBeforeConnectRequest.requestHeaders = headers; + } else { + c.state.onBeforeConnectRequest.hasRequest = false; + } + } + }, + onFetch: (c, request) => { + c.state.onFetchRequest.hasRequest = true; + c.state.onFetchRequest.requestUrl = request.url; + c.state.onFetchRequest.requestMethod = request.method; + const headers = {}; + request.headers.forEach((value, key) => { + headers[key] = value; + }); + c.state.onFetchRequest.requestHeaders = headers; + return new Response( + JSON.stringify({ + hasRequest: true, + requestUrl: request.url, + requestMethod: request.method, + requestHeaders: headers + }), + { + status: 200, + headers: { "Content-Type": "application/json" } + } + ); + }, + onWebSocket: (c, websocket, { request }) => { + c.state.onWebSocketRequest.hasRequest = true; + c.state.onWebSocketRequest.requestUrl = request.url; + c.state.onWebSocketRequest.requestMethod = request.method; + const headers = {}; + request.headers.forEach((value, key) => { + headers[key] = value; + }); + c.state.onWebSocketRequest.requestHeaders = headers; + websocket.send( + JSON.stringify({ + hasRequest: true, + requestUrl: request.url, + requestMethod: request.method, + requestHeaders: headers + }) + ); + websocket.addEventListener("message", (event) => { + websocket.send(event.data); + }); + }, + actions: { + getRequestInfo: (c) => { + return { + onBeforeConnect: c.state.onBeforeConnectRequest, + createConnState: c.state.createConnStateRequest, + onFetch: c.state.onFetchRequest, + onWebSocket: c.state.onWebSocketRequest + }; + } + } +}); + +// fixtures/driver-test-suite/request-access-auth.ts +var requestAccessAuthActor = actor({ + onAuth: ({ request, intents }, params) => { + if (params?.trackRequest) { + const headers = {}; + request.headers.forEach((value, key) => { + headers[key] = value; + }); + return { + hasRequest: true, + requestUrl: request.url, + requestMethod: request.method, + requestHeaders: headers, + intents: Array.from(intents) + }; + } + return {}; + }, + state: { + authData: null + }, + onConnect: (c, conn) => { + c.state.authData = conn.auth; + }, + actions: { + getAuthRequestInfo: (c) => { + const authData = c.state.authData || { + hasRequest: false, + requestUrl: null, + requestMethod: null, + requestHeaders: {}, + intents: [] + }; + return authData; + } + } +}); + +// fixtures/driver-test-suite/scheduled.ts +var scheduled = actor({ + onAuth: () => { + }, + state: { + lastRun: 0, + scheduledCount: 0, + taskHistory: [] + }, + actions: { + // Schedule using 'at' with specific timestamp + scheduleTaskAt: (c, timestamp) => { + c.schedule.at(timestamp, "onScheduledTask"); + return timestamp; + }, + // Schedule using 'after' with delay + scheduleTaskAfter: (c, delayMs) => { + c.schedule.after(delayMs, "onScheduledTask"); + return Date.now() + delayMs; + }, + // Schedule with a task ID for ordering tests + scheduleTaskAfterWithId: (c, taskId, delayMs) => { + c.schedule.after(delayMs, "onScheduledTaskWithId", taskId); + return { taskId, scheduledFor: Date.now() + delayMs }; + }, + // Original method for backward compatibility + scheduleTask: (c, delayMs) => { + const timestamp = Date.now() + delayMs; + c.schedule.at(timestamp, "onScheduledTask"); + return timestamp; + }, + // Getters for state + getLastRun: (c) => { + return c.state.lastRun; + }, + getScheduledCount: (c) => { + return c.state.scheduledCount; + }, + getTaskHistory: (c) => { + return c.state.taskHistory; + }, + clearHistory: (c) => { + c.state.taskHistory = []; + c.state.scheduledCount = 0; + c.state.lastRun = 0; + return true; + }, + // Scheduled task handlers + onScheduledTask: (c) => { + c.state.lastRun = Date.now(); + c.state.scheduledCount++; + c.broadcast("scheduled", { + time: c.state.lastRun, + count: c.state.scheduledCount + }); + }, + onScheduledTaskWithId: (c, taskId) => { + c.state.lastRun = Date.now(); + c.state.scheduledCount++; + c.state.taskHistory.push(taskId); + c.broadcast("scheduledWithId", { + taskId, + time: c.state.lastRun, + count: c.state.scheduledCount + }); + } + } +}); + +// fixtures/driver-test-suite/sleep.ts +var SLEEP_TIMEOUT = 500; +var sleep = actor({ + onAuth: () => { + }, + state: { startCount: 0, sleepCount: 0 }, + onStart: (c) => { + c.state.startCount += 1; + }, + onStop: (c) => { + c.state.sleepCount += 1; + }, + actions: { + triggerSleep: (c) => { + c.sleep(); + }, + getCounts: (c) => { + return { startCount: c.state.startCount, sleepCount: c.state.sleepCount }; + }, + setAlarm: async (c, duration) => { + await c.schedule.after(duration, "onAlarm"); + }, + onAlarm: (c) => { + c.log.info("alarm called"); + } + }, + options: { + sleepTimeout: SLEEP_TIMEOUT + } +}); +var sleepWithLongRpc = actor({ + onAuth: () => { + }, + state: { startCount: 0, sleepCount: 0 }, + createVars: () => ({}), + onStart: (c) => { + c.state.startCount += 1; + }, + onStop: (c) => { + c.state.sleepCount += 1; + }, + actions: { + getCounts: (c) => { + return { startCount: c.state.startCount, sleepCount: c.state.sleepCount }; + }, + longRunningRpc: async (c) => { + c.log.info("starting long running rpc"); + c.vars.longRunningResolve = Promise.withResolvers(); + c.broadcast("waiting"); + await c.vars.longRunningResolve.promise; + c.log.info("finished long running rpc"); + }, + finishLongRunningRpc: (c) => c.vars.longRunningResolve?.resolve() + }, + options: { + sleepTimeout: SLEEP_TIMEOUT + } +}); +var sleepWithRawHttp = actor({ + onAuth: () => { + }, + state: { startCount: 0, sleepCount: 0, requestCount: 0 }, + onStart: (c) => { + c.state.startCount += 1; + }, + onStop: (c) => { + c.state.sleepCount += 1; + }, + onFetch: async (c, request) => { + c.state.requestCount += 1; + const url = new URL(request.url); + if (url.pathname === "/long-request") { + const duration = parseInt(url.searchParams.get("duration") || "1000"); + c.log.info("starting long fetch request", { duration }); + await new Promise((resolve) => setTimeout(resolve, duration)); + c.log.info("finished long fetch request"); + return new Response(JSON.stringify({ completed: true }), { + headers: { "Content-Type": "application/json" } + }); + } + return new Response("Not Found", { status: 404 }); + }, + actions: { + getCounts: (c) => { + return { + startCount: c.state.startCount, + sleepCount: c.state.sleepCount, + requestCount: c.state.requestCount + }; + } + }, + options: { + sleepTimeout: SLEEP_TIMEOUT + } +}); +var sleepWithRawWebSocket = actor({ + onAuth: () => { + }, + state: { startCount: 0, sleepCount: 0, connectionCount: 0 }, + onStart: (c) => { + c.state.startCount += 1; + }, + onStop: (c) => { + c.state.sleepCount += 1; + }, + onWebSocket: (c, websocket, opts) => { + c.state.connectionCount += 1; + c.log.info("websocket connected", { + connectionCount: c.state.connectionCount + }); + websocket.send( + JSON.stringify({ + type: "connected", + connectionCount: c.state.connectionCount + }) + ); + websocket.addEventListener("message", (event) => { + const data = event.data; + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + if (parsed.type === "getCounts") { + websocket.send( + JSON.stringify({ + type: "counts", + startCount: c.state.startCount, + sleepCount: c.state.sleepCount, + connectionCount: c.state.connectionCount + }) + ); + } else if (parsed.type === "keepAlive") { + websocket.send(JSON.stringify({ type: "ack" })); + } + } catch { + websocket.send(data); + } + } + }); + websocket.addEventListener("close", () => { + c.state.connectionCount -= 1; + c.log.info("websocket disconnected", { + connectionCount: c.state.connectionCount + }); + }); + }, + actions: { + getCounts: (c) => { + return { + startCount: c.state.startCount, + sleepCount: c.state.sleepCount, + connectionCount: c.state.connectionCount + }; + } + }, + options: { + sleepTimeout: SLEEP_TIMEOUT + } +}); +var sleepWithNoSleepOption = actor({ + onAuth: () => { + }, + state: { startCount: 0, sleepCount: 0 }, + onStart: (c) => { + c.state.startCount += 1; + }, + onStop: (c) => { + c.state.sleepCount += 1; + }, + actions: { + getCounts: (c) => { + return { startCount: c.state.startCount, sleepCount: c.state.sleepCount }; + } + }, + options: { + sleepTimeout: SLEEP_TIMEOUT, + noSleep: true + } +}); + +// fixtures/driver-test-suite/vars.ts +var staticVarActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + connState: { hello: "world" }, + vars: { counter: 42, name: "test-actor" }, + actions: { + getVars: (c) => { + return c.vars; + }, + getName: (c) => { + return c.vars.name; + } + } +}); +var nestedVarActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + connState: { hello: "world" }, + vars: { + counter: 42, + nested: { + value: "original", + array: [1, 2, 3], + obj: { key: "value" } + } + }, + actions: { + getVars: (c) => { + return c.vars; + }, + modifyNested: (c) => { + c.vars.nested.value = "modified"; + c.vars.nested.array.push(4); + c.vars.nested.obj.key = "new-value"; + return c.vars; + } + } +}); +var dynamicVarActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + connState: { hello: "world" }, + createVars: () => { + return { + random: Math.random(), + computed: `Actor-${Math.floor(Math.random() * 1e3)}` + }; + }, + actions: { + getVars: (c) => { + return c.vars; + } + } +}); +var uniqueVarActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + connState: { hello: "world" }, + createVars: () => { + return { + id: Math.floor(Math.random() * 1e6) + }; + }, + actions: { + getVars: (c) => { + return c.vars; + } + } +}); +var driverCtxActor = actor({ + onAuth: () => { + }, + state: { value: 0 }, + connState: { hello: "world" }, + createVars: (c, driverCtx) => { + return { + hasDriverCtx: Boolean(driverCtx?.isTest) + }; + }, + actions: { + getVars: (c) => { + return c.vars; + } + } +}); + +// fixtures/driver-test-suite/registry.ts +var registry = setup({ + use: { + // From counter.ts + counter, + // From lifecycle.ts + counterWithLifecycle, + // From scheduled.ts + scheduled, + // From sleep.ts + sleep, + sleepWithLongRpc, + sleepWithRawHttp, + sleepWithRawWebSocket, + sleepWithNoSleepOption, + // From error-handling.ts + errorHandlingActor, + customTimeoutActor, + // From inline-client.ts + inlineClientActor, + // From action-inputs.ts + inputActor, + // From action-timeout.ts + shortTimeoutActor, + longTimeoutActor, + defaultTimeoutActor, + syncTimeoutActor, + // From action-types.ts + syncActionActor, + asyncActionActor, + promiseActor, + // From conn-params.ts + counterWithParams, + // From conn-state.ts + connStateActor, + // From actor-conn.ts + connLivenessActor, + // From metadata.ts + metadataActor, + // From vars.ts + staticVarActor, + nestedVarActor, + dynamicVarActor, + uniqueVarActor, + driverCtxActor, + // From auth.ts + authActor, + intentAuthActor, + publicActor, + noAuthActor, + asyncAuthActor, + // From raw-http.ts + rawHttpActor, + rawHttpNoHandlerActor, + rawHttpVoidReturnActor, + rawHttpHonoActor, + // From raw-http-auth.ts + rawHttpAuthActor, + rawHttpNoAuthActor, + rawHttpPublicActor, + rawHttpCustomAuthActor, + // From raw-http-request-properties.ts + rawHttpRequestPropertiesActor, + // From raw-websocket.ts + rawWebSocketActor, + rawWebSocketBinaryActor, + // From raw-websocket-auth.ts + rawWebSocketAuthActor, + rawWebSocketNoAuthActor, + rawWebSocketPublicActor, + rawWebSocketCustomAuthActor, + // From request-access.ts + requestAccessActor, + requestAccessAuthActor, + // From actor-onstatechange.ts + onStateChangeActor + } +}); +export { + registry +}; +//! These configs configs hold anything that's not platform-specific about running actors. +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2FjdG9yL2Nvbm5lY3Rpb24udHMiLCAic3JjL2NvbW1vbi92ZXJzaW9uZWQtZGF0YS50cyIsICJkaXN0L3NjaGVtYXMvY2xpZW50LXByb3RvY29sL3YxLnRzIiwgInNyYy9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWQudHMiLCAic3JjL2FjdG9yL2Vycm9ycy50cyIsICJzcmMvY29tbW9uL3V0aWxzLnRzIiwgInBhY2thZ2UuanNvbiIsICJzcmMvdXRpbHMudHMiLCAic3JjL2NvbW1vbi9sb2ctbGV2ZWxzLnRzIiwgInNyYy9jb21tb24vbG9nZm10LnRzIiwgInNyYy9jb21tb24vbG9nLnRzIiwgInNyYy9hY3Rvci9sb2cudHMiLCAic3JjL2FjdG9yL3Byb3RvY29sL3NlcmRlLnRzIiwgInNyYy9zZXJkZS50cyIsICJzcmMvYWN0b3IvdXRpbHMudHMiLCAic3JjL2FjdG9yL2NvbmZpZy50cyIsICJzcmMvYWN0b3IvaW5zdGFuY2UudHMiLCAic3JjL2luc3BlY3Rvci9hY3Rvci50cyIsICJzcmMvaW5zcGVjdG9yL3Byb3RvY29sL2NvbW1vbi50cyIsICJzcmMvbWFuYWdlci9wcm90b2NvbC9xdWVyeS50cyIsICJzcmMvYWN0b3Ivcm91dGVyLWVuZHBvaW50cy50cyIsICJzcmMvYWN0b3IvYWN0aW9uLnRzIiwgInNyYy9tYW5hZ2VyL2xvZy50cyIsICJzcmMvbWFuYWdlci9ob25vLXdlYnNvY2tldC1hZGFwdGVyLnRzIiwgInNyYy9hY3Rvci9wcm90b2NvbC9vbGQudHMiLCAiZGlzdC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvdjEudHMiLCAic3JjL3NjaGVtYXMvYWN0b3ItcGVyc2lzdC92ZXJzaW9uZWQudHMiLCAic3JjL2FjdG9yL2NvbnRleHQudHMiLCAic3JjL2FjdG9yL3NjaGVkdWxlLnRzIiwgInNyYy9hY3Rvci9kZWZpbml0aW9uLnRzIiwgInNyYy9hY3Rvci9nZW5lcmljLWNvbm4tZHJpdmVyLnRzIiwgInNyYy9hY3Rvci9yb3V0ZXIudHMiLCAic3JjL2NvbW1vbi9yb3V0ZXIudHMiLCAic3JjL2luc3BlY3Rvci91dGlscy50cyIsICJzcmMvaW5zcGVjdG9yL2xvZy50cyIsICJzcmMvYWN0b3IvbW9kLnRzIiwgInNyYy9jbGllbnQvYWN0b3ItY29ubi50cyIsICJzcmMvY2xpZW50L2Vycm9ycy50cyIsICJzcmMvY2xpZW50L2xvZy50cyIsICJzcmMvY2xpZW50L3V0aWxzLnRzIiwgInNyYy9jbGllbnQvYWN0b3ItaGFuZGxlLnRzIiwgInNyYy9jbGllbnQvcmF3LXV0aWxzLnRzIiwgInNyYy9jbGllbnQvY2xpZW50LnRzIiwgInNyYy9jb21tb24vaW5saW5lLXdlYnNvY2tldC1hZGFwdGVyMi50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUvYWN0b3ItZHJpdmVyLnRzIiwgInNyYy9yZWdpc3RyeS9ydW4tY29uZmlnLnRzIiwgInNyYy9pbnNwZWN0b3IvY29uZmlnLnRzIiwgInNyYy9kcml2ZXItaGVscGVycy91dGlscy50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUva2V5cy50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUva3YudHMiLCAic3JjL2RyaXZlcnMvZW5naW5lL2xvZy50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUvY29uZmlnLnRzIiwgInNyYy9kcml2ZXJzL2VuZ2luZS9tYW5hZ2VyLWRyaXZlci50cyIsICJzcmMvY29tbW9uL3dlYnNvY2tldC50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUvYXBpLXV0aWxzLnRzIiwgInNyYy9kcml2ZXJzL2VuZ2luZS9hcGktZW5kcG9pbnRzLnRzIiwgInNyYy9kcml2ZXJzL2VuZ2luZS93cy1wcm94eS50cyIsICJzcmMvZHJpdmVycy9lbmdpbmUvbW9kLnRzIiwgInNyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL2FjdG9yLnRzIiwgInNyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL2dsb2JhbC1zdGF0ZS50cyIsICJkaXN0L3NjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyL3YxLnRzIiwgInNyYy9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci92ZXJzaW9uZWQudHMiLCAic3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW0vbG9nLnRzIiwgInNyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL3V0aWxzLnRzIiwgInNyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL21hbmFnZXIudHMiLCAic3JjL2lubGluZS1jbGllbnQtZHJpdmVyL21vZC50cyIsICJzcmMvY29tbW9uL2V2ZW50c291cmNlLnRzIiwgInNyYy9pbmxpbmUtY2xpZW50LWRyaXZlci9sb2cudHMiLCAic3JjL2luc3BlY3Rvci9tYW5hZ2VyLnRzIiwgInNyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL21vZC50cyIsICJzcmMvZHJpdmVycy9kZWZhdWx0LnRzIiwgInNyYy9tYW5hZ2VyL3JvdXRlci50cyIsICJzcmMvbWFuYWdlci9hdXRoLnRzIiwgInNyYy9yZWdpc3RyeS9jb25maWcudHMiLCAic3JjL3JlZ2lzdHJ5L2xvZy50cyIsICJzcmMvcmVnaXN0cnkvc2VydmUudHMiLCAic3JjL3JlZ2lzdHJ5L21vZC50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9hY3Rpb24taW5wdXRzLnRzIiwgImZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2FjdGlvbi10aW1lb3V0LnRzIiwgImZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2FjdGlvbi10eXBlcy50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9hY3Rvci1vbnN0YXRlY2hhbmdlLnRzIiwgImZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2F1dGgudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvY29ubi1saXZlbmVzcy50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9jb25uLXBhcmFtcy50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9jb25uLXN0YXRlLnRzIiwgImZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2NvdW50ZXIudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvZXJyb3ItaGFuZGxpbmcudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvaW5saW5lLWNsaWVudC50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9saWZlY3ljbGUudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvbWV0YWRhdGEudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmF3LWh0dHAudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmF3LWh0dHAtYXV0aC50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9yYXctaHR0cC1yZXF1ZXN0LXByb3BlcnRpZXMudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmF3LXdlYnNvY2tldC50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9yYXctd2Vic29ja2V0LWF1dGgudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmVxdWVzdC1hY2Nlc3MudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmVxdWVzdC1hY2Nlc3MtYXV0aC50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9zY2hlZHVsZWQudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvc2xlZXAudHMiLCAiZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvdmFycy50cyIsICJmaXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9yZWdpc3RyeS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9jb25uZWN0aW9uLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2Nvbm5lY3Rpb24udHNcIjtpbXBvcnQgKiBhcyBjYm9yIGZyb20gXCJjYm9yLXhcIjtcbmltcG9ydCB0eXBlICogYXMgcHJvdG9jb2wgZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvbW9kXCI7XG5pbXBvcnQgeyBUT19DTElFTlRfVkVSU0lPTkVEIH0gZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdmVyc2lvbmVkXCI7XG5pbXBvcnQgeyBidWZmZXJUb0FycmF5QnVmZmVyIH0gZnJvbSBcIkAvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgQW55RGF0YWJhc2VQcm92aWRlciB9IGZyb20gXCIuL2RhdGFiYXNlXCI7XG5pbXBvcnQgeyB0eXBlIENvbm5Ecml2ZXIsIENvbm5lY3Rpb25SZWFkeVN0YXRlIH0gZnJvbSBcIi4vZHJpdmVyXCI7XG5pbXBvcnQgKiBhcyBlcnJvcnMgZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9ySW5zdGFuY2UgfSBmcm9tIFwiLi9pbnN0YW5jZVwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgdHlwZSB7IFBlcnNpc3RlZENvbm4gfSBmcm9tIFwiLi9wZXJzaXN0ZWRcIjtcbmltcG9ydCB7IENhY2hlZFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHsgZ2VuZXJhdGVTZWN1cmVUb2tlbiB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUNvbm5JZCgpOiBzdHJpbmcge1xuXHRyZXR1cm4gY3J5cHRvLnJhbmRvbVVVSUQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQ29ublRva2VuKCk6IHN0cmluZyB7XG5cdHJldHVybiBnZW5lcmF0ZVNlY3VyZVRva2VuKDMyKTtcbn1cblxuZXhwb3J0IHR5cGUgQ29ubklkID0gc3RyaW5nO1xuXG5leHBvcnQgdHlwZSBBbnlDb25uID0gQ29ubjxhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnk+O1xuXG5leHBvcnQgY29uc3QgQ09OTkVDVElPTl9EUklWRVJfV0VCU09DS0VUID0gXCJ3ZWJTb2NrZXRcIjtcbmV4cG9ydCBjb25zdCBDT05ORUNUSU9OX0RSSVZFUl9TU0UgPSBcInNzZVwiO1xuZXhwb3J0IGNvbnN0IENPTk5FQ1RJT05fRFJJVkVSX0hUVFAgPSBcImh0dHBcIjtcblxuZXhwb3J0IHR5cGUgQ29ubmVjdGlvbkRyaXZlciA9XG5cdHwgdHlwZW9mIENPTk5FQ1RJT05fRFJJVkVSX1dFQlNPQ0tFVFxuXHR8IHR5cGVvZiBDT05ORUNUSU9OX0RSSVZFUl9TU0Vcblx0fCB0eXBlb2YgQ09OTkVDVElPTl9EUklWRVJfSFRUUDtcblxuZXhwb3J0IHR5cGUgQ29ubmVjdGlvblN0YXR1cyA9IFwiY29ubmVjdGVkXCIgfCBcInJlY29ubmVjdGluZ1wiO1xuXG5leHBvcnQgY29uc3QgQ09OTkVDVElPTl9DSEVDS19MSVZFTkVTU19TWU1CT0wgPSBTeW1ib2woXCJjaGVja0xpdmVuZXNzXCIpO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBjbGllbnQgY29ubmVjdGlvbiB0byBhIGFjdG9yLlxuICpcbiAqIE1hbmFnZXMgY29ubmVjdGlvbi1zcGVjaWZpYyBkYXRhIGFuZCBjb250cm9scyB0aGUgY29ubmVjdGlvbiBsaWZlY3ljbGUuXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9yaXZldC5nZy9kb2NzL2Nvbm5lY3Rpb25zfENvbm5lY3Rpb24gRG9jdW1lbnRhdGlvbn1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm48UywgQ1AsIENTLCBWLCBJLCBBRCwgREIgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyPiB7XG5cdHN1YnNjcmlwdGlvbnM6IFNldDxzdHJpbmc+ID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cblx0I3N0YXRlRW5hYmxlZDogYm9vbGVhbjtcblxuXHQvLyBUT0RPOiBSZW1vdmUgdGhpcyBjeWNsaWNhbCByZWZlcmVuY2Vcblx0I2FjdG9yOiBBY3Rvckluc3RhbmNlPFMsIENQLCBDUywgViwgSSwgQUQsIERCPjtcblxuXHQjc3RhdHVzOiBDb25uZWN0aW9uU3RhdHVzID0gXCJjb25uZWN0ZWRcIjtcblxuXHQvKipcblx0ICogVGhlIHByb3hpZWQgc3RhdGUgdGhhdCBub3RpZmllcyBvZiBjaGFuZ2VzIGF1dG9tYXRpY2FsbHkuXG5cdCAqXG5cdCAqIEFueSBkYXRhIHRoYXQgc2hvdWxkIGJlIHN0b3JlZCBpbmRlZmluaXRlbHkgc2hvdWxkIGJlIGhlbGQgd2l0aGluIHRoaXMgb2JqZWN0LlxuXHQgKi9cblx0X19wZXJzaXN0OiBQZXJzaXN0ZWRDb25uPENQLCBDUz47XG5cblx0LyoqXG5cdCAqIERyaXZlciB1c2VkIHRvIG1hbmFnZSByZWFsdGltZSBjb25uZWN0aW9uIGNvbW11bmljYXRpb24uXG5cdCAqXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdCNkcml2ZXI6IENvbm5Ecml2ZXI7XG5cblx0cHVibGljIGdldCBwYXJhbXMoKTogQ1Age1xuXHRcdHJldHVybiB0aGlzLl9fcGVyc2lzdC5wYXJhbXM7XG5cdH1cblxuXHRwdWJsaWMgZ2V0IGF1dGgoKTogQUQge1xuXHRcdHJldHVybiB0aGlzLl9fcGVyc2lzdC5hdXRoRGF0YSBhcyBBRDtcblx0fVxuXG5cdHB1YmxpYyBnZXQgZHJpdmVyKCk6IENvbm5lY3Rpb25Ecml2ZXIge1xuXHRcdHJldHVybiB0aGlzLl9fcGVyc2lzdC5jb25uRHJpdmVyIGFzIENvbm5lY3Rpb25Ecml2ZXI7XG5cdH1cblxuXHRwdWJsaWMgZ2V0IF9zdGF0ZUVuYWJsZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuI3N0YXRlRW5hYmxlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBjb25uZWN0aW9uLlxuXHQgKlxuXHQgKiBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIHN0YXRlIGlzIG5vdCBlbmFibGVkLlxuXHQgKi9cblx0cHVibGljIGdldCBzdGF0ZSgpOiBDUyB7XG5cdFx0dGhpcy4jdmFsaWRhdGVTdGF0ZUVuYWJsZWQoKTtcblx0XHRpZiAoIXRoaXMuX19wZXJzaXN0LnN0YXRlKSB0aHJvdyBuZXcgRXJyb3IoXCJzdGF0ZSBzaG91bGQgZXhpc3RzXCIpO1xuXHRcdHJldHVybiB0aGlzLl9fcGVyc2lzdC5zdGF0ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzdGF0ZSBvZiB0aGUgY29ubmVjdGlvbi5cblx0ICpcblx0ICogVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBzdGF0ZSBpcyBub3QgZW5hYmxlZC5cblx0ICovXG5cdHB1YmxpYyBzZXQgc3RhdGUodmFsdWU6IENTKSB7XG5cdFx0dGhpcy4jdmFsaWRhdGVTdGF0ZUVuYWJsZWQoKTtcblx0XHR0aGlzLl9fcGVyc2lzdC5zdGF0ZSA9IHZhbHVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgY29ubmVjdGlvbi5cblx0ICovXG5cdHB1YmxpYyBnZXQgaWQoKTogQ29ubklkIHtcblx0XHRyZXR1cm4gdGhpcy5fX3BlcnNpc3QuY29ubklkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRva2VuIHVzZWQgdG8gYXV0aGVudGljYXRlIHRoaXMgcmVxdWVzdC5cblx0ICovXG5cdHB1YmxpYyBnZXQgX3Rva2VuKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuX19wZXJzaXN0LnRva2VuO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXR1cyBvZiB0aGUgY29ubmVjdGlvbi5cblx0ICovXG5cdHB1YmxpYyBnZXQgc3RhdHVzKCk6IENvbm5lY3Rpb25TdGF0dXMge1xuXHRcdHJldHVybiB0aGlzLiNzdGF0dXM7XG5cdH1cblxuXHQvKipcblx0ICogVGltZXN0YW1wIG9mIHRoZSBsYXN0IHRpbWUgdGhlIGNvbm5lY3Rpb24gd2FzIHNlZW4sIGkuZS4gdGhlIGxhc3QgdGltZSB0aGUgY29ubmVjdGlvbiB3YXMgYWN0aXZlIGFuZCBjaGVja2VkIGZvciBsaXZlbmVzcy5cblx0ICovXG5cdHB1YmxpYyBnZXQgbGFzdFNlZW4oKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5fX3BlcnNpc3QubGFzdFNlZW47XG5cdH1cblxuXHQvKipcblx0ICogSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIENvbm5lY3Rpb24gY2xhc3MuXG5cdCAqXG5cdCAqIFRoaXMgc2hvdWxkIG9ubHkgYmUgY29uc3RydWN0ZWQgYnkge0BsaW5rIEFjdG9yfS5cblx0ICpcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdGFjdG9yOiBBY3Rvckluc3RhbmNlPFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcblx0XHRwZXJzaXN0OiBQZXJzaXN0ZWRDb25uPENQLCBDUz4sXG5cdFx0ZHJpdmVyOiBDb25uRHJpdmVyLFxuXHRcdHN0YXRlRW5hYmxlZDogYm9vbGVhbixcblx0KSB7XG5cdFx0dGhpcy4jYWN0b3IgPSBhY3Rvcjtcblx0XHR0aGlzLl9fcGVyc2lzdCA9IHBlcnNpc3Q7XG5cdFx0dGhpcy4jZHJpdmVyID0gZHJpdmVyO1xuXHRcdHRoaXMuI3N0YXRlRW5hYmxlZCA9IHN0YXRlRW5hYmxlZDtcblx0fVxuXG5cdCN2YWxpZGF0ZVN0YXRlRW5hYmxlZCgpIHtcblx0XHRpZiAoIXRoaXMuI3N0YXRlRW5hYmxlZCkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5Db25uU3RhdGVOb3RFbmFibGVkKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNlbmRzIGEgV2ViU29ja2V0IG1lc3NhZ2UgdG8gdGhlIGNsaWVudC5cblx0ICpcblx0ICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBzZW5kLlxuXHQgKlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRwdWJsaWMgX3NlbmRNZXNzYWdlKG1lc3NhZ2U6IENhY2hlZFNlcmlhbGl6ZXI8cHJvdG9jb2wuVG9DbGllbnQ+KSB7XG5cdFx0dGhpcy4jZHJpdmVyLnNlbmRNZXNzYWdlPy4oXG5cdFx0XHR0aGlzLiNhY3Rvcixcblx0XHRcdHRoaXMsXG5cdFx0XHR0aGlzLl9fcGVyc2lzdC5jb25uRHJpdmVyU3RhdGUsXG5cdFx0XHRtZXNzYWdlLFxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogU2VuZHMgYW4gZXZlbnQgd2l0aCBhcmd1bWVudHMgdG8gdGhlIGNsaWVudC5cblx0ICpcblx0ICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cblx0ICogQHBhcmFtIGFyZ3MgLSBUaGUgYXJndW1lbnRzIGZvciB0aGUgZXZlbnQuXG5cdCAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9ldmVudHN8RXZlbnRzIERvY3VtZW50YXRpb259XG5cdCAqL1xuXHRwdWJsaWMgc2VuZChldmVudE5hbWU6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKSB7XG5cdFx0dGhpcy4jYWN0b3IuaW5zcGVjdG9yLmVtaXR0ZXIuZW1pdChcImV2ZW50RmlyZWRcIiwge1xuXHRcdFx0dHlwZTogXCJldmVudFwiLFxuXHRcdFx0ZXZlbnROYW1lLFxuXHRcdFx0YXJncyxcblx0XHRcdGNvbm5JZDogdGhpcy5pZCxcblx0XHR9KTtcblx0XHR0aGlzLl9zZW5kTWVzc2FnZShcblx0XHRcdG5ldyBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pihcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJvZHk6IHtcblx0XHRcdFx0XHRcdHRhZzogXCJFdmVudFwiLFxuXHRcdFx0XHRcdFx0dmFsOiB7XG5cdFx0XHRcdFx0XHRcdG5hbWU6IGV2ZW50TmFtZSxcblx0XHRcdFx0XHRcdFx0YXJnczogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShhcmdzKSksXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0sXG5cdFx0XHRcdFRPX0NMSUVOVF9WRVJTSU9ORUQsXG5cdFx0XHQpLFxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzY29ubmVjdHMgdGhlIGNsaWVudCB3aXRoIGFuIG9wdGlvbmFsIHJlYXNvbi5cblx0ICpcblx0ICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWFzb24gZm9yIGRpc2Nvbm5lY3Rpb24uXG5cdCAqL1xuXHRwdWJsaWMgYXN5bmMgZGlzY29ubmVjdChyZWFzb24/OiBzdHJpbmcpIHtcblx0XHR0aGlzLiNzdGF0dXMgPSBcInJlY29ubmVjdGluZ1wiO1xuXHRcdGF3YWl0IHRoaXMuI2RyaXZlci5kaXNjb25uZWN0KFxuXHRcdFx0dGhpcy4jYWN0b3IsXG5cdFx0XHR0aGlzLFxuXHRcdFx0dGhpcy5fX3BlcnNpc3QuY29ubkRyaXZlclN0YXRlLFxuXHRcdFx0cmVhc29uLFxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogVGhpcyBtZXRob2QgY2hlY2tzIHRoZSBjb25uZWN0aW9uJ3MgbGl2ZW5lc3MgYnkgcXVlcnlpbmcgdGhlIGRyaXZlciBmb3IgaXRzIHJlYWR5IHN0YXRlLlxuXHQgKiBJZiB0aGUgY29ubmVjdGlvbiBpcyBub3QgY2xvc2VkLCBpdCB1cGRhdGVzIHRoZSBsYXN0IGxpdmVuZXNzIHRpbWVzdGFtcCBhbmQgcmV0dXJucyBgdHJ1ZWAuXG5cdCAqIE90aGVyd2lzZSwgaXQgcmV0dXJucyBgZmFsc2VgLlxuXHQgKiBAaW50ZXJuYWxcblx0ICovXG5cdFtDT05ORUNUSU9OX0NIRUNLX0xJVkVORVNTX1NZTUJPTF0oKSB7XG5cdFx0Y29uc3QgcmVhZHlTdGF0ZSA9IHRoaXMuI2RyaXZlci5nZXRDb25uZWN0aW9uUmVhZHlTdGF0ZSh0aGlzLiNhY3RvciwgdGhpcyk7XG5cblx0XHRjb25zdCBpc0Nvbm5lY3Rpb25DbG9zZWQgPVxuXHRcdFx0cmVhZHlTdGF0ZSA9PT0gQ29ubmVjdGlvblJlYWR5U3RhdGUuQ0xPU0VEIHx8XG5cdFx0XHRyZWFkeVN0YXRlID09PSBDb25uZWN0aW9uUmVhZHlTdGF0ZS5DTE9TSU5HIHx8XG5cdFx0XHRyZWFkeVN0YXRlID09PSB1bmRlZmluZWQ7XG5cblx0XHRjb25zdCBuZXdMYXN0U2VlbiA9IERhdGUubm93KCk7XG5cdFx0Y29uc3QgbmV3U3RhdHVzID0gaXNDb25uZWN0aW9uQ2xvc2VkID8gXCJyZWNvbm5lY3RpbmdcIiA6IFwiY29ubmVjdGVkXCI7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImxpdmVuZXNzIHByb2JlIGZvciBjb25uZWN0aW9uXCIsIHtcblx0XHRcdGNvbm5JZDogdGhpcy5pZCxcblx0XHRcdGFjdG9ySWQ6IHRoaXMuI2FjdG9yLmlkLFxuXHRcdFx0cmVhZHlTdGF0ZSxcblxuXHRcdFx0c3RhdHVzOiB0aGlzLiNzdGF0dXMsXG5cdFx0XHRuZXdTdGF0dXMsXG5cblx0XHRcdGxhc3RTZWVuOiB0aGlzLl9fcGVyc2lzdC5sYXN0U2Vlbixcblx0XHRcdGN1cnJlbnRUczogbmV3TGFzdFNlZW4sXG5cdFx0fSk7XG5cblx0XHRpZiAoIWlzQ29ubmVjdGlvbkNsb3NlZCkge1xuXHRcdFx0dGhpcy5fX3BlcnNpc3QubGFzdFNlZW4gPSBuZXdMYXN0U2Vlbjtcblx0XHR9XG5cblx0XHR0aGlzLiNzdGF0dXMgPSBuZXdTdGF0dXM7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHN0YXR1czogdGhpcy4jc3RhdHVzLFxuXHRcdFx0bGFzdFNlZW46IHRoaXMuX19wZXJzaXN0Lmxhc3RTZWVuLFxuXHRcdH07XG5cdH1cbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi92ZXJzaW9uZWQtZGF0YS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb25cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL3ZlcnNpb25lZC1kYXRhLnRzXCI7ZXhwb3J0IGludGVyZmFjZSBWZXJzaW9uZWREYXRhPFQ+IHtcblx0dmVyc2lvbjogbnVtYmVyO1xuXHRkYXRhOiBUO1xufVxuXG5leHBvcnQgdHlwZSBNaWdyYXRpb25GbjxURnJvbSwgVFRvPiA9IChkYXRhOiBURnJvbSkgPT4gVFRvO1xuXG5leHBvcnQgaW50ZXJmYWNlIFZlcnNpb25lZERhdGFDb25maWc8VD4ge1xuXHRjdXJyZW50VmVyc2lvbjogbnVtYmVyO1xuXHRtaWdyYXRpb25zOiBNYXA8bnVtYmVyLCBNaWdyYXRpb25GbjxhbnksIGFueT4+O1xuXHRzZXJpYWxpemVWZXJzaW9uOiAoZGF0YTogVCkgPT4gVWludDhBcnJheTtcblx0ZGVzZXJpYWxpemVWZXJzaW9uOiAoYnl0ZXM6IFVpbnQ4QXJyYXkpID0+IFQ7XG59XG5cbmV4cG9ydCBjbGFzcyBWZXJzaW9uZWREYXRhSGFuZGxlcjxUPiB7XG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgY29uZmlnOiBWZXJzaW9uZWREYXRhQ29uZmlnPFQ+KSB7fVxuXG5cdHNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oZGF0YTogVCk6IFVpbnQ4QXJyYXkge1xuXHRcdGNvbnN0IHZlcnNpb25lZDogVmVyc2lvbmVkRGF0YTxVaW50OEFycmF5PiA9IHtcblx0XHRcdHZlcnNpb246IHRoaXMuY29uZmlnLmN1cnJlbnRWZXJzaW9uLFxuXHRcdFx0ZGF0YTogdGhpcy5jb25maWcuc2VyaWFsaXplVmVyc2lvbihkYXRhKSxcblx0XHR9O1xuXG5cdFx0cmV0dXJuIHRoaXMuZW1iZWRWZXJzaW9uKHZlcnNpb25lZCk7XG5cdH1cblxuXHRkZXNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oYnl0ZXM6IFVpbnQ4QXJyYXkpOiBUIHtcblx0XHRjb25zdCB2ZXJzaW9uZWQgPSB0aGlzLmV4dHJhY3RWZXJzaW9uKGJ5dGVzKTtcblx0XHRyZXR1cm4gdGhpcy5kZXNlcmlhbGl6ZSh2ZXJzaW9uZWQuZGF0YSwgdmVyc2lvbmVkLnZlcnNpb24pO1xuXHR9XG5cblx0c2VyaWFsaXplKGRhdGE6IFQsIHZlcnNpb246IG51bWJlcik6IFVpbnQ4QXJyYXkge1xuXHRcdHJldHVybiB0aGlzLmNvbmZpZy5zZXJpYWxpemVWZXJzaW9uKGRhdGEpO1xuXHR9XG5cblx0ZGVzZXJpYWxpemUoYnl0ZXM6IFVpbnQ4QXJyYXksIHZlcnNpb246IG51bWJlcik6IFQge1xuXHRcdGlmICh2ZXJzaW9uID09PSB0aGlzLmNvbmZpZy5jdXJyZW50VmVyc2lvbikge1xuXHRcdFx0cmV0dXJuIHRoaXMuY29uZmlnLmRlc2VyaWFsaXplVmVyc2lvbihieXRlcyk7XG5cdFx0fVxuXG5cdFx0aWYgKHZlcnNpb24gPiB0aGlzLmNvbmZpZy5jdXJyZW50VmVyc2lvbikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0XHRgQ2Fubm90IGRlY29kZSBkYXRhIGZyb20gdmVyc2lvbiAke3ZlcnNpb259LCBjdXJyZW50IHZlcnNpb24gaXMgJHt0aGlzLmNvbmZpZy5jdXJyZW50VmVyc2lvbn1gLFxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHRsZXQgY3VycmVudERhdGE6IGFueSA9IHRoaXMuY29uZmlnLmRlc2VyaWFsaXplVmVyc2lvbihieXRlcyk7XG5cdFx0bGV0IGN1cnJlbnRWZXJzaW9uID0gdmVyc2lvbjtcblxuXHRcdHdoaWxlIChjdXJyZW50VmVyc2lvbiA8IHRoaXMuY29uZmlnLmN1cnJlbnRWZXJzaW9uKSB7XG5cdFx0XHRjb25zdCBtaWdyYXRpb24gPSB0aGlzLmNvbmZpZy5taWdyYXRpb25zLmdldChjdXJyZW50VmVyc2lvbik7XG5cdFx0XHRpZiAoIW1pZ3JhdGlvbikge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdFx0YE5vIG1pZ3JhdGlvbiBmb3VuZCBmcm9tIHZlcnNpb24gJHtjdXJyZW50VmVyc2lvbn0gdG8gJHtjdXJyZW50VmVyc2lvbiArIDF9YCxcblx0XHRcdFx0KTtcblx0XHRcdH1cblxuXHRcdFx0Y3VycmVudERhdGEgPSBtaWdyYXRpb24oY3VycmVudERhdGEpO1xuXHRcdFx0Y3VycmVudFZlcnNpb24rKztcblx0XHR9XG5cblx0XHRyZXR1cm4gY3VycmVudERhdGE7XG5cdH1cblxuXHRwcml2YXRlIGVtYmVkVmVyc2lvbihkYXRhOiBWZXJzaW9uZWREYXRhPFVpbnQ4QXJyYXk+KTogVWludDhBcnJheSB7XG5cdFx0Y29uc3QgdmVyc2lvbkJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5cdFx0bmV3IERhdGFWaWV3KHZlcnNpb25CeXRlcy5idWZmZXIpLnNldFVpbnQzMigwLCBkYXRhLnZlcnNpb24sIHRydWUpO1xuXG5cdFx0Y29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkodmVyc2lvbkJ5dGVzLmxlbmd0aCArIGRhdGEuZGF0YS5sZW5ndGgpO1xuXHRcdHJlc3VsdC5zZXQodmVyc2lvbkJ5dGVzKTtcblx0XHRyZXN1bHQuc2V0KGRhdGEuZGF0YSwgdmVyc2lvbkJ5dGVzLmxlbmd0aCk7XG5cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0cHJpdmF0ZSBleHRyYWN0VmVyc2lvbihieXRlczogVWludDhBcnJheSk6IFZlcnNpb25lZERhdGE8VWludDhBcnJheT4ge1xuXHRcdGlmIChieXRlcy5sZW5ndGggPCA0KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHZlcnNpb25lZCBkYXRhOiB0b28gc2hvcnRcIik7XG5cdFx0fVxuXG5cdFx0Y29uc3QgdmVyc2lvbiA9IG5ldyBEYXRhVmlldyhieXRlcy5idWZmZXIsIGJ5dGVzLmJ5dGVPZmZzZXQpLmdldFVpbnQzMihcblx0XHRcdDAsXG5cdFx0XHR0cnVlLFxuXHRcdCk7XG5cdFx0Y29uc3QgZGF0YSA9IGJ5dGVzLnNsaWNlKDQpO1xuXG5cdFx0cmV0dXJuIHsgdmVyc2lvbiwgZGF0YSB9O1xuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcjxUPihcblx0Y29uZmlnOiBWZXJzaW9uZWREYXRhQ29uZmlnPFQ+LFxuKTogVmVyc2lvbmVkRGF0YUhhbmRsZXI8VD4ge1xuXHRyZXR1cm4gbmV3IFZlcnNpb25lZERhdGFIYW5kbGVyKGNvbmZpZyk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2Rpc3Qvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdjEudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9kaXN0L3NjaGVtYXMvY2xpZW50LXByb3RvY29sXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZGlzdC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92MS50c1wiO2ltcG9ydCAqIGFzIGJhcmUgZnJvbSBcIkBiYXJlLXRzL2xpYlwiXG5cbmNvbnN0IGNvbmZpZyA9IC8qIEBfX1BVUkVfXyAqLyBiYXJlLkNvbmZpZyh7fSlcblxuZXhwb3J0IHR5cGUgdWludCA9IGJpZ2ludFxuXG5leHBvcnQgdHlwZSBJbml0ID0ge1xuICAgIHJlYWRvbmx5IGFjdG9ySWQ6IHN0cmluZyxcbiAgICByZWFkb25seSBjb25uZWN0aW9uSWQ6IHN0cmluZyxcbiAgICByZWFkb25seSBjb25uZWN0aW9uVG9rZW46IHN0cmluZyxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRJbml0KGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBJbml0IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBhY3RvcklkOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBjb25uZWN0aW9uSWQ6IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIGNvbm5lY3Rpb25Ub2tlbjogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUluaXQoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogSW5pdCk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHguYWN0b3JJZClcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4LmNvbm5lY3Rpb25JZClcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4LmNvbm5lY3Rpb25Ub2tlbilcbn1cblxuZnVuY3Rpb24gcmVhZDAoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEFycmF5QnVmZmVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIGJhcmUucmVhZEJvb2woYmMpXG4gICAgICAgID8gYmFyZS5yZWFkRGF0YShiYylcbiAgICAgICAgOiBudWxsXG59XG5cbmZ1bmN0aW9uIHdyaXRlMChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBBcnJheUJ1ZmZlciB8IG51bGwpOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlQm9vbChiYywgeCAhPT0gbnVsbClcbiAgICBpZiAoeCAhPT0gbnVsbCkge1xuICAgICAgICBiYXJlLndyaXRlRGF0YShiYywgeClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlYWQxKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiB1aW50IHwgbnVsbCB7XG4gICAgcmV0dXJuIGJhcmUucmVhZEJvb2woYmMpXG4gICAgICAgID8gYmFyZS5yZWFkVWludChiYylcbiAgICAgICAgOiBudWxsXG59XG5cbmZ1bmN0aW9uIHdyaXRlMShiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiB1aW50IHwgbnVsbCk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVCb29sKGJjLCB4ICE9PSBudWxsKVxuICAgIGlmICh4ICE9PSBudWxsKSB7XG4gICAgICAgIGJhcmUud3JpdGVVaW50KGJjLCB4KVxuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgRXJyb3IgPSB7XG4gICAgcmVhZG9ubHkgY29kZTogc3RyaW5nLFxuICAgIHJlYWRvbmx5IG1lc3NhZ2U6IHN0cmluZyxcbiAgICByZWFkb25seSBtZXRhZGF0YTogQXJyYXlCdWZmZXIgfCBudWxsLFxuICAgIHJlYWRvbmx5IGFjdGlvbklkOiB1aW50IHwgbnVsbCxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRFcnJvcihiYzogYmFyZS5CeXRlQ3Vyc29yKTogRXJyb3Ige1xuICAgIHJldHVybiB7XG4gICAgICAgIGNvZGU6IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIG1lc3NhZ2U6IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIG1ldGFkYXRhOiByZWFkMChiYyksXG4gICAgICAgIGFjdGlvbklkOiByZWFkMShiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVFcnJvcihiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBFcnJvcik6IHZvaWQge1xuICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHguY29kZSlcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4Lm1lc3NhZ2UpXG4gICAgd3JpdGUwKGJjLCB4Lm1ldGFkYXRhKVxuICAgIHdyaXRlMShiYywgeC5hY3Rpb25JZClcbn1cblxuZXhwb3J0IHR5cGUgQWN0aW9uUmVzcG9uc2UgPSB7XG4gICAgcmVhZG9ubHkgaWQ6IHVpbnQsXG4gICAgcmVhZG9ubHkgb3V0cHV0OiBBcnJheUJ1ZmZlcixcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRBY3Rpb25SZXNwb25zZShiYzogYmFyZS5CeXRlQ3Vyc29yKTogQWN0aW9uUmVzcG9uc2Uge1xuICAgIHJldHVybiB7XG4gICAgICAgIGlkOiBiYXJlLnJlYWRVaW50KGJjKSxcbiAgICAgICAgb3V0cHV0OiBiYXJlLnJlYWREYXRhKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUFjdGlvblJlc3BvbnNlKGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IEFjdGlvblJlc3BvbnNlKTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVVpbnQoYmMsIHguaWQpXG4gICAgYmFyZS53cml0ZURhdGEoYmMsIHgub3V0cHV0KVxufVxuXG5leHBvcnQgdHlwZSBFdmVudCA9IHtcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgYXJnczogQXJyYXlCdWZmZXIsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkRXZlbnQoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEV2ZW50IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBhcmdzOiBiYXJlLnJlYWREYXRhKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUV2ZW50KGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IEV2ZW50KTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5uYW1lKVxuICAgIGJhcmUud3JpdGVEYXRhKGJjLCB4LmFyZ3MpXG59XG5cbmV4cG9ydCB0eXBlIFRvQ2xpZW50Qm9keSA9XG4gICAgfCB7IHJlYWRvbmx5IHRhZzogXCJJbml0XCIsIHJlYWRvbmx5IHZhbDogSW5pdCB9XG4gICAgfCB7IHJlYWRvbmx5IHRhZzogXCJFcnJvclwiLCByZWFkb25seSB2YWw6IEVycm9yIH1cbiAgICB8IHsgcmVhZG9ubHkgdGFnOiBcIkFjdGlvblJlc3BvbnNlXCIsIHJlYWRvbmx5IHZhbDogQWN0aW9uUmVzcG9uc2UgfVxuICAgIHwgeyByZWFkb25seSB0YWc6IFwiRXZlbnRcIiwgcmVhZG9ubHkgdmFsOiBFdmVudCB9XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkVG9DbGllbnRCb2R5KGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBUb0NsaWVudEJvZHkge1xuICAgIGNvbnN0IG9mZnNldCA9IGJjLm9mZnNldFxuICAgIGNvbnN0IHRhZyA9IGJhcmUucmVhZFU4KGJjKVxuICAgIHN3aXRjaCAodGFnKSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHJldHVybiB7IHRhZzogXCJJbml0XCIsIHZhbDogcmVhZEluaXQoYmMpIH1cbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIHsgdGFnOiBcIkVycm9yXCIsIHZhbDogcmVhZEVycm9yKGJjKSB9XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHJldHVybiB7IHRhZzogXCJBY3Rpb25SZXNwb25zZVwiLCB2YWw6IHJlYWRBY3Rpb25SZXNwb25zZShiYykgfVxuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICByZXR1cm4geyB0YWc6IFwiRXZlbnRcIiwgdmFsOiByZWFkRXZlbnQoYmMpIH1cbiAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgYmMub2Zmc2V0ID0gb2Zmc2V0XG4gICAgICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3Iob2Zmc2V0LCBcImludmFsaWQgdGFnXCIpXG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVRvQ2xpZW50Qm9keShiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBUb0NsaWVudEJvZHkpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKHgudGFnKSB7XG4gICAgICAgIGNhc2UgXCJJbml0XCI6IHtcbiAgICAgICAgICAgIGJhcmUud3JpdGVVOChiYywgMClcbiAgICAgICAgICAgIHdyaXRlSW5pdChiYywgeC52YWwpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJFcnJvclwiOiB7XG4gICAgICAgICAgICBiYXJlLndyaXRlVTgoYmMsIDEpXG4gICAgICAgICAgICB3cml0ZUVycm9yKGJjLCB4LnZhbClcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBcIkFjdGlvblJlc3BvbnNlXCI6IHtcbiAgICAgICAgICAgIGJhcmUud3JpdGVVOChiYywgMilcbiAgICAgICAgICAgIHdyaXRlQWN0aW9uUmVzcG9uc2UoYmMsIHgudmFsKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIFwiRXZlbnRcIjoge1xuICAgICAgICAgICAgYmFyZS53cml0ZVU4KGJjLCAzKVxuICAgICAgICAgICAgd3JpdGVFdmVudChiYywgeC52YWwpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBUb0NsaWVudCA9IHtcbiAgICByZWFkb25seSBib2R5OiBUb0NsaWVudEJvZHksXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkVG9DbGllbnQoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IFRvQ2xpZW50IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBib2R5OiByZWFkVG9DbGllbnRCb2R5KGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVRvQ2xpZW50KGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IFRvQ2xpZW50KTogdm9pZCB7XG4gICAgd3JpdGVUb0NsaWVudEJvZHkoYmMsIHguYm9keSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVRvQ2xpZW50KHg6IFRvQ2xpZW50KTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZVRvQ2xpZW50KGJjLCB4KVxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShiYy52aWV3LmJ1ZmZlciwgYmMudmlldy5ieXRlT2Zmc2V0LCBiYy5vZmZzZXQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUb0NsaWVudChieXRlczogVWludDhBcnJheSk6IFRvQ2xpZW50IHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkVG9DbGllbnQoYmMpXG4gICAgaWYgKGJjLm9mZnNldCA8IGJjLnZpZXcuYnl0ZUxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3IoYmMub2Zmc2V0LCBcInJlbWFpbmluZyBieXRlc1wiKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG5cbmV4cG9ydCB0eXBlIEFjdGlvblJlcXVlc3QgPSB7XG4gICAgcmVhZG9ubHkgaWQ6IHVpbnQsXG4gICAgcmVhZG9ubHkgbmFtZTogc3RyaW5nLFxuICAgIHJlYWRvbmx5IGFyZ3M6IEFycmF5QnVmZmVyLFxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFjdGlvblJlcXVlc3QoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEFjdGlvblJlcXVlc3Qge1xuICAgIHJldHVybiB7XG4gICAgICAgIGlkOiBiYXJlLnJlYWRVaW50KGJjKSxcbiAgICAgICAgbmFtZTogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICAgICAgYXJnczogYmFyZS5yZWFkRGF0YShiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVBY3Rpb25SZXF1ZXN0KGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IEFjdGlvblJlcXVlc3QpOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlVWludChiYywgeC5pZClcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4Lm5hbWUpXG4gICAgYmFyZS53cml0ZURhdGEoYmMsIHguYXJncylcbn1cblxuZXhwb3J0IHR5cGUgU3Vic2NyaXB0aW9uUmVxdWVzdCA9IHtcbiAgICByZWFkb25seSBldmVudE5hbWU6IHN0cmluZyxcbiAgICByZWFkb25seSBzdWJzY3JpYmU6IGJvb2xlYW4sXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkU3Vic2NyaXB0aW9uUmVxdWVzdChiYzogYmFyZS5CeXRlQ3Vyc29yKTogU3Vic2NyaXB0aW9uUmVxdWVzdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZXZlbnROYW1lOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBzdWJzY3JpYmU6IGJhcmUucmVhZEJvb2woYmMpLFxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlU3Vic2NyaXB0aW9uUmVxdWVzdChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBTdWJzY3JpcHRpb25SZXF1ZXN0KTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5ldmVudE5hbWUpXG4gICAgYmFyZS53cml0ZUJvb2woYmMsIHguc3Vic2NyaWJlKVxufVxuXG5leHBvcnQgdHlwZSBUb1NlcnZlckJvZHkgPVxuICAgIHwgeyByZWFkb25seSB0YWc6IFwiQWN0aW9uUmVxdWVzdFwiLCByZWFkb25seSB2YWw6IEFjdGlvblJlcXVlc3QgfVxuICAgIHwgeyByZWFkb25seSB0YWc6IFwiU3Vic2NyaXB0aW9uUmVxdWVzdFwiLCByZWFkb25seSB2YWw6IFN1YnNjcmlwdGlvblJlcXVlc3QgfVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZFRvU2VydmVyQm9keShiYzogYmFyZS5CeXRlQ3Vyc29yKTogVG9TZXJ2ZXJCb2R5IHtcbiAgICBjb25zdCBvZmZzZXQgPSBiYy5vZmZzZXRcbiAgICBjb25zdCB0YWcgPSBiYXJlLnJlYWRVOChiYylcbiAgICBzd2l0Y2ggKHRhZykge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICByZXR1cm4geyB0YWc6IFwiQWN0aW9uUmVxdWVzdFwiLCB2YWw6IHJlYWRBY3Rpb25SZXF1ZXN0KGJjKSB9XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiB7IHRhZzogXCJTdWJzY3JpcHRpb25SZXF1ZXN0XCIsIHZhbDogcmVhZFN1YnNjcmlwdGlvblJlcXVlc3QoYmMpIH1cbiAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgYmMub2Zmc2V0ID0gb2Zmc2V0XG4gICAgICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3Iob2Zmc2V0LCBcImludmFsaWQgdGFnXCIpXG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVRvU2VydmVyQm9keShiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBUb1NlcnZlckJvZHkpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKHgudGFnKSB7XG4gICAgICAgIGNhc2UgXCJBY3Rpb25SZXF1ZXN0XCI6IHtcbiAgICAgICAgICAgIGJhcmUud3JpdGVVOChiYywgMClcbiAgICAgICAgICAgIHdyaXRlQWN0aW9uUmVxdWVzdChiYywgeC52YWwpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJTdWJzY3JpcHRpb25SZXF1ZXN0XCI6IHtcbiAgICAgICAgICAgIGJhcmUud3JpdGVVOChiYywgMSlcbiAgICAgICAgICAgIHdyaXRlU3Vic2NyaXB0aW9uUmVxdWVzdChiYywgeC52YWwpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBUb1NlcnZlciA9IHtcbiAgICByZWFkb25seSBib2R5OiBUb1NlcnZlckJvZHksXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkVG9TZXJ2ZXIoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IFRvU2VydmVyIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBib2R5OiByZWFkVG9TZXJ2ZXJCb2R5KGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVRvU2VydmVyKGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IFRvU2VydmVyKTogdm9pZCB7XG4gICAgd3JpdGVUb1NlcnZlckJvZHkoYmMsIHguYm9keSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVRvU2VydmVyKHg6IFRvU2VydmVyKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZVRvU2VydmVyKGJjLCB4KVxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShiYy52aWV3LmJ1ZmZlciwgYmMudmlldy5ieXRlT2Zmc2V0LCBiYy5vZmZzZXQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUb1NlcnZlcihieXRlczogVWludDhBcnJheSk6IFRvU2VydmVyIHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkVG9TZXJ2ZXIoYmMpXG4gICAgaWYgKGJjLm9mZnNldCA8IGJjLnZpZXcuYnl0ZUxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3IoYmMub2Zmc2V0LCBcInJlbWFpbmluZyBieXRlc1wiKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG5cbmV4cG9ydCB0eXBlIEh0dHBBY3Rpb25SZXF1ZXN0ID0ge1xuICAgIHJlYWRvbmx5IGFyZ3M6IEFycmF5QnVmZmVyLFxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZEh0dHBBY3Rpb25SZXF1ZXN0KGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBIdHRwQWN0aW9uUmVxdWVzdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYXJnczogYmFyZS5yZWFkRGF0YShiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVIdHRwQWN0aW9uUmVxdWVzdChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBIdHRwQWN0aW9uUmVxdWVzdCk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVEYXRhKGJjLCB4LmFyZ3MpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVIdHRwQWN0aW9uUmVxdWVzdCh4OiBIdHRwQWN0aW9uUmVxdWVzdCk6IFVpbnQ4QXJyYXkge1xuICAgIGNvbnN0IGJjID0gbmV3IGJhcmUuQnl0ZUN1cnNvcihcbiAgICAgICAgbmV3IFVpbnQ4QXJyYXkoY29uZmlnLmluaXRpYWxCdWZmZXJMZW5ndGgpLFxuICAgICAgICBjb25maWdcbiAgICApXG4gICAgd3JpdGVIdHRwQWN0aW9uUmVxdWVzdChiYywgeClcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYmMudmlldy5idWZmZXIsIGJjLnZpZXcuYnl0ZU9mZnNldCwgYmMub2Zmc2V0KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlSHR0cEFjdGlvblJlcXVlc3QoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBIdHRwQWN0aW9uUmVxdWVzdCB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKGJ5dGVzLCBjb25maWcpXG4gICAgY29uc3QgcmVzdWx0ID0gcmVhZEh0dHBBY3Rpb25SZXF1ZXN0KGJjKVxuICAgIGlmIChiYy5vZmZzZXQgPCBiYy52aWV3LmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IGJhcmUuQmFyZUVycm9yKGJjLm9mZnNldCwgXCJyZW1haW5pbmcgYnl0ZXNcIilcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG5leHBvcnQgdHlwZSBIdHRwQWN0aW9uUmVzcG9uc2UgPSB7XG4gICAgcmVhZG9ubHkgb3V0cHV0OiBBcnJheUJ1ZmZlcixcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRIdHRwQWN0aW9uUmVzcG9uc2UoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEh0dHBBY3Rpb25SZXNwb25zZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgb3V0cHV0OiBiYXJlLnJlYWREYXRhKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUh0dHBBY3Rpb25SZXNwb25zZShiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBIdHRwQWN0aW9uUmVzcG9uc2UpOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlRGF0YShiYywgeC5vdXRwdXQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVIdHRwQWN0aW9uUmVzcG9uc2UoeDogSHR0cEFjdGlvblJlc3BvbnNlKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZUh0dHBBY3Rpb25SZXNwb25zZShiYywgeClcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYmMudmlldy5idWZmZXIsIGJjLnZpZXcuYnl0ZU9mZnNldCwgYmMub2Zmc2V0KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlSHR0cEFjdGlvblJlc3BvbnNlKGJ5dGVzOiBVaW50OEFycmF5KTogSHR0cEFjdGlvblJlc3BvbnNlIHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkSHR0cEFjdGlvblJlc3BvbnNlKGJjKVxuICAgIGlmIChiYy5vZmZzZXQgPCBiYy52aWV3LmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IGJhcmUuQmFyZUVycm9yKGJjLm9mZnNldCwgXCJyZW1haW5pbmcgYnl0ZXNcIilcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG5leHBvcnQgdHlwZSBIdHRwUmVzcG9uc2VFcnJvciA9IHtcbiAgICByZWFkb25seSBjb2RlOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nLFxuICAgIHJlYWRvbmx5IG1ldGFkYXRhOiBBcnJheUJ1ZmZlciB8IG51bGwsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkSHR0cFJlc3BvbnNlRXJyb3IoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEh0dHBSZXNwb25zZUVycm9yIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb2RlOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBtZXNzYWdlOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBtZXRhZGF0YTogcmVhZDAoYmMpLFxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlSHR0cFJlc3BvbnNlRXJyb3IoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogSHR0cFJlc3BvbnNlRXJyb3IpOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4LmNvZGUpXG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5tZXNzYWdlKVxuICAgIHdyaXRlMChiYywgeC5tZXRhZGF0YSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZUh0dHBSZXNwb25zZUVycm9yKHg6IEh0dHBSZXNwb25zZUVycm9yKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZUh0dHBSZXNwb25zZUVycm9yKGJjLCB4KVxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShiYy52aWV3LmJ1ZmZlciwgYmMudmlldy5ieXRlT2Zmc2V0LCBiYy5vZmZzZXQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVIdHRwUmVzcG9uc2VFcnJvcihieXRlczogVWludDhBcnJheSk6IEh0dHBSZXNwb25zZUVycm9yIHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkSHR0cFJlc3BvbnNlRXJyb3IoYmMpXG4gICAgaWYgKGJjLm9mZnNldCA8IGJjLnZpZXcuYnl0ZUxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3IoYmMub2Zmc2V0LCBcInJlbWFpbmluZyBieXRlc1wiKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG5cbmV4cG9ydCB0eXBlIEh0dHBSZXNvbHZlUmVxdWVzdCA9IG51bGxcblxuZXhwb3J0IHR5cGUgSHR0cFJlc29sdmVSZXNwb25zZSA9IHtcbiAgICByZWFkb25seSBhY3RvcklkOiBzdHJpbmcsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkSHR0cFJlc29sdmVSZXNwb25zZShiYzogYmFyZS5CeXRlQ3Vyc29yKTogSHR0cFJlc29sdmVSZXNwb25zZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWN0b3JJZDogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUh0dHBSZXNvbHZlUmVzcG9uc2UoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogSHR0cFJlc29sdmVSZXNwb25zZSk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHguYWN0b3JJZClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZUh0dHBSZXNvbHZlUmVzcG9uc2UoeDogSHR0cFJlc29sdmVSZXNwb25zZSk6IFVpbnQ4QXJyYXkge1xuICAgIGNvbnN0IGJjID0gbmV3IGJhcmUuQnl0ZUN1cnNvcihcbiAgICAgICAgbmV3IFVpbnQ4QXJyYXkoY29uZmlnLmluaXRpYWxCdWZmZXJMZW5ndGgpLFxuICAgICAgICBjb25maWdcbiAgICApXG4gICAgd3JpdGVIdHRwUmVzb2x2ZVJlc3BvbnNlKGJjLCB4KVxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShiYy52aWV3LmJ1ZmZlciwgYmMudmlldy5ieXRlT2Zmc2V0LCBiYy5vZmZzZXQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVIdHRwUmVzb2x2ZVJlc3BvbnNlKGJ5dGVzOiBVaW50OEFycmF5KTogSHR0cFJlc29sdmVSZXNwb25zZSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKGJ5dGVzLCBjb25maWcpXG4gICAgY29uc3QgcmVzdWx0ID0gcmVhZEh0dHBSZXNvbHZlUmVzcG9uc2UoYmMpXG4gICAgaWYgKGJjLm9mZnNldCA8IGJjLnZpZXcuYnl0ZUxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgYmFyZS5CYXJlRXJyb3IoYmMub2Zmc2V0LCBcInJlbWFpbmluZyBieXRlc1wiKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWQudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2xcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdmVyc2lvbmVkLnRzXCI7aW1wb3J0IHtcblx0Y3JlYXRlVmVyc2lvbmVkRGF0YUhhbmRsZXIsXG5cdHR5cGUgTWlncmF0aW9uRm4sXG59IGZyb20gXCJAL2NvbW1vbi92ZXJzaW9uZWQtZGF0YVwiO1xuaW1wb3J0ICogYXMgdjEgZnJvbSBcIi4uLy4uLy4uL2Rpc3Qvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdjFcIjtcblxuZXhwb3J0IGNvbnN0IENVUlJFTlRfVkVSU0lPTiA9IDE7XG5cbmNvbnN0IG1pZ3JhdGlvbnMgPSBuZXcgTWFwPG51bWJlciwgTWlncmF0aW9uRm48YW55LCBhbnk+PigpO1xuXG5leHBvcnQgY29uc3QgVE9fU0VSVkVSX1ZFUlNJT05FRCA9IGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPHYxLlRvU2VydmVyPih7XG5cdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdG1pZ3JhdGlvbnMsXG5cdHNlcmlhbGl6ZVZlcnNpb246IChkYXRhKSA9PiB2MS5lbmNvZGVUb1NlcnZlcihkYXRhKSxcblx0ZGVzZXJpYWxpemVWZXJzaW9uOiAoYnl0ZXMpID0+IHYxLmRlY29kZVRvU2VydmVyKGJ5dGVzKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgVE9fQ0xJRU5UX1ZFUlNJT05FRCA9IGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPHYxLlRvQ2xpZW50Pih7XG5cdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdG1pZ3JhdGlvbnMsXG5cdHNlcmlhbGl6ZVZlcnNpb246IChkYXRhKSA9PiB2MS5lbmNvZGVUb0NsaWVudChkYXRhKSxcblx0ZGVzZXJpYWxpemVWZXJzaW9uOiAoYnl0ZXMpID0+IHYxLmRlY29kZVRvQ2xpZW50KGJ5dGVzKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgSFRUUF9BQ1RJT05fUkVRVUVTVF9WRVJTSU9ORUQgPVxuXHRjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcjx2MS5IdHRwQWN0aW9uUmVxdWVzdD4oe1xuXHRcdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdFx0bWlncmF0aW9ucyxcblx0XHRzZXJpYWxpemVWZXJzaW9uOiAoZGF0YSkgPT4gdjEuZW5jb2RlSHR0cEFjdGlvblJlcXVlc3QoZGF0YSksXG5cdFx0ZGVzZXJpYWxpemVWZXJzaW9uOiAoYnl0ZXMpID0+IHYxLmRlY29kZUh0dHBBY3Rpb25SZXF1ZXN0KGJ5dGVzKSxcblx0fSk7XG5cbmV4cG9ydCBjb25zdCBIVFRQX0FDVElPTl9SRVNQT05TRV9WRVJTSU9ORUQgPVxuXHRjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcjx2MS5IdHRwQWN0aW9uUmVzcG9uc2U+KHtcblx0XHRjdXJyZW50VmVyc2lvbjogQ1VSUkVOVF9WRVJTSU9OLFxuXHRcdG1pZ3JhdGlvbnMsXG5cdFx0c2VyaWFsaXplVmVyc2lvbjogKGRhdGEpID0+IHYxLmVuY29kZUh0dHBBY3Rpb25SZXNwb25zZShkYXRhKSxcblx0XHRkZXNlcmlhbGl6ZVZlcnNpb246IChieXRlcykgPT4gdjEuZGVjb2RlSHR0cEFjdGlvblJlc3BvbnNlKGJ5dGVzKSxcblx0fSk7XG5cbmV4cG9ydCBjb25zdCBIVFRQX1JFU1BPTlNFX0VSUk9SX1ZFUlNJT05FRCA9XG5cdGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPHYxLkh0dHBSZXNwb25zZUVycm9yPih7XG5cdFx0Y3VycmVudFZlcnNpb246IENVUlJFTlRfVkVSU0lPTixcblx0XHRtaWdyYXRpb25zLFxuXHRcdHNlcmlhbGl6ZVZlcnNpb246IChkYXRhKSA9PiB2MS5lbmNvZGVIdHRwUmVzcG9uc2VFcnJvcihkYXRhKSxcblx0XHRkZXNlcmlhbGl6ZVZlcnNpb246IChieXRlcykgPT4gdjEuZGVjb2RlSHR0cFJlc3BvbnNlRXJyb3IoYnl0ZXMpLFxuXHR9KTtcblxuZXhwb3J0IGNvbnN0IEhUVFBfUkVTT0xWRV9SRVFVRVNUX1ZFUlNJT05FRCA9XG5cdGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPHYxLkh0dHBSZXNvbHZlUmVxdWVzdD4oe1xuXHRcdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdFx0bWlncmF0aW9ucyxcblx0XHRzZXJpYWxpemVWZXJzaW9uOiAoXykgPT4gbmV3IFVpbnQ4QXJyYXkoKSxcblx0XHRkZXNlcmlhbGl6ZVZlcnNpb246IChieXRlcykgPT4gbnVsbCxcblx0fSk7XG5cbmV4cG9ydCBjb25zdCBIVFRQX1JFU09MVkVfUkVTUE9OU0VfVkVSU0lPTkVEID1cblx0Y3JlYXRlVmVyc2lvbmVkRGF0YUhhbmRsZXI8djEuSHR0cFJlc29sdmVSZXNwb25zZT4oe1xuXHRcdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdFx0bWlncmF0aW9ucyxcblx0XHRzZXJpYWxpemVWZXJzaW9uOiAoZGF0YSkgPT4gdjEuZW5jb2RlSHR0cFJlc29sdmVSZXNwb25zZShkYXRhKSxcblx0XHRkZXNlcmlhbGl6ZVZlcnNpb246IChieXRlcykgPT4gdjEuZGVjb2RlSHR0cFJlc29sdmVSZXNwb25zZShieXRlcyksXG5cdH0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvZXJyb3JzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2Vycm9ycy50c1wiO2ltcG9ydCB0eXBlIHsgRGVjb25zdHJ1Y3RlZEVycm9yIH0gZnJvbSBcIkAvY29tbW9uL3V0aWxzXCI7XG5cbmV4cG9ydCBjb25zdCBJTlRFUk5BTF9FUlJPUl9DT0RFID0gXCJpbnRlcm5hbF9lcnJvclwiO1xuZXhwb3J0IGNvbnN0IElOVEVSTkFMX0VSUk9SX0RFU0NSSVBUSU9OID1cblx0XCJJbnRlcm5hbCBlcnJvci4gUmVhZCB0aGUgc2VydmVyIGxvZ3MgZm9yIG1vcmUgZGV0YWlscy5cIjtcbmV4cG9ydCB0eXBlIEludGVybmFsRXJyb3JNZXRhZGF0YSA9IHt9O1xuXG5leHBvcnQgY29uc3QgVVNFUl9FUlJPUl9DT0RFID0gXCJ1c2VyX2Vycm9yXCI7XG5cbmludGVyZmFjZSBBY3RvckVycm9yT3B0aW9ucyBleHRlbmRzIEVycm9yT3B0aW9ucyB7XG5cdC8qKiBFcnJvciBkYXRhIGNhbiBzYWZlbHkgYmUgc2VyaWFsaXplZCBpbiBhIHJlc3BvbnNlIHRvIHRoZSBjbGllbnQuICovXG5cdHB1YmxpYz86IGJvb2xlYW47XG5cdC8qKiBNZXRhZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhpcyBlcnJvci4gVGhpcyB3aWxsIGJlIHNlbnQgdG8gY2xpZW50cy4gKi9cblx0bWV0YWRhdGE/OiB1bmtub3duO1xufVxuXG5leHBvcnQgY2xhc3MgQWN0b3JFcnJvciBleHRlbmRzIEVycm9yIHtcblx0X190eXBlID0gXCJBY3RvckVycm9yXCI7XG5cblx0cHVibGljIHB1YmxpYzogYm9vbGVhbjtcblx0cHVibGljIG1ldGFkYXRhPzogdW5rbm93bjtcblx0cHVibGljIHN0YXR1c0NvZGUgPSA1MDA7XG5cblx0cHVibGljIHN0YXRpYyBpc0FjdG9yRXJyb3IoXG5cdFx0ZXJyb3I6IHVua25vd24sXG5cdCk6IGVycm9yIGlzIEFjdG9yRXJyb3IgfCBEZWNvbnN0cnVjdGVkRXJyb3Ige1xuXHRcdHJldHVybiAoXG5cdFx0XHR0eXBlb2YgZXJyb3IgPT09IFwib2JqZWN0XCIgJiZcblx0XHRcdChlcnJvciBhcyBBY3RvckVycm9yIHwgRGVjb25zdHJ1Y3RlZEVycm9yKS5fX3R5cGUgPT09IFwiQWN0b3JFcnJvclwiXG5cdFx0KTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHB1YmxpYyByZWFkb25seSBjb2RlOiBzdHJpbmcsXG5cdFx0bWVzc2FnZTogc3RyaW5nLFxuXHRcdG9wdHM/OiBBY3RvckVycm9yT3B0aW9ucyxcblx0KSB7XG5cdFx0c3VwZXIobWVzc2FnZSwgeyBjYXVzZTogb3B0cz8uY2F1c2UgfSk7XG5cdFx0dGhpcy5wdWJsaWMgPSBvcHRzPy5wdWJsaWMgPz8gZmFsc2U7XG5cdFx0dGhpcy5tZXRhZGF0YSA9IG9wdHM/Lm1ldGFkYXRhO1xuXG5cdFx0Ly8gU2V0IHN0YXR1cyBjb2RlIGJhc2VkIG9uIGVycm9yIHR5cGVcblx0XHRpZiAob3B0cz8ucHVibGljKSB7XG5cdFx0XHR0aGlzLnN0YXR1c0NvZGUgPSA0MDA7IC8vIEJhZCByZXF1ZXN0IGZvciBwdWJsaWMgZXJyb3JzXG5cdFx0fVxuXHR9XG5cblx0dG9TdHJpbmcoKSB7XG5cdFx0Ly8gRm9yY2Ugc3RyaW5naWZ5IHRvIHJldHVybiB0aGUgbWVzc2FnZVxuXHRcdHJldHVybiB0aGlzLm1lc3NhZ2U7XG5cdH1cblxuXHQvKipcblx0ICogU2VyaWFsaXplIGVycm9yIGZvciBIVFRQIHJlc3BvbnNlXG5cdCAqL1xuXHRzZXJpYWxpemVGb3JIdHRwKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR0eXBlOiB0aGlzLmNvZGUsXG5cdFx0XHRtZXNzYWdlOiB0aGlzLm1lc3NhZ2UsXG5cdFx0XHRtZXRhZGF0YTogdGhpcy5tZXRhZGF0YSxcblx0XHR9O1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBJbnRlcm5hbEVycm9yIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKElOVEVSTkFMX0VSUk9SX0NPREUsIG1lc3NhZ2UpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBVbnJlYWNoYWJsZSBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuXHRjb25zdHJ1Y3Rvcih4OiBuZXZlcikge1xuXHRcdHN1cGVyKGBVbnJlYWNoYWJsZSBjYXNlOiAke3h9YCk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFN0YXRlTm90RW5hYmxlZCBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcblx0XHRcdFwic3RhdGVfbm90X2VuYWJsZWRcIixcblx0XHRcdFwiU3RhdGUgbm90IGVuYWJsZWQuIE11c3QgaW1wbGVtZW50IGBjcmVhdGVTdGF0ZWAgb3IgYHN0YXRlYCB0byB1c2Ugc3RhdGUuIChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9zdGF0ZS8jaW5pdGlhbGl6aW5nLXN0YXRlKVwiLFxuXHRcdCk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIENvbm5TdGF0ZU5vdEVuYWJsZWQgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcImNvbm5fc3RhdGVfbm90X2VuYWJsZWRcIixcblx0XHRcdFwiQ29ubmVjdGlvbiBzdGF0ZSBub3QgZW5hYmxlZC4gTXVzdCBpbXBsZW1lbnQgYGNyZWF0ZUNvbm5lY3Rpb25TdGF0ZWAgb3IgYGNvbm5lY3Rpb25TdGF0ZWAgdG8gdXNlIGNvbm5lY3Rpb24gc3RhdGUuIChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9jb25uZWN0aW9ucy8jY29ubmVjdGlvbi1zdGF0ZSlcIixcblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBWYXJzTm90RW5hYmxlZCBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcblx0XHRcdFwidmFyc19ub3RfZW5hYmxlZFwiLFxuXHRcdFx0XCJWYXJpYWJsZXMgbm90IGVuYWJsZWQuIE11c3QgaW1wbGVtZW50IGBjcmVhdGVWYXJzYCBvciBgdmFyc2AgdG8gdXNlIHN0YXRlLiAoaHR0cHM6Ly93d3cucml2ZXQuZ2cvZG9jcy9hY3RvcnMvZXBoZW1lcmFsLXZhcmlhYmxlcy8jaW5pdGlhbGl6aW5nLXZhcmlhYmxlcylcIixcblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBBY3Rpb25UaW1lZE91dCBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcblx0XHRcdFwiYWN0aW9uX3RpbWVkX291dFwiLFxuXHRcdFx0XCJBY3Rpb24gdGltZWQgb3V0LiBUaGlzIGNhbiBiZSBpbmNyZWFzZWQgd2l0aDogYGFjdG9yKHsgb3B0aW9uczogeyBhY3Rpb246IHsgdGltZW91dDogLi4uIH0gfSB9KWBcIixcblx0XHRcdHsgcHVibGljOiB0cnVlIH0sXG5cdFx0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQWN0aW9uTm90Rm91bmQgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IobmFtZTogc3RyaW5nKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcImFjdGlvbl9ub3RfZm91bmRcIixcblx0XHRcdGBBY3Rpb24gJyR7bmFtZX0nIG5vdCBmb3VuZC4gVmFsaWRhdGUgdGhlIGFjdGlvbiBleGlzdHMgb24geW91ciBhY3Rvci5gLFxuXHRcdFx0eyBwdWJsaWM6IHRydWUgfSxcblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBJbnZhbGlkRW5jb2RpbmcgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoZm9ybWF0Pzogc3RyaW5nKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcImludmFsaWRfZW5jb2RpbmdcIixcblx0XHRcdGBJbnZhbGlkIGVuY29kaW5nIFxcYCR7Zm9ybWF0fVxcYC4gKGh0dHBzOi8vd3d3LnJpdmV0LmdnL2RvY3MvYWN0b3JzL2NsaWVudHMvI2FjdG9yLWNsaWVudClgLFxuXHRcdFx0e1xuXHRcdFx0XHRwdWJsaWM6IHRydWUsXG5cdFx0XHR9LFxuXHRcdCk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIENvbm5Ob3RGb3VuZCBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihpZD86IHN0cmluZykge1xuXHRcdHN1cGVyKFwiY29ubl9ub3RfZm91bmRcIiwgYENvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBJRDogJHtpZH1gLCB7XG5cdFx0XHRwdWJsaWM6IHRydWUsXG5cdFx0fSk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIEluY29ycmVjdENvbm5Ub2tlbiBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcImluY29ycmVjdF9jb25uX3Rva2VuXCIsIFwiSW5jb3JyZWN0IGNvbm5lY3Rpb24gdG9rZW4uXCIsIHtcblx0XHRcdHB1YmxpYzogdHJ1ZSxcblx0XHR9KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgTWVzc2FnZVRvb0xvbmcgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcIm1lc3NhZ2VfdG9vX2xvbmdcIixcblx0XHRcdFwiTWVzc2FnZSB0b28gbG9uZy4gVGhpcyBjYW4gYmUgY29uZmlndXJlZCB3aXRoOiBgcmVnaXN0cnkucnVuU2VydmVyKHsgbWF4SW5jb21pbmdNZXNzYWdlU2l6ZTogLi4uIH0pYFwiLFxuXHRcdFx0eyBwdWJsaWM6IHRydWUgfSxcblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBNYWxmb3JtZWRNZXNzYWdlIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKGNhdXNlPzogdW5rbm93bikge1xuXHRcdHN1cGVyKFwibWFsZm9ybWVkX21lc3NhZ2VcIiwgYE1hbGZvcm1lZCBtZXNzYWdlOiAke2NhdXNlfWAsIHtcblx0XHRcdHB1YmxpYzogdHJ1ZSxcblx0XHRcdGNhdXNlLFxuXHRcdH0pO1xuXHR9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW52YWxpZFN0YXRlVHlwZU9wdGlvbnMge1xuXHRwYXRoPzogdW5rbm93bjtcbn1cblxuZXhwb3J0IGNsYXNzIEludmFsaWRTdGF0ZVR5cGUgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3Iob3B0cz86IEludmFsaWRTdGF0ZVR5cGVPcHRpb25zKSB7XG5cdFx0bGV0IG1zZyA9IFwiXCI7XG5cdFx0aWYgKG9wdHM/LnBhdGgpIHtcblx0XHRcdG1zZyArPSBgQXR0ZW1wdGVkIHRvIHNldCBpbnZhbGlkIHN0YXRlIGF0IHBhdGggXFxgJHtvcHRzLnBhdGh9XFxgLmA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1zZyArPSBcIkF0dGVtcHRlZCB0byBzZXQgaW52YWxpZCBzdGF0ZS5cIjtcblx0XHR9XG5cdFx0bXNnICs9XG5cdFx0XHRcIiBWYWxpZCB0eXBlcyBpbmNsdWRlOiBudWxsLCB1bmRlZmluZWQsIGJvb2xlYW4sIHN0cmluZywgbnVtYmVyLCBCaWdJbnQsIERhdGUsIFJlZ0V4cCwgRXJyb3IsIHR5cGVkIGFycmF5cyAoVWludDhBcnJheSwgSW50OEFycmF5LCBGbG9hdDMyQXJyYXksIGV0Yy4pLCBNYXAsIFNldCwgQXJyYXksIGFuZCBwbGFpbiBvYmplY3RzLiAoaHR0cHM6Ly93d3cucml2ZXQuZ2cvZG9jcy9hY3RvcnMvc3RhdGUvI2xpbWl0YXRpb25zKVwiO1xuXHRcdHN1cGVyKFwiaW52YWxpZF9zdGF0ZV90eXBlXCIsIG1zZyk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFVuc3VwcG9ydGVkIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKGZlYXR1cmU6IHN0cmluZykge1xuXHRcdHN1cGVyKFwidW5zdXBwb3J0ZWRcIiwgYFVuc3VwcG9ydGVkIGZlYXR1cmU6ICR7ZmVhdHVyZX1gKTtcblx0fVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBVc2VyRXJyb3IgY2xhc3MuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVXNlckVycm9yT3B0aW9ucyBleHRlbmRzIEVycm9yT3B0aW9ucyB7XG5cdC8qKlxuXHQgKiBNYWNoaW5lIHJlYWRhYmxlIGNvZGUgZm9yIHRoaXMgZXJyb3IuIFVzZWZ1bCBmb3IgY2F0Y2hpbmcgZGlmZmVyZW50IHR5cGVzIG9mIGVycm9ycyBpbiB0cnktY2F0Y2guXG5cdCAqL1xuXHRjb2RlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBBZGRpdGlvbmFsIG1ldGFkYXRhIHJlbGF0ZWQgdG8gdGhlIGVycm9yLiBVc2VmdWwgZm9yIHVuZGVyc3RhbmRpbmcgY29udGV4dCBhYm91dCB0aGUgZXJyb3IuXG5cdCAqL1xuXHRtZXRhZGF0YT86IHVua25vd247XG59XG5cbi8qKiBFcnJvciB0aGF0IGNhbiBiZSBzYWZlbHkgcmV0dXJuZWQgdG8gdGhlIHVzZXIuICovXG5leHBvcnQgY2xhc3MgVXNlckVycm9yIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdC8qKlxuXHQgKiBDb25zdHJ1Y3RzIGEgbmV3IFVzZXJFcnJvciBpbnN0YW5jZS5cblx0ICpcblx0ICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQuXG5cdCAqIEBwYXJhbSBvcHRzIC0gT3B0aW9uYWwgcGFyYW1ldGVycyBmb3IgdGhlIGVycm9yLCBpbmNsdWRpbmcgYSBtYWNoaW5lLXJlYWRhYmxlIGNvZGUgYW5kIGFkZGl0aW9uYWwgbWV0YWRhdGEuXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcsIG9wdHM/OiBVc2VyRXJyb3JPcHRpb25zKSB7XG5cdFx0c3VwZXIob3B0cz8uY29kZSA/PyBVU0VSX0VSUk9SX0NPREUsIG1lc3NhZ2UsIHtcblx0XHRcdHB1YmxpYzogdHJ1ZSxcblx0XHRcdG1ldGFkYXRhOiBvcHRzPy5tZXRhZGF0YSxcblx0XHR9KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSW52YWxpZFF1ZXJ5SlNPTiBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihlcnJvcj86IHVua25vd24pIHtcblx0XHRzdXBlcihcImludmFsaWRfcXVlcnlfanNvblwiLCBgSW52YWxpZCBxdWVyeSBKU09OOiAke2Vycm9yfWAsIHtcblx0XHRcdHB1YmxpYzogdHJ1ZSxcblx0XHRcdGNhdXNlOiBlcnJvcixcblx0XHR9KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSW52YWxpZFJlcXVlc3QgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoZXJyb3I/OiB1bmtub3duKSB7XG5cdFx0c3VwZXIoXCJpbnZhbGlkX3JlcXVlc3RcIiwgYEludmFsaWQgcmVxdWVzdDogJHtlcnJvcn1gLCB7XG5cdFx0XHRwdWJsaWM6IHRydWUsXG5cdFx0XHRjYXVzZTogZXJyb3IsXG5cdFx0fSk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIEFjdG9yTm90Rm91bmQgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoaWRlbnRpZmllcj86IHN0cmluZykge1xuXHRcdHN1cGVyKFxuXHRcdFx0XCJhY3Rvcl9ub3RfZm91bmRcIixcblx0XHRcdGlkZW50aWZpZXJcblx0XHRcdFx0PyBgQWN0b3Igbm90IGZvdW5kOiAke2lkZW50aWZpZXJ9IChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9jbGllbnRzLyNhY3Rvci1jbGllbnQpYFxuXHRcdFx0XHQ6IFwiQWN0b3Igbm90IGZvdW5kIChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9jbGllbnRzLyNhY3Rvci1jbGllbnQpXCIsXG5cdFx0XHR7IHB1YmxpYzogdHJ1ZSB9LFxuXHRcdCk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIEFjdG9yQWxyZWFkeUV4aXN0cyBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcsIGtleTogc3RyaW5nW10pIHtcblx0XHRzdXBlcihcblx0XHRcdFwiYWN0b3JfYWxyZWFkeV9leGlzdHNcIixcblx0XHRcdGBBY3RvciBhbHJlYWR5IGV4aXN0cyB3aXRoIG5hbWUgJyR7bmFtZX0nIGFuZCBrZXkgJyR7SlNPTi5zdHJpbmdpZnkoa2V5KX0nIChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9jbGllbnRzLyNhY3Rvci1jbGllbnQpYCxcblx0XHRcdHsgcHVibGljOiB0cnVlIH0sXG5cdFx0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgUHJveHlFcnJvciBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihvcGVyYXRpb246IHN0cmluZywgZXJyb3I/OiB1bmtub3duKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcInByb3h5X2Vycm9yXCIsXG5cdFx0XHRgRXJyb3IgcHJveHlpbmcgJHtvcGVyYXRpb259LCB0aGlzIGlzIGxpa2VseSBhbiBpbnRlcm5hbCBlcnJvcjogJHtlcnJvcn1gLFxuXHRcdFx0e1xuXHRcdFx0XHRwdWJsaWM6IHRydWUsXG5cdFx0XHRcdGNhdXNlOiBlcnJvcixcblx0XHRcdH0sXG5cdFx0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSW52YWxpZEFjdGlvblJlcXVlc3QgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG5cdFx0c3VwZXIoXCJpbnZhbGlkX2FjdGlvbl9yZXF1ZXN0XCIsIG1lc3NhZ2UsIHsgcHVibGljOiB0cnVlIH0pO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBJbnZhbGlkUGFyYW1zIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKFwiaW52YWxpZF9wYXJhbXNcIiwgbWVzc2FnZSwgeyBwdWJsaWM6IHRydWUgfSk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFVuYXV0aG9yaXplZCBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlPzogc3RyaW5nKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcInVuYXV0aG9yaXplZFwiLFxuXHRcdFx0bWVzc2FnZSA/P1xuXHRcdFx0XHRcIlVuYXV0aG9yaXplZC4gQWNjZXNzIGRlbmllZC4gKGh0dHBzOi8vd3d3LnJpdmV0LmdnL2RvY3MvYWN0b3JzL2F1dGhlbnRpY2F0aW9uLylcIixcblx0XHRcdHtcblx0XHRcdFx0cHVibGljOiB0cnVlLFxuXHRcdFx0fSxcblx0XHQpO1xuXHRcdHRoaXMuc3RhdHVzQ29kZSA9IDQwMTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgRm9yYmlkZGVuIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKG1lc3NhZ2U/OiBzdHJpbmcsIG9wdHM/OiB7IG1ldGFkYXRhPzogdW5rbm93biB9KSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcImZvcmJpZGRlblwiLFxuXHRcdFx0bWVzc2FnZSA/P1xuXHRcdFx0XHRcIkZvcmJpZGRlbi4gQWNjZXNzIGRlbmllZC4gKGh0dHBzOi8vd3d3LnJpdmV0LmdnL2RvY3MvYWN0b3JzL2F1dGhlbnRpY2F0aW9uLylcIixcblx0XHRcdHtcblx0XHRcdFx0cHVibGljOiB0cnVlLFxuXHRcdFx0XHRtZXRhZGF0YTogb3B0cz8ubWV0YWRhdGEsXG5cdFx0XHR9LFxuXHRcdCk7XG5cdFx0dGhpcy5zdGF0dXNDb2RlID0gNDAzO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBEYXRhYmFzZU5vdEVuYWJsZWQgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcImRhdGFiYXNlX25vdF9lbmFibGVkXCIsXG5cdFx0XHRcIkRhdGFiYXNlIG5vdCBlbmFibGVkLiBNdXN0IGltcGxlbWVudCBgZGF0YWJhc2VgIHRvIHVzZSBkYXRhYmFzZS5cIixcblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBGZXRjaEhhbmRsZXJOb3REZWZpbmVkIGV4dGVuZHMgQWN0b3JFcnJvciB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKFxuXHRcdFx0XCJmZXRjaF9oYW5kbGVyX25vdF9kZWZpbmVkXCIsXG5cdFx0XHRcIlJhdyBIVFRQIGhhbmRsZXIgbm90IGRlZmluZWQuIEFjdG9yIG11c3QgaW1wbGVtZW50IGBvbkZldGNoYCB0byBoYW5kbGUgcmF3IEhUVFAgcmVxdWVzdHMuIChodHRwczovL3d3dy5yaXZldC5nZy9kb2NzL2FjdG9ycy9mZXRjaC1hbmQtd2Vic29ja2V0LWhhbmRsZXIvKVwiLFxuXHRcdFx0eyBwdWJsaWM6IHRydWUgfSxcblx0XHQpO1xuXHRcdHRoaXMuc3RhdHVzQ29kZSA9IDQwNDtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0SGFuZGxlck5vdERlZmluZWQgZXh0ZW5kcyBBY3RvckVycm9yIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoXG5cdFx0XHRcIndlYnNvY2tldF9oYW5kbGVyX25vdF9kZWZpbmVkXCIsXG5cdFx0XHRcIlJhdyBXZWJTb2NrZXQgaGFuZGxlciBub3QgZGVmaW5lZC4gQWN0b3IgbXVzdCBpbXBsZW1lbnQgYG9uV2ViU29ja2V0YCB0byBoYW5kbGUgcmF3IFdlYlNvY2tldCBjb25uZWN0aW9ucy4gKGh0dHBzOi8vd3d3LnJpdmV0LmdnL2RvY3MvYWN0b3JzL2ZldGNoLWFuZC13ZWJzb2NrZXQtaGFuZGxlci8pXCIsXG5cdFx0XHR7IHB1YmxpYzogdHJ1ZSB9LFxuXHRcdCk7XG5cdFx0dGhpcy5zdGF0dXNDb2RlID0gNDA0O1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBJbnZhbGlkRmV0Y2hSZXNwb25zZSBleHRlbmRzIEFjdG9yRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcblx0XHRcdFwiaW52YWxpZF9mZXRjaF9yZXNwb25zZVwiLFxuXHRcdFx0XCJBY3RvcidzIG9uRmV0Y2ggaGFuZGxlciBtdXN0IHJldHVybiBhIFJlc3BvbnNlIG9iamVjdC4gUmV0dXJuaW5nIHZvaWQvdW5kZWZpbmVkIGlzIG5vdCBhbGxvd2VkLiAoaHR0cHM6Ly93d3cucml2ZXQuZ2cvZG9jcy9hY3RvcnMvZmV0Y2gtYW5kLXdlYnNvY2tldC1oYW5kbGVyLylcIixcblx0XHRcdHsgcHVibGljOiB0cnVlIH0sXG5cdFx0KTtcblx0XHR0aGlzLnN0YXR1c0NvZGUgPSA1MDA7XG5cdH1cbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi91dGlscy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb25cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL3V0aWxzLnRzXCI7aW1wb3J0IHR5cGUgeyBOZXh0IH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB0eXBlIHsgQ29udGVudGZ1bFN0YXR1c0NvZGUgfSBmcm9tIFwiaG9uby91dGlscy9odHRwLXN0YXR1c1wiO1xuaW1wb3J0ICogYXMgZXJyb3JzIGZyb20gXCJAL2FjdG9yL2Vycm9yc1wiO1xuaW1wb3J0IHsgZ2V0RW52VW5pdmVyc2FsIH0gZnJvbSBcIkAvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRVbnJlYWNoYWJsZSh4OiBuZXZlcik6IG5ldmVyIHtcblx0dGhyb3cgbmV3IEVycm9yKGBVbnJlYWNoYWJsZSBjYXNlOiAke3h9YCk7XG59XG5cbi8qKlxuICogU2FmZWx5IHN0cmluZ2lmaWVzIGFuIG9iamVjdCwgZW5zdXJpbmcgdGhhdCB0aGUgc3RyaW5naWZpZWQgb2JqZWN0IGlzIHVuZGVyIGEgY2VydGFpbiBzaXplLlxuICogQHBhcmFtIG9iaiBhbnkgb2JqZWN0IHRvIHN0cmluZ2lmeVxuICogQHBhcmFtIG1heFNpemUgbWF4aW11bSBzaXplIG9mIHRoZSBzdHJpbmdpZmllZCBvYmplY3QgaW4gYnl0ZXNcbiAqIEByZXR1cm5zIHN0cmluZ2lmaWVkIG9iamVjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2FmZVN0cmluZ2lmeShvYmo6IHVua25vd24sIG1heFNpemU6IG51bWJlcikge1xuXHRsZXQgc2l6ZSA9IDA7XG5cblx0ZnVuY3Rpb24gcmVwbGFjZXIoa2V5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKSB7XG5cdFx0aWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybiB2YWx1ZTtcblx0XHRjb25zdCB2YWx1ZVNpemUgPVxuXHRcdFx0dHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiID8gdmFsdWUubGVuZ3RoIDogSlNPTi5zdHJpbmdpZnkodmFsdWUpLmxlbmd0aDtcblx0XHRzaXplICs9IGtleS5sZW5ndGggKyB2YWx1ZVNpemU7XG5cblx0XHRpZiAoc2l6ZSA+IG1heFNpemUpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgSlNPTiBvYmplY3QgZXhjZWVkcyBzaXplIGxpbWl0IG9mICR7bWF4U2l6ZX0gYnl0ZXMuYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbHVlO1xuXHR9XG5cblx0cmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgcmVwbGFjZXIpO1xufVxuXG4vLyBUT0RPOiBJbnN0ZWFkIG9mIGRvaW5nIHRoaXMsIHVzZSBhIHRlbXAgdmFyIGZvciBzdGF0ZSBhbmQgYXR0ZW1wdCB0byB3cml0ZVxuLy8gaXQuIFJvbGwgYmFjayBzdGF0ZSBpZiBmYWlscyB0byBzZXJpYWxpemUuXG5cbi8qKlxuICogQ2hlY2sgaWYgYSB2YWx1ZSBpcyBDQk9SIHNlcmlhbGl6YWJsZS5cbiAqIE9wdGlvbmFsbHkgcGFzcyBhbiBvbkludmFsaWQgY2FsbGJhY2sgdG8gcmVjZWl2ZSB0aGUgcGF0aCB0byBpbnZhbGlkIHZhbHVlcy5cbiAqXG4gKiBGb3IgYSBjb21wbGV0ZSBsaXN0IG9mIHN1cHBvcnRlZCBDQk9SIHRhZ3MsIHNlZTpcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9rcmlzenlwL2Nib3IteC9ibG9iL2NjMWNmOWRmOGJhNzIyODhjNzg0MmFmMWRkMzc0ZDczZTM0Y2RiYzEvUkVBRE1FLm1kI2xpc3Qtb2Ytc3VwcG9ydGVkLXRhZ3MtZm9yLWRlY29kaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Nib3JTZXJpYWxpemFibGUoXG5cdHZhbHVlOiB1bmtub3duLFxuXHRvbkludmFsaWQ/OiAocGF0aDogc3RyaW5nKSA9PiB2b2lkLFxuXHRjdXJyZW50UGF0aCA9IFwiXCIsXG4pOiBib29sZWFuIHtcblx0Ly8gSGFuZGxlIHByaW1pdGl2ZSB0eXBlcyBkaXJlY3RseVxuXHRpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0aWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuXHRcdGlmICghTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkge1xuXHRcdFx0b25JbnZhbGlkPy4oY3VycmVudFBhdGgpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGlmICh0eXBlb2YgdmFsdWUgPT09IFwiYm9vbGVhblwiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0Ly8gSGFuZGxlIEJpZ0ludCAoQ0JPUiB0YWdzIDIgYW5kIDMpXG5cdGlmICh0eXBlb2YgdmFsdWUgPT09IFwiYmlnaW50XCIpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8vIEhhbmRsZSBEYXRlIG9iamVjdHMgKENCT1IgdGFncyAwIGFuZCAxKVxuXHRpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBIYW5kbGUgdHlwZWQgYXJyYXlzIChDQk9SIHRhZ3MgNjQtODIpXG5cdGlmIChcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5IHx8XG5cdFx0dmFsdWUgaW5zdGFuY2VvZiBVaW50MTZBcnJheSB8fFxuXHRcdHZhbHVlIGluc3RhbmNlb2YgVWludDMyQXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5IHx8XG5cdFx0dmFsdWUgaW5zdGFuY2VvZiBJbnQ4QXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIEludDE2QXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIEludDMyQXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIEJpZ0ludDY0QXJyYXkgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSB8fFxuXHRcdHZhbHVlIGluc3RhbmNlb2YgRmxvYXQ2NEFycmF5XG5cdCkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0Ly8gSGFuZGxlIE1hcCAoQ0JPUiB0YWcgMjU5KVxuXHRpZiAodmFsdWUgaW5zdGFuY2VvZiBNYXApIHtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdmFsdWUuZW50cmllcygpKSB7XG5cdFx0XHRjb25zdCBrZXlQYXRoID0gY3VycmVudFBhdGhcblx0XHRcdFx0PyBgJHtjdXJyZW50UGF0aH0ua2V5KCR7U3RyaW5nKGtleSl9KWBcblx0XHRcdFx0OiBga2V5KCR7U3RyaW5nKGtleSl9KWA7XG5cdFx0XHRjb25zdCB2YWxQYXRoID0gY3VycmVudFBhdGhcblx0XHRcdFx0PyBgJHtjdXJyZW50UGF0aH0udmFsdWUoJHtTdHJpbmcoa2V5KX0pYFxuXHRcdFx0XHQ6IGB2YWx1ZSgke1N0cmluZyhrZXkpfSlgO1xuXHRcdFx0aWYgKFxuXHRcdFx0XHQhaXNDYm9yU2VyaWFsaXphYmxlKGtleSwgb25JbnZhbGlkLCBrZXlQYXRoKSB8fFxuXHRcdFx0XHQhaXNDYm9yU2VyaWFsaXphYmxlKHZhbCwgb25JbnZhbGlkLCB2YWxQYXRoKVxuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBIYW5kbGUgU2V0IChDQk9SIHRhZyAyNTgpXG5cdGlmICh2YWx1ZSBpbnN0YW5jZW9mIFNldCkge1xuXHRcdGxldCBpbmRleCA9IDA7XG5cdFx0Zm9yIChjb25zdCBpdGVtIG9mIHZhbHVlLnZhbHVlcygpKSB7XG5cdFx0XHRjb25zdCBpdGVtUGF0aCA9IGN1cnJlbnRQYXRoXG5cdFx0XHRcdD8gYCR7Y3VycmVudFBhdGh9LnNldFske2luZGV4fV1gXG5cdFx0XHRcdDogYHNldFske2luZGV4fV1gO1xuXHRcdFx0aWYgKCFpc0Nib3JTZXJpYWxpemFibGUoaXRlbSwgb25JbnZhbGlkLCBpdGVtUGF0aCkpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0aW5kZXgrKztcblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBIYW5kbGUgUmVnRXhwIChDQk9SIHRhZyAyNylcblx0aWYgKHZhbHVlIGluc3RhbmNlb2YgUmVnRXhwKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBIYW5kbGUgRXJyb3Igb2JqZWN0cyAoQ0JPUiB0YWcgMjcpXG5cdGlmICh2YWx1ZSBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBIYW5kbGUgYXJyYXlzXG5cdGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGl0ZW1QYXRoID0gY3VycmVudFBhdGggPyBgJHtjdXJyZW50UGF0aH1bJHtpfV1gIDogYFske2l9XWA7XG5cdFx0XHRpZiAoIWlzQ2JvclNlcmlhbGl6YWJsZSh2YWx1ZVtpXSwgb25JbnZhbGlkLCBpdGVtUGF0aCkpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8vIEhhbmRsZSBwbGFpbiBvYmplY3RzIGFuZCByZWNvcmRzIChDQk9SIHRhZ3MgMTA1LCA1MSwgNTczNDQtNTc1OTkpXG5cdGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBBbGxvdyBwbGFpbiBvYmplY3RzIGFuZCBvYmplY3RzIHdpdGggcHJvdG90eXBlcyAoZm9yIHJlY29yZHMgYW5kIG5hbWVkIG9iamVjdHMpXG5cdFx0Y29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuXHRcdGlmIChwcm90byAhPT0gbnVsbCAmJiBwcm90byAhPT0gT2JqZWN0LnByb3RvdHlwZSkge1xuXHRcdFx0Ly8gQ2hlY2sgaWYgaXQncyBhIGtub3duIHNlcmlhbGl6YWJsZSBvYmplY3QgdHlwZVxuXHRcdFx0Y29uc3QgcHJvdG9Db25zdHJ1Y3RvciA9IHZhbHVlLmNvbnN0cnVjdG9yO1xuXHRcdFx0aWYgKHByb3RvQ29uc3RydWN0b3IgJiYgdHlwZW9mIHByb3RvQ29uc3RydWN0b3IubmFtZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHQvLyBBbGxvdyBvYmplY3RzIHdpdGggbmFtZWQgY29uc3RydWN0b3JzIChyZWNvcmRzLCBuYW1lZCBvYmplY3RzKVxuXHRcdFx0XHQvLyBUaGlzIGluY2x1ZGVzIHVzZXItZGVmaW5lZCBjbGFzc2VzIGFuZCBidWlsdC1pbiBvYmplY3RzXG5cdFx0XHRcdC8vIHRoYXQgQ0JPUiBjYW4gc2VyaWFsaXplIHdpdGggdGFnIDI3IG9yIHJlY29yZCB0YWdzXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2hlY2sgYWxsIHByb3BlcnRpZXMgcmVjdXJzaXZlbHlcblx0XHRmb3IgKGNvbnN0IGtleSBpbiB2YWx1ZSkge1xuXHRcdFx0Y29uc3QgcHJvcFBhdGggPSBjdXJyZW50UGF0aCA/IGAke2N1cnJlbnRQYXRofS4ke2tleX1gIDoga2V5O1xuXHRcdFx0aWYgKFxuXHRcdFx0XHQhaXNDYm9yU2VyaWFsaXphYmxlKFxuXHRcdFx0XHRcdHZhbHVlW2tleSBhcyBrZXlvZiB0eXBlb2YgdmFsdWVdLFxuXHRcdFx0XHRcdG9uSW52YWxpZCxcblx0XHRcdFx0XHRwcm9wUGF0aCxcblx0XHRcdFx0KVxuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyBOb3Qgc2VyaWFsaXphYmxlXG5cdG9uSW52YWxpZD8uKGN1cnJlbnRQYXRoKTtcblx0cmV0dXJuIGZhbHNlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERlY29uc3RydWN0ZWRFcnJvciB7XG5cdF9fdHlwZTogXCJBY3RvckVycm9yXCI7XG5cdHN0YXR1c0NvZGU6IENvbnRlbnRmdWxTdGF0dXNDb2RlO1xuXHRwdWJsaWM6IGJvb2xlYW47XG5cdGNvZGU6IHN0cmluZztcblx0bWVzc2FnZTogc3RyaW5nO1xuXHRtZXRhZGF0YT86IHVua25vd247XG59XG5cbi8qKiBEZWNvbnN0cnVjdHMgZXJyb3IgaW4gdG8gY29tcG9uZW50cyB0aGF0IGFyZSB1c2VkIHRvIGJ1aWxkIHJlc3BvbnNlcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvbnN0cnVjdEVycm9yKFxuXHRlcnJvcjogdW5rbm93bixcblx0bG9nZ2VyOiBMb2dnZXIsXG5cdGV4dHJhTG9nOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcblx0ZXhwb3NlSW50ZXJuYWxFcnJvciA9IGZhbHNlLFxuKTogRGVjb25zdHJ1Y3RlZEVycm9yIHtcblx0Ly8gQnVpbGQgcmVzcG9uc2UgZXJyb3IgaW5mb3JtYXRpb24uIE9ubHkgcmV0dXJuIGVycm9ycyBpZiBmbGFnZ2VkIGFzIHB1YmxpYyBpbiBvcmRlciB0byBwcmV2ZW50IGxlYWtpbmcgaW50ZXJuYWwgYmVoYXZpb3IuXG5cdC8vXG5cdC8vIFdlIGxvZyB0aGUgZXJyb3IgaGVyZSBpbnN0ZWFkIG9mIGFmdGVyIGdlbmVyYXRpbmcgdGhlIGNvZGUgJiBtZXNzYWdlIGJlY2F1c2Ugd2UgbmVlZCB0byBsb2cgdGhlIG9yaWdpbmFsIGVycm9yLCBub3QgdGhlIG1hc2tlZCBpbnRlcm5hbCBlcnJvci5cblx0bGV0IHN0YXR1c0NvZGU6IENvbnRlbnRmdWxTdGF0dXNDb2RlO1xuXHRsZXQgcHVibGljXzogYm9vbGVhbjtcblx0bGV0IGNvZGU6IHN0cmluZztcblx0bGV0IG1lc3NhZ2U6IHN0cmluZztcblx0bGV0IG1ldGFkYXRhOiB1bmtub3duO1xuXHRpZiAoZXJyb3JzLkFjdG9yRXJyb3IuaXNBY3RvckVycm9yKGVycm9yKSAmJiBlcnJvci5wdWJsaWMpIHtcblx0XHQvLyBDaGVjayBpZiBlcnJvciBoYXMgc3RhdHVzQ29kZSAoY291bGQgYmUgQWN0b3JFcnJvciBpbnN0YW5jZSBvciBEZWNvbnN0cnVjdGVkRXJyb3IpXG5cdFx0c3RhdHVzQ29kZSA9IChcblx0XHRcdFwic3RhdHVzQ29kZVwiIGluIGVycm9yICYmIGVycm9yLnN0YXR1c0NvZGUgPyBlcnJvci5zdGF0dXNDb2RlIDogNDAwXG5cdFx0KSBhcyBDb250ZW50ZnVsU3RhdHVzQ29kZTtcblx0XHRwdWJsaWNfID0gdHJ1ZTtcblx0XHRjb2RlID0gZXJyb3IuY29kZTtcblx0XHRtZXNzYWdlID0gZ2V0RXJyb3JNZXNzYWdlKGVycm9yKTtcblx0XHRtZXRhZGF0YSA9IGVycm9yLm1ldGFkYXRhO1xuXG5cdFx0bG9nZ2VyLmluZm8oXCJwdWJsaWMgZXJyb3JcIiwge1xuXHRcdFx0Y29kZSxcblx0XHRcdG1lc3NhZ2UsXG5cdFx0XHRpc3N1ZXM6IFwiaHR0cHM6Ly9naXRodWIuY29tL3JpdmV0LWdnL3JpdmV0a2l0L2lzc3Vlc1wiLFxuXHRcdFx0c3VwcG9ydDogXCJodHRwczovL3JpdmV0LmdnL2Rpc2NvcmRcIixcblx0XHRcdC4uLmV4dHJhTG9nLFxuXHRcdH0pO1xuXHR9IGVsc2UgaWYgKGV4cG9zZUludGVybmFsRXJyb3IpIHtcblx0XHRpZiAoZXJyb3JzLkFjdG9yRXJyb3IuaXNBY3RvckVycm9yKGVycm9yKSkge1xuXHRcdFx0c3RhdHVzQ29kZSA9IDUwMDtcblx0XHRcdHB1YmxpY18gPSBmYWxzZTtcblx0XHRcdGNvZGUgPSBlcnJvci5jb2RlO1xuXHRcdFx0bWVzc2FnZSA9IGdldEVycm9yTWVzc2FnZShlcnJvcik7XG5cdFx0XHRtZXRhZGF0YSA9IGVycm9yLm1ldGFkYXRhO1xuXG5cdFx0XHRsb2dnZXIuaW5mbyhcImludGVybmFsIGVycm9yXCIsIHtcblx0XHRcdFx0Y29kZSxcblx0XHRcdFx0bWVzc2FnZSxcblx0XHRcdFx0aXNzdWVzOiBcImh0dHBzOi8vZ2l0aHViLmNvbS9yaXZldC1nZy9yaXZldGtpdC9pc3N1ZXNcIixcblx0XHRcdFx0c3VwcG9ydDogXCJodHRwczovL3JpdmV0LmdnL2Rpc2NvcmRcIixcblx0XHRcdFx0Li4uZXh0cmFMb2csXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c3RhdHVzQ29kZSA9IDUwMDtcblx0XHRcdHB1YmxpY18gPSBmYWxzZTtcblx0XHRcdGNvZGUgPSBlcnJvcnMuSU5URVJOQUxfRVJST1JfQ09ERTtcblx0XHRcdG1lc3NhZ2UgPSBnZXRFcnJvck1lc3NhZ2UoZXJyb3IpO1xuXG5cdFx0XHRsb2dnZXIuaW5mbyhcImludGVybmFsIGVycm9yXCIsIHtcblx0XHRcdFx0Y29kZSxcblx0XHRcdFx0bWVzc2FnZSxcblx0XHRcdFx0aXNzdWVzOiBcImh0dHBzOi8vZ2l0aHViLmNvbS9yaXZldC1nZy9yaXZldGtpdC9pc3N1ZXNcIixcblx0XHRcdFx0c3VwcG9ydDogXCJodHRwczovL3JpdmV0LmdnL2Rpc2NvcmRcIixcblx0XHRcdFx0Li4uZXh0cmFMb2csXG5cdFx0XHR9KTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0c3RhdHVzQ29kZSA9IDUwMDtcblx0XHRwdWJsaWNfID0gZmFsc2U7XG5cdFx0Y29kZSA9IGVycm9ycy5JTlRFUk5BTF9FUlJPUl9DT0RFO1xuXHRcdG1lc3NhZ2UgPSBlcnJvcnMuSU5URVJOQUxfRVJST1JfREVTQ1JJUFRJT047XG5cdFx0bWV0YWRhdGEgPSB7XG5cdFx0XHQvL3VybDogYGh0dHBzOi8vaHViLnJpdmV0LmdnL3Byb2plY3RzLyR7YWN0b3JNZXRhZGF0YS5wcm9qZWN0LnNsdWd9L2Vudmlyb25tZW50cy8ke2FjdG9yTWV0YWRhdGEuZW52aXJvbm1lbnQuc2x1Z30vYWN0b3JzP2FjdG9ySWQ9JHthY3Rvck1ldGFkYXRhLmFjdG9yLmlkfWAsXG5cdFx0fSBzYXRpc2ZpZXMgZXJyb3JzLkludGVybmFsRXJyb3JNZXRhZGF0YTtcblxuXHRcdGxvZ2dlci53YXJuKFwiaW50ZXJuYWwgZXJyb3JcIiwge1xuXHRcdFx0ZXJyb3I6IGdldEVycm9yTWVzc2FnZShlcnJvciksXG5cdFx0XHRzdGFjazogKGVycm9yIGFzIEVycm9yKT8uc3RhY2ssXG5cdFx0XHRpc3N1ZXM6IFwiaHR0cHM6Ly9naXRodWIuY29tL3JpdmV0LWdnL3JpdmV0a2l0L2lzc3Vlc1wiLFxuXHRcdFx0c3VwcG9ydDogXCJodHRwczovL3JpdmV0LmdnL2Rpc2NvcmRcIixcblx0XHRcdC4uLmV4dHJhTG9nLFxuXHRcdH0pO1xuXHR9XG5cblx0cmV0dXJuIHtcblx0XHRfX3R5cGU6IFwiQWN0b3JFcnJvclwiLFxuXHRcdHN0YXR1c0NvZGUsXG5cdFx0cHVibGljOiBwdWJsaWNfLFxuXHRcdGNvZGUsXG5cdFx0bWVzc2FnZSxcblx0XHRtZXRhZGF0YSxcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmluZ2lmeUVycm9yKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcblx0aWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRpZiAoXG5cdFx0XHR0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuXHRcdFx0Z2V0RW52VW5pdmVyc2FsKFwiX1JJVkVUS0lUX0VSUk9SX1NUQUNLXCIpID09PSBcIjFcIlxuXHRcdCkge1xuXHRcdFx0cmV0dXJuIGAke2Vycm9yLm5hbWV9OiAke2Vycm9yLm1lc3NhZ2V9JHtlcnJvci5zdGFjayA/IGBcXG4ke2Vycm9yLnN0YWNrfWAgOiBcIlwifWA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBgJHtlcnJvci5uYW1lfTogJHtlcnJvci5tZXNzYWdlfWA7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKHR5cGVvZiBlcnJvciA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHJldHVybiBlcnJvcjtcblx0fSBlbHNlIGlmICh0eXBlb2YgZXJyb3IgPT09IFwib2JqZWN0XCIgJiYgZXJyb3IgIT09IG51bGwpIHtcblx0XHR0cnkge1xuXHRcdFx0cmV0dXJuIGAke0pTT04uc3RyaW5naWZ5KGVycm9yKX1gO1xuXHRcdH0gY2F0Y2gge1xuXHRcdFx0cmV0dXJuIFwiW2Nhbm5vdCBzdHJpbmdpZnkgZXJyb3JdXCI7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBgVW5rbm93biBlcnJvcjogJHtnZXRFcnJvck1lc3NhZ2UoZXJyb3IpfWA7XG5cdH1cbn1cblxuZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGVycjogdW5rbm93bik6IHN0cmluZyB7XG5cdGlmIChcblx0XHRlcnIgJiZcblx0XHR0eXBlb2YgZXJyID09PSBcIm9iamVjdFwiICYmXG5cdFx0XCJtZXNzYWdlXCIgaW4gZXJyICYmXG5cdFx0dHlwZW9mIGVyci5tZXNzYWdlID09PSBcInN0cmluZ1wiXG5cdCkge1xuXHRcdHJldHVybiBlcnIubWVzc2FnZTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gU3RyaW5nKGVycik7XG5cdH1cbn1cblxuLyoqIEdlbmVyYXRlcyBhIGBOZXh0YCBoYW5kbGVyIHRvIHBhc3MgdG8gbWlkZGxld2FyZSBpbiBvcmRlciB0byBiZSBhYmxlIHRvIGNhbGwgYXJiaXRyYXJ5IG1pZGRsZXdhcmUuICovXG5leHBvcnQgZnVuY3Rpb24gbm9vcE5leHQoKTogTmV4dCB7XG5cdHJldHVybiBhc3luYyAoKSA9PiB7fTtcbn1cbiIsICJ7XG4gIFwibmFtZVwiOiBcInJpdmV0a2l0XCIsXG4gIFwidmVyc2lvblwiOiBcIjIuMC4yXCIsXG4gIFwibGljZW5zZVwiOiBcIkFwYWNoZS0yLjBcIixcbiAgXCJrZXl3b3Jkc1wiOiBbXG4gICAgXCJyaXZldGtpdFwiLFxuICAgIFwic3RhdGVmdWxcIixcbiAgICBcInNlcnZlcmxlc3NcIixcbiAgICBcImFjdG9yc1wiLFxuICAgIFwiYWdlbnRzXCIsXG4gICAgXCJyZWFsdGltZVwiLFxuICAgIFwid2Vic29ja2V0XCIsXG4gICAgXCJhY3RvcnNcIixcbiAgICBcImZyYW1ld29ya1wiXG4gIF0sXG4gIFwiZmlsZXNcIjogW1xuICAgIFwiZGlzdFwiLFxuICAgIFwic3JjXCIsXG4gICAgXCJkZW5vLmpzb25cIixcbiAgICBcImJ1bi5qc29uXCIsXG4gICAgXCJwYWNrYWdlLmpzb25cIlxuICBdLFxuICBcInR5cGVcIjogXCJtb2R1bGVcIixcbiAgXCJleHBvcnRzXCI6IHtcbiAgICBcIi5cIjoge1xuICAgICAgXCJpbXBvcnRcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvbW9kLmQudHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvbW9kLmpzXCJcbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvbW9kLmQuY3RzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL21vZC5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL2NsaWVudFwiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9jbGllbnQvbW9kLmQudHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY2xpZW50L21vZC5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL2NsaWVudC9tb2QuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY2xpZW50L21vZC5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL2xvZ1wiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9jb21tb24vbG9nLmQudHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY29tbW9uL2xvZy5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL2NvbW1vbi9sb2cuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY29tbW9uL2xvZy5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL2Vycm9yc1wiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9hY3Rvci9lcnJvcnMuZC50c1wiLFxuICAgICAgICBcImRlZmF1bHRcIjogXCIuL2Rpc3QvdHN1cC9hY3Rvci9lcnJvcnMuanNcIlxuICAgICAgfSxcbiAgICAgIFwicmVxdWlyZVwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9hY3Rvci9lcnJvcnMuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvYWN0b3IvZXJyb3JzLmNqc1wiXG4gICAgICB9XG4gICAgfSxcbiAgICBcIi4vdXRpbHNcIjoge1xuICAgICAgXCJpbXBvcnRcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvdXRpbHMuZC50c1wiLFxuICAgICAgICBcImRlZmF1bHRcIjogXCIuL2Rpc3QvdHN1cC91dGlscy5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL3V0aWxzLmQuY3RzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL3V0aWxzLmNqc1wiXG4gICAgICB9XG4gICAgfSxcbiAgICBcIi4vZHJpdmVyLWhlbHBlcnNcIjoge1xuICAgICAgXCJpbXBvcnRcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvZHJpdmVyLWhlbHBlcnMvbW9kLmQudHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvZHJpdmVyLWhlbHBlcnMvbW9kLmpzXCJcbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvZHJpdmVyLWhlbHBlcnMvbW9kLmQuY3RzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL2RyaXZlci1oZWxwZXJzL21vZC5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL2RyaXZlci1oZWxwZXJzL3dlYnNvY2tldFwiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9jb21tb24vd2Vic29ja2V0LmQudHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY29tbW9uL3dlYnNvY2tldC5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL2NvbW1vbi93ZWJzb2NrZXQuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvY29tbW9uL3dlYnNvY2tldC5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL2RyaXZlci10ZXN0LXN1aXRlXCI6IHtcbiAgICAgIFwiaW1wb3J0XCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL2RyaXZlci10ZXN0LXN1aXRlL21vZC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL2RyaXZlci10ZXN0LXN1aXRlL21vZC5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC90c3VwL2RyaXZlci10ZXN0LXN1aXRlL21vZC5kLmN0c1wiLFxuICAgICAgICBcImRlZmF1bHRcIjogXCIuL2Rpc3QvdHN1cC9kcml2ZXItdGVzdC1zdWl0ZS9tb2QuY2pzXCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwiLi90b3BvbG9naWVzL2Nvb3JkaW5hdGVcIjoge1xuICAgICAgXCJpbXBvcnRcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvdG9wb2xvZ2llcy9jb29yZGluYXRlL21vZC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL3RvcG9sb2dpZXMvY29vcmRpbmF0ZS9tb2QuanNcIlxuICAgICAgfSxcbiAgICAgIFwicmVxdWlyZVwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC90b3BvbG9naWVzL2Nvb3JkaW5hdGUvbW9kLmQuY3RzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL3RvcG9sb2dpZXMvY29vcmRpbmF0ZS9tb2QuY2pzXCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwiLi90b3BvbG9naWVzL3BhcnRpdGlvblwiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC90b3BvbG9naWVzL3BhcnRpdGlvbi9tb2QuZC50c1wiLFxuICAgICAgICBcImRlZmF1bHRcIjogXCIuL2Rpc3QvdHN1cC90b3BvbG9naWVzL3BhcnRpdGlvbi9tb2QuanNcIlxuICAgICAgfSxcbiAgICAgIFwicmVxdWlyZVwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC90b3BvbG9naWVzL3BhcnRpdGlvbi9tb2QuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvdG9wb2xvZ2llcy9wYXJ0aXRpb24vbW9kLmNqc1wiXG4gICAgICB9XG4gICAgfSxcbiAgICBcIi4vdGVzdFwiOiB7XG4gICAgICBcImltcG9ydFwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC90ZXN0L21vZC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL3Rlc3QvbW9kLmpzXCJcbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvdGVzdC9tb2QuZC5jdHNcIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IFwiLi9kaXN0L3RzdXAvdGVzdC9tb2QuY2pzXCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwiLi9pbnNwZWN0b3JcIjoge1xuICAgICAgXCJpbXBvcnRcIjoge1xuICAgICAgICBcInR5cGVzXCI6IFwiLi9kaXN0L3RzdXAvaW5zcGVjdG9yL21vZC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL2luc3BlY3Rvci9tb2QuanNcIlxuICAgICAgfSxcbiAgICAgIFwicmVxdWlyZVwiOiB7XG4gICAgICAgIFwidHlwZXNcIjogXCIuL2Rpc3QvdHN1cC9pbnNwZWN0b3IvbW9kLmQuY3RzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC90c3VwL2luc3BlY3Rvci9tb2QuY2pzXCJcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIFwiZW5naW5lc1wiOiB7XG4gICAgXCJub2RlXCI6IFwiPj0yMi4wLjBcIlxuICB9LFxuICBcInNpZGVFZmZlY3RzXCI6IGZhbHNlLFxuICBcInNjcmlwdHNcIjoge1xuICAgIFwiZGV2XCI6IFwicG5wbSBidWlsZCAtLXdhdGNoXCIsXG4gICAgXCJidWlsZFwiOiBcInRzdXAgc3JjL21vZC50cyBzcmMvY2xpZW50L21vZC50cyBzcmMvY29tbW9uL2xvZy50cyBzcmMvY29tbW9uL3dlYnNvY2tldC50cyBzcmMvYWN0b3IvZXJyb3JzLnRzIHNyYy90b3BvbG9naWVzL2Nvb3JkaW5hdGUvbW9kLnRzIHNyYy90b3BvbG9naWVzL3BhcnRpdGlvbi9tb2QudHMgc3JjL3V0aWxzLnRzIHNyYy9kcml2ZXItaGVscGVycy9tb2QudHMgc3JjL2RyaXZlci10ZXN0LXN1aXRlL21vZC50cyBzcmMvdGVzdC9tb2QudHMgc3JjL2luc3BlY3Rvci9tb2QudHNcIixcbiAgICBcImJ1aWxkOnNjaGVtYVwiOiBcIi4vc2NyaXB0cy9jb21waWxlLWJhcmUudHMgY29tcGlsZSBzY2hlbWFzL2NsaWVudC1wcm90b2NvbC92MS5iYXJlIC1vIGRpc3Qvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdjEudHMgJiYgLi9zY3JpcHRzL2NvbXBpbGUtYmFyZS50cyBjb21waWxlIHNjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyL3YxLmJhcmUgLW8gZGlzdC9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci92MS50cyAmJiAuL3NjcmlwdHMvY29tcGlsZS1iYXJlLnRzIGNvbXBpbGUgc2NoZW1hcy9hY3Rvci1wZXJzaXN0L3YxLmJhcmUgLW8gZGlzdC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvdjEudHNcIixcbiAgICBcImNoZWNrLXR5cGVzXCI6IFwidHNjIC0tbm9FbWl0XCIsXG4gICAgXCJ0ZXN0XCI6IFwidml0ZXN0IHJ1blwiLFxuICAgIFwidGVzdDp3YXRjaFwiOiBcInZpdGVzdFwiLFxuICAgIFwiZHVtcC1vcGVuYXBpXCI6IFwidHN4IHNjcmlwdHMvZHVtcC1vcGVuYXBpLnRzXCJcbiAgfSxcbiAgXCJkZXBlbmRlbmNpZXNcIjoge1xuICAgIFwiQGJhcmUtdHMvbGliXCI6IFwifjAuMy4wXCIsXG4gICAgXCJAaG9uby9zdGFuZGFyZC12YWxpZGF0b3JcIjogXCJeMC4xLjNcIixcbiAgICBcIkBob25vL3pvZC1vcGVuYXBpXCI6IFwiXjAuMTkuMTBcIixcbiAgICBcIkByaXZldGtpdC9lbmdpbmUtcnVubmVyXCI6IFwiaHR0cHM6Ly9wa2cucHIubmV3L3JpdmV0LWdnL2VuZ2luZS9Acml2ZXRraXQvZW5naW5lLXJ1bm5lckA2NjRhMzc3XCIsXG4gICAgXCJAcml2ZXRraXQvZmFzdC1qc29uLXBhdGNoXCI6IFwiXjMuMS4yXCIsXG4gICAgXCJjYm9yLXhcIjogXCJeMS42LjBcIixcbiAgICBcImhvbm9cIjogXCJeNC43LjBcIixcbiAgICBcImludmFyaWFudFwiOiBcIl4yLjIuNFwiLFxuICAgIFwibmFub2V2ZW50c1wiOiBcIl45LjEuMFwiLFxuICAgIFwib24tY2hhbmdlXCI6IFwiXjUuMC4xXCIsXG4gICAgXCJwLXJldHJ5XCI6IFwiXjYuMi4xXCIsXG4gICAgXCJ6b2RcIjogXCJeMy4yNS43NlwiXG4gIH0sXG4gIFwiZGV2RGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcIkBiYXJlLXRzL3Rvb2xzXCI6IFwiXjAuMTMuMFwiLFxuICAgIFwiQGhvbm8vbm9kZS1zZXJ2ZXJcIjogXCJeMS4xOC4yXCIsXG4gICAgXCJAaG9uby9ub2RlLXdzXCI6IFwiXjEuMS4xXCIsXG4gICAgXCJAcml2ZXQtZ2cvYWN0b3ItY29yZVwiOiBcIl4yNS4xLjBcIixcbiAgICBcIkB0eXBlcy9pbnZhcmlhbnRcIjogXCJeMlwiLFxuICAgIFwiQHR5cGVzL25vZGVcIjogXCJeMjIuMTMuMVwiLFxuICAgIFwiQHR5cGVzL3dzXCI6IFwiXjhcIixcbiAgICBcIkB2aXRlc3QvdWlcIjogXCIzLjEuMVwiLFxuICAgIFwiYnVuZGxlLXJlcXVpcmVcIjogXCJeNS4xLjBcIixcbiAgICBcImV2ZW50c291cmNlXCI6IFwiXjMuMC41XCIsXG4gICAgXCJ0c3VwXCI6IFwiXjguNC4wXCIsXG4gICAgXCJ0c3hcIjogXCJeNC4xOS40XCIsXG4gICAgXCJ0eXBlc2NyaXB0XCI6IFwiXjUuNy4zXCIsXG4gICAgXCJ2aXRlc3RcIjogXCJeMy4xLjFcIixcbiAgICBcIndzXCI6IFwiXjguMTguMVwiXG4gIH0sXG4gIFwicGVlckRlcGVuZGVuY2llc1wiOiB7XG4gICAgXCJAaG9uby9ub2RlLXNlcnZlclwiOiBcIl4xLjE0LjBcIixcbiAgICBcIkBob25vL25vZGUtd3NcIjogXCJeMS4xLjFcIixcbiAgICBcImV2ZW50c291cmNlXCI6IFwiXjMuMC41XCIsXG4gICAgXCJ3c1wiOiBcIl44LjAuMFwiXG4gIH0sXG4gIFwicGVlckRlcGVuZGVuY2llc01ldGFcIjoge1xuICAgIFwiQGhvbm8vbm9kZS1zZXJ2ZXJcIjoge1xuICAgICAgXCJvcHRpb25hbFwiOiB0cnVlXG4gICAgfSxcbiAgICBcIkBob25vL25vZGUtd3NcIjoge1xuICAgICAgXCJvcHRpb25hbFwiOiB0cnVlXG4gICAgfSxcbiAgICBcImV2ZW50c291cmNlXCI6IHtcbiAgICAgIFwib3B0aW9uYWxcIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJ3c1wiOiB7XG4gICAgICBcIm9wdGlvbmFsXCI6IHRydWVcbiAgICB9XG4gIH0sXG4gIFwic3RhYmxlVmVyc2lvblwiOiBcIjAuOC4wXCJcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3V0aWxzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3V0aWxzLnRzXCI7ZXhwb3J0IHsgc3RyaW5naWZ5RXJyb3IgfSBmcm9tIFwiQC9jb21tb24vdXRpbHNcIjtcbmV4cG9ydCB7IGFzc2VydFVucmVhY2hhYmxlIH0gZnJvbSBcIi4vY29tbW9uL3V0aWxzXCI7XG5cbmltcG9ydCB0eXBlIHsgQ29udGV4dCBhcyBIb25vQ29udGV4dCwgSGFuZGxlciBhcyBIb25vSGFuZGxlciB9IGZyb20gXCJob25vXCI7XG5cbmltcG9ydCBwa2dKc29uIGZyb20gXCIuLi9wYWNrYWdlLmpzb25cIiB3aXRoIHsgdHlwZTogXCJqc29uXCIgfTtcblxuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBwa2dKc29uLnZlcnNpb247XG5cbmxldCBfdXNlckFnZW50OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBmdW5jdGlvbiBodHRwVXNlckFnZW50KCk6IHN0cmluZyB7XG5cdC8vIFJldHVybiBjYWNoZWQgdmFsdWUgaWYgYWxyZWFkeSBpbml0aWFsaXplZFxuXHRpZiAoX3VzZXJBZ2VudCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIF91c2VyQWdlbnQ7XG5cdH1cblxuXHQvLyBMaWJyYXJ5XG5cdGxldCB1c2VyQWdlbnQgPSBgUml2ZXRLaXQvJHtWRVJTSU9OfWA7XG5cblx0Ly8gTmF2aWdhdG9yXG5cdGNvbnN0IG5hdmlnYXRvck9iaiA9IHR5cGVvZiBuYXZpZ2F0b3IgIT09IFwidW5kZWZpbmVkXCIgPyBuYXZpZ2F0b3IgOiB1bmRlZmluZWQ7XG5cdGlmIChuYXZpZ2F0b3JPYmo/LnVzZXJBZ2VudCkgdXNlckFnZW50ICs9IGAgJHtuYXZpZ2F0b3JPYmoudXNlckFnZW50fWA7XG5cblx0X3VzZXJBZ2VudCA9IHVzZXJBZ2VudDtcblxuXHRyZXR1cm4gdXNlckFnZW50O1xufVxuXG5leHBvcnQgdHlwZSBVcGdyYWRlV2ViU29ja2V0ID0gKFxuXHRjcmVhdGVFdmVudHM6IChjOiBIb25vQ29udGV4dCkgPT4gYW55LFxuKSA9PiBIb25vSGFuZGxlcjtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVudlVuaXZlcnNhbChrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdGlmICh0eXBlb2YgRGVubyAhPT0gXCJ1bmRlZmluZWRcIikge1xuXHRcdHJldHVybiBEZW5vLmVudi5nZXQoa2V5KTtcblx0fSBlbHNlIGlmICh0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIikge1xuXHRcdC8vIERvIHRoaXMgYWZ0ZXIgRGVubyBzaW5jZSBgcHJvY2Vzc2AgaXMgc29tZXRpbWVzIHBvbHlmaWxsZWRcblx0XHRyZXR1cm4gcHJvY2Vzcy5lbnZba2V5XTtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGJnPFQ+KHg6IFQpOiBUIHtcblx0Y29uc29sZS50cmFjZShgPT09IERFQlVHID09PVxcbiR7eH1gKTtcblx0cmV0dXJuIHg7XG59XG5cbi8qKlxuICogQ29udmVydHMgdmFyaW91cyBBcnJheUJ1ZmZlci1saWtlIHR5cGVzIHRvIFVpbnQ4QXJyYXkuXG4gKiBIYW5kbGVzIEFycmF5QnVmZmVyLCBBcnJheUJ1ZmZlclZpZXcgKGluY2x1ZGluZyB0eXBlZCBhcnJheXMpLCBhbmQgcGFzc2VzIHRocm91Z2ggZXhpc3RpbmcgVWludDhBcnJheS5cbiAqXG4gKiBAcGFyYW0gZGF0YSAtIFRoZSBBcnJheUJ1ZmZlciBvciBBcnJheUJ1ZmZlclZpZXcgdG8gY29udmVydFxuICogQHJldHVybnMgQSBVaW50OEFycmF5IHZpZXcgb2YgdGhlIGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvVWludDhBcnJheShkYXRhOiBBcnJheUJ1ZmZlciB8IEFycmF5QnVmZmVyVmlldyk6IFVpbnQ4QXJyYXkge1xuXHRpZiAoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcblx0XHRyZXR1cm4gZGF0YTtcblx0fSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcblx0XHRyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG5cdH0gZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGRhdGEpKSB7XG5cdFx0Ly8gSGFuZGxlIG90aGVyIEFycmF5QnVmZmVyVmlldyB0eXBlcyAoSW50OEFycmF5LCBVaW50MTZBcnJheSwgRGF0YVZpZXcsIGV0Yy4pXG5cdFx0cmV0dXJuIG5ldyBVaW50OEFycmF5KFxuXHRcdFx0ZGF0YS5idWZmZXIuc2xpY2UoZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVPZmZzZXQgKyBkYXRhLmJ5dGVMZW5ndGgpLFxuXHRcdCk7XG5cdH0gZWxzZSB7XG5cdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihcIklucHV0IG11c3QgYmUgQXJyYXlCdWZmZXIgb3IgQXJyYXlCdWZmZXJWaWV3XCIpO1xuXHR9XG59XG5cbi8vIExvbmcgdGltZW91dHNcbi8vXG4vLyBKYXZhU2NyaXB0IHRpbWVycyB1c2UgYSBzaWduZWQgMzItYml0IGludGVnZXIgZm9yIGRlbGF5cywgc28gdmFsdWVzIGFib3ZlIDJeMzEtMSAofjI0LjggZGF5cylcbi8vIGFyZSBub3QgcmVsaWFibGUgYW5kIG1heSBmaXJlIGltbWVkaWF0ZWx5IG9yIG92ZXJmbG93LlxuLy9cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3cvc2V0VGltZW91dCNtYXhpbXVtX2RlbGF5X3ZhbHVlXG5jb25zdCBUSU1FT1VUX01BWCA9IDIxNDc0ODM2NDc7IC8vIDJeMzEtMVxuXG5leHBvcnQgdHlwZSBMb25nVGltZW91dEhhbmRsZSA9IHsgYWJvcnQ6ICgpID0+IHZvaWQgfTtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldExvbmdUaW1lb3V0KFxuXHRsaXN0ZW5lcjogKCkgPT4gdm9pZCxcblx0YWZ0ZXI6IG51bWJlcixcbik6IExvbmdUaW1lb3V0SGFuZGxlIHtcblx0bGV0IHRpbWVvdXQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuXG5cdGZ1bmN0aW9uIHN0YXJ0KHJlbWFpbmluZzogbnVtYmVyKSB7XG5cdFx0aWYgKHJlbWFpbmluZyA8PSBUSU1FT1VUX01BWCkge1xuXHRcdFx0dGltZW91dCA9IHNldFRpbWVvdXQobGlzdGVuZXIsIHJlbWFpbmluZyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0c3RhcnQocmVtYWluaW5nIC0gVElNRU9VVF9NQVgpO1xuXHRcdFx0fSwgVElNRU9VVF9NQVgpO1xuXHRcdH1cblx0fVxuXG5cdHN0YXJ0KGFmdGVyKTtcblxuXHRyZXR1cm4ge1xuXHRcdGFib3J0OiAoKSA9PiB7XG5cdFx0XHRpZiAodGltZW91dCAhPT0gdW5kZWZpbmVkKSBjbGVhclRpbWVvdXQodGltZW91dCk7XG5cdFx0fSxcblx0fTtcbn1cblxuLyoqXG4gKiBBIHRpbnkgdXRpbGl0eSB0aGF0IGNvYWxlc2Nlcy9lbnF1ZXVlcyBhc3luYyBvcGVyYXRpb25zIHNvIG9ubHkgdGhlIGxhdGVzdFxuICogcXVldWVkIHRhc2sgcnVucyBwZXIgY3ljbGUsIHdoaWxlIGNhbGxlcnMgcmVjZWl2ZSBhIHByb21pc2UgdGhhdCByZXNvbHZlc1xuICogd2hlbiB0aGUgdGFzayBmb3IgdGhlIGN5Y2xlIHRoZXkgam9pbmVkIGhhcyBjb21wbGV0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBTaW5nbGVQcm9taXNlUXVldWUge1xuXHQvKiogTmV4dCBvcGVyYXRpb24gdG8gZXhlY3V0ZSBpbiB0aGUgcXVldWUuIElmIGF0dGVtcHRpbmcgdG8gZW5xdWV1ZSBhbm90aGVyIG9wLCBpdCB3aWxsIG92ZXJyaWRlIHRoZSBleGlzdGluZyBvcC4gKi9cblx0I3F1ZXVlZE9wPzogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuXHQvKiogVGhlIGN1cnJlbnRseSBydW5uaW5nIHByb21pc2Ugb2YgI2RyYWluTG9vcC4gRG8gbm90IGF3YWl0IHRoaXMsIGluc3RlYWQgYXdhaXQgYHBlbmRpbmdgIHRvIGF3YWl0IHRoZSBjdXJyZW50IGN5Y2xlLiAqL1xuXHRydW5uaW5nRHJhaW5Mb29wPzogUHJvbWlzZTx2b2lkPjtcblxuXHQvKiogUGVuZGluZyByZXNvbHZlciBmcm8gdGhlIGN1cnJlbnRseSBxdWV1ZWQgZW50cnkuICovXG5cdCNwZW5kaW5nPzogUHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD47XG5cblx0LyoqIFF1ZXVlIHRoZSBuZXh0IG9wZXJhdGlvbiBhbmQgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gaXQgZmx1c2hlcy4gKi9cblx0ZW5xdWV1ZShvcDogKCkgPT4gUHJvbWlzZTx2b2lkPik6IFByb21pc2U8dm9pZD4ge1xuXHRcdC8vIFJlcGxhY2UgYW55IHByZXZpb3VzbHkgcXVldWVkIG9wZXJhdGlvbiB3aXRoIHRoZSBsYXRlc3Qgb25lXG5cdFx0dGhpcy4jcXVldWVkT3AgPSBvcDtcblxuXHRcdC8vIEVuc3VyZSBhIHNoYXJlZCByZXNvbHZlciBleGlzdHMgZm9yIGFsbCBjYWxsZXJzIGluIHRoaXMgY3ljbGVcblx0XHRpZiAoIXRoaXMuI3BlbmRpbmcpIHtcblx0XHRcdHRoaXMuI3BlbmRpbmcgPSBQcm9taXNlLndpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblx0XHR9XG5cblx0XHRjb25zdCB3YWl0Rm9yVGhpc0N5Y2xlID0gdGhpcy4jcGVuZGluZy5wcm9taXNlO1xuXG5cdFx0Ly8gU3RhcnQgcnVubmVyIGlmIG5vdCBhbHJlYWR5IHJ1bm5pbmdcblx0XHRpZiAoIXRoaXMucnVubmluZ0RyYWluTG9vcCkge1xuXHRcdFx0dGhpcy5ydW5uaW5nRHJhaW5Mb29wID0gdGhpcy4jZHJhaW5Mb29wKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHdhaXRGb3JUaGlzQ3ljbGU7XG5cdH1cblxuXHQvKiogRHJhaW4gcXVldWVkIG9wZXJhdGlvbnMgc2VxdWVudGlhbGx5IHVudGlsIHRoZXJlIGlzIG5vdGhpbmcgbGVmdC4gKi9cblx0YXN5bmMgI2RyYWluTG9vcCgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHR0cnkge1xuXHRcdFx0d2hpbGUgKHRoaXMuI3F1ZXVlZE9wKSB7XG5cdFx0XHRcdC8vIENhcHR1cmUgY3VycmVudCBjeWNsZSByZXNvbHZlciB0aGVuIHJlc2V0IGZvciB0aGUgbmV4dCBjeWNsZVxuXHRcdFx0XHRjb25zdCByZXNvbHZlciA9IHRoaXMuI3BlbmRpbmc7XG5cdFx0XHRcdHRoaXMuI3BlbmRpbmcgPSB1bmRlZmluZWQ7XG5cblx0XHRcdFx0Ly8gQ2FwdHVyZSBhbmQgY2xlYXIgdGhlIGN1cnJlbnRseSBxdWV1ZWQgb3BlcmF0aW9uXG5cdFx0XHRcdGNvbnN0IG9wID0gdGhpcy4jcXVldWVkT3A7XG5cdFx0XHRcdHRoaXMuI3F1ZXVlZE9wID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0YXdhaXQgb3AoKTtcblx0XHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdFx0Ly8gU3dhbGxvdyBlcnJvcnM6IGNhbGxlcnMgb25seSBhd2FpdCBjeWNsZSBjb21wbGV0aW9uLCBub3Qgc3VjY2Vzc1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTm90aWZ5IGFsbCB3YWl0ZXJzIGZvciB0aGlzIGN5Y2xlXG5cdFx0XHRcdHJlc29sdmVyPy5yZXNvbHZlKCk7XG5cdFx0XHR9XG5cdFx0fSBmaW5hbGx5IHtcblx0XHRcdHRoaXMucnVubmluZ0RyYWluTG9vcCA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1ZmZlclRvQXJyYXlCdWZmZXIoYnVmOiBCdWZmZXIgfCBVaW50OEFycmF5KTogQXJyYXlCdWZmZXIge1xuXHRyZXR1cm4gYnVmLmJ1ZmZlci5zbGljZShcblx0XHRidWYuYnl0ZU9mZnNldCxcblx0XHRidWYuYnl0ZU9mZnNldCArIGJ1Zi5ieXRlTGVuZ3RoLFxuXHQpIGFzIEFycmF5QnVmZmVyO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL2xvZy1sZXZlbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi9sb2ctbGV2ZWxzLnRzXCI7ZXhwb3J0IHR5cGUgTG9nTGV2ZWwgPVxuXHR8IFwiVFJBQ0VcIlxuXHR8IFwiREVCVUdcIlxuXHR8IFwiSU5GT1wiXG5cdHwgXCJXQVJOXCJcblx0fCBcIkVSUk9SXCJcblx0fCBcIkNSSVRJQ0FMXCI7XG5cbmV4cG9ydCBjb25zdCBMb2dMZXZlbHM6IFJlY29yZDxMb2dMZXZlbCwgTGV2ZWxJbmRleD4gPSB7XG5cdFRSQUNFOiAwLFxuXHRERUJVRzogMSxcblx0SU5GTzogMixcblx0V0FSTjogMyxcblx0RVJST1I6IDQsXG5cdENSSVRJQ0FMOiA1LFxufSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IExldmVsTmFtZU1hcDogUmVjb3JkPG51bWJlciwgTG9nTGV2ZWw+ID0ge1xuXHQwOiBcIlRSQUNFXCIsXG5cdDE6IFwiREVCVUdcIixcblx0MjogXCJJTkZPXCIsXG5cdDM6IFwiV0FSTlwiLFxuXHQ0OiBcIkVSUk9SXCIsXG5cdDU6IFwiQ1JJVElDQUxcIixcbn07XG5cbmV4cG9ydCB0eXBlIExldmVsSW5kZXggPSBudW1iZXI7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb24vbG9nZm10LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vblwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb24vbG9nZm10LnRzXCI7aW1wb3J0IHsgdHlwZSBMb2dMZXZlbCwgTG9nTGV2ZWxzIH0gZnJvbSBcIi4vbG9nLWxldmVsc1wiO1xuXG5leHBvcnQgdHlwZSBMb2dFbnRyeSA9IFtzdHJpbmcsIExvZ1ZhbHVlXTtcbmV4cG9ydCB0eXBlIExvZ1ZhbHVlID0gc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50IHwgYm9vbGVhbiB8IG51bGwgfCB1bmRlZmluZWQ7XG5cbmNvbnN0IExPR19MRVZFTF9DT0xPUlM6IFJlY29yZDxudW1iZXIsIHN0cmluZz4gPSB7XG5cdFtMb2dMZXZlbHMuQ1JJVElDQUxdOiBcIlxceDFiWzMxbVwiLCAvLyBSZWRcblx0W0xvZ0xldmVscy5FUlJPUl06IFwiXFx4MWJbMzFtXCIsIC8vIFJlZFxuXHRbTG9nTGV2ZWxzLldBUk5dOiBcIlxceDFiWzMzbVwiLCAvLyBZZWxsb3dcblx0W0xvZ0xldmVscy5JTkZPXTogXCJcXHgxYlszMm1cIiwgLy8gR3JlZW5cblx0W0xvZ0xldmVscy5ERUJVR106IFwiXFx4MWJbMzZtXCIsIC8vIEN5YW5cblx0W0xvZ0xldmVscy5UUkFDRV06IFwiXFx4MWJbMzZtXCIsIC8vIEN5YW5cbn07XG5cbmNvbnN0IFJFU0VUX0NPTE9SID0gXCJcXHgxYlswbVwiO1xuXG4vKipcbiAqIFNlcmlhbGl6ZXMgbG9nZm10IGxpbmUgdXNpbmcgb3JkZXJlciBwYXJhbWV0ZXJzLlxuICpcbiAqIFdlIHVzZSB2YXJhcmdzIGJlY2F1c2UgaXQncyBvcmRlcmVkICYgaXQgaGFzIGxlc3Mgb3ZlcmhlYWQgdGhhbiBhbiBvYmplY3QuXG4gKlxuICogIyMgU3R5bGluZyBNZXRob2RvbG9neVxuICpcbiAqIFRoZSB0aHJlZSB0aGluZ3MgeW91IG5lZWQgdG8ga25vdyBmb3IgZXZlcnkgbG9nIGxpbmUgaXMgdGhlIGxldmVsLCB0aGVcbiAqIG1lc3NhZ2UsIGFuZCB3aG8gY2FsbGVkIGl0LiBUaGVzZSBwcm9wZXJ0aWVzIGFyZSBoaWdobGlnaHRlZCBpbiBkaWZmZXJlbnQgY29scm9zXG4gKiBhbmQgc29ydGVkIGluIHRoIGVvcmRlciB0aGF0IHlvdSB1c3VhbGx5IHJlYWQgdGhlbS5cbiAqXG4gKiBPbmNlIHlvdSd2ZSBmb3VuZCBhIGxvZyBsaW5lIHlvdSBjYXJlIGFib3V0LCB0aGVuIHlvdSB3YW50IHRvIGZpbmQgdGhlXG4gKiBwcm9wZXJ0eSB5b3UgbmVlZCB0byBzZWUuIFRoZSBwcm9wZXJ0eSBuYW1lcyBhcmUgYm9sZGVkIGFuZCB0aGUgZGVmYXVsdCBjb2xvclxuICogd2hpbGUgdGhlIHJlc3Qgb2YgdGhlIGRhdGEgaXMgZGltLiBUaGlzIGxldHMgeW91IHNjYW4gdG8gZmluZCB0aGUgcHJvcGVydHlcbiAqIG5hbWUgcXVpY2tseSB0aGVuIGxvb2sgY2xvc2VyIHRvIHJlYWQgdGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZVxuICogcHJvcGVydHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpbmdpZnkoLi4uZGF0YTogTG9nRW50cnlbXSkge1xuXHRsZXQgbGluZSA9IFwiXCI7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgW2tleSwgdmFsdWVSYXddID0gZGF0YVtpXTtcblxuXHRcdGxldCBpc051bGwgPSBmYWxzZTtcblx0XHRsZXQgdmFsdWVTdHJpbmc6IHN0cmluZztcblx0XHRpZiAodmFsdWVSYXcgPT0gbnVsbCkge1xuXHRcdFx0aXNOdWxsID0gdHJ1ZTtcblx0XHRcdHZhbHVlU3RyaW5nID0gXCJcIjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFsdWVTdHJpbmcgPSB2YWx1ZVJhdy50b1N0cmluZygpO1xuXHRcdH1cblxuXHRcdC8vIENsaXAgdmFsdWUgdW5sZXNzIHNwZWNpZmljYWxseSB0aGUgZXJyb3IgbWVzc2FnZVxuXHRcdGlmICh2YWx1ZVN0cmluZy5sZW5ndGggPiA1MTIgJiYga2V5ICE9PSBcIm1zZ1wiICYmIGtleSAhPT0gXCJlcnJvclwiKVxuXHRcdFx0dmFsdWVTdHJpbmcgPSBgJHt2YWx1ZVN0cmluZy5zbGljZSgwLCA1MTIpfS4uLmA7XG5cblx0XHRjb25zdCBuZWVkc1F1b3RpbmcgPVxuXHRcdFx0dmFsdWVTdHJpbmcuaW5kZXhPZihcIiBcIikgPiAtMSB8fCB2YWx1ZVN0cmluZy5pbmRleE9mKFwiPVwiKSA+IC0xO1xuXHRcdGNvbnN0IG5lZWRzRXNjYXBpbmcgPVxuXHRcdFx0dmFsdWVTdHJpbmcuaW5kZXhPZignXCInKSA+IC0xIHx8IHZhbHVlU3RyaW5nLmluZGV4T2YoXCJcXFxcXCIpID4gLTE7XG5cblx0XHR2YWx1ZVN0cmluZyA9IHZhbHVlU3RyaW5nLnJlcGxhY2UoL1xcbi9nLCBcIlxcXFxuXCIpO1xuXHRcdGlmIChuZWVkc0VzY2FwaW5nKSB2YWx1ZVN0cmluZyA9IHZhbHVlU3RyaW5nLnJlcGxhY2UoL1tcIlxcXFxdL2csIFwiXFxcXCQmXCIpO1xuXHRcdGlmIChuZWVkc1F1b3RpbmcgfHwgbmVlZHNFc2NhcGluZykgdmFsdWVTdHJpbmcgPSBgXCIke3ZhbHVlU3RyaW5nfVwiYDtcblx0XHRpZiAodmFsdWVTdHJpbmcgPT09IFwiXCIgJiYgIWlzTnVsbCkgdmFsdWVTdHJpbmcgPSAnXCJcIic7XG5cblx0XHRpZiAoTE9HR0VSX0NPTkZJRy5lbmFibGVDb2xvcikge1xuXHRcdFx0Ly8gV2l0aCBjb2xvclxuXG5cdFx0XHQvLyBTcGVjaWFsIG1lc3NhZ2UgY29sb3JzXG5cdFx0XHRsZXQgY29sb3IgPSBcIlxceDFiWzJtXCI7XG5cdFx0XHRpZiAoa2V5ID09PSBcImxldmVsXCIpIHtcblx0XHRcdFx0Y29uc3QgbGV2ZWwgPSBMb2dMZXZlbHNbdmFsdWVTdHJpbmcgYXMgTG9nTGV2ZWxdO1xuXHRcdFx0XHRjb25zdCBsZXZlbENvbG9yID0gTE9HX0xFVkVMX0NPTE9SU1tsZXZlbF07XG5cdFx0XHRcdGlmIChsZXZlbENvbG9yKSB7XG5cdFx0XHRcdFx0Y29sb3IgPSBsZXZlbENvbG9yO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKGtleSA9PT0gXCJtc2dcIikge1xuXHRcdFx0XHRjb2xvciA9IFwiXFx4MWJbMzJtXCI7XG5cdFx0XHR9IGVsc2UgaWYgKGtleSA9PT0gXCJ0cmFjZVwiKSB7XG5cdFx0XHRcdGNvbG9yID0gXCJcXHgxYlszNG1cIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRm9ybWF0IGxpbmVcblx0XHRcdGxpbmUgKz0gYFxceDFiWzBtXFx4MWJbMW0ke2tleX1cXHgxYlswbVxceDFiWzJtPVxceDFiWzBtJHtjb2xvcn0ke3ZhbHVlU3RyaW5nfSR7UkVTRVRfQ09MT1J9YDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gTm8gY29sb3Jcblx0XHRcdGxpbmUgKz0gYCR7a2V5fT0ke3ZhbHVlU3RyaW5nfWA7XG5cdFx0fVxuXG5cdFx0aWYgKGkgIT09IGRhdGEubGVuZ3RoIC0gMSkge1xuXHRcdFx0bGluZSArPSBcIiBcIjtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbGluZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFRpbWVzdGFtcChkYXRlOiBEYXRlKTogc3RyaW5nIHtcblx0Y29uc3QgeWVhciA9IGRhdGUuZ2V0VVRDRnVsbFllYXIoKTtcblx0Y29uc3QgbW9udGggPSBTdHJpbmcoZGF0ZS5nZXRVVENNb250aCgpICsgMSkucGFkU3RhcnQoMiwgXCIwXCIpO1xuXHRjb25zdCBkYXkgPSBTdHJpbmcoZGF0ZS5nZXRVVENEYXRlKCkpLnBhZFN0YXJ0KDIsIFwiMFwiKTtcblx0Y29uc3QgaG91cnMgPSBTdHJpbmcoZGF0ZS5nZXRVVENIb3VycygpKS5wYWRTdGFydCgyLCBcIjBcIik7XG5cdGNvbnN0IG1pbnV0ZXMgPSBTdHJpbmcoZGF0ZS5nZXRVVENNaW51dGVzKCkpLnBhZFN0YXJ0KDIsIFwiMFwiKTtcblx0Y29uc3Qgc2Vjb25kcyA9IFN0cmluZyhkYXRlLmdldFVUQ1NlY29uZHMoKSkucGFkU3RhcnQoMiwgXCIwXCIpO1xuXHRjb25zdCBtaWxsaXNlY29uZHMgPSBTdHJpbmcoZGF0ZS5nZXRVVENNaWxsaXNlY29uZHMoKSkucGFkU3RhcnQoMywgXCIwXCIpO1xuXG5cdHJldHVybiBgJHt5ZWFyfS0ke21vbnRofS0ke2RheX1UJHtob3Vyc306JHttaW51dGVzfToke3NlY29uZHN9LiR7bWlsbGlzZWNvbmRzfVpgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FzdFRvTG9nVmFsdWUodjogdW5rbm93bik6IExvZ1ZhbHVlIHtcblx0aWYgKFxuXHRcdHR5cGVvZiB2ID09PSBcInN0cmluZ1wiIHx8XG5cdFx0dHlwZW9mIHYgPT09IFwibnVtYmVyXCIgfHxcblx0XHR0eXBlb2YgdiA9PT0gXCJiaWdpbnRcIiB8fFxuXHRcdHR5cGVvZiB2ID09PSBcImJvb2xlYW5cIiB8fFxuXHRcdHYgPT09IG51bGwgfHxcblx0XHR2ID09PSB1bmRlZmluZWRcblx0KSB7XG5cdFx0cmV0dXJuIHY7XG5cdH1cblx0aWYgKHYgaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdC8vYXJncy5wdXNoKC4uLmVycm9yVG9Mb2dFbnRyaWVzKGssIHYpKTtcblx0XHRyZXR1cm4gU3RyaW5nKHYpO1xuXHR9XG5cdHRyeSB7XG5cdFx0cmV0dXJuIEpTT04uc3RyaW5naWZ5KHYpO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gXCJbY2Fubm90IHN0cmluZ2lmeV1cIjtcblx0fVxufVxuXG4vLyBNQVJLOiBDb25maWdcbmludGVyZmFjZSBHbG9iYWxMb2dnZXJDb25maWcge1xuXHRlbmFibGVDb2xvcjogYm9vbGVhbjtcblx0ZW5hYmxlU3ByZWFkT2JqZWN0OiBib29sZWFuO1xuXHRlbmFibGVFcnJvclN0YWNrOiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgTE9HR0VSX0NPTkZJRzogR2xvYmFsTG9nZ2VyQ29uZmlnID0ge1xuXHRlbmFibGVDb2xvcjogZmFsc2UsXG5cdGVuYWJsZVNwcmVhZE9iamVjdDogZmFsc2UsXG5cdGVuYWJsZUVycm9yU3RhY2s6IGZhbHNlLFxufTtcblxuLy8gTUFSSzogVXRpbHNcbi8qKlxuICogQ29udmVydHMgYW4gb2JqZWN0IGluIHRvIGFuIGVhc2llciB0byByZWFkIEtWIG9mIGVudHJpZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcHJlYWRPYmplY3RUb0xvZ0VudHJpZXMoXG5cdGJhc2U6IHN0cmluZyxcblx0ZGF0YTogdW5rbm93bixcbik6IExvZ0VudHJ5W10ge1xuXHRpZiAoXG5cdFx0TE9HR0VSX0NPTkZJRy5lbmFibGVTcHJlYWRPYmplY3QgJiZcblx0XHR0eXBlb2YgZGF0YSA9PT0gXCJvYmplY3RcIiAmJlxuXHRcdCFBcnJheS5pc0FycmF5KGRhdGEpICYmXG5cdFx0ZGF0YSAhPT0gbnVsbCAmJlxuXHRcdE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCAhPT0gMCAmJlxuXHRcdE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCA8IDE2XG5cdCkge1xuXHRcdGNvbnN0IGxvZ0RhdGE6IExvZ0VudHJ5W10gPSBbXTtcblx0XHRmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG5cdFx0XHQvLyBsb2dEYXRhLnB1c2goW2Ake2Jhc2V9LiR7a2V5fWAsIEpTT04uc3RyaW5naWZ5KChkYXRhIGFzIGFueSlba2V5XSldKTtcblxuXHRcdFx0bG9nRGF0YS5wdXNoKFxuXHRcdFx0XHQuLi5zcHJlYWRPYmplY3RUb0xvZ0VudHJpZXMoXG5cdFx0XHRcdFx0YCR7YmFzZX0uJHtrZXl9YCxcblx0XHRcdFx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IEZJWE1FXG5cdFx0XHRcdFx0KGRhdGEgYXMgYW55KVtrZXldLFxuXHRcdFx0XHQpLFxuXHRcdFx0KTtcblx0XHR9XG5cdFx0cmV0dXJuIGxvZ0RhdGE7XG5cdH1cblxuXHRyZXR1cm4gW1tiYXNlLCBKU09OLnN0cmluZ2lmeShkYXRhKV1dO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXJyb3JUb0xvZ0VudHJpZXMoYmFzZTogc3RyaW5nLCBlcnJvcjogdW5rbm93bik6IExvZ0VudHJ5W10ge1xuXHRpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdHJldHVybiBbXG5cdFx0XHQvL1tgJHtiYXNlfS5uYW1lYCwgZXJyb3IubmFtZV0sXG5cdFx0XHRbYCR7YmFzZX0ubWVzc2FnZWAsIGVycm9yLm1lc3NhZ2VdLFxuXHRcdFx0Li4uKExPR0dFUl9DT05GSUcuZW5hYmxlRXJyb3JTdGFjayAmJiBlcnJvci5zdGFja1xuXHRcdFx0XHQ/IFtbYCR7YmFzZX0uc3RhY2tgLCBmb3JtYXRTdGFja1RyYWNlKGVycm9yLnN0YWNrKV0gYXMgTG9nRW50cnldXG5cdFx0XHRcdDogW10pLFxuXHRcdFx0Li4uKGVycm9yLmNhdXNlID8gZXJyb3JUb0xvZ0VudHJpZXMoYCR7YmFzZX0uY2F1c2VgLCBlcnJvci5jYXVzZSkgOiBbXSksXG5cdFx0XTtcblx0fVxuXHRyZXR1cm4gW1tiYXNlLCBgJHtlcnJvcn1gXV07XG59XG5cbi8vIGV4cG9ydCBmdW5jdGlvbiBlcnJvclRvTG9nRW50cmllcyhiYXNlOiBzdHJpbmcsIGVycm9yOiB1bmtub3duKTogTG9nRW50cnlbXSB7XG4vLyBcdGlmIChlcnJvciBpbnN0YW5jZW9mIFJ1bnRpbWVFcnJvcikge1xuLy8gXHRcdHJldHVybiBbXG4vLyBcdFx0XHRbYCR7YmFzZX0uY29kZWAsIGVycm9yLmNvZGVdLFxuLy8gXHRcdFx0W2Ake2Jhc2V9LmRlc2NyaXB0aW9uYCwgZXJyb3IuZXJyb3JDb25maWc/LmRlc2NyaXB0aW9uXSxcbi8vIFx0XHRcdFtgJHtiYXNlfS5tb2R1bGVgLCBlcnJvci5tb2R1bGVOYW1lXSxcbi8vIFx0XHRcdC4uLihlcnJvci50cmFjZSA/IFtbYCR7YmFzZX0udHJhY2VgLCBzdHJpbmdpZnlUcmFjZShlcnJvci50cmFjZSldIGFzIExvZ0VudHJ5XSA6IFtdKSxcbi8vIFx0XHRcdC4uLihMT0dHRVJfQ09ORklHLmVuYWJsZUVycm9yU3RhY2sgJiYgZXJyb3Iuc3RhY2tcbi8vIFx0XHRcdFx0PyBbW2Ake2Jhc2V9LnN0YWNrYCwgZm9ybWF0U3RhY2tUcmFjZShlcnJvci5zdGFjayldIGFzIExvZ0VudHJ5XVxuLy8gXHRcdFx0XHQ6IFtdKSxcbi8vIFx0XHRcdC4uLihlcnJvci5tZXRhID8gW1tgJHtiYXNlfS5tZXRhYCwgSlNPTi5zdHJpbmdpZnkoZXJyb3IubWV0YSldIGFzIExvZ0VudHJ5XSA6IFtdKSxcbi8vIFx0XHRcdC4uLihlcnJvci5jYXVzZSA/IGVycm9yVG9Mb2dFbnRyaWVzKGAke2Jhc2V9LmNhdXNlYCwgZXJyb3IuY2F1c2UpIDogW10pLFxuLy8gXHRcdF07XG4vLyBcdH0gZWxzZSBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuLy8gXHRcdHJldHVybiBbXG4vLyBcdFx0XHRbYCR7YmFzZX0ubmFtZWAsIGVycm9yLm5hbWVdLFxuLy8gXHRcdFx0W2Ake2Jhc2V9Lm1lc3NhZ2VgLCBlcnJvci5tZXNzYWdlXSxcbi8vIFx0XHRcdC4uLihMT0dHRVJfQ09ORklHLmVuYWJsZUVycm9yU3RhY2sgJiYgZXJyb3Iuc3RhY2tcbi8vIFx0XHRcdFx0PyBbW2Ake2Jhc2V9LnN0YWNrYCwgZm9ybWF0U3RhY2tUcmFjZShlcnJvci5zdGFjayldIGFzIExvZ0VudHJ5XVxuLy8gXHRcdFx0XHQ6IFtdKSxcbi8vIFx0XHRcdC4uLihlcnJvci5jYXVzZSA/IGVycm9yVG9Mb2dFbnRyaWVzKGAke2Jhc2V9LmNhdXNlYCwgZXJyb3IuY2F1c2UpIDogW10pLFxuLy8gXHRcdF07XG4vLyBcdH0gZWxzZSB7XG4vLyBcdFx0cmV0dXJuIFtcbi8vIFx0XHRcdFtiYXNlLCBgJHtlcnJvcn1gXSxcbi8vIFx0XHRdO1xuLy8gXHR9XG4vLyB9XG5cbi8qKlxuICogRm9ybWF0cyBhIEpTIHN0YWNrIHRyYWNlIGluIHRvIGEgbGVnaWJsZSBvbmUtbGluZXIuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdFN0YWNrVHJhY2Uoc3RhY2tUcmFjZTogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3QgcmVnZXggPSAvYXQgKC4rPykkL2dtO1xuXHRjb25zdCBtYXRjaGVzID0gWy4uLnN0YWNrVHJhY2UubWF0Y2hBbGwocmVnZXgpXTtcblx0Ly8gUmV2ZXJzZSBhcnJheSBzaW5jZSB0aGUgc3RhY2sgZ29lcyBmcm9tIHRvcCBsZXZlbCAtPiBib3R0b20gbGV2ZWxcblx0bWF0Y2hlcy5yZXZlcnNlKCk7XG5cdHJldHVybiBtYXRjaGVzLm1hcCgobWF0Y2gpID0+IG1hdGNoWzFdLnRyaW0oKSkuam9pbihcIiA+IFwiKTtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi9sb2cudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi9sb2cudHNcIjtpbXBvcnQgeyBnZXRFbnZVbml2ZXJzYWwgfSBmcm9tIFwiQC91dGlsc1wiO1xuaW1wb3J0IHtcblx0dHlwZSBMZXZlbEluZGV4LFxuXHRMZXZlbE5hbWVNYXAsXG5cdHR5cGUgTG9nTGV2ZWwsXG5cdExvZ0xldmVscyxcbn0gZnJvbSBcIi4vbG9nLWxldmVsc1wiO1xuaW1wb3J0IHtcblx0Y2FzdFRvTG9nVmFsdWUsXG5cdGZvcm1hdFRpbWVzdGFtcCxcblx0dHlwZSBMb2dFbnRyeSxcblx0c3RyaW5naWZ5LFxufSBmcm9tIFwiLi9sb2dmbXRcIjtcblxuaW50ZXJmYWNlIExvZ1JlY29yZCB7XG5cdGFyZ3M6IHVua25vd25bXTtcblx0ZGF0ZXRpbWU6IERhdGU7XG5cdGxldmVsOiBudW1iZXI7XG5cdGxldmVsTmFtZTogc3RyaW5nO1xuXHRsb2dnZXJOYW1lOiBzdHJpbmc7XG5cdG1zZzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgTG9nZ2VyIHtcblx0bmFtZTogc3RyaW5nO1xuXHRsZXZlbDogTG9nTGV2ZWw7XG5cblx0Y29uc3RydWN0b3IobmFtZTogc3RyaW5nLCBsZXZlbDogTG9nTGV2ZWwpIHtcblx0XHR0aGlzLm5hbWUgPSBuYW1lO1xuXHRcdHRoaXMubGV2ZWwgPSBsZXZlbDtcblx0fVxuXG5cdGxvZyhsZXZlbDogTGV2ZWxJbmRleCwgbWVzc2FnZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHRjb25zdCByZWNvcmQ6IExvZ1JlY29yZCA9IHtcblx0XHRcdG1zZzogbWVzc2FnZSxcblx0XHRcdGFyZ3MsXG5cdFx0XHRsZXZlbCxcblx0XHRcdGxvZ2dlck5hbWU6IHRoaXMubmFtZSxcblx0XHRcdGRhdGV0aW1lOiBuZXcgRGF0ZSgpLFxuXHRcdFx0bGV2ZWxOYW1lOiBMZXZlbE5hbWVNYXBbbGV2ZWxdLFxuXHRcdH07XG5cblx0XHRpZiAodGhpcy4jc2hvdWxkTG9nKGxldmVsKSkge1xuXHRcdFx0dGhpcy4jbG9nUmVjb3JkKHJlY29yZCk7XG5cdFx0fVxuXHR9XG5cblx0I3Nob3VsZExvZyhsZXZlbDogTGV2ZWxJbmRleCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBsZXZlbCA+PSBMb2dMZXZlbHNbdGhpcy5sZXZlbF07XG5cdH1cblxuXHQjbG9nUmVjb3JkKHJlY29yZDogTG9nUmVjb3JkKTogdm9pZCB7XG5cdFx0Y29uc29sZS5sb2coZm9ybWF0dGVyKHJlY29yZCkpO1xuXHR9XG5cblx0dHJhY2UobWVzc2FnZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHR0aGlzLmxvZyhMb2dMZXZlbHMuVFJBQ0UsIG1lc3NhZ2UsIC4uLmFyZ3MpO1xuXHR9XG5cblx0ZGVidWcobWVzc2FnZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHR0aGlzLmxvZyhMb2dMZXZlbHMuREVCVUcsIG1lc3NhZ2UsIC4uLmFyZ3MpO1xuXHR9XG5cblx0aW5mbyhtZXNzYWdlOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKExvZ0xldmVscy5JTkZPLCBtZXNzYWdlLCAuLi5hcmdzKTtcblx0fVxuXG5cdHdhcm4obWVzc2FnZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHR0aGlzLmxvZyhMb2dMZXZlbHMuV0FSTiwgbWVzc2FnZSwgLi4uYXJncyk7XG5cdH1cblxuXHRlcnJvcihtZXNzYWdlOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKExvZ0xldmVscy5FUlJPUiwgbWVzc2FnZSwgLi4uYXJncyk7XG5cdH1cblxuXHRjcml0aWNhbChtZXNzYWdlOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKExvZ0xldmVscy5DUklUSUNBTCwgbWVzc2FnZSwgLi4uYXJncyk7XG5cdH1cbn1cblxuY29uc3QgbG9nZ2VyczogUmVjb3JkPHN0cmluZywgTG9nZ2VyPiA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9nZ2VyKG5hbWUgPSBcImRlZmF1bHRcIik6IExvZ2dlciB7XG5cdGNvbnN0IGRlZmF1bHRMb2dMZXZlbEVudjogTG9nTGV2ZWwgfCB1bmRlZmluZWQgPSBnZXRFbnZVbml2ZXJzYWwoXG5cdFx0XCJfTE9HX0xFVkVMXCIsXG5cdCkgYXMgTG9nTGV2ZWwgfCB1bmRlZmluZWQ7XG5cblx0Y29uc3QgZGVmYXVsdExvZ0xldmVsOiBMb2dMZXZlbCA9IGRlZmF1bHRMb2dMZXZlbEVudiA/PyBcIklORk9cIjtcblx0aWYgKCFsb2dnZXJzW25hbWVdKSB7XG5cdFx0bG9nZ2Vyc1tuYW1lXSA9IG5ldyBMb2dnZXIobmFtZSwgZGVmYXVsdExvZ0xldmVsKTtcblx0fVxuXHRyZXR1cm4gbG9nZ2Vyc1tuYW1lXTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0dGVyKGxvZzogTG9nUmVjb3JkKTogc3RyaW5nIHtcblx0Y29uc3QgYXJnczogTG9nRW50cnlbXSA9IFtdO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IGxvZy5hcmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgbG9nQXJnID0gbG9nLmFyZ3NbaV07XG5cdFx0aWYgKGxvZ0FyZyAmJiB0eXBlb2YgbG9nQXJnID09PSBcIm9iamVjdFwiKSB7XG5cdFx0XHQvLyBTcHJlYWQgb2JqZWN0XG5cdFx0XHRmb3IgKGNvbnN0IGsgaW4gbG9nQXJnKSB7XG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogVW5rbm93biB0eXBlXG5cdFx0XHRcdGNvbnN0IHYgPSAobG9nQXJnIGFzIGFueSlba107XG5cblx0XHRcdFx0cHVzaEFyZyhrLCB2LCBhcmdzKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0cHVzaEFyZyhgYXJnJHtpfWAsIGxvZ0FyZywgYXJncyk7XG5cdFx0fVxuXHR9XG5cblx0Y29uc3QgbG9nVHMgPSBnZXRFbnZVbml2ZXJzYWwoXCJfTE9HX1RJTUVTVEFNUFwiKSA9PT0gXCIxXCI7XG5cdGNvbnN0IGxvZ1RhcmdldCA9IGdldEVudlVuaXZlcnNhbChcIl9MT0dfVEFSR0VUXCIpID09PSBcIjFcIjtcblxuXHRyZXR1cm4gc3RyaW5naWZ5KFxuXHRcdC4uLihsb2dUcyA/IFtbXCJ0c1wiLCBmb3JtYXRUaW1lc3RhbXAobmV3IERhdGUoKSldIGFzIExvZ0VudHJ5XSA6IFtdKSxcblx0XHRbXCJsZXZlbFwiLCBMZXZlbE5hbWVNYXBbbG9nLmxldmVsXV0sXG5cdFx0Li4uKGxvZ1RhcmdldCA/IFtbXCJ0YXJnZXRcIiwgbG9nLmxvZ2dlck5hbWVdIGFzIExvZ0VudHJ5XSA6IFtdKSxcblx0XHRbXCJtc2dcIiwgbG9nLm1zZ10sXG5cdFx0Li4uYXJncyxcblx0KTtcbn1cblxuZnVuY3Rpb24gcHVzaEFyZyhrOiBzdHJpbmcsIHY6IHVua25vd24sIGFyZ3M6IExvZ0VudHJ5W10pIHtcblx0YXJncy5wdXNoKFtrLCBjYXN0VG9Mb2dWYWx1ZSh2KV0pO1xufVxuXG4vLyBmdW5jdGlvbiBnZXRFbnYobmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbi8vIFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgJiYgd2luZG93LmxvY2FsU3RvcmFnZSkge1xuLy8gXHRcdHJldHVybiB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0obmFtZSkgfHwgdW5kZWZpbmVkO1xuLy8gXHR9XG4vLyBcdHJldHVybiB1bmRlZmluZWQ7XG4vLyBcdC8vIFRPRE8oQUNUUi05KTogQWRkIGJhY2sgZW52IGNvbmZpZyBvbmNlIG5vZGUgY29tcGF0IGxheWVyIHdvcmtzXG4vLyBcdC8vcmV0dXJuIGNyb3NzR2V0RW52KG5hbWUpO1xuLy8gfVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBMb2dnaW5nKCkge1xuXHQvLyBEbyBub3RoaW5nIGZvciBub3dcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2xvZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3RvclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9sb2cudHNcIjtpbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQC9jb21tb24vL2xvZ1wiO1xuXG4vKiogTG9nZ2VyIGZvciB0aGlzIGxpYnJhcnkuICovXG5leHBvcnQgY29uc3QgUlVOVElNRV9MT0dHRVJfTkFNRSA9IFwiYWN0b3ItcnVudGltZVwiO1xuXG4vKiogTG9nZ2VyIHVzZWQgZm9yIGxvZ3MgZnJvbSB0aGUgYWN0b3IgaW5zdGFuY2UgaXRzZWxmLiAqL1xuZXhwb3J0IGNvbnN0IEFDVE9SX0xPR0dFUl9OQU1FID0gXCJhY3RvclwiO1xuXG5leHBvcnQgZnVuY3Rpb24gbG9nZ2VyKCkge1xuXHRyZXR1cm4gZ2V0TG9nZ2VyKFJVTlRJTUVfTE9HR0VSX05BTUUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5zdGFuY2VMb2dnZXIoKSB7XG5cdHJldHVybiBnZXRMb2dnZXIoQUNUT1JfTE9HR0VSX05BTUUpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvcHJvdG9jb2wvc2VyZGUudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvcHJvdG9jb2xcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvcHJvdG9jb2wvc2VyZGUudHNcIjtpbXBvcnQgKiBhcyBjYm9yIGZyb20gXCJjYm9yLXhcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgKiBhcyBlcnJvcnMgZnJvbSBcIkAvYWN0b3IvZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IFZlcnNpb25lZERhdGFIYW5kbGVyIH0gZnJvbSBcIkAvY29tbW9uL3ZlcnNpb25lZC1kYXRhXCI7XG5pbXBvcnQgeyBzZXJpYWxpemVXaXRoRW5jb2RpbmcgfSBmcm9tIFwiQC9zZXJkZVwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4uL2xvZ1wiO1xuaW1wb3J0IHsgYXNzZXJ0VW5yZWFjaGFibGUgfSBmcm9tIFwiLi4vdXRpbHNcIjtcblxuLyoqIERhdGEgdGhhdCBjYW4gYmUgZGVzZXJpYWxpemVkLiAqL1xuZXhwb3J0IHR5cGUgSW5wdXREYXRhID0gc3RyaW5nIHwgQnVmZmVyIHwgQmxvYiB8IEFycmF5QnVmZmVyTGlrZSB8IFVpbnQ4QXJyYXk7XG5cbi8qKiBEYXRhIHRoYXQncyBiZWVuIHNlcmlhbGl6ZWQuICovXG5leHBvcnQgdHlwZSBPdXRwdXREYXRhID0gc3RyaW5nIHwgVWludDhBcnJheTtcblxuZXhwb3J0IGNvbnN0IEVuY29kaW5nU2NoZW1hID0gei5lbnVtKFtcImpzb25cIiwgXCJjYm9yXCIsIFwiYmFyZVwiXSk7XG5cbi8qKlxuICogRW5jb2RpbmcgdXNlZCB0byBjb21tdW5pY2F0ZSBiZXR3ZWVuIHRoZSBjbGllbnQgJiBhY3Rvci5cbiAqL1xuZXhwb3J0IHR5cGUgRW5jb2RpbmcgPSB6LmluZmVyPHR5cGVvZiBFbmNvZGluZ1NjaGVtYT47XG5cbi8qKlxuICogSGVscGVyIGNsYXNzIHRoYXQgaGVscHMgc2VyaWFsaXplIGRhdGEgd2l0aG91dCByZS1zZXJpYWxpemluZyBmb3IgdGhlIHNhbWUgZW5jb2RpbmcuXG4gKi9cbmV4cG9ydCBjbGFzcyBDYWNoZWRTZXJpYWxpemVyPFQ+IHtcblx0I2RhdGE6IFQ7XG5cdCNjYWNoZSA9IG5ldyBNYXA8RW5jb2RpbmcsIE91dHB1dERhdGE+KCk7XG5cdCN2ZXJzaW9uZWREYXRhSGFuZGxlcjogVmVyc2lvbmVkRGF0YUhhbmRsZXI8VD47XG5cblx0Y29uc3RydWN0b3IoZGF0YTogVCwgdmVyc2lvbmVkRGF0YUhhbmRsZXI6IFZlcnNpb25lZERhdGFIYW5kbGVyPFQ+KSB7XG5cdFx0dGhpcy4jZGF0YSA9IGRhdGE7XG5cdFx0dGhpcy4jdmVyc2lvbmVkRGF0YUhhbmRsZXIgPSB2ZXJzaW9uZWREYXRhSGFuZGxlcjtcblx0fVxuXG5cdHB1YmxpYyBnZXQgcmF3RGF0YSgpOiBUIHtcblx0XHRyZXR1cm4gdGhpcy4jZGF0YTtcblx0fVxuXG5cdHB1YmxpYyBzZXJpYWxpemUoZW5jb2Rpbmc6IEVuY29kaW5nKTogT3V0cHV0RGF0YSB7XG5cdFx0Y29uc3QgY2FjaGVkID0gdGhpcy4jY2FjaGUuZ2V0KGVuY29kaW5nKTtcblx0XHRpZiAoY2FjaGVkKSB7XG5cdFx0XHRyZXR1cm4gY2FjaGVkO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBzZXJpYWxpemVkID0gc2VyaWFsaXplV2l0aEVuY29kaW5nKFxuXHRcdFx0XHRlbmNvZGluZyxcblx0XHRcdFx0dGhpcy4jZGF0YSxcblx0XHRcdFx0dGhpcy4jdmVyc2lvbmVkRGF0YUhhbmRsZXIsXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy4jY2FjaGUuc2V0KGVuY29kaW5nLCBzZXJpYWxpemVkKTtcblx0XHRcdHJldHVybiBzZXJpYWxpemVkO1xuXHRcdH1cblx0fVxufVxuXG4vLy8qKlxuLy8gKiBVc2UgYENhY2hlZFNlcmlhbGl6ZXJgIGlmIHNlcmlhbGl6aW5nIHRoZSBzYW1lIGRhdGEgcmVwZWF0ZWRseS5cbi8vICovXG4vL2V4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemU8VD4odmFsdWU6IFQsIGVuY29kaW5nOiBFbmNvZGluZyk6IE91dHB1dERhdGEge1xuLy9cdGlmIChlbmNvZGluZyA9PT0gXCJqc29uXCIpIHtcbi8vXHRcdHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4vL1x0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJjYm9yXCIpIHtcbi8vXHRcdC8vIFRPRE86IFJlbW92ZSB0aGlzIGhhY2ssIGJ1dCBjYm9yLXggY2FuJ3QgaGFuZGxlIGFueXRoaW5nIGV4dHJhIGluIGRhdGEgc3RydWN0dXJlc1xuLy9cdFx0Y29uc3QgY2xlYW5WYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcbi8vXHRcdHJldHVybiBjYm9yLmVuY29kZShjbGVhblZhbHVlKTtcbi8vXHR9IGVsc2Uge1xuLy9cdFx0YXNzZXJ0VW5yZWFjaGFibGUoZW5jb2RpbmcpO1xuLy9cdH1cbi8vfVxuLy9cbi8vZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlc2VyaWFsaXplKGRhdGE6IElucHV0RGF0YSwgZW5jb2Rpbmc6IEVuY29kaW5nKSB7XG4vL1x0aWYgKGVuY29kaW5nID09PSBcImpzb25cIikge1xuLy9cdFx0aWYgKHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiKSB7XG4vL1x0XHRcdGxvZ2dlcigpLndhcm4oXCJyZWNlaXZlZCBub24tc3RyaW5nIGZvciBqc29uIHBhcnNlXCIpO1xuLy9cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLk1hbGZvcm1lZE1lc3NhZ2UoKTtcbi8vXHRcdH0gZWxzZSB7XG4vL1x0XHRcdHJldHVybiBKU09OLnBhcnNlKGRhdGEpO1xuLy9cdFx0fVxuLy9cdH0gZWxzZSBpZiAoZW5jb2RpbmcgPT09IFwiY2JvclwiKSB7XG4vL1x0XHRpZiAoZGF0YSBpbnN0YW5jZW9mIEJsb2IpIHtcbi8vXHRcdFx0Y29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBkYXRhLmFycmF5QnVmZmVyKCk7XG4vL1x0XHRcdHJldHVybiBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikpO1xuLy9cdFx0fSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuLy9cdFx0XHRyZXR1cm4gY2Jvci5kZWNvZGUoZGF0YSk7XG4vL1x0XHR9IGVsc2UgaWYgKFxuLy9cdFx0XHRkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcbi8vXHRcdFx0ZGF0YSBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyXG4vL1x0XHQpIHtcbi8vXHRcdFx0cmV0dXJuIGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGRhdGEpKTtcbi8vXHRcdH0gZWxzZSB7XG4vL1x0XHRcdGxvZ2dlcigpLndhcm4oXCJyZWNlaXZlZCBub24tYmluYXJ5IHR5cGUgZm9yIGNib3IgcGFyc2VcIik7XG4vL1x0XHRcdHRocm93IG5ldyBlcnJvcnMuTWFsZm9ybWVkTWVzc2FnZSgpO1xuLy9cdFx0fVxuLy9cdH0gZWxzZSB7XG4vL1x0XHRhc3NlcnRVbnJlYWNoYWJsZShlbmNvZGluZyk7XG4vL1x0fVxuLy99XG5cbi8vIFRPRE86IEVuY29kZSBiYXNlIDEyOFxuZnVuY3Rpb24gYmFzZTY0RW5jb2RlVWludDhBcnJheSh1aW50OEFycmF5OiBVaW50OEFycmF5KTogc3RyaW5nIHtcblx0bGV0IGJpbmFyeSA9IFwiXCI7XG5cdGNvbnN0IGxlbiA9IHVpbnQ4QXJyYXkuYnl0ZUxlbmd0aDtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXHRcdGJpbmFyeSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVpbnQ4QXJyYXlbaV0pO1xuXHR9XG5cdHJldHVybiBidG9hKGJpbmFyeSk7XG59XG5cbmZ1bmN0aW9uIGJhc2U2NEVuY29kZUFycmF5QnVmZmVyKGFycmF5QnVmZmVyOiBBcnJheUJ1ZmZlcik6IHN0cmluZyB7XG5cdGNvbnN0IHVpbnQ4QXJyYXkgPSBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7XG5cdHJldHVybiBiYXNlNjRFbmNvZGVVaW50OEFycmF5KHVpbnQ4QXJyYXkpO1xufVxuXG4vKiogQ29udmVydHMgZGF0YSB0aGF0IHdhcyBlbmNvZGVkIHRvIGEgc3RyaW5nLiBTb21lIGZvcm1hdHMgKGxpa2UgU1NFKSBkb24ndCBzdXBwb3J0IHJhdyBiaW5hcnkgZGF0YS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVEYXRhVG9TdHJpbmcobWVzc2FnZTogT3V0cHV0RGF0YSk6IHN0cmluZyB7XG5cdGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHJldHVybiBtZXNzYWdlO1xuXHR9IGVsc2UgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuXHRcdHJldHVybiBiYXNlNjRFbmNvZGVBcnJheUJ1ZmZlcihtZXNzYWdlKTtcblx0fSBlbHNlIGlmIChtZXNzYWdlIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuXHRcdHJldHVybiBiYXNlNjRFbmNvZGVVaW50OEFycmF5KG1lc3NhZ2UpO1xuXHR9IGVsc2Uge1xuXHRcdGFzc2VydFVucmVhY2hhYmxlKG1lc3NhZ2UpO1xuXHR9XG59XG5cbi8qKiBTdHJpbmdpZmllcyB3aXRoIGNvbXBhdCBmb3IgdmFsdWVzIHRoYXQgQkFSRSAmIENCT1Igc3VwcG9ydHMuICovXG5leHBvcnQgZnVuY3Rpb24ganNvblN0cmluZ2lmeUNvbXBhdChpbnB1dDogYW55KTogc3RyaW5nIHtcblx0cmV0dXJuIEpTT04uc3RyaW5naWZ5KGlucHV0LCAoX2tleSwgdmFsdWUpID0+XG5cdFx0dHlwZW9mIHZhbHVlID09PSBcImJpZ2ludFwiID8gdmFsdWUudG9TdHJpbmcoKSA6IHZhbHVlLFxuXHQpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvc2VyZGUudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmNcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvc2VyZGUudHNcIjtpbXBvcnQgKiBhcyBjYm9yIGZyb20gXCJjYm9yLXhcIjtcbmltcG9ydCBpbnZhcmlhbnQgZnJvbSBcImludmFyaWFudFwiO1xuaW1wb3J0IHsgYXNzZXJ0VW5yZWFjaGFibGUgfSBmcm9tIFwiQC9jb21tb24vdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgVmVyc2lvbmVkRGF0YUhhbmRsZXIgfSBmcm9tIFwiQC9jb21tb24vdmVyc2lvbmVkLWRhdGFcIjtcbmltcG9ydCB0eXBlIHsgRW5jb2RpbmcgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB7IGpzb25TdHJpbmdpZnlDb21wYXQgfSBmcm9tIFwiLi9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RpbmdJc0JpbmFyeShlbmNvZGluZzogRW5jb2RpbmcpOiBib29sZWFuIHtcblx0aWYgKGVuY29kaW5nID09PSBcImpzb25cIikge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJjYm9yXCIgfHwgZW5jb2RpbmcgPT09IFwiYmFyZVwiKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH0gZWxzZSB7XG5cdFx0YXNzZXJ0VW5yZWFjaGFibGUoZW5jb2RpbmcpO1xuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb250ZW50VHlwZUZvckVuY29kaW5nKGVuY29kaW5nOiBFbmNvZGluZyk6IHN0cmluZyB7XG5cdGlmIChlbmNvZGluZyA9PT0gXCJqc29uXCIpIHtcblx0XHRyZXR1cm4gXCJhcHBsaWNhdGlvbi9qc29uXCI7XG5cdH0gZWxzZSBpZiAoZW5jb2RpbmcgPT09IFwiY2JvclwiIHx8IGVuY29kaW5nID09PSBcImJhcmVcIikge1xuXHRcdHJldHVybiBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiO1xuXHR9IGVsc2Uge1xuXHRcdGFzc2VydFVucmVhY2hhYmxlKGVuY29kaW5nKTtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3NCaW5hcnlUeXBlRm9yRW5jb2RpbmcoXG5cdGVuY29kaW5nOiBFbmNvZGluZyxcbik6IFwiYXJyYXlidWZmZXJcIiB8IFwiYmxvYlwiIHtcblx0aWYgKGVuY29kaW5nID09PSBcImpzb25cIikge1xuXHRcdHJldHVybiBcImJsb2JcIjtcblx0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJjYm9yXCIgfHwgZW5jb2RpbmcgPT09IFwiYmFyZVwiKSB7XG5cdFx0cmV0dXJuIFwiYXJyYXlidWZmZXJcIjtcblx0fSBlbHNlIHtcblx0XHRhc3NlcnRVbnJlYWNoYWJsZShlbmNvZGluZyk7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNlcmlhbGl6ZVdpdGhFbmNvZGluZzxUPihcblx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHR2YWx1ZTogVCxcblx0dmVyc2lvbmVkRGF0YUhhbmRsZXI6IFZlcnNpb25lZERhdGFIYW5kbGVyPFQ+LFxuKTogVWludDhBcnJheSB8IHN0cmluZyB7XG5cdGlmIChlbmNvZGluZyA9PT0gXCJqc29uXCIpIHtcblx0XHRyZXR1cm4ganNvblN0cmluZ2lmeUNvbXBhdCh2YWx1ZSk7XG5cdH0gZWxzZSBpZiAoZW5jb2RpbmcgPT09IFwiY2JvclwiKSB7XG5cdFx0cmV0dXJuIGNib3IuZW5jb2RlKHZhbHVlKTtcblx0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJiYXJlXCIpIHtcblx0XHRyZXR1cm4gdmVyc2lvbmVkRGF0YUhhbmRsZXIuc2VyaWFsaXplV2l0aEVtYmVkZGVkVmVyc2lvbih2YWx1ZSk7XG5cdH0gZWxzZSB7XG5cdFx0YXNzZXJ0VW5yZWFjaGFibGUoZW5jb2RpbmcpO1xuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXNlcmlhbGl6ZVdpdGhFbmNvZGluZzxUPihcblx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRidWZmZXI6IFVpbnQ4QXJyYXkgfCBzdHJpbmcsXG5cdHZlcnNpb25lZERhdGFIYW5kbGVyOiBWZXJzaW9uZWREYXRhSGFuZGxlcjxUPixcbik6IFQge1xuXHRpZiAoZW5jb2RpbmcgPT09IFwianNvblwiKSB7XG5cdFx0aWYgKHR5cGVvZiBidWZmZXIgPT09IFwic3RyaW5nXCIpIHtcblx0XHRcdHJldHVybiBKU09OLnBhcnNlKGJ1ZmZlcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGYtOFwiKTtcblx0XHRcdGNvbnN0IGpzb25TdHJpbmcgPSBkZWNvZGVyLmRlY29kZShidWZmZXIpO1xuXHRcdFx0cmV0dXJuIEpTT04ucGFyc2UoanNvblN0cmluZyk7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKGVuY29kaW5nID09PSBcImNib3JcIikge1xuXHRcdGludmFyaWFudChcblx0XHRcdHR5cGVvZiBidWZmZXIgIT09IFwic3RyaW5nXCIsXG5cdFx0XHRcImJ1ZmZlciBjYW5ub3QgYmUgc3RyaW5nIGZvciBjYm9yIGVuY29kaW5nXCIsXG5cdFx0KTtcblx0XHRyZXR1cm4gY2Jvci5kZWNvZGUoYnVmZmVyKTtcblx0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJiYXJlXCIpIHtcblx0XHRpbnZhcmlhbnQoXG5cdFx0XHR0eXBlb2YgYnVmZmVyICE9PSBcInN0cmluZ1wiLFxuXHRcdFx0XCJidWZmZXIgY2Fubm90IGJlIHN0cmluZyBmb3IgYmFyZSBlbmNvZGluZ1wiLFxuXHRcdCk7XG5cdFx0cmV0dXJuIHZlcnNpb25lZERhdGFIYW5kbGVyLmRlc2VyaWFsaXplV2l0aEVtYmVkZGVkVmVyc2lvbihidWZmZXIpO1xuXHR9IGVsc2Uge1xuXHRcdGFzc2VydFVucmVhY2hhYmxlKGVuY29kaW5nKTtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvdXRpbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3JcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvdXRpbHMudHNcIjtpbXBvcnQgKiBhcyBlcnJvcnMgZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFVucmVhY2hhYmxlKHg6IG5ldmVyKTogbmV2ZXIge1xuXHRsb2dnZXIoKS5lcnJvcihcInVucmVhY2hhYmxlXCIsIHsgdmFsdWU6IGAke3h9YCwgc3RhY2s6IG5ldyBFcnJvcigpLnN0YWNrIH0pO1xuXHR0aHJvdyBuZXcgZXJyb3JzLlVucmVhY2hhYmxlKHgpO1xufVxuXG5leHBvcnQgY29uc3QgdGhyb3R0bGUgPSA8XG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogd2Ugd2FudCB0byBhbGxvdyBhbnkgZnVuY3Rpb25cblx0Rm4gZXh0ZW5kcyAoLi4uYXJnczogYW55KSA9PiBhbnksXG4+KFxuXHRmbjogRm4sXG5cdGRlbGF5OiBudW1iZXIsXG4pID0+IHtcblx0bGV0IGxhc3RSYW4gPSBmYWxzZTtcblx0bGV0IGxhc3RBcmdzOiBQYXJhbWV0ZXJzPEZuPiB8IG51bGwgPSBudWxsO1xuXG5cdHJldHVybiAoLi4uYXJnczogUGFyYW1ldGVyczxGbj4pID0+IHtcblx0XHRpZiAoIWxhc3RSYW4pIHtcblx0XHRcdGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0bGFzdFJhbiA9IHRydWU7XG5cdFx0XHRjb25zdCB0aW1lciA9ICgpID0+XG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdGxhc3RSYW4gPSBmYWxzZTtcblx0XHRcdFx0XHRpZiAobGFzdEFyZ3MpIHtcblx0XHRcdFx0XHRcdGZuLmFwcGx5KHRoaXMsIGxhc3RBcmdzKTtcblx0XHRcdFx0XHRcdGxhc3RSYW4gPSB0cnVlO1xuXHRcdFx0XHRcdFx0bGFzdEFyZ3MgPSBudWxsO1xuXHRcdFx0XHRcdFx0dGltZXIoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sIGRlbGF5KTtcblx0XHRcdHRpbWVyKCk7XG5cdFx0fSBlbHNlIGxhc3RBcmdzID0gYXJncztcblx0fTtcbn07XG5cbmV4cG9ydCBjbGFzcyBEZWFkbGluZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcIlByb21pc2UgZGlkIG5vdCBjb21wbGV0ZSBiZWZvcmUgZGVhZGxpbmUuXCIpO1xuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWFkbGluZTxUPihwcm9taXNlOiBQcm9taXNlPFQ+LCB0aW1lb3V0OiBudW1iZXIpOiBQcm9taXNlPFQ+IHtcblx0Y29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblx0Y29uc3Qgc2lnbmFsID0gY29udHJvbGxlci5zaWduYWw7XG5cblx0Ly8gU2V0IGEgdGltZW91dCB0byBhYm9ydCB0aGUgb3BlcmF0aW9uXG5cdGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0KTtcblxuXHRyZXR1cm4gUHJvbWlzZS5yYWNlPFQ+KFtcblx0XHRwcm9taXNlLFxuXHRcdG5ldyBQcm9taXNlPFQ+KChfLCByZWplY3QpID0+IHtcblx0XHRcdHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgKCkgPT4gcmVqZWN0KG5ldyBEZWFkbGluZUVycm9yKCkpKTtcblx0XHR9KSxcblx0XSkuZmluYWxseSgoKSA9PiB7XG5cdFx0Y2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG5cdH0pO1xufVxuXG5leHBvcnQgY2xhc3MgTG9jazxUPiB7XG5cdHByaXZhdGUgX2xvY2tlZCA9IGZhbHNlO1xuXHRwcml2YXRlIF93YWl0aW5nOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xuXG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgX3ZhbHVlOiBUKSB7fVxuXG5cdGFzeW5jIGxvY2soZm46ICh2YWx1ZTogVCkgPT4gUHJvbWlzZTx2b2lkPik6IFByb21pc2U8dm9pZD4ge1xuXHRcdGlmICh0aGlzLl9sb2NrZWQpIHtcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB0aGlzLl93YWl0aW5nLnB1c2gocmVzb2x2ZSkpO1xuXHRcdH1cblx0XHR0aGlzLl9sb2NrZWQgPSB0cnVlO1xuXG5cdFx0dHJ5IHtcblx0XHRcdGF3YWl0IGZuKHRoaXMuX3ZhbHVlKTtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dGhpcy5fbG9ja2VkID0gZmFsc2U7XG5cdFx0XHRjb25zdCBuZXh0ID0gdGhpcy5fd2FpdGluZy5zaGlmdCgpO1xuXHRcdFx0aWYgKG5leHQpIG5leHQoKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlU2VjdXJlVG9rZW4obGVuZ3RoID0gMzIpIHtcblx0Y29uc3QgYXJyYXkgPSBuZXcgVWludDhBcnJheShsZW5ndGgpO1xuXHRjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KTtcblx0cmV0dXJuIGJ0b2EoU3RyaW5nLmZyb21DaGFyQ29kZSguLi5hcnJheSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVSYW5kb21TdHJpbmcobGVuZ3RoID0gMzIpIHtcblx0Y29uc3QgY2hhcmFjdGVycyA9XG5cdFx0XCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OVwiO1xuXHRsZXQgcmVzdWx0ID0gXCJcIjtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IHJhbmRvbUluZGV4ID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2hhcmFjdGVycy5sZW5ndGgpO1xuXHRcdHJlc3VsdCArPSBjaGFyYWN0ZXJzW3JhbmRvbUluZGV4XTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvY29uZmlnLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2NvbmZpZy50c1wiO2ltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IFVuaXZlcnNhbFdlYlNvY2tldCB9IGZyb20gXCJAL2NvbW1vbi93ZWJzb2NrZXQtaW50ZXJmYWNlXCI7XG5pbXBvcnQgdHlwZSB7IEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi9hY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgQ29ubiB9IGZyb20gXCIuL2Nvbm5lY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JDb250ZXh0IH0gZnJvbSBcIi4vY29udGV4dFwiO1xuaW1wb3J0IHR5cGUgeyBBbnlEYXRhYmFzZVByb3ZpZGVyIH0gZnJvbSBcIi4vZGF0YWJhc2VcIjtcblxuZXhwb3J0IHR5cGUgSW5pdENvbnRleHQgPSBBY3RvckNvbnRleHQ8XG5cdHVuZGVmaW5lZCxcblx0dW5kZWZpbmVkLFxuXHR1bmRlZmluZWQsXG5cdHVuZGVmaW5lZCxcblx0dW5kZWZpbmVkLFxuXHR1bmRlZmluZWQsXG5cdHVuZGVmaW5lZFxuPjtcblxuZXhwb3J0IGludGVyZmFjZSBBY3RvclR5cGVzPFxuXHRUU3RhdGUsXG5cdFRDb25uUGFyYW1zLFxuXHRUQ29ublN0YXRlLFxuXHRUVmFycyxcblx0VElucHV0LFxuXHRUQXV0aERhdGEsXG5cdFREYXRhYmFzZSBleHRlbmRzIEFueURhdGFiYXNlUHJvdmlkZXIsXG4+IHtcblx0c3RhdGU/OiBUU3RhdGU7XG5cdGNvbm5QYXJhbXM/OiBUQ29ublBhcmFtcztcblx0Y29ublN0YXRlPzogVENvbm5TdGF0ZTtcblx0dmFycz86IFRWYXJzO1xuXHRpbnB1dD86IFRJbnB1dDtcblx0YXV0aERhdGE/OiBUQXV0aERhdGE7XG5cdGRhdGFiYXNlPzogVERhdGFiYXNlO1xufVxuXG4vLyBUaGlzIHNjaGVtYSBpcyB1c2VkIHRvIHZhbGlkYXRlIHRoZSBpbnB1dCBhdCBydW50aW1lLiBUaGUgZ2VuZXJpYyB0eXBlcyBhcmUgZGVmaW5lZCBiZWxvdyBpbiBgQWN0b3JDb25maWdgLlxuLy9cbi8vIFdlIGRvbid0IHVzZSBab2QgZ2VuZXJpY3Mgd2l0aCBgei5jdXN0b21gIGJlY2F1c2U6XG4vLyAoYSkgdGhlcmUgc2VlbXMgdG8gYmUgYSB3ZWlyZCBidWcgaW4gZWl0aGVyIFpvZCwgdHN1cCwgb3IgVFNDIHRoYXQgY2F1c2VzZSBleHRlcm5hbCBwYWNrYWdlcyB0byBoYXZlIGRpZmZlcmVudCB0eXBlcyBmcm9tIGB6LmluZmVyYCB0aGFuIGZyb20gd2l0aGluIHRoZSBzYW1lIHBhY2thZ2UgYW5kXG4vLyAoYikgaXQgbWFrZXMgdGhlIHR5cGUgZGVmaW5pdGlvbnMgaW5jcmVkaWJseSBkaWZmaWN1bHQgdG8gcmVhZCBhcyBvcHBvc2VkIHRvIHZhbmlsbGEgVHlwZVNjcmlwdC5cbmV4cG9ydCBjb25zdCBBY3RvckNvbmZpZ1NjaGVtYSA9IHpcblx0Lm9iamVjdCh7XG5cdFx0b25BdXRoOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvbkNyZWF0ZTogei5mdW5jdGlvbigpLm9wdGlvbmFsKCksXG5cdFx0b25TdGFydDogei5mdW5jdGlvbigpLm9wdGlvbmFsKCksXG5cdFx0b25TdG9wOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvblN0YXRlQ2hhbmdlOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvbkJlZm9yZUNvbm5lY3Q6IHouZnVuY3Rpb24oKS5vcHRpb25hbCgpLFxuXHRcdG9uQ29ubmVjdDogei5mdW5jdGlvbigpLm9wdGlvbmFsKCksXG5cdFx0b25EaXNjb25uZWN0OiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvbkJlZm9yZUFjdGlvblJlc3BvbnNlOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvbkZldGNoOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRvbldlYlNvY2tldDogei5mdW5jdGlvbigpLm9wdGlvbmFsKCksXG5cdFx0YWN0aW9uczogei5yZWNvcmQoei5mdW5jdGlvbigpKS5kZWZhdWx0KHt9KSxcblx0XHRzdGF0ZTogei5hbnkoKS5vcHRpb25hbCgpLFxuXHRcdGNyZWF0ZVN0YXRlOiB6LmZ1bmN0aW9uKCkub3B0aW9uYWwoKSxcblx0XHRjb25uU3RhdGU6IHouYW55KCkub3B0aW9uYWwoKSxcblx0XHRjcmVhdGVDb25uU3RhdGU6IHouZnVuY3Rpb24oKS5vcHRpb25hbCgpLFxuXHRcdHZhcnM6IHouYW55KCkub3B0aW9uYWwoKSxcblx0XHRkYjogei5hbnkoKS5vcHRpb25hbCgpLFxuXHRcdGNyZWF0ZVZhcnM6IHouZnVuY3Rpb24oKS5vcHRpb25hbCgpLFxuXHRcdG9wdGlvbnM6IHpcblx0XHRcdC5vYmplY3Qoe1xuXHRcdFx0XHRjcmVhdGVWYXJzVGltZW91dDogei5udW1iZXIoKS5wb3NpdGl2ZSgpLmRlZmF1bHQoNTAwMCksXG5cdFx0XHRcdGNyZWF0ZUNvbm5TdGF0ZVRpbWVvdXQ6IHoubnVtYmVyKCkucG9zaXRpdmUoKS5kZWZhdWx0KDUwMDApLFxuXHRcdFx0XHRvbkNvbm5lY3RUaW1lb3V0OiB6Lm51bWJlcigpLnBvc2l0aXZlKCkuZGVmYXVsdCg1MDAwKSxcblx0XHRcdFx0Ly8gVGhpcyBtdXN0IGJlIGxlc3MgdGhhbiBBQ1RPUl9TVE9QX1RIUkVTSE9MRF9NU1xuXHRcdFx0XHRvblN0b3BUaW1lb3V0OiB6Lm51bWJlcigpLnBvc2l0aXZlKCkuZGVmYXVsdCg1MDAwKSxcblx0XHRcdFx0c3RhdGVTYXZlSW50ZXJ2YWw6IHoubnVtYmVyKCkucG9zaXRpdmUoKS5kZWZhdWx0KDEwXzAwMCksXG5cdFx0XHRcdGFjdGlvblRpbWVvdXQ6IHoubnVtYmVyKCkucG9zaXRpdmUoKS5kZWZhdWx0KDYwXzAwMCksXG5cdFx0XHRcdC8vIE1heCB0aW1lIHRvIHdhaXQgZm9yIHdhaXRVbnRpbCBiYWNrZ3JvdW5kIHByb21pc2VzIGR1cmluZyBzaHV0ZG93blxuXHRcdFx0XHR3YWl0VW50aWxUaW1lb3V0OiB6Lm51bWJlcigpLnBvc2l0aXZlKCkuZGVmYXVsdCgxNV8wMDApLFxuXHRcdFx0XHRjb25uZWN0aW9uTGl2ZW5lc3NUaW1lb3V0OiB6Lm51bWJlcigpLnBvc2l0aXZlKCkuZGVmYXVsdCgyNTAwKSxcblx0XHRcdFx0Y29ubmVjdGlvbkxpdmVuZXNzSW50ZXJ2YWw6IHoubnVtYmVyKCkucG9zaXRpdmUoKS5kZWZhdWx0KDUwMDApLFxuXHRcdFx0XHRub1NsZWVwOiB6LmJvb2xlYW4oKS5kZWZhdWx0KGZhbHNlKSxcblx0XHRcdFx0c2xlZXBUaW1lb3V0OiB6Lm51bWJlcigpLnBvc2l0aXZlKCkuZGVmYXVsdCgzMF8wMDApLFxuXHRcdFx0fSlcblx0XHRcdC5zdHJpY3QoKVxuXHRcdFx0LmRlZmF1bHQoe30pLFxuXHR9KVxuXHQuc3RyaWN0KClcblx0LnJlZmluZShcblx0XHQoZGF0YSkgPT4gIShkYXRhLnN0YXRlICE9PSB1bmRlZmluZWQgJiYgZGF0YS5jcmVhdGVTdGF0ZSAhPT0gdW5kZWZpbmVkKSxcblx0XHR7XG5cdFx0XHRtZXNzYWdlOiBcIkNhbm5vdCBkZWZpbmUgYm90aCAnc3RhdGUnIGFuZCAnY3JlYXRlU3RhdGUnXCIsXG5cdFx0XHRwYXRoOiBbXCJzdGF0ZVwiXSxcblx0XHR9LFxuXHQpXG5cdC5yZWZpbmUoXG5cdFx0KGRhdGEpID0+XG5cdFx0XHQhKGRhdGEuY29ublN0YXRlICE9PSB1bmRlZmluZWQgJiYgZGF0YS5jcmVhdGVDb25uU3RhdGUgIT09IHVuZGVmaW5lZCksXG5cdFx0e1xuXHRcdFx0bWVzc2FnZTogXCJDYW5ub3QgZGVmaW5lIGJvdGggJ2Nvbm5TdGF0ZScgYW5kICdjcmVhdGVDb25uU3RhdGUnXCIsXG5cdFx0XHRwYXRoOiBbXCJjb25uU3RhdGVcIl0sXG5cdFx0fSxcblx0KVxuXHQucmVmaW5lKFxuXHRcdChkYXRhKSA9PiAhKGRhdGEudmFycyAhPT0gdW5kZWZpbmVkICYmIGRhdGEuY3JlYXRlVmFycyAhPT0gdW5kZWZpbmVkKSxcblx0XHR7XG5cdFx0XHRtZXNzYWdlOiBcIkNhbm5vdCBkZWZpbmUgYm90aCAndmFycycgYW5kICdjcmVhdGVWYXJzJ1wiLFxuXHRcdFx0cGF0aDogW1widmFyc1wiXSxcblx0XHR9LFxuXHQpO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdE9wdGlvbnMge1xuXHQvKipcblx0ICogVGhlIHJlcXVlc3Qgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgY29ubmVjdGlvbi5cblx0ICpcblx0ICogQGV4cGVyaW1lbnRhbFxuXHQgKi9cblx0cmVxdWVzdD86IFJlcXVlc3Q7XG59XG5cbi8vIENyZWF0ZXMgc3RhdGUgY29uZmlnXG4vL1xuLy8gVGhpcyBtdXN0IGhhdmUgb25seSBvbmUgb3IgdGhlIG90aGVyIG9yIGVsc2UgVFN0YXRlIHdpbGwgbm90IGJlIGFibGUgdG8gYmUgaW5mZXJyZWRcbi8vXG4vLyBEYXRhIHJldHVybmVkIGZyb20gdGhpcyBoYW5kbGVyIHdpbGwgYmUgYXZhaWxhYmxlIG9uIGBjLnN0YXRlYC5cbnR5cGUgQ3JlYXRlU3RhdGU8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlLFxuPiA9XG5cdHwgeyBzdGF0ZTogVFN0YXRlIH1cblx0fCB7XG5cdFx0XHRjcmVhdGVTdGF0ZTogKGM6IEluaXRDb250ZXh0LCBpbnB1dDogVElucHV0KSA9PiBUU3RhdGUgfCBQcm9taXNlPFRTdGF0ZT47XG5cdCAgfVxuXHR8IFJlY29yZDxuZXZlciwgbmV2ZXI+O1xuXG4vLyBDcmVhdGVzIGNvbm5lY3Rpb24gc3RhdGUgY29uZmlnXG4vL1xuLy8gVGhpcyBtdXN0IGhhdmUgb25seSBvbmUgb3IgdGhlIG90aGVyIG9yIGVsc2UgVFN0YXRlIHdpbGwgbm90IGJlIGFibGUgdG8gYmUgaW5mZXJyZWRcbi8vXG4vLyBEYXRhIHJldHVybmVkIGZyb20gdGhpcyBoYW5kbGVyIHdpbGwgYmUgYXZhaWxhYmxlIG9uIGBjLmNvbm4uc3RhdGVgLlxudHlwZSBDcmVhdGVDb25uU3RhdGU8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlLFxuPiA9XG5cdHwgeyBjb25uU3RhdGU6IFRDb25uU3RhdGUgfVxuXHR8IHtcblx0XHRcdGNyZWF0ZUNvbm5TdGF0ZTogKFxuXHRcdFx0XHRjOiBJbml0Q29udGV4dCxcblx0XHRcdFx0b3B0czogT25Db25uZWN0T3B0aW9ucyxcblx0XHRcdFx0cGFyYW1zOiBUQ29ublBhcmFtcyxcblx0XHRcdCkgPT4gVENvbm5TdGF0ZSB8IFByb21pc2U8VENvbm5TdGF0ZT47XG5cdCAgfVxuXHR8IFJlY29yZDxuZXZlciwgbmV2ZXI+O1xuXG4vLyBDcmVhdGVzIHZhcnMgY29uZmlnXG4vL1xuLy8gVGhpcyBtdXN0IGhhdmUgb25seSBvbmUgb3IgdGhlIG90aGVyIG9yIGVsc2UgVFN0YXRlIHdpbGwgbm90IGJlIGFibGUgdG8gYmUgaW5mZXJyZWRcbi8qKlxuICogQGV4cGVyaW1lbnRhbFxuICovXG50eXBlIENyZWF0ZVZhcnM8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlLFxuPiA9XG5cdHwge1xuXHRcdFx0LyoqXG5cdFx0XHQgKiBAZXhwZXJpbWVudGFsXG5cdFx0XHQgKi9cblx0XHRcdHZhcnM6IFRWYXJzO1xuXHQgIH1cblx0fCB7XG5cdFx0XHQvKipcblx0XHRcdCAqIEBleHBlcmltZW50YWxcblx0XHRcdCAqL1xuXHRcdFx0Y3JlYXRlVmFyczogKGM6IEluaXRDb250ZXh0LCBkcml2ZXJDdHg6IGFueSkgPT4gVFZhcnMgfCBQcm9taXNlPFRWYXJzPjtcblx0ICB9XG5cdHwgUmVjb3JkPG5ldmVyLCBuZXZlcj47XG5cbi8vIENyZWF0ZXMgYXV0aCBjb25maWdcbi8vXG4vLyBUaGlzIG11c3QgaGF2ZSBvbmx5IG9uZSBvciB0aGUgb3RoZXIgb3IgZWxzZSBUQXV0aERhdGEgd2lsbCBub3QgYmUgYWJsZSB0byBiZSBpbmZlcnJlZFxudHlwZSBPbkF1dGg8VENvbm5QYXJhbXMsIFRBdXRoRGF0YT4gPVxuXHR8IHtcblx0XHRcdC8qKlxuXHRcdFx0ICogQ2FsbGVkIG9uIHRoZSBIVFRQIHNlcnZlciBiZWZvcmUgY2xpZW50cyBjYW4gaW50ZXJhY3Qgd2l0aCB0aGUgYWN0b3IuXG5cdFx0XHQgKlxuXHRcdFx0ICogT25seSBjYWxsZWQgZm9yIHB1YmxpYyBlbmRwb2ludHMuIENhbGxzIHRvIGFjdG9ycyBmcm9tIHdpdGhpbiB0aGUgYmFja2VuZFxuXHRcdFx0ICogZG8gbm90IHRyaWdnZXIgdGhpcyBoYW5kbGVyLlxuXHRcdFx0ICpcblx0XHRcdCAqIERhdGEgcmV0dXJuZWQgZnJvbSB0aGlzIGhhbmRsZXIgd2lsbCBiZSBhdmFpbGFibGUgb24gYGMuY29ubi5hdXRoYC5cblx0XHRcdCAqXG5cdFx0XHQgKiBUaGlzIGZ1bmN0aW9uIGlzIHJlcXVpcmVkIGZvciBhbnkgcHVibGljIEhUVFAgZW5kcG9pbnQgYWNjZXNzLiBVc2UgdGhpcyBob29rXG5cdFx0XHQgKiB0byB2YWxpZGF0ZSBjbGllbnQgY3JlZGVudGlhbHMgYW5kIHJldHVybiBhdXRoZW50aWNhdGlvbiBkYXRhIHRoYXQgd2lsbCBiZVxuXHRcdFx0ICogYXZhaWxhYmxlIG9uIGNvbm5lY3Rpb25zLiBUaGlzIHJ1bnMgb24gdGhlIEhUVFAgc2VydmVyIChub3QgdGhlIGFjdG9yKVxuXHRcdFx0ICogaW4gb3JkZXIgdG8gcmVkdWNlIGxvYWQgb24gdGhlIGFjdG9yICYgcHJldmVudCBkZW5pYWwgb2Ygc2VydmVyIGF0dGFja3Ncblx0XHRcdCAqIGFnYWluc3QgaW5kaXZpZHVhbCBhY3RvcnMuXG5cdFx0XHQgKlxuXHRcdFx0ICogSWYgeW91IG5lZWQgYWNjZXNzIHRvIGFjdG9yIHN0YXRlIGZvciBhdXRoZW50aWNhdGlvbiwgdXNlIG9uQmVmb3JlQ29ubmVjdFxuXHRcdFx0ICogd2l0aCBhbiBlbXB0eSBvbkF1dGggZnVuY3Rpb24gaW5zdGVhZC5cblx0XHRcdCAqXG5cdFx0XHQgKiBZb3UgY2FuIGFsc28gcHJvdmlkZSB5b3VyIG93biBhdXRoZW50aWNhdGlvbiBtaWRkbGV3YXJlIG9uIHlvdXIgcm91dGVyIGlmIHlvdVxuXHRcdFx0ICogY2hvb3NlLCB0aGVuIHVzZSBvbkF1dGggdG8gcGFzcyB0aGUgYXV0aGVudGljYXRpb24gZGF0YSAoZS5nLiB1c2VyIElEKSB0byB0aGVcblx0XHRcdCAqIGFjdG9yIGl0c2VsZi5cblx0XHRcdCAqXG5cdFx0XHQgKiBAcGFyYW0gb3B0cyBBdXRoZW50aWNhdGlvbiBvcHRpb25zIGluY2x1ZGluZyByZXF1ZXN0IGFuZCBpbnRlbnRcblx0XHRcdCAqIEByZXR1cm5zIEF1dGhlbnRpY2F0aW9uIGRhdGEgdG8gYXR0YWNoIHRvIGNvbm5lY3Rpb25zIChtdXN0IGJlIHNlcmlhbGl6YWJsZSlcblx0XHRcdCAqIEB0aHJvd3MgVGhyb3cgYW4gZXJyb3IgdG8gZGVueSBhY2Nlc3MgdG8gdGhlIGFjdG9yXG5cdFx0XHQgKi9cblx0XHRcdG9uQXV0aDogKFxuXHRcdFx0XHRvcHRzOiBPbkF1dGhPcHRpb25zLFxuXHRcdFx0XHRwYXJhbXM6IFRDb25uUGFyYW1zLFxuXHRcdFx0KSA9PiBUQXV0aERhdGEgfCBQcm9taXNlPFRBdXRoRGF0YT47XG5cdCAgfVxuXHR8IFJlY29yZDxuZXZlciwgbmV2ZXI+O1xuXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbnM8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlIGV4dGVuZHMgQW55RGF0YWJhc2VQcm92aWRlcixcbj4ge1xuXHRbQWN0aW9uOiBzdHJpbmddOiAoXG5cdFx0YzogQWN0aW9uQ29udGV4dDxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0XHQuLi5hcmdzOiBhbnlbXVxuXHQpID0+IGFueTtcbn1cblxuLy9leHBvcnQgdHlwZSBBY3RvckNvbmZpZzxUU3RhdGUsIFRDb25uUGFyYW1zLCBUQ29ublN0YXRlLCBUVmFycywgVElucHV0LCBUQXV0aERhdGE+ID0gQmFzZUFjdG9yQ29uZmlnPFRTdGF0ZSwgVENvbm5QYXJhbXMsIFRDb25uU3RhdGUsIFRWYXJzLCBUSW5wdXQsIFRBdXRoRGF0YT4gJlxuLy9cdEFjdG9yQ29uZmlnTGlmZWN5Y2xlPFRTdGF0ZSwgVENvbm5QYXJhbXMsIFRDb25uU3RhdGUsIFRWYXJzLCBUSW5wdXQsIFRBdXRoRGF0YT4gJlxuLy9cdENyZWF0ZVN0YXRlPFRTdGF0ZSwgVENvbm5QYXJhbXMsIFRDb25uU3RhdGUsIFRWYXJzLCBUSW5wdXQsIFRBdXRoRGF0YT4gJlxuLy9cdENyZWF0ZUNvbm5TdGF0ZTxUU3RhdGUsIFRDb25uUGFyYW1zLCBUQ29ublN0YXRlLCBUVmFycywgVElucHV0LCBUQXV0aERhdGE+O1xuXG4vKipcbiAqIEBleHBlcmltZW50YWxcbiAqL1xuZXhwb3J0IHR5cGUgQXV0aEludGVudCA9IFwiZ2V0XCIgfCBcImNyZWF0ZVwiIHwgXCJjb25uZWN0XCIgfCBcImFjdGlvblwiIHwgXCJtZXNzYWdlXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25BdXRoT3B0aW9ucyB7XG5cdHJlcXVlc3Q6IFJlcXVlc3Q7XG5cdC8qKlxuXHQgKiBAZXhwZXJpbWVudGFsXG5cdCAqL1xuXHRpbnRlbnRzOiBTZXQ8QXV0aEludGVudD47XG59XG5cbmludGVyZmFjZSBCYXNlQWN0b3JDb25maWc8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlIGV4dGVuZHMgQW55RGF0YWJhc2VQcm92aWRlcixcblx0VEFjdGlvbnMgZXh0ZW5kcyBBY3Rpb25zPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4sXG4+IHtcblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIHRoZSBhY3RvciBpcyBmaXJzdCBpbml0aWFsaXplZC5cblx0ICpcblx0ICogVXNlIHRoaXMgaG9vayB0byBpbml0aWFsaXplIHlvdXIgYWN0b3IncyBzdGF0ZS5cblx0ICogVGhpcyBpcyBjYWxsZWQgYmVmb3JlIGFueSBvdGhlciBsaWZlY3ljbGUgaG9va3MuXG5cdCAqL1xuXHRvbkNyZWF0ZT86IChcblx0XHRjOiBBY3RvckNvbnRleHQ8XG5cdFx0XHRUU3RhdGUsXG5cdFx0XHRUQ29ublBhcmFtcyxcblx0XHRcdFRDb25uU3RhdGUsXG5cdFx0XHRUVmFycyxcblx0XHRcdFRJbnB1dCxcblx0XHRcdFRBdXRoRGF0YSxcblx0XHRcdFREYXRhYmFzZVxuXHRcdD4sXG5cdFx0aW5wdXQ6IFRJbnB1dCxcblx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPjtcblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gdGhlIGFjdG9yIGlzIHN0YXJ0ZWQgYW5kIHJlYWR5IHRvIHJlY2VpdmUgY29ubmVjdGlvbnMgYW5kIGFjdGlvbi5cblx0ICpcblx0ICogVXNlIHRoaXMgaG9vayB0byBpbml0aWFsaXplIHJlc291cmNlcyBuZWVkZWQgZm9yIHRoZSBhY3RvcidzIG9wZXJhdGlvblxuXHQgKiAodGltZXJzLCBleHRlcm5hbCBjb25uZWN0aW9ucywgZXRjLilcblx0ICpcblx0ICogQHJldHVybnMgVm9pZCBvciBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHN0YXJ0dXAgaXMgY29tcGxldGVcblx0ICovXG5cdG9uU3RhcnQ/OiAoXG5cdFx0YzogQWN0b3JDb250ZXh0PFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+LFxuXHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG5cdC8qKlxuXHQgKiBDYWxsZWQgd2hlbiB0aGUgYWN0b3IgaXMgc3RvcHBpbmcgb3Igc2xlZXBpbmcuXG5cdCAqXG5cdCAqIFVzZSB0aGlzIGhvb2sgdG8gY2xlYW4gdXAgcmVzb3VyY2VzLCBzYXZlIHN0YXRlLCBvciBwZXJmb3JtXG5cdCAqIGFueSBzaHV0ZG93biBvcGVyYXRpb25zIGJlZm9yZSB0aGUgYWN0b3Igc2xlZXBzIG9yIHN0b3BzLlxuXHQgKlxuXHQgKiBOb3Qgc3VwcG9ydGVkIG9uIGFsbCBwbGF0Zm9ybXMuXG5cdCAqXG5cdCAqIEByZXR1cm5zIFZvaWQgb3IgYSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBzaHV0ZG93biBpcyBjb21wbGV0ZVxuXHQgKi9cblx0b25TdG9wPzogKFxuXHRcdGM6IEFjdG9yQ29udGV4dDxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPjtcblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gdGhlIGFjdG9yJ3Mgc3RhdGUgY2hhbmdlcy5cblx0ICpcblx0ICogVXNlIHRoaXMgaG9vayB0byByZWFjdCB0byBzdGF0ZSBjaGFuZ2VzLCBzdWNoIGFzIHVwZGF0aW5nXG5cdCAqIGV4dGVybmFsIHN5c3RlbXMgb3IgdHJpZ2dlcmluZyBldmVudHMuXG5cdCAqXG5cdCAqIE5vdGU6IFN0YXRlIGNoYW5nZXMgbWFkZSB3aXRoaW4gdGhpcyBob29rIHdpbGwgTk9UIHRyaWdnZXJcblx0ICogYW5vdGhlciBvblN0YXRlQ2hhbmdlIGNhbGwsIHByZXZlbnRpbmcgaW5maW5pdGUgcmVjdXJzaW9uLlxuXHQgKlxuXHQgKiBAcGFyYW0gbmV3U3RhdGUgVGhlIHVwZGF0ZWQgc3RhdGVcblx0ICovXG5cdG9uU3RhdGVDaGFuZ2U/OiAoXG5cdFx0YzogQWN0b3JDb250ZXh0PFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+LFxuXHRcdG5ld1N0YXRlOiBUU3RhdGUsXG5cdCkgPT4gdm9pZDtcblxuXHQvKipcblx0ICogQ2FsbGVkIGJlZm9yZSBhIGNsaWVudCBjb25uZWN0cyB0byB0aGUgYWN0b3IuXG5cdCAqXG5cdCAqIFVubGlrZSBvbkF1dGgsIHRoaXMgaGFuZGxlciBpcyBzdGlsbCBjYWxsZWQgZm9yIGJvdGggaW50ZXJuYWwgYW5kXG5cdCAqIHB1YmxpYyBjbGllbnRzLlxuXHQgKlxuXHQgKiBVc2UgdGhpcyBob29rIHRvIGRldGVybWluZSBpZiBhIGNvbm5lY3Rpb24gc2hvdWxkIGJlIGFjY2VwdGVkXG5cdCAqIGFuZCB0byBpbml0aWFsaXplIGNvbm5lY3Rpb24tc3BlY2lmaWMgc3RhdGUuIFVubGlrZSBvbkF1dGgsIHRoaXMgcnVuc1xuXHQgKiBvbiB0aGUgYWN0b3IgYW5kIGhhcyBhY2Nlc3MgdG8gYWN0b3Igc3RhdGUsIGJ1dCB1c2VzIHNsaWdodGx5XG5cdCAqIG1vcmUgcmVzb3VyY2VzIG9uIHRoZSBhY3RvciByYXRoZXIgdGhhbiBhdXRoZW50aWNhdGluZyB3aXRoIG9uQXV0aC5cblx0ICpcblx0ICogRm9yIGF1dGhlbnRpY2F0aW9uIHdpdGhvdXQgYWN0b3Igc3RhdGUgYWNjZXNzLCBwcmVmZXIgb25BdXRoLlxuXHQgKlxuXHQgKiBGb3IgYXV0aGVudGljYXRpb24gd2l0aCBhY3RvciBzdGF0ZSwgdXNlIG9uQmVmb3JlQ29ubmVjdCB3aXRoIGFuIGVtcHR5XG5cdCAqIG9uQXV0aCBoYW5kbGVyLlxuXHQgKlxuXHQgKiBAcGFyYW0gb3B0cyBDb25uZWN0aW9uIHBhcmFtZXRlcnMgaW5jbHVkaW5nIGNsaWVudC1wcm92aWRlZCBkYXRhXG5cdCAqIEByZXR1cm5zIFRoZSBpbml0aWFsIGNvbm5lY3Rpb24gc3RhdGUgb3IgYSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gaXRcblx0ICogQHRocm93cyBUaHJvdyBhbiBlcnJvciB0byByZWplY3QgdGhlIGNvbm5lY3Rpb25cblx0ICovXG5cdG9uQmVmb3JlQ29ubmVjdD86IChcblx0XHRjOiBBY3RvckNvbnRleHQ8XG5cdFx0XHRUU3RhdGUsXG5cdFx0XHRUQ29ublBhcmFtcyxcblx0XHRcdFRDb25uU3RhdGUsXG5cdFx0XHRUVmFycyxcblx0XHRcdFRJbnB1dCxcblx0XHRcdFRBdXRoRGF0YSxcblx0XHRcdFREYXRhYmFzZVxuXHRcdD4sXG5cdFx0b3B0czogT25Db25uZWN0T3B0aW9ucyxcblx0XHRwYXJhbXM6IFRDb25uUGFyYW1zLFxuXHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG5cdC8qKlxuXHQgKiBDYWxsZWQgd2hlbiBhIGNsaWVudCBzdWNjZXNzZnVsbHkgY29ubmVjdHMgdG8gdGhlIGFjdG9yLlxuXHQgKlxuXHQgKiBVc2UgdGhpcyBob29rIHRvIHBlcmZvcm0gYWN0aW9ucyB3aGVuIGEgY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZCxcblx0ICogc3VjaCBhcyBzZW5kaW5nIGluaXRpYWwgZGF0YSBvciB1cGRhdGluZyB0aGUgYWN0b3IncyBzdGF0ZS5cblx0ICpcblx0ICogQHBhcmFtIGNvbm4gVGhlIGNvbm5lY3Rpb24gb2JqZWN0XG5cdCAqIEByZXR1cm5zIFZvaWQgb3IgYSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBjb25uZWN0aW9uIGhhbmRsaW5nIGlzIGNvbXBsZXRlXG5cdCAqL1xuXHRvbkNvbm5lY3Q/OiAoXG5cdFx0YzogQWN0b3JDb250ZXh0PFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+LFxuXHRcdGNvbm46IENvbm48XG5cdFx0XHRUU3RhdGUsXG5cdFx0XHRUQ29ublBhcmFtcyxcblx0XHRcdFRDb25uU3RhdGUsXG5cdFx0XHRUVmFycyxcblx0XHRcdFRJbnB1dCxcblx0XHRcdFRBdXRoRGF0YSxcblx0XHRcdFREYXRhYmFzZVxuXHRcdD4sXG5cdCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIGEgY2xpZW50IGRpc2Nvbm5lY3RzIGZyb20gdGhlIGFjdG9yLlxuXHQgKlxuXHQgKiBVc2UgdGhpcyBob29rIHRvIGNsZWFuIHVwIHJlc291cmNlcyBhc3NvY2lhdGVkIHdpdGggdGhlIGNvbm5lY3Rpb25cblx0ICogb3IgdXBkYXRlIHRoZSBhY3RvcidzIHN0YXRlLlxuXHQgKlxuXHQgKiBAcGFyYW0gY29ubiBUaGUgY29ubmVjdGlvbiB0aGF0IGlzIGJlaW5nIGNsb3NlZFxuXHQgKiBAcmV0dXJucyBWb2lkIG9yIGEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gZGlzY29ubmVjdCBoYW5kbGluZyBpcyBjb21wbGV0ZVxuXHQgKi9cblx0b25EaXNjb25uZWN0PzogKFxuXHRcdGM6IEFjdG9yQ29udGV4dDxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0XHRjb25uOiBDb25uPFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+LFxuXHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG5cdC8qKlxuXHQgKiBDYWxsZWQgYmVmb3JlIHNlbmRpbmcgYW4gYWN0aW9uIHJlc3BvbnNlIHRvIHRoZSBjbGllbnQuXG5cdCAqXG5cdCAqIFVzZSB0aGlzIGhvb2sgdG8gbW9kaWZ5IG9yIHRyYW5zZm9ybSB0aGUgb3V0cHV0IG9mIGFuIGFjdGlvbiBiZWZvcmUgaXQncyBzZW50XG5cdCAqIHRvIHRoZSBjbGllbnQuIFRoaXMgaXMgdXNlZnVsIGZvciBmb3JtYXR0aW5nIHJlc3BvbnNlcywgYWRkaW5nIG1ldGFkYXRhLFxuXHQgKiBvciBhcHBseWluZyB0cmFuc2Zvcm1hdGlvbnMgdG8gdGhlIG91dHB1dC5cblx0ICpcblx0ICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGFjdGlvbiB0aGF0IHdhcyBjYWxsZWRcblx0ICogQHBhcmFtIGFyZ3MgVGhlIGFyZ3VtZW50cyB0aGF0IHdlcmUgcGFzc2VkIHRvIHRoZSBhY3Rpb25cblx0ICogQHBhcmFtIG91dHB1dCBUaGUgb3V0cHV0IHRoYXQgd2lsbCBiZSBzZW50IHRvIHRoZSBjbGllbnRcblx0ICogQHJldHVybnMgVGhlIG1vZGlmaWVkIG91dHB1dCB0byBzZW5kIHRvIHRoZSBjbGllbnRcblx0ICovXG5cdG9uQmVmb3JlQWN0aW9uUmVzcG9uc2U/OiA8T3V0Pihcblx0XHRjOiBBY3RvckNvbnRleHQ8XG5cdFx0XHRUU3RhdGUsXG5cdFx0XHRUQ29ublBhcmFtcyxcblx0XHRcdFRDb25uU3RhdGUsXG5cdFx0XHRUVmFycyxcblx0XHRcdFRJbnB1dCxcblx0XHRcdFRBdXRoRGF0YSxcblx0XHRcdFREYXRhYmFzZVxuXHRcdD4sXG5cdFx0bmFtZTogc3RyaW5nLFxuXHRcdGFyZ3M6IHVua25vd25bXSxcblx0XHRvdXRwdXQ6IE91dCxcblx0KSA9PiBPdXQgfCBQcm9taXNlPE91dD47XG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIGEgcmF3IEhUVFAgcmVxdWVzdCBpcyBtYWRlIHRvIHRoZSBhY3Rvci5cblx0ICpcblx0ICogVGhpcyBoYW5kbGVyIHJlY2VpdmVzIHJhdyBIVFRQIHJlcXVlc3RzIG1hZGUgdG8gYC9hY3RvcnMve2FjdG9yTmFtZX0vaHR0cC8qYCBlbmRwb2ludHMuXG5cdCAqIFVzZSB0aGlzIGhvb2sgdG8gaGFuZGxlIGN1c3RvbSBIVFRQIHBhdHRlcm5zLCBSRVNUIEFQSXMsIG9yIG90aGVyIEhUVFAtYmFzZWQgcHJvdG9jb2xzLlxuXHQgKlxuXHQgKiBAcGFyYW0gcmVxdWVzdCBUaGUgcmF3IEhUVFAgcmVxdWVzdCBvYmplY3Rcblx0ICogQHJldHVybnMgQSBSZXNwb25zZSBvYmplY3QgdG8gc2VuZCBiYWNrLCBvciB2b2lkIHRvIGNvbnRpbnVlIHdpdGggZGVmYXVsdCByb3V0aW5nXG5cdCAqL1xuXHRvbkZldGNoPzogKFxuXHRcdGM6IEFjdG9yQ29udGV4dDxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0XHRyZXF1ZXN0OiBSZXF1ZXN0LFxuXHRcdG9wdHM6IHsgYXV0aDogVEF1dGhEYXRhIH0sXG5cdCkgPT4gUmVzcG9uc2UgfCBQcm9taXNlPFJlc3BvbnNlPjtcblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gYSByYXcgV2ViU29ja2V0IGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQgdG8gdGhlIGFjdG9yLlxuXHQgKlxuXHQgKiBUaGlzIGhhbmRsZXIgcmVjZWl2ZXMgV2ViU29ja2V0IGNvbm5lY3Rpb25zIG1hZGUgdG8gYC9hY3RvcnMve2FjdG9yTmFtZX0vd2Vic29ja2V0LypgIGVuZHBvaW50cy5cblx0ICogVXNlIHRoaXMgaG9vayB0byBoYW5kbGUgY3VzdG9tIFdlYlNvY2tldCBwcm90b2NvbHMsIGJpbmFyeSBzdHJlYW1zLCBvciBvdGhlciBXZWJTb2NrZXQtYmFzZWQgY29tbXVuaWNhdGlvbi5cblx0ICpcblx0ICogQHBhcmFtIHdlYnNvY2tldCBUaGUgcmF3IFdlYlNvY2tldCBjb25uZWN0aW9uXG5cdCAqIEBwYXJhbSByZXF1ZXN0IFRoZSBvcmlnaW5hbCBIVFRQIHVwZ3JhZGUgcmVxdWVzdFxuXHQgKi9cblx0b25XZWJTb2NrZXQ/OiAoXG5cdFx0YzogQWN0b3JDb250ZXh0PFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+LFxuXHRcdHdlYnNvY2tldDogVW5pdmVyc2FsV2ViU29ja2V0LFxuXHRcdG9wdHM6IHsgcmVxdWVzdDogUmVxdWVzdDsgYXV0aDogVEF1dGhEYXRhIH0sXG5cdCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG5cblx0YWN0aW9uczogVEFjdGlvbnM7XG59XG5cbnR5cGUgQWN0b3JEYXRhYmFzZUNvbmZpZzxURGF0YWJhc2UgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyPiA9XG5cdHwge1xuXHRcdFx0LyoqXG5cdFx0XHQgKiBAZXhwZXJpbWVudGFsXG5cdFx0XHQgKi9cblx0XHRcdGRiOiBURGF0YWJhc2U7XG5cdCAgfVxuXHR8IFJlY29yZDxuZXZlciwgbmV2ZXI+O1xuXG4vLyAxLiBJbmZlciBzY2hlbWFcbi8vIDIuIE9taXQga2V5cyB0aGF0IHdlJ2xsIG1hbnVhbGx5IGRlZmluZSAoYmVjYXVzZSBvZiBnZW5lcmljcylcbi8vIDMuIERlZmluZSBvdXIgb3duIHR5cGVzIHRoYXQgaGF2ZSBnZW5lcmljIGNvbnN0cmFpbnRzXG5leHBvcnQgdHlwZSBBY3RvckNvbmZpZzxcblx0VFN0YXRlLFxuXHRUQ29ublBhcmFtcyxcblx0VENvbm5TdGF0ZSxcblx0VFZhcnMsXG5cdFRJbnB1dCxcblx0VEF1dGhEYXRhLFxuXHRURGF0YWJhc2UgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyLFxuPiA9IE9taXQ8XG5cdHouaW5mZXI8dHlwZW9mIEFjdG9yQ29uZmlnU2NoZW1hPixcblx0fCBcImFjdGlvbnNcIlxuXHR8IFwib25BdXRoXCJcblx0fCBcIm9uQ3JlYXRlXCJcblx0fCBcIm9uU3RhcnRcIlxuXHR8IFwib25TdGF0ZUNoYW5nZVwiXG5cdHwgXCJvbkJlZm9yZUNvbm5lY3RcIlxuXHR8IFwib25Db25uZWN0XCJcblx0fCBcIm9uRGlzY29ubmVjdFwiXG5cdHwgXCJvbkJlZm9yZUFjdGlvblJlc3BvbnNlXCJcblx0fCBcIm9uRmV0Y2hcIlxuXHR8IFwib25XZWJTb2NrZXRcIlxuXHR8IFwic3RhdGVcIlxuXHR8IFwiY3JlYXRlU3RhdGVcIlxuXHR8IFwiY29ublN0YXRlXCJcblx0fCBcImNyZWF0ZUNvbm5TdGF0ZVwiXG5cdHwgXCJ2YXJzXCJcblx0fCBcImNyZWF0ZVZhcnNcIlxuXHR8IFwiZGJcIlxuPiAmXG5cdEJhc2VBY3RvckNvbmZpZzxcblx0XHRUU3RhdGUsXG5cdFx0VENvbm5QYXJhbXMsXG5cdFx0VENvbm5TdGF0ZSxcblx0XHRUVmFycyxcblx0XHRUSW5wdXQsXG5cdFx0VEF1dGhEYXRhLFxuXHRcdFREYXRhYmFzZSxcblx0XHRBY3Rpb25zPFxuXHRcdFx0VFN0YXRlLFxuXHRcdFx0VENvbm5QYXJhbXMsXG5cdFx0XHRUQ29ublN0YXRlLFxuXHRcdFx0VFZhcnMsXG5cdFx0XHRUSW5wdXQsXG5cdFx0XHRUQXV0aERhdGEsXG5cdFx0XHRURGF0YWJhc2Vcblx0XHQ+XG5cdD4gJlxuXHRPbkF1dGg8VENvbm5QYXJhbXMsIFRBdXRoRGF0YT4gJlxuXHRDcmVhdGVTdGF0ZTxcblx0XHRUU3RhdGUsXG5cdFx0VENvbm5QYXJhbXMsXG5cdFx0VENvbm5TdGF0ZSxcblx0XHRUVmFycyxcblx0XHRUSW5wdXQsXG5cdFx0VEF1dGhEYXRhLFxuXHRcdFREYXRhYmFzZVxuXHQ+ICZcblx0Q3JlYXRlQ29ublN0YXRlPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4gJlxuXHRDcmVhdGVWYXJzPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4gJlxuXHRBY3RvckRhdGFiYXNlQ29uZmlnPFREYXRhYmFzZT47XG5cbi8vIFNlZSBkZXNjcmlwdGlvbiBvbiBgQWN0b3JDb25maWdgXG5leHBvcnQgdHlwZSBBY3RvckNvbmZpZ0lucHV0PFxuXHRUU3RhdGUgPSB1bmRlZmluZWQsXG5cdFRDb25uUGFyYW1zID0gdW5kZWZpbmVkLFxuXHRUQ29ublN0YXRlID0gdW5kZWZpbmVkLFxuXHRUVmFycyA9IHVuZGVmaW5lZCxcblx0VElucHV0ID0gdW5kZWZpbmVkLFxuXHRUQXV0aERhdGEgPSB1bmRlZmluZWQsXG5cdFREYXRhYmFzZSBleHRlbmRzIEFueURhdGFiYXNlUHJvdmlkZXIgPSB1bmRlZmluZWQsXG5cdFRBY3Rpb25zIGV4dGVuZHMgQWN0aW9uczxcblx0XHRUU3RhdGUsXG5cdFx0VENvbm5QYXJhbXMsXG5cdFx0VENvbm5TdGF0ZSxcblx0XHRUVmFycyxcblx0XHRUSW5wdXQsXG5cdFx0VEF1dGhEYXRhLFxuXHRcdFREYXRhYmFzZVxuXHQ+ID0gUmVjb3JkPG5ldmVyLCBuZXZlcj4sXG4+ID0ge1xuXHR0eXBlcz86IEFjdG9yVHlwZXM8XG5cdFx0VFN0YXRlLFxuXHRcdFRDb25uUGFyYW1zLFxuXHRcdFRDb25uU3RhdGUsXG5cdFx0VFZhcnMsXG5cdFx0VElucHV0LFxuXHRcdFRBdXRoRGF0YSxcblx0XHRURGF0YWJhc2Vcblx0Pjtcbn0gJiBPbWl0PFxuXHR6LmlucHV0PHR5cGVvZiBBY3RvckNvbmZpZ1NjaGVtYT4sXG5cdHwgXCJhY3Rpb25zXCJcblx0fCBcIm9uQXV0aFwiXG5cdHwgXCJvbkNyZWF0ZVwiXG5cdHwgXCJvblN0YXJ0XCJcblx0fCBcIm9uU3RvcFwiXG5cdHwgXCJvblN0YXRlQ2hhbmdlXCJcblx0fCBcIm9uQmVmb3JlQ29ubmVjdFwiXG5cdHwgXCJvbkNvbm5lY3RcIlxuXHR8IFwib25EaXNjb25uZWN0XCJcblx0fCBcIm9uQmVmb3JlQWN0aW9uUmVzcG9uc2VcIlxuXHR8IFwib25GZXRjaFwiXG5cdHwgXCJvbldlYlNvY2tldFwiXG5cdHwgXCJzdGF0ZVwiXG5cdHwgXCJjcmVhdGVTdGF0ZVwiXG5cdHwgXCJjb25uU3RhdGVcIlxuXHR8IFwiY3JlYXRlQ29ublN0YXRlXCJcblx0fCBcInZhcnNcIlxuXHR8IFwiY3JlYXRlVmFyc1wiXG5cdHwgXCJkYlwiXG4+ICZcblx0QmFzZUFjdG9yQ29uZmlnPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlLFxuXHRcdFRBY3Rpb25zXG5cdD4gJlxuXHRPbkF1dGg8VENvbm5QYXJhbXMsIFRBdXRoRGF0YT4gJlxuXHRDcmVhdGVTdGF0ZTxcblx0XHRUU3RhdGUsXG5cdFx0VENvbm5QYXJhbXMsXG5cdFx0VENvbm5TdGF0ZSxcblx0XHRUVmFycyxcblx0XHRUSW5wdXQsXG5cdFx0VEF1dGhEYXRhLFxuXHRcdFREYXRhYmFzZVxuXHQ+ICZcblx0Q3JlYXRlQ29ublN0YXRlPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4gJlxuXHRDcmVhdGVWYXJzPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4gJlxuXHRBY3RvckRhdGFiYXNlQ29uZmlnPFREYXRhYmFzZT47XG5cbi8vIEZvciB0ZXN0aW5nIHR5cGUgZGVmaW5pdGlvbnM6XG5leHBvcnQgZnVuY3Rpb24gdGVzdDxcblx0VFN0YXRlLFxuXHRUQ29ublBhcmFtcyxcblx0VENvbm5TdGF0ZSxcblx0VFZhcnMsXG5cdFRJbnB1dCxcblx0VEF1dGhEYXRhLFxuXHRURGF0YWJhc2UgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyLFxuXHRUQWN0aW9ucyBleHRlbmRzIEFjdGlvbnM8XG5cdFx0VFN0YXRlLFxuXHRcdFRDb25uUGFyYW1zLFxuXHRcdFRDb25uU3RhdGUsXG5cdFx0VFZhcnMsXG5cdFx0VElucHV0LFxuXHRcdFRBdXRoRGF0YSxcblx0XHRURGF0YWJhc2Vcblx0Pixcbj4oXG5cdGlucHV0OiBBY3RvckNvbmZpZ0lucHV0PFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlLFxuXHRcdFRBY3Rpb25zXG5cdD4sXG4pOiBBY3RvckNvbmZpZzxcblx0VFN0YXRlLFxuXHRUQ29ublBhcmFtcyxcblx0VENvbm5TdGF0ZSxcblx0VFZhcnMsXG5cdFRJbnB1dCxcblx0VEF1dGhEYXRhLFxuXHRURGF0YWJhc2Vcbj4ge1xuXHRjb25zdCBjb25maWcgPSBBY3RvckNvbmZpZ1NjaGVtYS5wYXJzZShpbnB1dCkgYXMgQWN0b3JDb25maWc8XG5cdFx0VFN0YXRlLFxuXHRcdFRDb25uUGFyYW1zLFxuXHRcdFRDb25uU3RhdGUsXG5cdFx0VFZhcnMsXG5cdFx0VElucHV0LFxuXHRcdFRBdXRoRGF0YSxcblx0XHRURGF0YWJhc2Vcblx0Pjtcblx0cmV0dXJuIGNvbmZpZztcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2luc3RhbmNlLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2luc3RhbmNlLnRzXCI7aW1wb3J0ICogYXMgY2JvciBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgaW52YXJpYW50IGZyb20gXCJpbnZhcmlhbnRcIjtcbmltcG9ydCBvbkNoYW5nZSBmcm9tIFwib24tY2hhbmdlXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yS2V5IH0gZnJvbSBcIkAvYWN0b3IvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSBcIkAvY29tbW9uL2xvZ1wiO1xuaW1wb3J0IHsgaXNDYm9yU2VyaWFsaXphYmxlLCBzdHJpbmdpZnlFcnJvciB9IGZyb20gXCJAL2NvbW1vbi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBVbml2ZXJzYWxXZWJTb2NrZXQgfSBmcm9tIFwiQC9jb21tb24vd2Vic29ja2V0LWludGVyZmFjZVwiO1xuaW1wb3J0IHsgQWN0b3JJbnNwZWN0b3IgfSBmcm9tIFwiQC9pbnNwZWN0b3IvYWN0b3JcIjtcbmltcG9ydCB0eXBlIHsgUmVnaXN0cnkgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB0eXBlICogYXMgYmFyZVNjaGVtYSBmcm9tIFwiQC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvbW9kXCI7XG5pbXBvcnQgeyBQRVJTSVNURURfQUNUT1JfVkVSU0lPTkVEIH0gZnJvbSBcIkAvc2NoZW1hcy9hY3Rvci1wZXJzaXN0L3ZlcnNpb25lZFwiO1xuaW1wb3J0IHR5cGUgKiBhcyBwcm90b2NvbCBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC9tb2RcIjtcbmltcG9ydCB7IFRPX0NMSUVOVF9WRVJTSU9ORUQgfSBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWRcIjtcbmltcG9ydCB7IGJ1ZmZlclRvQXJyYXlCdWZmZXIsIFNpbmdsZVByb21pc2VRdWV1ZSB9IGZyb20gXCJAL3V0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi9hY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JDb25maWcsIE9uQ29ubmVjdE9wdGlvbnMgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB7XG5cdENPTk5FQ1RJT05fQ0hFQ0tfTElWRU5FU1NfU1lNQk9MLFxuXHRDb25uLFxuXHR0eXBlIENvbm5lY3Rpb25Ecml2ZXIsXG5cdHR5cGUgQ29ubklkLFxufSBmcm9tIFwiLi9jb25uZWN0aW9uXCI7XG5pbXBvcnQgeyBBY3RvckNvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCI7XG5pbXBvcnQgdHlwZSB7IEFueURhdGFiYXNlUHJvdmlkZXIsIEluZmVyRGF0YWJhc2VDbGllbnQgfSBmcm9tIFwiLi9kYXRhYmFzZVwiO1xuaW1wb3J0IHR5cGUgeyBBY3RvckRyaXZlciwgQ29ubkRyaXZlciwgQ29ubmVjdGlvbkRyaXZlcnNNYXAgfSBmcm9tIFwiLi9kcml2ZXJcIjtcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IGluc3RhbmNlTG9nZ2VyLCBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB0eXBlIHtcblx0UGVyc2lzdGVkQWN0b3IsXG5cdFBlcnNpc3RlZENvbm4sXG5cdFBlcnNpc3RlZFNjaGVkdWxlRXZlbnQsXG59IGZyb20gXCIuL3BlcnNpc3RlZFwiO1xuaW1wb3J0IHsgcHJvY2Vzc01lc3NhZ2UgfSBmcm9tIFwiLi9wcm90b2NvbC9vbGRcIjtcbmltcG9ydCB7IENhY2hlZFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHsgU2NoZWR1bGUgfSBmcm9tIFwiLi9zY2hlZHVsZVwiO1xuaW1wb3J0IHsgRGVhZGxpbmVFcnJvciwgZGVhZGxpbmUgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBgX3NhdmVTdGF0ZWAgbWV0aG9kLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVTdGF0ZU9wdGlvbnMge1xuXHQvKipcblx0ICogRm9yY2VzIHRoZSBzdGF0ZSB0byBiZSBzYXZlZCBpbW1lZGlhdGVseS4gVGhpcyBmdW5jdGlvbiB3aWxsIHJldHVybiB3aGVuIHRoZSBzdGF0ZSBoYXMgc2F2ZWQgc3VjY2Vzc2Z1bGx5LlxuXHQgKi9cblx0aW1tZWRpYXRlPzogYm9vbGVhbjtcblx0LyoqIEJ5cGFzcyByZWFkeSBjaGVjayBmb3Igc3RvcHBpbmcuICovXG5cdGFsbG93U3RvcHBpbmdTdGF0ZT86IGJvb2xlYW47XG59XG5cbi8qKiBBY3RvciB0eXBlIGFsaWFzIHdpdGggYWxsIGBhbnlgIHR5cGVzLiBVc2VkIGZvciBgZXh0ZW5kc2AgaW4gY2xhc3NlcyByZWZlcmVuY2luZyB0aGlzIGFjdG9yLiAqL1xuZXhwb3J0IHR5cGUgQW55QWN0b3JJbnN0YW5jZSA9IEFjdG9ySW5zdGFuY2U8XG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTmVlZHMgdG8gYmUgdXNlZCBpbiBgZXh0ZW5kc2Bcblx0YW55LFxuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE5lZWRzIHRvIGJlIHVzZWQgaW4gYGV4dGVuZHNgXG5cdGFueSxcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBOZWVkcyB0byBiZSB1c2VkIGluIGBleHRlbmRzYFxuXHRhbnksXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTmVlZHMgdG8gYmUgdXNlZCBpbiBgZXh0ZW5kc2Bcblx0YW55LFxuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE5lZWRzIHRvIGJlIHVzZWQgaW4gYGV4dGVuZHNgXG5cdGFueSxcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBOZWVkcyB0byBiZSB1c2VkIGluIGBleHRlbmRzYFxuXHRhbnksXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTmVlZHMgdG8gYmUgdXNlZCBpbiBgZXh0ZW5kc2Bcblx0YW55XG4+O1xuXG5leHBvcnQgdHlwZSBFeHRyYWN0QWN0b3JTdGF0ZTxBIGV4dGVuZHMgQW55QWN0b3JJbnN0YW5jZT4gPVxuXHRBIGV4dGVuZHMgQWN0b3JJbnN0YW5jZTxcblx0XHRpbmZlciBTdGF0ZSxcblx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE11c3QgYmUgdXNlZCBmb3IgYGV4dGVuZHNgXG5cdFx0YW55LFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueSxcblx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE11c3QgYmUgdXNlZCBmb3IgYGV4dGVuZHNgXG5cdFx0YW55LFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueVxuXHQ+XG5cdFx0PyBTdGF0ZVxuXHRcdDogbmV2ZXI7XG5cbmV4cG9ydCB0eXBlIEV4dHJhY3RBY3RvckNvbm5QYXJhbXM8QSBleHRlbmRzIEFueUFjdG9ySW5zdGFuY2U+ID1cblx0QSBleHRlbmRzIEFjdG9ySW5zdGFuY2U8XG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueSxcblx0XHRpbmZlciBDb25uUGFyYW1zLFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueSxcblx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE11c3QgYmUgdXNlZCBmb3IgYGV4dGVuZHNgXG5cdFx0YW55LFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueVxuXHQ+XG5cdFx0PyBDb25uUGFyYW1zXG5cdFx0OiBuZXZlcjtcblxuZXhwb3J0IHR5cGUgRXh0cmFjdEFjdG9yQ29ublN0YXRlPEEgZXh0ZW5kcyBBbnlBY3Rvckluc3RhbmNlPiA9XG5cdEEgZXh0ZW5kcyBBY3Rvckluc3RhbmNlPFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueSxcblx0XHRpbmZlciBDb25uU3RhdGUsXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueSxcblx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE11c3QgYmUgdXNlZCBmb3IgYGV4dGVuZHNgXG5cdFx0YW55LFxuXHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTXVzdCBiZSB1c2VkIGZvciBgZXh0ZW5kc2Bcblx0XHRhbnksXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBNdXN0IGJlIHVzZWQgZm9yIGBleHRlbmRzYFxuXHRcdGFueVxuXHQ+XG5cdFx0PyBDb25uU3RhdGVcblx0XHQ6IG5ldmVyO1xuXG5leHBvcnQgY2xhc3MgQWN0b3JJbnN0YW5jZTxcblx0Uyxcblx0Q1AsXG5cdENTLFxuXHRWLFxuXHRJLFxuXHRBRCxcblx0REIgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyLFxuPiB7XG5cdC8vIFNoYXJlZCBhY3RvciBjb250ZXh0IGZvciB0aGlzIGluc3RhbmNlXG5cdGFjdG9yQ29udGV4dDogQWN0b3JDb250ZXh0PFMsIENQLCBDUywgViwgSSwgQUQsIERCPjtcblx0I3NsZWVwQ2FsbGVkID0gZmFsc2U7XG5cdCNzdG9wQ2FsbGVkID0gZmFsc2U7XG5cblx0Z2V0IGlzU3RvcHBpbmcoKSB7XG5cdFx0cmV0dXJuIHRoaXMuI3N0b3BDYWxsZWQgfHwgdGhpcy4jc2xlZXBDYWxsZWQ7XG5cdH1cblxuXHQjcGVyc2lzdENoYW5nZWQgPSBmYWxzZTtcblx0I2lzSW5PblN0YXRlQ2hhbmdlID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqIFRoZSBwcm94aWVkIHN0YXRlIHRoYXQgbm90aWZpZXMgb2YgY2hhbmdlcyBhdXRvbWF0aWNhbGx5LlxuXHQgKlxuXHQgKiBBbnkgZGF0YSB0aGF0IHNob3VsZCBiZSBzdG9yZWQgaW5kZWZpbml0ZWx5IHNob3VsZCBiZSBoZWxkIHdpdGhpbiB0aGlzIG9iamVjdC5cblx0ICovXG5cdCNwZXJzaXN0ITogUGVyc2lzdGVkQWN0b3I8UywgQ1AsIENTLCBJPjtcblxuXHQvKiogUmF3IHN0YXRlIHdpdGhvdXQgdGhlIHByb3h5IHdyYXBwZXIgKi9cblx0I3BlcnNpc3RSYXchOiBQZXJzaXN0ZWRBY3RvcjxTLCBDUCwgQ1MsIEk+O1xuXG5cdCNwZXJzaXN0V3JpdGVRdWV1ZSA9IG5ldyBTaW5nbGVQcm9taXNlUXVldWUoKTtcblx0I2FsYXJtV3JpdGVRdWV1ZSA9IG5ldyBTaW5nbGVQcm9taXNlUXVldWUoKTtcblxuXHQjbGFzdFNhdmVUaW1lID0gMDtcblx0I3BlbmRpbmdTYXZlVGltZW91dD86IE5vZGVKUy5UaW1lb3V0O1xuXG5cdCN2YXJzPzogVjtcblxuXHQjYmFja2dyb3VuZFByb21pc2VzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblx0I2Fib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblx0I2NvbmZpZzogQWN0b3JDb25maWc8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+O1xuXHQjY29ubmVjdGlvbkRyaXZlcnMhOiBDb25uZWN0aW9uRHJpdmVyc01hcDtcblx0I2FjdG9yRHJpdmVyITogQWN0b3JEcml2ZXI7XG5cdCNpbmxpbmVDbGllbnQhOiBDbGllbnQ8UmVnaXN0cnk8YW55Pj47XG5cdCNhY3RvcklkITogc3RyaW5nO1xuXHQjbmFtZSE6IHN0cmluZztcblx0I2tleSE6IEFjdG9yS2V5O1xuXHQjcmVnaW9uITogc3RyaW5nO1xuXHQjcmVhZHkgPSBmYWxzZTtcblxuXHQjY29ubmVjdGlvbnMgPSBuZXcgTWFwPENvbm5JZCwgQ29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4+KCk7XG5cdCNzdWJzY3JpcHRpb25JbmRleCA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8Q29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4+PigpO1xuXHQjY2hlY2tDb25uTGl2ZW5lc3NJbnRlcnZhbD86IE5vZGVKUy5UaW1lb3V0O1xuXG5cdCNzbGVlcFRpbWVvdXQ/OiBOb2RlSlMuVGltZW91dDtcblxuXHQvLyBUcmFjayBhY3RpdmUgcmF3IHJlcXVlc3RzIHNvIHNsZWVwIGxvZ2ljIGNhbiBhY2NvdW50IGZvciB0aGVtXG5cdCNhY3RpdmVSYXdGZXRjaENvdW50ID0gMDtcblx0I2FjdGl2ZVJhd1dlYlNvY2tldHMgPSBuZXcgU2V0PFVuaXZlcnNhbFdlYlNvY2tldD4oKTtcblxuXHQjc2NoZWR1bGUhOiBTY2hlZHVsZTtcblx0I2RiITogSW5mZXJEYXRhYmFzZUNsaWVudDxEQj47XG5cblx0I2luc3BlY3RvciA9IG5ldyBBY3Rvckluc3BlY3RvcigoKSA9PiB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGlzRGJFbmFibGVkOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdHJldHVybiB0aGlzLiNkYiAhPT0gdW5kZWZpbmVkO1xuXHRcdFx0fSxcblx0XHRcdGdldERiOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmRiO1xuXHRcdFx0fSxcblx0XHRcdGlzU3RhdGVFbmFibGVkOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdHJldHVybiB0aGlzLnN0YXRlRW5hYmxlZDtcblx0XHRcdH0sXG5cdFx0XHRnZXRTdGF0ZTogYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHR0aGlzLiN2YWxpZGF0ZVN0YXRlRW5hYmxlZCgpO1xuXG5cdFx0XHRcdC8vIE11c3QgcmV0dXJuIGZyb20gYCNwZXJzaXN0UmF3YCBpbiBvcmRlciB0byBub3QgcmV0dXJuIHRoZSBgb25jaGFuZ2VgIHByb3h5XG5cdFx0XHRcdHJldHVybiB0aGlzLiNwZXJzaXN0UmF3LnN0YXRlIGFzIFJlY29yZDxzdHJpbmcsIGFueT4gYXMgdW5rbm93bjtcblx0XHRcdH0sXG5cdFx0XHRnZXRScGNzOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLiNjb25maWcuYWN0aW9ucyk7XG5cdFx0XHR9LFxuXHRcdFx0Z2V0Q29ubmVjdGlvbnM6IGFzeW5jICgpID0+IHtcblx0XHRcdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy4jY29ubmVjdGlvbnMuZW50cmllcygpKS5tYXAoKFtpZCwgY29ubl0pID0+ICh7XG5cdFx0XHRcdFx0aWQsXG5cdFx0XHRcdFx0c3RhdGVFbmFibGVkOiBjb25uLl9zdGF0ZUVuYWJsZWQsXG5cdFx0XHRcdFx0cGFyYW1zOiBjb25uLnBhcmFtcyBhcyB7fSxcblx0XHRcdFx0XHRzdGF0ZTogY29ubi5fc3RhdGVFbmFibGVkID8gY29ubi5zdGF0ZSA6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRhdXRoOiBjb25uLmF1dGggYXMge30sXG5cdFx0XHRcdH0pKTtcblx0XHRcdH0sXG5cdFx0XHRzZXRTdGF0ZTogYXN5bmMgKHN0YXRlOiB1bmtub3duKSA9PiB7XG5cdFx0XHRcdHRoaXMuI3ZhbGlkYXRlU3RhdGVFbmFibGVkKCk7XG5cblx0XHRcdFx0Ly8gTXVzdCBzZXQgb24gYCNwZXJzaXN0YCBpbnN0ZWFkIG9mIGAjcGVyc2lzdFJhd2AgaW4gb3JkZXIgdG8gZW5zdXJlIHRoYXQgdGhlIGBQcm94eWAgaXMgY29ycmVjdGx5IGNvbmZpZ3VyZWRcblx0XHRcdFx0Ly9cblx0XHRcdFx0Ly8gV2UgaGF2ZSB0byB1c2UgYC4uLmAgc28gYG9uLWNoYW5nZWAgcmVjb2duaXplcyB0aGUgY2hhbmdlcyB0byBgc3RhdGVgIChpLmUuIHNldCAjcGVyc2lzdENoYW5nZWRgIHRvIHRydWUpLiBUaGlzIGlzIGJlY2F1c2U6XG5cdFx0XHRcdC8vIDEuIEluIGBnZXRTdGF0ZWAsIHdlIHJldHVybmVkIHRoZSB2YWx1ZSBmcm9tIGBwZXJzaXN0UmF3YCwgd2hpY2ggZG9lcyBub3QgaGF2ZSB0aGUgUHJveHkgdG8gbW9uaXRvciBzdGF0ZSBjaGFuZ2VzXG5cdFx0XHRcdC8vIDIuIElmIHdlIHdlcmUgdG8gYXNzaWduIGBzdGF0ZWAgdG8gYCNwZXJzaXN0LnNgLCBgb24tY2hhbmdlYCB3b3VsZCBhc3N1bWUgbm90aGluZyBjaGFuZ2VkIHNpbmNlIGBzdGF0ZWAgaXMgc3RpbGwgPT09IGAjcGVyc2lzdC5zYCBzaW5jZSB3ZSByZXR1cm5lZCBhIHJlZmVyZW5jZSBpbiBgZ2V0U3RhdGVgXG5cdFx0XHRcdHRoaXMuI3BlcnNpc3Quc3RhdGUgPSB7IC4uLihzdGF0ZSBhcyBTKSB9O1xuXHRcdFx0XHRhd2FpdCB0aGlzLnNhdmVTdGF0ZSh7IGltbWVkaWF0ZTogdHJ1ZSB9KTtcblx0XHRcdH0sXG5cdFx0fTtcblx0fSk7XG5cblx0Z2V0IGlkKCkge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvcklkO1xuXHR9XG5cblx0Z2V0IGlubGluZUNsaWVudCgpOiBDbGllbnQ8UmVnaXN0cnk8YW55Pj4ge1xuXHRcdHJldHVybiB0aGlzLiNpbmxpbmVDbGllbnQ7XG5cdH1cblxuXHRnZXQgaW5zcGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLiNpbnNwZWN0b3I7XG5cdH1cblxuXHRnZXQgI3NsZWVwaW5nU3VwcG9ydGVkKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckRyaXZlci5zbGVlcCAhPT0gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoaXMgY29uc3RydWN0b3Igc2hvdWxkIG5ldmVyIGJlIHVzZWQgZGlyZWN0bHkuXG5cdCAqXG5cdCAqIENvbnN0cnVjdGVkIGluIHtAbGluayBBY3Rvckluc3RhbmNlLnN0YXJ0fS5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICovXG5cdGNvbnN0cnVjdG9yKGNvbmZpZzogQWN0b3JDb25maWc8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+KSB7XG5cdFx0dGhpcy4jY29uZmlnID0gY29uZmlnO1xuXHRcdHRoaXMuYWN0b3JDb250ZXh0ID0gbmV3IEFjdG9yQ29udGV4dCh0aGlzKTtcblx0fVxuXG5cdGFzeW5jIHN0YXJ0KFxuXHRcdGNvbm5lY3Rpb25Ecml2ZXJzOiBDb25uZWN0aW9uRHJpdmVyc01hcCxcblx0XHRhY3RvckRyaXZlcjogQWN0b3JEcml2ZXIsXG5cdFx0aW5saW5lQ2xpZW50OiBDbGllbnQ8UmVnaXN0cnk8YW55Pj4sXG5cdFx0YWN0b3JJZDogc3RyaW5nLFxuXHRcdG5hbWU6IHN0cmluZyxcblx0XHRrZXk6IEFjdG9yS2V5LFxuXHRcdHJlZ2lvbjogc3RyaW5nLFxuXHQpIHtcblx0XHR0aGlzLiNjb25uZWN0aW9uRHJpdmVycyA9IGNvbm5lY3Rpb25Ecml2ZXJzO1xuXHRcdHRoaXMuI2FjdG9yRHJpdmVyID0gYWN0b3JEcml2ZXI7XG5cdFx0dGhpcy4jaW5saW5lQ2xpZW50ID0gaW5saW5lQ2xpZW50O1xuXHRcdHRoaXMuI2FjdG9ySWQgPSBhY3RvcklkO1xuXHRcdHRoaXMuI25hbWUgPSBuYW1lO1xuXHRcdHRoaXMuI2tleSA9IGtleTtcblx0XHR0aGlzLiNyZWdpb24gPSByZWdpb247XG5cdFx0dGhpcy4jc2NoZWR1bGUgPSBuZXcgU2NoZWR1bGUodGhpcyk7XG5cblx0XHQvLyBJbml0aWFsaXplIHNlcnZlclxuXHRcdC8vXG5cdFx0Ly8gU3RvcmUgdGhlIHByb21pc2Ugc28gbmV0d29yayByZXF1ZXN0cyBjYW4gYXdhaXQgaW5pdGlhbGl6YXRpb25cblx0XHRhd2FpdCB0aGlzLiNpbml0aWFsaXplKCk7XG5cblx0XHQvLyBUT0RPOiBFeGl0IHByb2Nlc3MgaWYgdGhpcyBlcnJvcnNcblx0XHRpZiAodGhpcy4jdmFyc0VuYWJsZWQpIHtcblx0XHRcdGxldCB2YXJzOiBWIHwgdW5kZWZpbmVkO1xuXHRcdFx0aWYgKFwiY3JlYXRlVmFyc1wiIGluIHRoaXMuI2NvbmZpZykge1xuXHRcdFx0XHRjb25zdCBkYXRhT3JQcm9taXNlID0gdGhpcy4jY29uZmlnLmNyZWF0ZVZhcnMoXG5cdFx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQgYXMgdW5rbm93biBhcyBBY3RvckNvbnRleHQ8XG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHRhbnlcblx0XHRcdFx0XHQ+LFxuXHRcdFx0XHRcdHRoaXMuI2FjdG9yRHJpdmVyLmdldENvbnRleHQodGhpcy4jYWN0b3JJZCksXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGlmIChkYXRhT3JQcm9taXNlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuXHRcdFx0XHRcdHZhcnMgPSBhd2FpdCBkZWFkbGluZShcblx0XHRcdFx0XHRcdGRhdGFPclByb21pc2UsXG5cdFx0XHRcdFx0XHR0aGlzLiNjb25maWcub3B0aW9ucy5jcmVhdGVWYXJzVGltZW91dCxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhcnMgPSBkYXRhT3JQcm9taXNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKFwidmFyc1wiIGluIHRoaXMuI2NvbmZpZykge1xuXHRcdFx0XHR2YXJzID0gc3RydWN0dXJlZENsb25lKHRoaXMuI2NvbmZpZy52YXJzKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCB2YXJpYWJsZXMgZnJvbSAnY3JlYXRlVmFycycgb3IgJ3ZhcnMnXCIpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy4jdmFycyA9IHZhcnM7XG5cdFx0fVxuXG5cdFx0Ly8gVE9ETzogRXhpdCBwcm9jZXNzIGlmIHRoaXMgZXJyb3JzXG5cdFx0bG9nZ2VyKCkuaW5mbyhcImFjdG9yIHN0YXJ0aW5nXCIpO1xuXHRcdGlmICh0aGlzLiNjb25maWcub25TdGFydCkge1xuXHRcdFx0Y29uc3QgcmVzdWx0ID0gdGhpcy4jY29uZmlnLm9uU3RhcnQodGhpcy5hY3RvckNvbnRleHQpO1xuXHRcdFx0aWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcblx0XHRcdFx0YXdhaXQgcmVzdWx0O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldHVwIERhdGFiYXNlXG5cdFx0aWYgKFwiZGJcIiBpbiB0aGlzLiNjb25maWcgJiYgdGhpcy4jY29uZmlnLmRiKSB7XG5cdFx0XHRjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLiNjb25maWcuZGIuY3JlYXRlQ2xpZW50KHtcblx0XHRcdFx0Z2V0RGF0YWJhc2U6ICgpID0+IGFjdG9yRHJpdmVyLmdldERhdGFiYXNlKHRoaXMuI2FjdG9ySWQpLFxuXHRcdFx0fSk7XG5cdFx0XHRsb2dnZXIoKS5pbmZvKFwiZGF0YWJhc2UgbWlncmF0aW9uIHN0YXJ0aW5nXCIpO1xuXHRcdFx0YXdhaXQgdGhpcy4jY29uZmlnLmRiLm9uTWlncmF0ZT8uKGNsaWVudCk7XG5cdFx0XHRsb2dnZXIoKS5pbmZvKFwiZGF0YWJhc2UgbWlncmF0aW9uIGNvbXBsZXRlXCIpO1xuXHRcdFx0dGhpcy4jZGIgPSBjbGllbnQ7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IGFsYXJtIGZvciBuZXh0IHNjaGVkdWxlZCBldmVudCBpZiBhbnkgZXhpc3QgYWZ0ZXIgZmluaXNoaW5nIGluaXRpYXRpb24gc2VxdWVuY2Vcblx0XHRpZiAodGhpcy4jcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMubGVuZ3RoID4gMCkge1xuXHRcdFx0YXdhaXQgdGhpcy4jcXVldWVTZXRBbGFybSh0aGlzLiNwZXJzaXN0LnNjaGVkdWxlZEV2ZW50c1swXS50aW1lc3RhbXApO1xuXHRcdH1cblxuXHRcdGxvZ2dlcigpLmluZm8oXCJhY3RvciByZWFkeVwiKTtcblx0XHR0aGlzLiNyZWFkeSA9IHRydWU7XG5cblx0XHQvLyBNdXN0IGJlIGNhbGxlZCBhZnRlciBzZXR0aW5nIGAjcmVhZHlgIG9yIGVsc2UgaXQgd2lsbCBub3Qgc2NoZWR1bGUgc2xlZXBcblx0XHR0aGlzLiNyZXNldFNsZWVwVGltZXIoKTtcblxuXHRcdC8vIFN0YXJ0IGNvbm4gbGl2ZW5lc3MgaW50ZXJ2YWxcblx0XHQvL1xuXHRcdC8vIENoZWNrIGZvciBsaXZlbmVzcyBpbW1lZGlhdGVseSBzaW5jZSB3ZSBtYXkgaGF2ZSBjb25uZWN0aW9ucyB0aGF0XG5cdFx0Ly8gd2VyZSBpbiBgcmVjb25uZWN0aW5nYCBzdGF0ZSB3aGVuIHRoZSBhY3RvciB3ZW50IHRvIHNsZWVwIHRoYXQgd2Vcblx0XHQvLyBuZWVkIHRvIHB1cmdlLlxuXHRcdC8vXG5cdFx0Ly8gV2UgZG9uJ3QgdXNlIGFsYXJtcyBmb3IgY29ubmVjdGlvbiBsaXZlbmVzcyBzaW5jZSBhbGFybXMgcmVxdWlyZVxuXHRcdC8vIGR1cmFiaWxpdHkgJiBhcmUgZXhwZW5zaXZlLiBDb25uZWN0aW9uIGxpdmVuZXNzIGlzIHNhZmUgdG8gYXNzdW1lXG5cdFx0Ly8gaXQgb25seSBuZWVkcyB0byBiZSByYW4gd2hpbGUgdGhlIGFjdG9yIGlzIGF3YWtlIGFuZCBkb2VzIG5vdCBuZWVkXG5cdFx0Ly8gdG8gbWFudWFsbHkgd2FrZSB0aGUgYWN0b3IuIFRoZSBvbmx5IGNhc2UgdGhpcyBpcyBub3QgdHJ1ZSBpcyBpZiB0aGVcblx0XHQvLyBjb25uZWN0aW9uIGxpdmVuZXNzIHRpbWVvdXQgaXMgZ3JlYXRlciB0aGFuIHRoZSBhY3RvciBzbGVlcCB0aW1lb3V0XG5cdFx0Ly8gT1IgaWYgdGhlIGFjdG9yIGlzIG1hbnVhbGx5IHB1dCB0byBzbGVlcC4gSW4gdGhpcyBjYXNlLCB0aGUgY29ubmVjdGlvbnNcblx0XHQvLyB3aWxsIGJlIHN0dWNrIGluIGEgYHJlY29ubmVjdGluZ2Agc3RhdGUgdW50aWwgdGhlIGFjdG9yIGlzIGF3YWtlbiBhZ2Fpbi5cblx0XHR0aGlzLiNjaGVja0Nvbm5MaXZlbmVzc0ludGVydmFsID0gc2V0SW50ZXJ2YWwoXG5cdFx0XHR0aGlzLiNjaGVja0Nvbm5lY3Rpb25zTGl2ZW5lc3MuYmluZCh0aGlzKSxcblx0XHRcdHRoaXMuI2NvbmZpZy5vcHRpb25zLmNvbm5lY3Rpb25MaXZlbmVzc0ludGVydmFsLFxuXHRcdCk7XG5cdFx0dGhpcy4jY2hlY2tDb25uZWN0aW9uc0xpdmVuZXNzKCk7XG5cdH1cblxuXHRhc3luYyAjc2NoZWR1bGVFdmVudElubmVyKG5ld0V2ZW50OiBQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KSB7XG5cdFx0dGhpcy5hY3RvckNvbnRleHQubG9nLmluZm8oXCJzY2hlZHVsaW5nIGV2ZW50XCIsIG5ld0V2ZW50KTtcblxuXHRcdC8vIEluc2VydCBldmVudCBpbiB0byBpbmRleFxuXHRcdGNvbnN0IGluc2VydEluZGV4ID0gdGhpcy4jcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMuZmluZEluZGV4KFxuXHRcdFx0KHgpID0+IHgudGltZXN0YW1wID4gbmV3RXZlbnQudGltZXN0YW1wLFxuXHRcdCk7XG5cdFx0aWYgKGluc2VydEluZGV4ID09PSAtMSkge1xuXHRcdFx0dGhpcy4jcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMucHVzaChuZXdFdmVudCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzLnNwbGljZShpbnNlcnRJbmRleCwgMCwgbmV3RXZlbnQpO1xuXHRcdH1cblxuXHRcdC8vIFVwZGF0ZSBhbGFybSBpZjpcblx0XHQvLyAtIHRoaXMgaXMgdGhlIG5ld2VzdCBldmVudCAoaS5lLiBhdCBiZWdpbm5pbmcgb2YgYXJyYXkpIG9yXG5cdFx0Ly8gLSB0aGlzIGlzIHRoZSBvbmx5IGV2ZW50IChpLmUuIHRoZSBvbmx5IGV2ZW50IGluIHRoZSBhcnJheSlcblx0XHRpZiAoaW5zZXJ0SW5kZXggPT09IDAgfHwgdGhpcy4jcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHR0aGlzLmFjdG9yQ29udGV4dC5sb2cuaW5mbyhcInNldHRpbmcgYWxhcm1cIiwge1xuXHRcdFx0XHR0aW1lc3RhbXA6IG5ld0V2ZW50LnRpbWVzdGFtcCxcblx0XHRcdFx0ZXZlbnRDb3VudDogdGhpcy4jcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMubGVuZ3RoLFxuXHRcdFx0fSk7XG5cdFx0XHRhd2FpdCB0aGlzLiNxdWV1ZVNldEFsYXJtKG5ld0V2ZW50LnRpbWVzdGFtcCk7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgX29uQWxhcm0oKSB7XG5cdFx0Y29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcblx0XHR0aGlzLmFjdG9yQ29udGV4dC5sb2cuZGVidWcoXCJhbGFybSB0cmlnZ2VyZWRcIiwge1xuXHRcdFx0bm93LFxuXHRcdFx0ZXZlbnRzOiB0aGlzLiNwZXJzaXN0LnNjaGVkdWxlZEV2ZW50cy5sZW5ndGgsXG5cdFx0fSk7XG5cblx0XHQvLyBVcGRhdGUgc2xlZXBcblx0XHQvL1xuXHRcdC8vIERvIHRoaXMgYmVmb3JlIGFueSBhc3luYyBsb2dpY1xuXHRcdHRoaXMuI3Jlc2V0U2xlZXBUaW1lcigpO1xuXG5cdFx0Ly8gUmVtb3ZlIGV2ZW50cyBmcm9tIHNjaGVkdWxlIHRoYXQgd2UncmUgYWJvdXQgdG8gcnVuXG5cdFx0Y29uc3QgcnVuSW5kZXggPSB0aGlzLiNwZXJzaXN0LnNjaGVkdWxlZEV2ZW50cy5maW5kSW5kZXgoXG5cdFx0XHQoeCkgPT4geC50aW1lc3RhbXAgPD0gbm93LFxuXHRcdCk7XG5cdFx0aWYgKHJ1bkluZGV4ID09PSAtMSkge1xuXHRcdFx0Ly8gTm8gZXZlbnRzIGFyZSBkdWUgeWV0LiBUaGlzIHdpbGwgaGFwcGVuIGlmIHRpbWVycyBmaXJlIHNsaWdodGx5IGVhcmx5LlxuXHRcdFx0Ly8gRW5zdXJlIHdlIHJlc2NoZWR1bGUgdGhlIGFsYXJtIGZvciB0aGUgbmV4dCB1cGNvbWluZyBldmVudCB0byBhdm9pZCBsb3NpbmcgaXQuXG5cdFx0XHRsb2dnZXIoKS53YXJuKFwibm8gZXZlbnRzIGFyZSBkdWUgeWV0LCB0aW1lIG1heSBoYXZlIGJyb2tlblwiKTtcblx0XHRcdGlmICh0aGlzLiNwZXJzaXN0LnNjaGVkdWxlZEV2ZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdGNvbnN0IG5leHRUcyA9IHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzWzBdLnRpbWVzdGFtcDtcblx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQubG9nLndhcm4oXG5cdFx0XHRcdFx0XCJhbGFybSBmaXJlZCBlYXJseSwgcmVzY2hlZHVsaW5nIGZvciBuZXh0IGV2ZW50XCIsXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0bm93LFxuXHRcdFx0XHRcdFx0bmV4dFRzLFxuXHRcdFx0XHRcdFx0ZGVsdGE6IG5leHRUcyAtIG5vdyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHQpO1xuXHRcdFx0XHRhd2FpdCB0aGlzLiNxdWV1ZVNldEFsYXJtKG5leHRUcyk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmFjdG9yQ29udGV4dC5sb2cuZGVidWcoXCJubyBldmVudHMgdG8gcnVuXCIsIHsgbm93IH0pO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRjb25zdCBzY2hlZHVsZUV2ZW50cyA9IHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzLnNwbGljZShcblx0XHRcdDAsXG5cdFx0XHRydW5JbmRleCArIDEsXG5cdFx0KTtcblx0XHR0aGlzLmFjdG9yQ29udGV4dC5sb2cuZGVidWcoXCJydW5uaW5nIGV2ZW50c1wiLCB7XG5cdFx0XHRjb3VudDogc2NoZWR1bGVFdmVudHMubGVuZ3RoLFxuXHRcdH0pO1xuXG5cdFx0Ly8gU2V0IGFsYXJtIGZvciBuZXh0IGV2ZW50XG5cdFx0aWYgKHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzLmxlbmd0aCA+IDApIHtcblx0XHRcdGNvbnN0IG5leHRUcyA9IHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzWzBdLnRpbWVzdGFtcDtcblx0XHRcdHRoaXMuYWN0b3JDb250ZXh0LmxvZy5pbmZvKFwic2V0dGluZyBuZXh0IGFsYXJtXCIsIHtcblx0XHRcdFx0bmV4dFRzLFxuXHRcdFx0XHRyZW1haW5pbmdFdmVudHM6IHRoaXMuI3BlcnNpc3Quc2NoZWR1bGVkRXZlbnRzLmxlbmd0aCxcblx0XHRcdH0pO1xuXHRcdFx0YXdhaXQgdGhpcy4jcXVldWVTZXRBbGFybShuZXh0VHMpO1xuXHRcdH1cblxuXHRcdC8vIEl0ZXJhdGUgYnkgZXZlbnQga2V5IGluIG9yZGVyIHRvIGVuc3VyZSB3ZSBjYWxsIHRoZSBldmVudHMgaW4gb3JkZXJcblx0XHRmb3IgKGNvbnN0IGV2ZW50IG9mIHNjaGVkdWxlRXZlbnRzKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR0aGlzLmFjdG9yQ29udGV4dC5sb2cuaW5mbyhcInJ1bm5pbmcgYWN0aW9uIGZvciBldmVudFwiLCB7XG5cdFx0XHRcdFx0ZXZlbnQ6IGV2ZW50LmV2ZW50SWQsXG5cdFx0XHRcdFx0dGltZXN0YW1wOiBldmVudC50aW1lc3RhbXAsXG5cdFx0XHRcdFx0YWN0aW9uOiBldmVudC5raW5kLmdlbmVyaWMuYWN0aW9uTmFtZSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gTG9vayB1cCBmdW5jdGlvblxuXHRcdFx0XHRjb25zdCBmbjogdW5rbm93biA9IHRoaXMuI2NvbmZpZy5hY3Rpb25zW2V2ZW50LmtpbmQuZ2VuZXJpYy5hY3Rpb25OYW1lXTtcblxuXHRcdFx0XHRpZiAoIWZuKVxuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihcblx0XHRcdFx0XHRcdGBNaXNzaW5nIGFjdGlvbiBmb3IgYWxhcm0gJHtldmVudC5raW5kLmdlbmVyaWMuYWN0aW9uTmFtZX1gLFxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdGlmICh0eXBlb2YgZm4gIT09IFwiZnVuY3Rpb25cIilcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdFx0XHRgQWxhcm0gZnVuY3Rpb24gbG9va3VwIGZvciAke2V2ZW50LmtpbmQuZ2VuZXJpYy5hY3Rpb25OYW1lfSByZXR1cm5lZCAke3R5cGVvZiBmbn1gLFxuXHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gQ2FsbCBmdW5jdGlvblxuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGNvbnN0IGFyZ3MgPSBldmVudC5raW5kLmdlbmVyaWMuYXJnc1xuXHRcdFx0XHRcdFx0PyBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShldmVudC5raW5kLmdlbmVyaWMuYXJncykpXG5cdFx0XHRcdFx0XHQ6IFtdO1xuXHRcdFx0XHRcdGF3YWl0IGZuLmNhbGwodW5kZWZpbmVkLCB0aGlzLmFjdG9yQ29udGV4dCwgLi4uYXJncyk7XG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQubG9nLmVycm9yKFwiZXJyb3Igd2hpbGUgcnVubmluZyBldmVudFwiLCB7XG5cdFx0XHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyb3IpLFxuXHRcdFx0XHRcdFx0ZXZlbnQ6IGV2ZW50LmV2ZW50SWQsXG5cdFx0XHRcdFx0XHR0aW1lc3RhbXA6IGV2ZW50LnRpbWVzdGFtcCxcblx0XHRcdFx0XHRcdGFjdGlvbjogZXZlbnQua2luZC5nZW5lcmljLmFjdGlvbk5hbWUsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdHRoaXMuYWN0b3JDb250ZXh0LmxvZy5lcnJvcihcImludGVybmFsIGVycm9yIHdoaWxlIHJ1bm5pbmcgZXZlbnRcIiwge1xuXHRcdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHRcdFx0Li4uZXZlbnQsXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGFzeW5jIHNjaGVkdWxlRXZlbnQoXG5cdFx0dGltZXN0YW1wOiBudW1iZXIsXG5cdFx0YWN0aW9uOiBzdHJpbmcsXG5cdFx0YXJnczogdW5rbm93bltdLFxuXHQpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRyZXR1cm4gdGhpcy4jc2NoZWR1bGVFdmVudElubmVyKHtcblx0XHRcdGV2ZW50SWQ6IGNyeXB0by5yYW5kb21VVUlEKCksXG5cdFx0XHR0aW1lc3RhbXAsXG5cdFx0XHRraW5kOiB7XG5cdFx0XHRcdGdlbmVyaWM6IHtcblx0XHRcdFx0XHRhY3Rpb25OYW1lOiBhY3Rpb24sXG5cdFx0XHRcdFx0YXJnczogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShhcmdzKSksXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdH0pO1xuXHR9XG5cblx0Z2V0IHN0YXRlRW5hYmxlZCgpIHtcblx0XHRyZXR1cm4gXCJjcmVhdGVTdGF0ZVwiIGluIHRoaXMuI2NvbmZpZyB8fCBcInN0YXRlXCIgaW4gdGhpcy4jY29uZmlnO1xuXHR9XG5cblx0I3ZhbGlkYXRlU3RhdGVFbmFibGVkKCkge1xuXHRcdGlmICghdGhpcy5zdGF0ZUVuYWJsZWQpIHtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuU3RhdGVOb3RFbmFibGVkKCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0ICNjb25uU3RhdGVFbmFibGVkKCkge1xuXHRcdHJldHVybiBcImNyZWF0ZUNvbm5TdGF0ZVwiIGluIHRoaXMuI2NvbmZpZyB8fCBcImNvbm5TdGF0ZVwiIGluIHRoaXMuI2NvbmZpZztcblx0fVxuXG5cdGdldCAjdmFyc0VuYWJsZWQoKSB7XG5cdFx0cmV0dXJuIFwiY3JlYXRlVmFyc1wiIGluIHRoaXMuI2NvbmZpZyB8fCBcInZhcnNcIiBpbiB0aGlzLiNjb25maWc7XG5cdH1cblxuXHQjdmFsaWRhdGVWYXJzRW5hYmxlZCgpIHtcblx0XHRpZiAoIXRoaXMuI3ZhcnNFbmFibGVkKSB7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLlZhcnNOb3RFbmFibGVkKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIFByb21pc2UgdXNlZCB0byB3YWl0IGZvciBhIHNhdmUgdG8gY29tcGxldGUuIFRoaXMgaXMgcmVxdWlyZWQgc2luY2UgeW91IGNhbm5vdCBhd2FpdCBgI3NhdmVTdGF0ZVRocm90dGxlZGAuICovXG5cdCNvblBlcnNpc3RTYXZlZFByb21pc2U/OiBQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPjtcblxuXHQvKiogVGhyb3R0bGVkIHNhdmUgc3RhdGUgbWV0aG9kLiBVc2VkIHRvIHdyaXRlIHRvIEtWIGF0IGEgcmVhc29uYWJsZSBjYWRlbmNlLiAqL1xuXHQjc2F2ZVBlcnNpc3RUaHJvdHRsZWQoKSB7XG5cdFx0Y29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcblx0XHRjb25zdCB0aW1lU2luY2VMYXN0U2F2ZSA9IG5vdyAtIHRoaXMuI2xhc3RTYXZlVGltZTtcblx0XHRjb25zdCBzYXZlSW50ZXJ2YWwgPSB0aGlzLiNjb25maWcub3B0aW9ucy5zdGF0ZVNhdmVJbnRlcnZhbDtcblxuXHRcdC8vIElmIHdlJ3JlIHdpdGhpbiB0aGUgdGhyb3R0bGUgd2luZG93IGFuZCBub3QgYWxyZWFkeSBzY2hlZHVsZWQsIHNjaGVkdWxlIHRoZSBuZXh0IHNhdmUuXG5cdFx0aWYgKHRpbWVTaW5jZUxhc3RTYXZlIDwgc2F2ZUludGVydmFsKSB7XG5cdFx0XHRpZiAodGhpcy4jcGVuZGluZ1NhdmVUaW1lb3V0ID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0dGhpcy4jcGVuZGluZ1NhdmVUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy4jcGVuZGluZ1NhdmVUaW1lb3V0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdHRoaXMuI3NhdmVQZXJzaXN0SW5uZXIoKTtcblx0XHRcdFx0fSwgc2F2ZUludGVydmFsIC0gdGltZVNpbmNlTGFzdFNhdmUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBJZiB3ZSdyZSBvdXRzaWRlIHRoZSB0aHJvdHRsZSB3aW5kb3csIHNhdmUgaW1tZWRpYXRlbHlcblx0XHRcdHRoaXMuI3NhdmVQZXJzaXN0SW5uZXIoKTtcblx0XHR9XG5cdH1cblxuXHQvKiogU2F2ZXMgdGhlIHN0YXRlIHRvIEtWLiBZb3UgcHJvYmFibHkgd2FudCB0byB1c2UgI3NhdmVTdGF0ZVRocm90dGxlZCBpbnN0ZWFkIGV4Y2VwdCBmb3IgYSBmZXcgZWRnZSBjYXNlcy4gKi9cblx0YXN5bmMgI3NhdmVQZXJzaXN0SW5uZXIoKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHRoaXMuI2xhc3RTYXZlVGltZSA9IERhdGUubm93KCk7XG5cblx0XHRcdGlmICh0aGlzLiNwZXJzaXN0Q2hhbmdlZCkge1xuXHRcdFx0XHRjb25zdCBmaW5pc2hlZCA9IHRoaXMuI3BlcnNpc3RXcml0ZVF1ZXVlLmVucXVldWUoYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic2F2aW5nIHBlcnNpc3RcIik7XG5cblx0XHRcdFx0XHQvLyBUaGVyZSBtaWdodCBiZSBtb3JlIGNoYW5nZXMgd2hpbGUgd2UncmUgd3JpdGluZywgc28gd2Ugc2V0IHRoaXNcblx0XHRcdFx0XHQvLyBiZWZvcmUgd3JpdGluZyB0byBLViBpbiBvcmRlciB0byBhdm9pZCBhIHJhY2UgY29uZGl0aW9uLlxuXHRcdFx0XHRcdHRoaXMuI3BlcnNpc3RDaGFuZ2VkID0gZmFsc2U7XG5cblx0XHRcdFx0XHQvLyBDb252ZXJ0IHRvIEJBUkUgdHlwZXMgYW5kIHdyaXRlIHRvIEtWXG5cdFx0XHRcdFx0Y29uc3QgYmFyZURhdGEgPSB0aGlzLiNjb252ZXJ0VG9CYXJlUGVyc2lzdGVkKHRoaXMuI3BlcnNpc3RSYXcpO1xuXHRcdFx0XHRcdGF3YWl0IHRoaXMuI2FjdG9yRHJpdmVyLndyaXRlUGVyc2lzdGVkRGF0YShcblx0XHRcdFx0XHRcdHRoaXMuI2FjdG9ySWQsXG5cdFx0XHRcdFx0XHRQRVJTSVNURURfQUNUT1JfVkVSU0lPTkVELnNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oYmFyZURhdGEpLFxuXHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInBlcnNpc3Qgc2F2ZWRcIik7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGF3YWl0IGZpbmlzaGVkO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLiNvblBlcnNpc3RTYXZlZFByb21pc2U/LnJlc29sdmUoKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0dGhpcy4jb25QZXJzaXN0U2F2ZWRQcm9taXNlPy5yZWplY3QoZXJyb3IpO1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgI3F1ZXVlU2V0QWxhcm0odGltZXN0YW1wOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRhd2FpdCB0aGlzLiNhbGFybVdyaXRlUXVldWUuZW5xdWV1ZShhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCB0aGlzLiNhY3RvckRyaXZlci5zZXRBbGFybSh0aGlzLCB0aW1lc3RhbXApO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgcHJveHkgZm9yIGAjcGVyc2lzdGAgdGhhdCBoYW5kbGVzIGF1dG9tYXRpY2FsbHkgZmxhZ2dpbmcgd2hlbiBzdGF0ZSBuZWVkcyB0byBiZSB1cGRhdGVkLlxuXHQgKi9cblx0I3NldFBlcnNpc3QodGFyZ2V0OiBQZXJzaXN0ZWRBY3RvcjxTLCBDUCwgQ1MsIEk+KSB7XG5cdFx0Ly8gU2V0IHJhdyBwZXJzaXN0IG9iamVjdFxuXHRcdHRoaXMuI3BlcnNpc3RSYXcgPSB0YXJnZXQ7XG5cblx0XHQvLyBUT0RPOiBPbmx5IHZhbGlkYXRlIHRoaXMgZm9yIGNvbm4gc3RhdGVcblx0XHQvLyBUT0RPOiBBbGxvdyBkaXNhYmxpbmcgaW4gcHJvZHVjdGlvblxuXHRcdC8vIElmIHRoaXMgY2FuJ3QgYmUgcHJveGllZCwgcmV0dXJuIHJhdyB2YWx1ZVxuXHRcdGlmICh0YXJnZXQgPT09IG51bGwgfHwgdHlwZW9mIHRhcmdldCAhPT0gXCJvYmplY3RcIikge1xuXHRcdFx0bGV0IGludmFsaWRQYXRoID0gXCJcIjtcblx0XHRcdGlmIChcblx0XHRcdFx0IWlzQ2JvclNlcmlhbGl6YWJsZShcblx0XHRcdFx0XHR0YXJnZXQsXG5cdFx0XHRcdFx0KHBhdGgpID0+IHtcblx0XHRcdFx0XHRcdGludmFsaWRQYXRoID0gcGF0aDtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdClcblx0XHRcdCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRTdGF0ZVR5cGUoeyBwYXRoOiBpbnZhbGlkUGF0aCB9KTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB0YXJnZXQ7XG5cdFx0fVxuXG5cdFx0Ly8gVW5zdWJzY3JpYmUgZnJvbSBvbGQgc3RhdGVcblx0XHRpZiAodGhpcy4jcGVyc2lzdCkge1xuXHRcdFx0b25DaGFuZ2UudW5zdWJzY3JpYmUodGhpcy4jcGVyc2lzdCk7XG5cdFx0fVxuXG5cdFx0Ly8gTGlzdGVuIGZvciBjaGFuZ2VzIHRvIHRoZSBvYmplY3QgaW4gb3JkZXIgdG8gYXV0b21hdGljYWxseSB3cml0ZSBzdGF0ZVxuXHRcdHRoaXMuI3BlcnNpc3QgPSBvbkNoYW5nZShcblx0XHRcdHRhcmdldCxcblx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogRG9uJ3Qga25vdyB0eXBlcyBpbiBwcm94eVxuXHRcdFx0KHBhdGg6IHN0cmluZywgdmFsdWU6IGFueSwgX3ByZXZpb3VzVmFsdWU6IGFueSwgX2FwcGx5RGF0YTogYW55KSA9PiB7XG5cdFx0XHRcdGlmIChwYXRoICE9PSBcInN0YXRlXCIgJiYgIXBhdGguc3RhcnRzV2l0aChcInN0YXRlLlwiKSkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGxldCBpbnZhbGlkUGF0aCA9IFwiXCI7XG5cdFx0XHRcdGlmIChcblx0XHRcdFx0XHQhaXNDYm9yU2VyaWFsaXphYmxlKFxuXHRcdFx0XHRcdFx0dmFsdWUsXG5cdFx0XHRcdFx0XHQoaW52YWxpZFBhdGhQYXJ0KSA9PiB7XG5cdFx0XHRcdFx0XHRcdGludmFsaWRQYXRoID0gaW52YWxpZFBhdGhQYXJ0O1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0KVxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRTdGF0ZVR5cGUoe1xuXHRcdFx0XHRcdFx0cGF0aDogcGF0aCArIChpbnZhbGlkUGF0aCA/IGAuJHtpbnZhbGlkUGF0aH1gIDogXCJcIiksXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy4jcGVyc2lzdENoYW5nZWQgPSB0cnVlO1xuXG5cdFx0XHRcdC8vIEluZm9ybSB0aGUgaW5zcGVjdG9yIGFib3V0IHN0YXRlIGNoYW5nZXNcblx0XHRcdFx0dGhpcy5pbnNwZWN0b3IuZW1pdHRlci5lbWl0KFwic3RhdGVVcGRhdGVkXCIsIHRoaXMuI3BlcnNpc3Quc3RhdGUpO1xuXG5cdFx0XHRcdC8vIENhbGwgb25TdGF0ZUNoYW5nZSBpZiBpdCBleGlzdHNcblx0XHRcdFx0Ly8gU2tpcCBpZiB3ZSdyZSBhbHJlYWR5IGluc2lkZSBvblN0YXRlQ2hhbmdlIHRvIHByZXZlbnQgaW5maW5pdGUgcmVjdXJzaW9uXG5cdFx0XHRcdGlmICh0aGlzLiNjb25maWcub25TdGF0ZUNoYW5nZSAmJiB0aGlzLiNyZWFkeSAmJiAhdGhpcy4jaXNJbk9uU3RhdGVDaGFuZ2UpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0dGhpcy4jaXNJbk9uU3RhdGVDaGFuZ2UgPSB0cnVlO1xuXHRcdFx0XHRcdFx0dGhpcy4jY29uZmlnLm9uU3RhdGVDaGFuZ2UoXG5cdFx0XHRcdFx0XHRcdHRoaXMuYWN0b3JDb250ZXh0LFxuXHRcdFx0XHRcdFx0XHR0aGlzLiNwZXJzaXN0UmF3LnN0YXRlLFxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBgX29uU3RhdGVDaGFuZ2VgXCIsIHtcblx0XHRcdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHR0aGlzLiNpc0luT25TdGF0ZUNoYW5nZSA9IGZhbHNlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN0YXRlIHdpbGwgYmUgZmx1c2hlZCBhdCB0aGUgZW5kIG9mIHRoZSBhY3Rpb25cblx0XHRcdH0sXG5cdFx0XHR7IGlnbm9yZURldGFjaGVkOiB0cnVlIH0sXG5cdFx0KTtcblx0fVxuXG5cdGFzeW5jICNpbml0aWFsaXplKCkge1xuXHRcdC8vIFJlYWQgaW5pdGlhbCBzdGF0ZVxuXHRcdGNvbnN0IHBlcnNpc3REYXRhQnVmZmVyID0gYXdhaXQgdGhpcy4jYWN0b3JEcml2ZXIucmVhZFBlcnNpc3RlZERhdGEoXG5cdFx0XHR0aGlzLiNhY3RvcklkLFxuXHRcdCk7XG5cdFx0aW52YXJpYW50KFxuXHRcdFx0cGVyc2lzdERhdGFCdWZmZXIgIT09IHVuZGVmaW5lZCxcblx0XHRcdFwicGVyc2lzdCBkYXRhIGhhcyBub3QgYmVlbiBzZXQsIGl0IHNob3VsZCBiZSBzZXQgd2hlbiBpbml0aWFsaXplZFwiLFxuXHRcdCk7XG5cdFx0Y29uc3QgYmFyZURhdGEgPVxuXHRcdFx0UEVSU0lTVEVEX0FDVE9SX1ZFUlNJT05FRC5kZXNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oXG5cdFx0XHRcdHBlcnNpc3REYXRhQnVmZmVyLFxuXHRcdFx0KTtcblx0XHRjb25zdCBwZXJzaXN0RGF0YSA9IHRoaXMuI2NvbnZlcnRGcm9tQmFyZVBlcnNpc3RlZChiYXJlRGF0YSk7XG5cblx0XHRpZiAocGVyc2lzdERhdGEuaGFzSW5pdGlhdGVkKSB7XG5cdFx0XHRsb2dnZXIoKS5pbmZvKFwiYWN0b3IgcmVzdG9yaW5nXCIsIHtcblx0XHRcdFx0Y29ubmVjdGlvbnM6IHBlcnNpc3REYXRhLmNvbm5lY3Rpb25zLmxlbmd0aCxcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBTZXQgaW5pdGlhbCBzdGF0ZVxuXHRcdFx0dGhpcy4jc2V0UGVyc2lzdChwZXJzaXN0RGF0YSk7XG5cblx0XHRcdC8vIExvYWQgY29ubmVjdGlvbnNcblx0XHRcdGZvciAoY29uc3QgY29ublBlcnNpc3Qgb2YgdGhpcy4jcGVyc2lzdC5jb25uZWN0aW9ucykge1xuXHRcdFx0XHQvLyBDcmVhdGUgY29ubmVjdGlvbnNcblx0XHRcdFx0Y29uc3QgZHJpdmVyID0gdGhpcy5fX2dldENvbm5Ecml2ZXIoY29ublBlcnNpc3QuY29ubkRyaXZlcik7XG5cdFx0XHRcdGNvbnN0IGNvbm4gPSBuZXcgQ29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4oXG5cdFx0XHRcdFx0dGhpcyxcblx0XHRcdFx0XHRjb25uUGVyc2lzdCxcblx0XHRcdFx0XHRkcml2ZXIsXG5cdFx0XHRcdFx0dGhpcy4jY29ublN0YXRlRW5hYmxlZCxcblx0XHRcdFx0KTtcblx0XHRcdFx0dGhpcy4jY29ubmVjdGlvbnMuc2V0KGNvbm4uaWQsIGNvbm4pO1xuXG5cdFx0XHRcdC8vIFJlZ2lzdGVyIGV2ZW50IHN1YnNjcmlwdGlvbnNcblx0XHRcdFx0Zm9yIChjb25zdCBzdWIgb2YgY29ublBlcnNpc3Quc3Vic2NyaXB0aW9ucykge1xuXHRcdFx0XHRcdHRoaXMuI2FkZFN1YnNjcmlwdGlvbihzdWIuZXZlbnROYW1lLCBjb25uLCB0cnVlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRsb2dnZXIoKS5pbmZvKFwiYWN0b3IgY3JlYXRpbmdcIik7XG5cblx0XHRcdC8vIEluaXRpYWxpemUgYWN0b3Igc3RhdGVcblx0XHRcdGxldCBzdGF0ZURhdGE6IHVua25vd247XG5cdFx0XHRpZiAodGhpcy5zdGF0ZUVuYWJsZWQpIHtcblx0XHRcdFx0bG9nZ2VyKCkuaW5mbyhcImFjdG9yIHN0YXRlIGluaXRpYWxpemluZ1wiKTtcblxuXHRcdFx0XHRpZiAoXCJjcmVhdGVTdGF0ZVwiIGluIHRoaXMuI2NvbmZpZykge1xuXHRcdFx0XHRcdHRoaXMuI2NvbmZpZy5jcmVhdGVTdGF0ZTtcblxuXHRcdFx0XHRcdC8vIENvbnZlcnQgc3RhdGUgdG8gdW5kZWZpbmVkIHNpbmNlIHN0YXRlIGlzIG5vdCBkZWZpbmVkIHlldCBoZXJlXG5cdFx0XHRcdFx0c3RhdGVEYXRhID0gYXdhaXQgdGhpcy4jY29uZmlnLmNyZWF0ZVN0YXRlKFxuXHRcdFx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQgYXMgdW5rbm93biBhcyBBY3RvckNvbnRleHQ8XG5cdFx0XHRcdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHRcdHVuZGVmaW5lZFxuXHRcdFx0XHRcdFx0Pixcblx0XHRcdFx0XHRcdHBlcnNpc3REYXRhLmlucHV0ISxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKFwic3RhdGVcIiBpbiB0aGlzLiNjb25maWcpIHtcblx0XHRcdFx0XHRzdGF0ZURhdGEgPSBzdHJ1Y3R1cmVkQ2xvbmUodGhpcy4jY29uZmlnLnN0YXRlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJCb3RoICdjcmVhdGVTdGF0ZScgb3IgJ3N0YXRlJyB3ZXJlIG5vdCBkZWZpbmVkXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInN0YXRlIG5vdCBlbmFibGVkXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTYXZlIHN0YXRlIGFuZCBtYXJrIGFzIGluaXRpYWxpemVkXG5cdFx0XHRwZXJzaXN0RGF0YS5zdGF0ZSA9IHN0YXRlRGF0YSBhcyBTO1xuXHRcdFx0cGVyc2lzdERhdGEuaGFzSW5pdGlhdGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gVXBkYXRlIHN0YXRlXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcIndyaXRpbmcgc3RhdGVcIik7XG5cdFx0XHRjb25zdCBiYXJlRGF0YSA9IHRoaXMuI2NvbnZlcnRUb0JhcmVQZXJzaXN0ZWQocGVyc2lzdERhdGEpO1xuXHRcdFx0YXdhaXQgdGhpcy4jYWN0b3JEcml2ZXIud3JpdGVQZXJzaXN0ZWREYXRhKFxuXHRcdFx0XHR0aGlzLiNhY3RvcklkLFxuXHRcdFx0XHRQRVJTSVNURURfQUNUT1JfVkVSU0lPTkVELnNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oYmFyZURhdGEpLFxuXHRcdFx0KTtcblxuXHRcdFx0dGhpcy4jc2V0UGVyc2lzdChwZXJzaXN0RGF0YSk7XG5cblx0XHRcdC8vIE5vdGlmeSBjcmVhdGlvblxuXHRcdFx0aWYgKHRoaXMuI2NvbmZpZy5vbkNyZWF0ZSkge1xuXHRcdFx0XHRhd2FpdCB0aGlzLiNjb25maWcub25DcmVhdGUodGhpcy5hY3RvckNvbnRleHQsIHBlcnNpc3REYXRhLmlucHV0ISk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0X19nZXRDb25uRm9ySWQoaWQ6IHN0cmluZyk6IENvbm48UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+IHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gdGhpcy4jY29ubmVjdGlvbnMuZ2V0KGlkKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgY29ubmVjdGlvbiBhbmQgY2xlYW5zIHVwIGl0cyByZXNvdXJjZXMuXG5cdCAqL1xuXHRfX3JlbW92ZUNvbm4oY29ubjogQ29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4gfCB1bmRlZmluZWQpIHtcblx0XHRpZiAoIWNvbm4pIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXCJgY29ubmAgZG9lcyBub3QgZXhpc3RcIik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIGZyb20gcGVyc2lzdCAmIHNhdmUgaW1tZWRpYXRlbHlcblx0XHRjb25zdCBjb25uSWR4ID0gdGhpcy4jcGVyc2lzdC5jb25uZWN0aW9ucy5maW5kSW5kZXgoXG5cdFx0XHQoYykgPT4gYy5jb25uSWQgPT09IGNvbm4uaWQsXG5cdFx0KTtcblx0XHRpZiAoY29ubklkeCAhPT0gLTEpIHtcblx0XHRcdHRoaXMuI3BlcnNpc3QuY29ubmVjdGlvbnMuc3BsaWNlKGNvbm5JZHgsIDEpO1xuXHRcdFx0dGhpcy5zYXZlU3RhdGUoeyBpbW1lZGlhdGU6IHRydWUsIGFsbG93U3RvcHBpbmdTdGF0ZTogdHJ1ZSB9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bG9nZ2VyKCkud2FybihcImNvdWxkIG5vdCBmaW5kIHBlcnNpc3RlZCBjb25uZWN0aW9uIHRvIHJlbW92ZVwiLCB7XG5cdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdC8vIFJlbW92ZSBmcm9tIHN0YXRlXG5cdFx0dGhpcy4jY29ubmVjdGlvbnMuZGVsZXRlKGNvbm4uaWQpO1xuXG5cdFx0Ly8gUmVtb3ZlIHN1YnNjcmlwdGlvbnNcblx0XHRmb3IgKGNvbnN0IGV2ZW50TmFtZSBvZiBbLi4uY29ubi5zdWJzY3JpcHRpb25zLnZhbHVlcygpXSkge1xuXHRcdFx0dGhpcy4jcmVtb3ZlU3Vic2NyaXB0aW9uKGV2ZW50TmFtZSwgY29ubiwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5pbnNwZWN0b3IuZW1pdHRlci5lbWl0KFwiY29ubmVjdGlvblVwZGF0ZWRcIik7XG5cdFx0aWYgKHRoaXMuI2NvbmZpZy5vbkRpc2Nvbm5lY3QpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGNvbnN0IHJlc3VsdCA9IHRoaXMuI2NvbmZpZy5vbkRpc2Nvbm5lY3QodGhpcy5hY3RvckNvbnRleHQsIGNvbm4pO1xuXHRcdFx0XHRpZiAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkge1xuXHRcdFx0XHRcdC8vIEhhbmRsZSBwcm9taXNlIGJ1dCBkb24ndCBhd2FpdCBpdCB0byBwcmV2ZW50IGJsb2NraW5nXG5cdFx0XHRcdFx0cmVzdWx0LmNhdGNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBgb25EaXNjb25uZWN0YFwiLCB7XG5cdFx0XHRcdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBgb25EaXNjb25uZWN0YFwiLCB7XG5cdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gVXBkYXRlIHNsZWVwXG5cdFx0dGhpcy4jcmVzZXRTbGVlcFRpbWVyKCk7XG5cdH1cblxuXHRhc3luYyBwcmVwYXJlQ29ubihcblx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFR5cGVTY3JpcHQgYnVnIHdpdGggRXh0cmFjdEFjdG9yQ29ublBhcmFtczx0aGlzPixcblx0XHRwYXJhbXM6IGFueSxcblx0XHRyZXF1ZXN0PzogUmVxdWVzdCxcblx0KTogUHJvbWlzZTxDUz4ge1xuXHRcdC8vIEF1dGhlbnRpY2F0ZSBjb25uZWN0aW9uXG5cdFx0bGV0IGNvbm5TdGF0ZTogQ1MgfCB1bmRlZmluZWQ7XG5cblx0XHRjb25zdCBvbkJlZm9yZUNvbm5lY3RPcHRzID0ge1xuXHRcdFx0cmVxdWVzdCxcblx0XHR9IHNhdGlzZmllcyBPbkNvbm5lY3RPcHRpb25zO1xuXG5cdFx0aWYgKHRoaXMuI2NvbmZpZy5vbkJlZm9yZUNvbm5lY3QpIHtcblx0XHRcdGF3YWl0IHRoaXMuI2NvbmZpZy5vbkJlZm9yZUNvbm5lY3QoXG5cdFx0XHRcdHRoaXMuYWN0b3JDb250ZXh0LFxuXHRcdFx0XHRvbkJlZm9yZUNvbm5lY3RPcHRzLFxuXHRcdFx0XHRwYXJhbXMsXG5cdFx0XHQpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLiNjb25uU3RhdGVFbmFibGVkKSB7XG5cdFx0XHRpZiAoXCJjcmVhdGVDb25uU3RhdGVcIiBpbiB0aGlzLiNjb25maWcpIHtcblx0XHRcdFx0Y29uc3QgZGF0YU9yUHJvbWlzZSA9IHRoaXMuI2NvbmZpZy5jcmVhdGVDb25uU3RhdGUoXG5cdFx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQgYXMgdW5rbm93biBhcyBBY3RvckNvbnRleHQ8XG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdFx0XHR1bmRlZmluZWRcblx0XHRcdFx0XHQ+LFxuXHRcdFx0XHRcdG9uQmVmb3JlQ29ubmVjdE9wdHMsXG5cdFx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0XHQpO1xuXHRcdFx0XHRpZiAoZGF0YU9yUHJvbWlzZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcblx0XHRcdFx0XHRjb25uU3RhdGUgPSBhd2FpdCBkZWFkbGluZShcblx0XHRcdFx0XHRcdGRhdGFPclByb21pc2UsXG5cdFx0XHRcdFx0XHR0aGlzLiNjb25maWcub3B0aW9ucy5jcmVhdGVDb25uU3RhdGVUaW1lb3V0LFxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29ublN0YXRlID0gZGF0YU9yUHJvbWlzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChcImNvbm5TdGF0ZVwiIGluIHRoaXMuI2NvbmZpZykge1xuXHRcdFx0XHRjb25uU3RhdGUgPSBzdHJ1Y3R1cmVkQ2xvbmUodGhpcy4jY29uZmlnLmNvbm5TdGF0ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdFx0XCJDb3VsZCBub3QgY3JlYXRlIGNvbm5lY3Rpb24gc3RhdGUgZnJvbSAnY3JlYXRlQ29ublN0YXRlJyBvciAnY29ublN0YXRlJ1wiLFxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBjb25uU3RhdGUgYXMgQ1M7XG5cdH1cblxuXHRfX2dldENvbm5Ecml2ZXIoZHJpdmVySWQ6IENvbm5lY3Rpb25Ecml2ZXIpOiBDb25uRHJpdmVyIHtcblx0XHQvLyBHZXQgZHJpdmVyXG5cdFx0Y29uc3QgZHJpdmVyID0gdGhpcy4jY29ubmVjdGlvbkRyaXZlcnNbZHJpdmVySWRdO1xuXHRcdGlmICghZHJpdmVyKSB0aHJvdyBuZXcgRXJyb3IoYE5vIGNvbm5lY3Rpb24gZHJpdmVyOiAke2RyaXZlcklkfWApO1xuXHRcdHJldHVybiBkcml2ZXI7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIGFmdGVyIGVzdGFibGlzaGluZyBhIGNvbm5lY3Rpb24gaGFuZHNoYWtlLlxuXHQgKi9cblx0YXN5bmMgY3JlYXRlQ29ubihcblx0XHRjb25uZWN0aW9uSWQ6IHN0cmluZyxcblx0XHRjb25uZWN0aW9uVG9rZW46IHN0cmluZyxcblx0XHRwYXJhbXM6IENQLFxuXHRcdHN0YXRlOiBDUyxcblx0XHRkcml2ZXJJZDogQ29ubmVjdGlvbkRyaXZlcixcblx0XHRkcml2ZXJTdGF0ZTogdW5rbm93bixcblx0XHRhdXRoRGF0YTogdW5rbm93bixcblx0KTogUHJvbWlzZTxDb25uPFMsIENQLCBDUywgViwgSSwgQUQsIERCPj4ge1xuXHRcdHRoaXMuI2Fzc2VydFJlYWR5KCk7XG5cblx0XHRpZiAodGhpcy4jY29ubmVjdGlvbnMuaGFzKGNvbm5lY3Rpb25JZCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgQ29ubmVjdGlvbiBhbHJlYWR5IGV4aXN0czogJHtjb25uZWN0aW9uSWR9YCk7XG5cdFx0fVxuXG5cdFx0Ly8gQ3JlYXRlIGNvbm5lY3Rpb25cblx0XHRjb25zdCBkcml2ZXIgPSB0aGlzLl9fZ2V0Q29ubkRyaXZlcihkcml2ZXJJZCk7XG5cdFx0Y29uc3QgcGVyc2lzdDogUGVyc2lzdGVkQ29ubjxDUCwgQ1M+ID0ge1xuXHRcdFx0Y29ubklkOiBjb25uZWN0aW9uSWQsXG5cdFx0XHR0b2tlbjogY29ubmVjdGlvblRva2VuLFxuXHRcdFx0Y29ubkRyaXZlcjogZHJpdmVySWQsXG5cdFx0XHRjb25uRHJpdmVyU3RhdGU6IGRyaXZlclN0YXRlLFxuXHRcdFx0cGFyYW1zOiBwYXJhbXMsXG5cdFx0XHRzdGF0ZTogc3RhdGUsXG5cdFx0XHRhdXRoRGF0YTogYXV0aERhdGEsXG5cdFx0XHRsYXN0U2VlbjogRGF0ZS5ub3coKSxcblx0XHRcdHN1YnNjcmlwdGlvbnM6IFtdLFxuXHRcdH07XG5cdFx0Y29uc3QgY29ubiA9IG5ldyBDb25uPFMsIENQLCBDUywgViwgSSwgQUQsIERCPihcblx0XHRcdHRoaXMsXG5cdFx0XHRwZXJzaXN0LFxuXHRcdFx0ZHJpdmVyLFxuXHRcdFx0dGhpcy4jY29ublN0YXRlRW5hYmxlZCxcblx0XHQpO1xuXHRcdHRoaXMuI2Nvbm5lY3Rpb25zLnNldChjb25uLmlkLCBjb25uKTtcblxuXHRcdC8vIFVwZGF0ZSBzbGVlcFxuXHRcdC8vXG5cdFx0Ly8gRG8gdGhpcyBpbW1lZGlhdGVseSBhZnRlciBhZGRpbmcgY29ubmVjdGlvbiAmIGJlZm9yZSBhbnkgYXN5bmMgbG9naWMgaW4gb3JkZXIgdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zIHdpdGggc2xlZXAgdGltZW91dHNcblx0XHR0aGlzLiNyZXNldFNsZWVwVGltZXIoKTtcblxuXHRcdC8vIEFkZCB0byBwZXJzaXN0ZW5jZSAmIHNhdmUgaW1tZWRpYXRlbHlcblx0XHR0aGlzLiNwZXJzaXN0LmNvbm5lY3Rpb25zLnB1c2gocGVyc2lzdCk7XG5cdFx0dGhpcy5zYXZlU3RhdGUoeyBpbW1lZGlhdGU6IHRydWUgfSk7XG5cblx0XHQvLyBIYW5kbGUgY29ubmVjdGlvblxuXHRcdGlmICh0aGlzLiNjb25maWcub25Db25uZWN0KSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSB0aGlzLiNjb25maWcub25Db25uZWN0KHRoaXMuYWN0b3JDb250ZXh0LCBjb25uKTtcblx0XHRcdFx0aWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcblx0XHRcdFx0XHRkZWFkbGluZShyZXN1bHQsIHRoaXMuI2NvbmZpZy5vcHRpb25zLm9uQ29ubmVjdFRpbWVvdXQpLmNhdGNoKFxuXHRcdFx0XHRcdFx0KGVycm9yKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gYG9uQ29ubmVjdGAsIGNsb3Npbmcgc29ja2V0XCIsIHtcblx0XHRcdFx0XHRcdFx0XHRlcnJvcixcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdGNvbm4/LmRpc2Nvbm5lY3QoXCJgb25Db25uZWN0YCBmYWlsZWRcIik7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gYG9uQ29ubmVjdGBcIiwge1xuXHRcdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRjb25uPy5kaXNjb25uZWN0KFwiYG9uQ29ubmVjdGAgZmFpbGVkXCIpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuaW5zcGVjdG9yLmVtaXR0ZXIuZW1pdChcImNvbm5lY3Rpb25VcGRhdGVkXCIpO1xuXG5cdFx0Ly8gU2VuZCBpbml0IG1lc3NhZ2Vcblx0XHRjb25uLl9zZW5kTWVzc2FnZShcblx0XHRcdG5ldyBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pihcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJvZHk6IHtcblx0XHRcdFx0XHRcdHRhZzogXCJJbml0XCIsXG5cdFx0XHRcdFx0XHR2YWw6IHtcblx0XHRcdFx0XHRcdFx0YWN0b3JJZDogdGhpcy5pZCxcblx0XHRcdFx0XHRcdFx0Y29ubmVjdGlvbklkOiBjb25uLmlkLFxuXHRcdFx0XHRcdFx0XHRjb25uZWN0aW9uVG9rZW46IGNvbm4uX3Rva2VuLFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRUT19DTElFTlRfVkVSU0lPTkVELFxuXHRcdFx0KSxcblx0XHQpO1xuXG5cdFx0cmV0dXJuIGNvbm47XG5cdH1cblxuXHQvLyBNQVJLOiBNZXNzYWdlc1xuXHRhc3luYyBwcm9jZXNzTWVzc2FnZShcblx0XHRtZXNzYWdlOiBwcm90b2NvbC5Ub1NlcnZlcixcblx0XHRjb25uOiBDb25uPFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcblx0KSB7XG5cdFx0YXdhaXQgcHJvY2Vzc01lc3NhZ2UobWVzc2FnZSwgdGhpcywgY29ubiwge1xuXHRcdFx0b25FeGVjdXRlQWN0aW9uOiBhc3luYyAoY3R4LCBuYW1lLCBhcmdzKSA9PiB7XG5cdFx0XHRcdHRoaXMuaW5zcGVjdG9yLmVtaXR0ZXIuZW1pdChcImV2ZW50RmlyZWRcIiwge1xuXHRcdFx0XHRcdHR5cGU6IFwiYWN0aW9uXCIsXG5cdFx0XHRcdFx0bmFtZSxcblx0XHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybiBhd2FpdCB0aGlzLmV4ZWN1dGVBY3Rpb24oY3R4LCBuYW1lLCBhcmdzKTtcblx0XHRcdH0sXG5cdFx0XHRvblN1YnNjcmliZTogYXN5bmMgKGV2ZW50TmFtZSwgY29ubikgPT4ge1xuXHRcdFx0XHR0aGlzLmluc3BlY3Rvci5lbWl0dGVyLmVtaXQoXCJldmVudEZpcmVkXCIsIHtcblx0XHRcdFx0XHR0eXBlOiBcInN1YnNjcmliZVwiLFxuXHRcdFx0XHRcdGV2ZW50TmFtZSxcblx0XHRcdFx0XHRjb25uSWQ6IGNvbm4uaWQsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHR0aGlzLiNhZGRTdWJzY3JpcHRpb24oZXZlbnROYW1lLCBjb25uLCBmYWxzZSk7XG5cdFx0XHR9LFxuXHRcdFx0b25VbnN1YnNjcmliZTogYXN5bmMgKGV2ZW50TmFtZSwgY29ubikgPT4ge1xuXHRcdFx0XHR0aGlzLmluc3BlY3Rvci5lbWl0dGVyLmVtaXQoXCJldmVudEZpcmVkXCIsIHtcblx0XHRcdFx0XHR0eXBlOiBcInVuc3Vic2NyaWJlXCIsXG5cdFx0XHRcdFx0ZXZlbnROYW1lLFxuXHRcdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuI3JlbW92ZVN1YnNjcmlwdGlvbihldmVudE5hbWUsIGNvbm4sIGZhbHNlKTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cdH1cblxuXHQvLyBNQVJLOiBFdmVudHNcblx0I2FkZFN1YnNjcmlwdGlvbihcblx0XHRldmVudE5hbWU6IHN0cmluZyxcblx0XHRjb25uZWN0aW9uOiBDb25uPFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcblx0XHRmcm9tUGVyc2lzdDogYm9vbGVhbixcblx0KSB7XG5cdFx0aWYgKGNvbm5lY3Rpb24uc3Vic2NyaXB0aW9ucy5oYXMoZXZlbnROYW1lKSkge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjb25uZWN0aW9uIGFscmVhZHkgaGFzIHN1YnNjcmlwdGlvblwiLCB7IGV2ZW50TmFtZSB9KTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBQZXJzaXN0IHN1YnNjcmlwdGlvbnMgJiBzYXZlIGltbWVkaWF0ZWx5XG5cdFx0Ly9cblx0XHQvLyBEb24ndCB1cGRhdGUgcGVyc2lzdGVuY2UgaWYgYWxyZWFkeSByZXN0b3JpbmcgZnJvbSBwZXJzaXN0ZW5jZVxuXHRcdGlmICghZnJvbVBlcnNpc3QpIHtcblx0XHRcdGNvbm5lY3Rpb24uX19wZXJzaXN0LnN1YnNjcmlwdGlvbnMucHVzaCh7IGV2ZW50TmFtZTogZXZlbnROYW1lIH0pO1xuXHRcdFx0dGhpcy5zYXZlU3RhdGUoeyBpbW1lZGlhdGU6IHRydWUgfSk7XG5cdFx0fVxuXG5cdFx0Ly8gVXBkYXRlIHN1YnNjcmlwdGlvbnNcblx0XHRjb25uZWN0aW9uLnN1YnNjcmlwdGlvbnMuYWRkKGV2ZW50TmFtZSk7XG5cblx0XHQvLyBVcGRhdGUgc3Vic2NyaXB0aW9uIGluZGV4XG5cdFx0bGV0IHN1YnNjcmliZXJzID0gdGhpcy4jc3Vic2NyaXB0aW9uSW5kZXguZ2V0KGV2ZW50TmFtZSk7XG5cdFx0aWYgKCFzdWJzY3JpYmVycykge1xuXHRcdFx0c3Vic2NyaWJlcnMgPSBuZXcgU2V0KCk7XG5cdFx0XHR0aGlzLiNzdWJzY3JpcHRpb25JbmRleC5zZXQoZXZlbnROYW1lLCBzdWJzY3JpYmVycyk7XG5cdFx0fVxuXHRcdHN1YnNjcmliZXJzLmFkZChjb25uZWN0aW9uKTtcblx0fVxuXG5cdCNyZW1vdmVTdWJzY3JpcHRpb24oXG5cdFx0ZXZlbnROYW1lOiBzdHJpbmcsXG5cdFx0Y29ubmVjdGlvbjogQ29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4sXG5cdFx0ZnJvbVJlbW92ZUNvbm46IGJvb2xlYW4sXG5cdCkge1xuXHRcdGlmICghY29ubmVjdGlvbi5zdWJzY3JpcHRpb25zLmhhcyhldmVudE5hbWUpKSB7XG5cdFx0XHRsb2dnZXIoKS53YXJuKFwiY29ubmVjdGlvbiBkb2VzIG5vdCBoYXZlIHN1YnNjcmlwdGlvblwiLCB7IGV2ZW50TmFtZSB9KTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBQZXJzaXN0IHN1YnNjcmlwdGlvbnMgJiBzYXZlIGltbWVkaWF0ZWx5XG5cdFx0Ly9cblx0XHQvLyBEb24ndCB1cGRhdGUgdGhlIGNvbm5lY3Rpb24gaXRzZWxmIGlmIHRoZSBjb25uZWN0aW9uIGlzIGFscmVhZHkgYmVpbmcgcmVtb3ZlZFxuXHRcdGlmICghZnJvbVJlbW92ZUNvbm4pIHtcblx0XHRcdGNvbm5lY3Rpb24uc3Vic2NyaXB0aW9ucy5kZWxldGUoZXZlbnROYW1lKTtcblxuXHRcdFx0Y29uc3Qgc3ViSWR4ID0gY29ubmVjdGlvbi5fX3BlcnNpc3Quc3Vic2NyaXB0aW9ucy5maW5kSW5kZXgoXG5cdFx0XHRcdChzKSA9PiBzLmV2ZW50TmFtZSA9PT0gZXZlbnROYW1lLFxuXHRcdFx0KTtcblx0XHRcdGlmIChzdWJJZHggIT09IC0xKSB7XG5cdFx0XHRcdGNvbm5lY3Rpb24uX19wZXJzaXN0LnN1YnNjcmlwdGlvbnMuc3BsaWNlKHN1YklkeCwgMSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRsb2dnZXIoKS53YXJuKFwic3Vic2NyaXB0aW9uIGRvZXMgbm90IGV4aXN0IHdpdGggbmFtZVwiLCB7IGV2ZW50TmFtZSB9KTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zYXZlU3RhdGUoeyBpbW1lZGlhdGU6IHRydWUgfSk7XG5cdFx0fVxuXG5cdFx0Ly8gVXBkYXRlIHNjcmlwdGlvbnMgaW5kZXhcblx0XHRjb25zdCBzdWJzY3JpYmVycyA9IHRoaXMuI3N1YnNjcmlwdGlvbkluZGV4LmdldChldmVudE5hbWUpO1xuXHRcdGlmIChzdWJzY3JpYmVycykge1xuXHRcdFx0c3Vic2NyaWJlcnMuZGVsZXRlKGNvbm5lY3Rpb24pO1xuXHRcdFx0aWYgKHN1YnNjcmliZXJzLnNpemUgPT09IDApIHtcblx0XHRcdFx0dGhpcy4jc3Vic2NyaXB0aW9uSW5kZXguZGVsZXRlKGV2ZW50TmFtZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0I2Fzc2VydFJlYWR5KGFsbG93U3RvcHBpbmdTdGF0ZTogYm9vbGVhbiA9IGZhbHNlKSB7XG5cdFx0aWYgKCF0aGlzLiNyZWFkeSkgdGhyb3cgbmV3IGVycm9ycy5JbnRlcm5hbEVycm9yKFwiQWN0b3Igbm90IHJlYWR5XCIpO1xuXHRcdGlmICghYWxsb3dTdG9wcGluZ1N0YXRlICYmIHRoaXMuI3NsZWVwQ2FsbGVkKVxuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnRlcm5hbEVycm9yKFwiQWN0b3IgaXMgZ29pbmcgdG8gc2xlZXBcIik7XG5cdFx0aWYgKCFhbGxvd1N0b3BwaW5nU3RhdGUgJiYgdGhpcy4jc3RvcENhbGxlZClcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuSW50ZXJuYWxFcnJvcihcIkFjdG9yIGlzIHN0b3BwaW5nXCIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIHRoZSBsaXZlbmVzcyBvZiBhbGwgY29ubmVjdGlvbnMuXG5cdCAqIFNldHMgdXAgYSByZWN1cnJpbmcgY2hlY2sgYmFzZWQgb24gdGhlIGNvbmZpZ3VyZWQgaW50ZXJ2YWwuXG5cdCAqL1xuXHQjY2hlY2tDb25uZWN0aW9uc0xpdmVuZXNzKCkge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiY2hlY2tpbmcgY29ubmVjdGlvbnMgbGl2ZW5lc3NcIik7XG5cblx0XHRmb3IgKGNvbnN0IGNvbm4gb2YgdGhpcy4jY29ubmVjdGlvbnMudmFsdWVzKCkpIHtcblx0XHRcdGNvbnN0IGxpdmVuZXNzID0gY29ubltDT05ORUNUSU9OX0NIRUNLX0xJVkVORVNTX1NZTUJPTF0oKTtcblx0XHRcdGlmIChsaXZlbmVzcy5zdGF0dXMgPT09IFwiY29ubmVjdGVkXCIpIHtcblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjb25uZWN0aW9uIGlzIGFsaXZlXCIsIHsgY29ubklkOiBjb25uLmlkIH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgbGFzdFNlZW4gPSBsaXZlbmVzcy5sYXN0U2Vlbjtcblx0XHRcdFx0Y29uc3Qgc2luY2VMYXN0U2VlbiA9IERhdGUubm93KCkgLSBsYXN0U2Vlbjtcblx0XHRcdFx0aWYgKHNpbmNlTGFzdFNlZW4gPCB0aGlzLiNjb25maWcub3B0aW9ucy5jb25uZWN0aW9uTGl2ZW5lc3NUaW1lb3V0KSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjb25uZWN0aW9uIG1pZ2h0IGJlIGFsaXZlLCB3aWxsIGNoZWNrIGxhdGVyXCIsIHtcblx0XHRcdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdFx0XHRcdGxhc3RTZWVuLFxuXHRcdFx0XHRcdFx0c2luY2VMYXN0U2Vlbixcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIENvbm5lY3Rpb24gaXMgZGVhZCwgcmVtb3ZlIGl0XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJjb25uZWN0aW9uIGlzIGRlYWQsIHJlbW92aW5nXCIsIHtcblx0XHRcdFx0XHRjb25uSWQ6IGNvbm4uaWQsXG5cdFx0XHRcdFx0bGFzdFNlZW4sXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdC8vIFRPRE86IERvIHdlIG5lZWQgdG8gZm9yY2UgZGlzY29ubmVjdCB0aGUgY29ubmVjdGlvbiBoZXJlP1xuXG5cdFx0XHRcdHRoaXMuX19yZW1vdmVDb25uKGNvbm4pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiB0aGUgYWN0b3IgaXMgcmVhZHkgdG8gaGFuZGxlIHJlcXVlc3RzLlxuXHQgKi9cblx0aXNSZWFkeSgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy4jcmVhZHk7XG5cdH1cblxuXHQvKipcblx0ICogRXhlY3V0ZSBhbiBhY3Rpb24gY2FsbCBmcm9tIGEgY2xpZW50LlxuXHQgKlxuXHQgKiBUaGlzIG1ldGhvZCBoYW5kbGVzOlxuXHQgKiAxLiBWYWxpZGF0aW5nIHRoZSBhY3Rpb24gbmFtZVxuXHQgKiAyLiBFeGVjdXRpbmcgdGhlIGFjdGlvbiBmdW5jdGlvblxuXHQgKiAzLiBQcm9jZXNzaW5nIHRoZSByZXN1bHQgdGhyb3VnaCBvbkJlZm9yZUFjdGlvblJlc3BvbnNlIChpZiBjb25maWd1cmVkKVxuXHQgKiA0LiBIYW5kbGluZyB0aW1lb3V0cyBhbmQgZXJyb3JzXG5cdCAqIDUuIFNhdmluZyBzdGF0ZSBjaGFuZ2VzXG5cdCAqXG5cdCAqIEBwYXJhbSBjdHggVGhlIGFjdGlvbiBjb250ZXh0XG5cdCAqIEBwYXJhbSBhY3Rpb25OYW1lIFRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gYmVpbmcgY2FsbGVkXG5cdCAqIEBwYXJhbSBhcmdzIFRoZSBhcmd1bWVudHMgcGFzc2VkIHRvIHRoZSBhY3Rpb25cblx0ICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiB0aGUgYWN0aW9uIGNhbGxcblx0ICogQHRocm93cyB7QWN0aW9uTm90Rm91bmR9IElmIHRoZSBhY3Rpb24gZG9lc24ndCBleGlzdFxuXHQgKiBAdGhyb3dzIHtBY3Rpb25UaW1lZE91dH0gSWYgdGhlIGFjdGlvbiB0aW1lcyBvdXRcblx0ICogQGludGVybmFsXG5cdCAqL1xuXHRhc3luYyBleGVjdXRlQWN0aW9uKFxuXHRcdGN0eDogQWN0aW9uQ29udGV4dDxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4sXG5cdFx0YWN0aW9uTmFtZTogc3RyaW5nLFxuXHRcdGFyZ3M6IHVua25vd25bXSxcblx0KTogUHJvbWlzZTx1bmtub3duPiB7XG5cdFx0aW52YXJpYW50KHRoaXMuI3JlYWR5LCBcImV4ZWN1dGluZyBhY3Rpb24gYmVmb3JlIHJlYWR5XCIpO1xuXG5cdFx0Ly8gUHJldmVudCBjYWxsaW5nIHByaXZhdGUgb3IgcmVzZXJ2ZWQgbWV0aG9kc1xuXHRcdGlmICghKGFjdGlvbk5hbWUgaW4gdGhpcy4jY29uZmlnLmFjdGlvbnMpKSB7XG5cdFx0XHRsb2dnZXIoKS53YXJuKFwiYWN0aW9uIGRvZXMgbm90IGV4aXN0XCIsIHsgYWN0aW9uTmFtZSB9KTtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuQWN0aW9uTm90Rm91bmQoYWN0aW9uTmFtZSk7XG5cdFx0fVxuXG5cdFx0Ly8gQ2hlY2sgaWYgdGhlIG1ldGhvZCBleGlzdHMgb24gdGhpcyBvYmplY3Rcblx0XHRjb25zdCBhY3Rpb25GdW5jdGlvbiA9IHRoaXMuI2NvbmZpZy5hY3Rpb25zW2FjdGlvbk5hbWVdO1xuXHRcdGlmICh0eXBlb2YgYWN0aW9uRnVuY3Rpb24gIT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0bG9nZ2VyKCkud2FybihcImFjdGlvbiBpcyBub3QgYSBmdW5jdGlvblwiLCB7XG5cdFx0XHRcdGFjdGlvbk5hbWU6IGFjdGlvbk5hbWUsXG5cdFx0XHRcdHR5cGU6IHR5cGVvZiBhY3Rpb25GdW5jdGlvbixcblx0XHRcdH0pO1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5BY3Rpb25Ob3RGb3VuZChhY3Rpb25OYW1lKTtcblx0XHR9XG5cblx0XHQvLyBUT0RPOiBwYXNzIGFib3J0YWJsZSB0byB0aGUgYWN0aW9uIHRvIGRlY2lkZSB3aGVuIHRvIGFib3J0XG5cdFx0Ly8gVE9ETzogTWFudWFsbHkgY2FsbCBhYm9ydGFibGUgZm9yIGJldHRlciBlcnJvciBoYW5kbGluZ1xuXHRcdC8vIENhbGwgdGhlIGZ1bmN0aW9uIG9uIHRoaXMgb2JqZWN0IHdpdGggdGhvc2UgYXJndW1lbnRzXG5cdFx0dHJ5IHtcblx0XHRcdC8vIExvZyB3aGVuIHdlIHN0YXJ0IGV4ZWN1dGluZyB0aGUgYWN0aW9uXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImV4ZWN1dGluZyBhY3Rpb25cIiwgeyBhY3Rpb25OYW1lOiBhY3Rpb25OYW1lLCBhcmdzIH0pO1xuXG5cdFx0XHRjb25zdCBvdXRwdXRPclByb21pc2UgPSBhY3Rpb25GdW5jdGlvbi5jYWxsKHVuZGVmaW5lZCwgY3R4LCAuLi5hcmdzKTtcblx0XHRcdGxldCBvdXRwdXQ6IHVua25vd247XG5cdFx0XHRpZiAob3V0cHV0T3JQcm9taXNlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuXHRcdFx0XHQvLyBMb2cgdGhhdCB3ZSdyZSB3YWl0aW5nIGZvciBhbiBhc3luYyBhY3Rpb25cblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJhd2FpdGluZyBhc3luYyBhY3Rpb25cIiwgeyBhY3Rpb25OYW1lOiBhY3Rpb25OYW1lIH0pO1xuXG5cdFx0XHRcdG91dHB1dCA9IGF3YWl0IGRlYWRsaW5lKFxuXHRcdFx0XHRcdG91dHB1dE9yUHJvbWlzZSxcblx0XHRcdFx0XHR0aGlzLiNjb25maWcub3B0aW9ucy5hY3Rpb25UaW1lb3V0LFxuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdC8vIExvZyB0aGF0IGFzeW5jIGFjdGlvbiBjb21wbGV0ZWRcblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJhc3luYyBhY3Rpb24gY29tcGxldGVkXCIsIHsgYWN0aW9uTmFtZTogYWN0aW9uTmFtZSB9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG91dHB1dCA9IG91dHB1dE9yUHJvbWlzZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUHJvY2VzcyB0aGUgb3V0cHV0IHRocm91Z2ggb25CZWZvcmVBY3Rpb25SZXNwb25zZSBpZiBjb25maWd1cmVkXG5cdFx0XHRpZiAodGhpcy4jY29uZmlnLm9uQmVmb3JlQWN0aW9uUmVzcG9uc2UpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBwcm9jZXNzZWRPdXRwdXQgPSB0aGlzLiNjb25maWcub25CZWZvcmVBY3Rpb25SZXNwb25zZShcblx0XHRcdFx0XHRcdHRoaXMuYWN0b3JDb250ZXh0LFxuXHRcdFx0XHRcdFx0YWN0aW9uTmFtZSxcblx0XHRcdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdFx0XHRvdXRwdXQsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRpZiAocHJvY2Vzc2VkT3V0cHV0IGluc3RhbmNlb2YgUHJvbWlzZSkge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJhd2FpdGluZyBvbkJlZm9yZUFjdGlvblJlc3BvbnNlXCIsIHtcblx0XHRcdFx0XHRcdFx0YWN0aW9uTmFtZTogYWN0aW9uTmFtZSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0b3V0cHV0ID0gYXdhaXQgcHJvY2Vzc2VkT3V0cHV0O1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJvbkJlZm9yZUFjdGlvblJlc3BvbnNlIGNvbXBsZXRlZFwiLCB7XG5cdFx0XHRcdFx0XHRcdGFjdGlvbk5hbWU6IGFjdGlvbk5hbWUsXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0b3V0cHV0ID0gcHJvY2Vzc2VkT3V0cHV0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGluIGBvbkJlZm9yZUFjdGlvblJlc3BvbnNlYFwiLCB7XG5cdFx0XHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyb3IpLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIExvZyB0aGUgb3V0cHV0IGJlZm9yZSByZXR1cm5pbmdcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiYWN0aW9uIGNvbXBsZXRlZFwiLCB7XG5cdFx0XHRcdGFjdGlvbk5hbWU6IGFjdGlvbk5hbWUsXG5cdFx0XHRcdG91dHB1dFR5cGU6IHR5cGVvZiBvdXRwdXQsXG5cdFx0XHRcdGlzUHJvbWlzZTogb3V0cHV0IGluc3RhbmNlb2YgUHJvbWlzZSxcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBUaGlzIG91dHB1dCAqbWlnaHQqIHJlZmVyZW5jZSBhIHBhcnQgb2YgdGhlIHN0YXRlICh1c2luZyBvbkNoYW5nZSksIGJ1dFxuXHRcdFx0Ly8gdGhhdCdzIE9LIHNpbmNlIHRoaXMgdmFsdWUgYWx3YXlzIGdldHMgc2VyaWFsaXplZCBhbmQgc2VudCBvdmVyIHRoZVxuXHRcdFx0Ly8gbmV0d29yay5cblx0XHRcdHJldHVybiBvdXRwdXQ7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGlmIChlcnJvciBpbnN0YW5jZW9mIERlYWRsaW5lRXJyb3IpIHtcblx0XHRcdFx0dGhyb3cgbmV3IGVycm9ycy5BY3Rpb25UaW1lZE91dCgpO1xuXHRcdFx0fVxuXHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJhY3Rpb24gZXJyb3JcIiwge1xuXHRcdFx0XHRhY3Rpb25OYW1lOiBhY3Rpb25OYW1lLFxuXHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyb3IpLFxuXHRcdFx0fSk7XG5cdFx0XHR0aHJvdyBlcnJvcjtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dGhpcy4jc2F2ZVBlcnNpc3RUaHJvdHRsZWQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIGxpc3Qgb2YgYWN0aW9uIG1ldGhvZHMgYXZhaWxhYmxlIG9uIHRoaXMgYWN0b3IuXG5cdCAqL1xuXHRnZXQgYWN0aW9ucygpOiBzdHJpbmdbXSB7XG5cdFx0cmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuI2NvbmZpZy5hY3Rpb25zKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIHJhdyBIVFRQIHJlcXVlc3RzIHRvIHRoZSBhY3Rvci5cblx0ICovXG5cdGFzeW5jIGhhbmRsZUZldGNoKHJlcXVlc3Q6IFJlcXVlc3QsIG9wdHM6IHsgYXV0aDogQUQgfSk6IFByb21pc2U8UmVzcG9uc2U+IHtcblx0XHR0aGlzLiNhc3NlcnRSZWFkeSgpO1xuXG5cdFx0aWYgKCF0aGlzLiNjb25maWcub25GZXRjaCkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5GZXRjaEhhbmRsZXJOb3REZWZpbmVkKCk7XG5cdFx0fVxuXG5cdFx0Ly8gVHJhY2sgYWN0aXZlIHJhdyBmZXRjaCB3aGlsZSBoYW5kbGVyIHJ1bnNcblx0XHR0aGlzLiNhY3RpdmVSYXdGZXRjaENvdW50Kys7XG5cdFx0dGhpcy4jcmVzZXRTbGVlcFRpbWVyKCk7XG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLiNjb25maWcub25GZXRjaChcblx0XHRcdFx0dGhpcy5hY3RvckNvbnRleHQsXG5cdFx0XHRcdHJlcXVlc3QsXG5cdFx0XHRcdG9wdHMsXG5cdFx0XHQpO1xuXHRcdFx0aWYgKCFyZXNwb25zZSkge1xuXHRcdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRGZXRjaFJlc3BvbnNlKCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzcG9uc2U7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwib25GZXRjaCBlcnJvclwiLCB7XG5cdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHR9KTtcblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH0gZmluYWxseSB7XG5cdFx0XHQvLyBEZWNyZW1lbnQgYWN0aXZlIHJhdyBmZXRjaCBjb3VudGVyIGFuZCByZS1ldmFsdWF0ZSBzbGVlcFxuXHRcdFx0dGhpcy4jYWN0aXZlUmF3RmV0Y2hDb3VudCA9IE1hdGgubWF4KDAsIHRoaXMuI2FjdGl2ZVJhd0ZldGNoQ291bnQgLSAxKTtcblx0XHRcdHRoaXMuI3Jlc2V0U2xlZXBUaW1lcigpO1xuXHRcdFx0dGhpcy4jc2F2ZVBlcnNpc3RUaHJvdHRsZWQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyByYXcgV2ViU29ja2V0IGNvbm5lY3Rpb25zIHRvIHRoZSBhY3Rvci5cblx0ICovXG5cdGFzeW5jIGhhbmRsZVdlYlNvY2tldChcblx0XHR3ZWJzb2NrZXQ6IFVuaXZlcnNhbFdlYlNvY2tldCxcblx0XHRvcHRzOiB7IHJlcXVlc3Q6IFJlcXVlc3Q7IGF1dGg6IEFEIH0sXG5cdCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdHRoaXMuI2Fzc2VydFJlYWR5KCk7XG5cblx0XHRpZiAoIXRoaXMuI2NvbmZpZy5vbldlYlNvY2tldCkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnRlcm5hbEVycm9yKFwib25XZWJTb2NrZXQgaGFuZGxlciBub3QgZGVmaW5lZFwiKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gU2V0IHVwIHN0YXRlIHRyYWNraW5nIHRvIGRldGVjdCBjaGFuZ2VzIGR1cmluZyBXZWJTb2NrZXQgaGFuZGxpbmdcblx0XHRcdGNvbnN0IHN0YXRlQmVmb3JlSGFuZGxlciA9IHRoaXMuI3BlcnNpc3RDaGFuZ2VkO1xuXG5cdFx0XHQvLyBUcmFjayBhY3RpdmUgd2Vic29ja2V0IHVudGlsIGl0IGZ1bGx5IGNsb3Nlc1xuXHRcdFx0dGhpcy4jYWN0aXZlUmF3V2ViU29ja2V0cy5hZGQod2Vic29ja2V0KTtcblx0XHRcdHRoaXMuI3Jlc2V0U2xlZXBUaW1lcigpO1xuXG5cdFx0XHQvLyBUcmFjayBzb2NrZXQgY2xvc2Vcblx0XHRcdGNvbnN0IG9uU29ja2V0Q2xvc2VkID0gKCkgPT4ge1xuXHRcdFx0XHQvLyBSZW1vdmUgbGlzdGVuZXIgYW5kIHNvY2tldCBmcm9tIHRyYWNraW5nXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0d2Vic29ja2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCBvblNvY2tldENsb3NlZCk7XG5cdFx0XHRcdFx0d2Vic29ja2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBvblNvY2tldENsb3NlZCk7XG5cdFx0XHRcdH0gY2F0Y2gge31cblx0XHRcdFx0dGhpcy4jYWN0aXZlUmF3V2ViU29ja2V0cy5kZWxldGUod2Vic29ja2V0KTtcblx0XHRcdFx0dGhpcy4jcmVzZXRTbGVlcFRpbWVyKCk7XG5cdFx0XHR9O1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCBvblNvY2tldENsb3NlZCk7XG5cdFx0XHRcdHdlYnNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgb25Tb2NrZXRDbG9zZWQpO1xuXHRcdFx0fSBjYXRjaCB7fVxuXG5cdFx0XHQvLyBIYW5kbGUgV2ViU29ja2V0XG5cdFx0XHRhd2FpdCB0aGlzLiNjb25maWcub25XZWJTb2NrZXQodGhpcy5hY3RvckNvbnRleHQsIHdlYnNvY2tldCwgb3B0cyk7XG5cblx0XHRcdC8vIElmIHN0YXRlIGNoYW5nZWQgZHVyaW5nIHRoZSBoYW5kbGVyLCBzYXZlIGl0XG5cdFx0XHRpZiAodGhpcy4jcGVyc2lzdENoYW5nZWQgJiYgIXN0YXRlQmVmb3JlSGFuZGxlcikge1xuXHRcdFx0XHRhd2FpdCB0aGlzLnNhdmVTdGF0ZSh7IGltbWVkaWF0ZTogdHJ1ZSB9KTtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJvbldlYlNvY2tldCBlcnJvclwiLCB7XG5cdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHR9KTtcblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH0gZmluYWxseSB7XG5cdFx0XHR0aGlzLiNzYXZlUGVyc2lzdFRocm90dGxlZCgpO1xuXHRcdH1cblx0fVxuXG5cdC8vIE1BUks6IExpZmVjeWNsZSBob29rc1xuXG5cdC8vIE1BUks6IEV4cG9zZWQgbWV0aG9kc1xuXHQvKipcblx0ICogR2V0cyB0aGUgbG9nZ2VyIGluc3RhbmNlLlxuXHQgKi9cblx0Z2V0IGxvZygpOiBMb2dnZXIge1xuXHRcdHJldHVybiBpbnN0YW5jZUxvZ2dlcigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIG5hbWUuXG5cdCAqL1xuXHRnZXQgbmFtZSgpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLiNuYW1lO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGtleS5cblx0ICovXG5cdGdldCBrZXkoKTogQWN0b3JLZXkge1xuXHRcdHJldHVybiB0aGlzLiNrZXk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcmVnaW9uLlxuXHQgKi9cblx0Z2V0IHJlZ2lvbigpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLiNyZWdpb247XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NoZWR1bGVyLlxuXHQgKi9cblx0Z2V0IHNjaGVkdWxlKCk6IFNjaGVkdWxlIHtcblx0XHRyZXR1cm4gdGhpcy4jc2NoZWR1bGU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbWFwIG9mIGNvbm5lY3Rpb25zLlxuXHQgKi9cblx0Z2V0IGNvbm5zKCk6IE1hcDxDb25uSWQsIENvbm48UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+PiB7XG5cdFx0cmV0dXJuIHRoaXMuI2Nvbm5lY3Rpb25zO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGN1cnJlbnQgc3RhdGUuXG5cdCAqXG5cdCAqIENoYW5naW5nIHByb3BlcnRpZXMgb2YgdGhpcyB2YWx1ZSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgcGVyc2lzdGVkLlxuXHQgKi9cblx0Z2V0IHN0YXRlKCk6IFMge1xuXHRcdHRoaXMuI3ZhbGlkYXRlU3RhdGVFbmFibGVkKCk7XG5cdFx0cmV0dXJuIHRoaXMuI3BlcnNpc3Quc3RhdGU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGF0YWJhc2UuXG5cdCAqIEBleHBlcmltZW50YWxcblx0ICogQHRocm93cyB7RGF0YWJhc2VOb3RFbmFibGVkfSBJZiB0aGUgZGF0YWJhc2UgaXMgbm90IGVuYWJsZWQuXG5cdCAqL1xuXHRnZXQgZGIoKTogSW5mZXJEYXRhYmFzZUNsaWVudDxEQj4ge1xuXHRcdGlmICghdGhpcy4jZGIpIHtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuRGF0YWJhc2VOb3RFbmFibGVkKCk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLiNkYjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjdXJyZW50IHN0YXRlLlxuXHQgKlxuXHQgKiBUaGlzIHByb3BlcnR5IHdpbGwgYXV0b21hdGljYWxseSBiZSBwZXJzaXN0ZWQuXG5cdCAqL1xuXHRzZXQgc3RhdGUodmFsdWU6IFMpIHtcblx0XHR0aGlzLiN2YWxpZGF0ZVN0YXRlRW5hYmxlZCgpO1xuXHRcdHRoaXMuI3BlcnNpc3Quc3RhdGUgPSB2YWx1ZTtcblx0fVxuXG5cdGdldCB2YXJzKCk6IFYge1xuXHRcdHRoaXMuI3ZhbGlkYXRlVmFyc0VuYWJsZWQoKTtcblx0XHRpbnZhcmlhbnQodGhpcy4jdmFycyAhPT0gdW5kZWZpbmVkLCBcInZhcnMgbm90IGVuYWJsZWRcIik7XG5cdFx0cmV0dXJuIHRoaXMuI3ZhcnM7XG5cdH1cblxuXHQvKipcblx0ICogQnJvYWRjYXN0cyBhbiBldmVudCB0byBhbGwgY29ubmVjdGVkIGNsaWVudHMuXG5cdCAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50LlxuXHQgKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gc2VuZCB3aXRoIHRoZSBldmVudC5cblx0ICovXG5cdF9icm9hZGNhc3Q8QXJncyBleHRlbmRzIEFycmF5PHVua25vd24+PihuYW1lOiBzdHJpbmcsIC4uLmFyZ3M6IEFyZ3MpIHtcblx0XHR0aGlzLiNhc3NlcnRSZWFkeSgpO1xuXG5cdFx0dGhpcy5pbnNwZWN0b3IuZW1pdHRlci5lbWl0KFwiZXZlbnRGaXJlZFwiLCB7XG5cdFx0XHR0eXBlOiBcImJyb2FkY2FzdFwiLFxuXHRcdFx0ZXZlbnROYW1lOiBuYW1lLFxuXHRcdFx0YXJncyxcblx0XHR9KTtcblxuXHRcdC8vIFNlbmQgdG8gYWxsIGNvbm5lY3RlZCBjbGllbnRzXG5cdFx0Y29uc3Qgc3Vic2NyaXB0aW9ucyA9IHRoaXMuI3N1YnNjcmlwdGlvbkluZGV4LmdldChuYW1lKTtcblx0XHRpZiAoIXN1YnNjcmlwdGlvbnMpIHJldHVybjtcblxuXHRcdGNvbnN0IHRvQ2xpZW50U2VyaWFsaXplciA9IG5ldyBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pihcblx0XHRcdHtcblx0XHRcdFx0Ym9keToge1xuXHRcdFx0XHRcdHRhZzogXCJFdmVudFwiLFxuXHRcdFx0XHRcdHZhbDoge1xuXHRcdFx0XHRcdFx0bmFtZSxcblx0XHRcdFx0XHRcdGFyZ3M6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUoYXJncykpLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdFx0VE9fQ0xJRU5UX1ZFUlNJT05FRCxcblx0XHQpO1xuXG5cdFx0Ly8gU2VuZCBtZXNzYWdlIHRvIGNsaWVudHNcblx0XHRmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2Ygc3Vic2NyaXB0aW9ucykge1xuXHRcdFx0Y29ubmVjdGlvbi5fc2VuZE1lc3NhZ2UodG9DbGllbnRTZXJpYWxpemVyKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUHJldmVudHMgdGhlIGFjdG9yIGZyb20gc2xlZXBpbmcgdW50aWwgcHJvbWlzZSBpcyBjb21wbGV0ZS5cblx0ICpcblx0ICogVGhpcyBhbGxvd3MgdGhlIGFjdG9yIHJ1bnRpbWUgdG8gZW5zdXJlIHRoYXQgYSBwcm9taXNlIGNvbXBsZXRlcyB3aGlsZVxuXHQgKiByZXR1cm5pbmcgZnJvbSBhbiBhY3Rpb24gcmVxdWVzdCBlYXJseS5cblx0ICpcblx0ICogQHBhcmFtIHByb21pc2UgLSBUaGUgcHJvbWlzZSB0byBydW4gaW4gdGhlIGJhY2tncm91bmQuXG5cdCAqL1xuXHRfd2FpdFVudGlsKHByb21pc2U6IFByb21pc2U8dm9pZD4pIHtcblx0XHR0aGlzLiNhc3NlcnRSZWFkeSgpO1xuXG5cdFx0Ly8gVE9ETzogU2hvdWxkIHdlIGZvcmNlIHNhdmUgdGhlIHN0YXRlP1xuXHRcdC8vIEFkZCBsb2dnaW5nIHRvIHByb21pc2UgYW5kIG1ha2UgaXQgbm9uLWZhaWxhYmxlXG5cdFx0Y29uc3Qgbm9uZmFpbGFibGVQcm9taXNlID0gcHJvbWlzZVxuXHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcIndhaXQgdW50aWwgcHJvbWlzZSBjb21wbGV0ZVwiKTtcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKGVycm9yKSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwid2FpdCB1bnRpbCBwcm9taXNlIGZhaWxlZFwiLCB7XG5cdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblx0XHR0aGlzLiNiYWNrZ3JvdW5kUHJvbWlzZXMucHVzaChub25mYWlsYWJsZVByb21pc2UpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZvcmNlcyB0aGUgc3RhdGUgdG8gZ2V0IHNhdmVkLlxuXHQgKlxuXHQgKiBUaGlzIGlzIGhlbHBmdWwgaWYgcnVubmluZyBhIGxvbmcgdGFzayB0aGF0IG1heSBmYWlsIGxhdGVyIG9yIHdoZW5cblx0ICogcnVubmluZyBhIGJhY2tncm91bmQgam9iIHRoYXQgdXBkYXRlcyB0aGUgc3RhdGUuXG5cdCAqXG5cdCAqIEBwYXJhbSBvcHRzIC0gT3B0aW9ucyBmb3Igc2F2aW5nIHRoZSBzdGF0ZS5cblx0ICovXG5cdGFzeW5jIHNhdmVTdGF0ZShvcHRzOiBTYXZlU3RhdGVPcHRpb25zKSB7XG5cdFx0dGhpcy4jYXNzZXJ0UmVhZHkob3B0cy5hbGxvd1N0b3BwaW5nU3RhdGUpO1xuXG5cdFx0aWYgKHRoaXMuI3BlcnNpc3RDaGFuZ2VkKSB7XG5cdFx0XHRpZiAob3B0cy5pbW1lZGlhdGUpIHtcblx0XHRcdFx0Ly8gU2F2ZSBpbW1lZGlhdGVseVxuXHRcdFx0XHRhd2FpdCB0aGlzLiNzYXZlUGVyc2lzdElubmVyKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBDcmVhdGUgY2FsbGJhY2tcblx0XHRcdFx0aWYgKCF0aGlzLiNvblBlcnNpc3RTYXZlZFByb21pc2UpIHtcblx0XHRcdFx0XHR0aGlzLiNvblBlcnNpc3RTYXZlZFByb21pc2UgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFNhdmUgc3RhdGUgdGhyb3R0bGVkXG5cdFx0XHRcdHRoaXMuI3NhdmVQZXJzaXN0VGhyb3R0bGVkKCk7XG5cblx0XHRcdFx0Ly8gV2FpdCBmb3Igc2F2ZVxuXHRcdFx0XHRhd2FpdCB0aGlzLiNvblBlcnNpc3RTYXZlZFByb21pc2UucHJvbWlzZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBNQVJLOiBTbGVlcFxuXHQvKipcblx0ICogUmVzZXQgdGltZXIgZnJvbSB0aGUgbGFzdCBhY3RvciBpbnRlcmFjdGlvbiB0aGF0IGFsbG93cyBpdCB0byBiZSBwdXQgdG8gc2xlZXAuXG5cdCAqXG5cdCAqIFRoaXMgc2hvdWxkIGJlIGNhbGxlZCBhbnkgdGltZSBhIHNsZWVwLXJlbGF0ZWQgZXZlbnQgaGFwcGVuczpcblx0ICogLSBDb25uZWN0aW9uIG9wZW5zICh3aWxsIGNsZWFyIHRpbWVyKVxuXHQgKiAtIENvbm5lY3Rpb24gY2xvc2VzICh3aWxsIHNjaGVkdWxlIHRpbWVyIGlmIHRoZXJlIGFyZSBubyBvcGVuIGNvbm5lY3Rpb25zKVxuXHQgKiAtIEFsYXJtIHRyaWdnZXJzICh3aWxsIHJlc2V0IHRpbWVyKVxuXHQgKlxuXHQgKiBXZSBkb24ndCBuZWVkIHRvIGNhbGwgdGhpcyBvbiBldmVudHMgbGlrZSBpbmRpdmlkdWFsIGFjdGlvbiBjYWxscywgc2luY2UgdGhlcmUgd2lsbCBhbHdheXMgYmUgYSBjb25uZWN0aW9uIG9wZW4gZm9yIHRoZXNlLlxuXHQgKiovXG5cdCNyZXNldFNsZWVwVGltZXIoKSB7XG5cdFx0aWYgKHRoaXMuI2NvbmZpZy5vcHRpb25zLm5vU2xlZXAgfHwgIXRoaXMuI3NsZWVwaW5nU3VwcG9ydGVkKSByZXR1cm47XG5cblx0XHRjb25zdCBjYW5TbGVlcCA9IHRoaXMuI2NhblNsZWVwKCk7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJlc2V0dGluZyBzbGVlcCB0aW1lclwiLCB7XG5cdFx0XHRjYW5TbGVlcCxcblx0XHRcdGV4aXN0aW5nVGltZW91dDogISF0aGlzLiNzbGVlcFRpbWVvdXQsXG5cdFx0fSk7XG5cblx0XHRpZiAodGhpcy4jc2xlZXBUaW1lb3V0KSB7XG5cdFx0XHRjbGVhclRpbWVvdXQodGhpcy4jc2xlZXBUaW1lb3V0KTtcblx0XHRcdHRoaXMuI3NsZWVwVGltZW91dCA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBEb24ndCBzZXQgYSBuZXcgdGltZXIgaWYgYWxyZWFkeSBzbGVlcGluZ1xuXHRcdGlmICh0aGlzLiNzbGVlcENhbGxlZCkgcmV0dXJuO1xuXG5cdFx0aWYgKGNhblNsZWVwKSB7XG5cdFx0XHR0aGlzLiNzbGVlcFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0dGhpcy5fc2xlZXAoKS5jYXRjaCgoZXJyb3IpID0+IHtcblx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGR1cmluZyBzbGVlcFwiLCB7XG5cdFx0XHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyb3IpLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0sIHRoaXMuI2NvbmZpZy5vcHRpb25zLnNsZWVwVGltZW91dCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIElmIHRoaXMgYWN0b3IgY2FuIGJlIHB1dCBpbiBhIHNsZWVwaW5nIHN0YXRlLiAqL1xuXHQjY2FuU2xlZXAoKTogYm9vbGVhbiB7XG5cdFx0aWYgKCF0aGlzLiNyZWFkeSkgcmV0dXJuIGZhbHNlO1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIGFjdGl2ZSBjb25ucy4gVGhpcyB3aWxsIGFsc28gY292ZXIgYWN0aXZlIGFjdGlvbnMsIHNpbmNlIGFsbCBhY3Rpb25zIGhhdmUgYSBjb25uZWN0aW9uLlxuXHRcdGZvciAoY29uc3QgY29ubiBvZiB0aGlzLiNjb25uZWN0aW9ucy52YWx1ZXMoKSkge1xuXHRcdFx0aWYgKGNvbm4uc3RhdHVzID09PSBcImNvbm5lY3RlZFwiKSByZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gRG8gbm90IHNsZWVwIGlmIHJhdyBmZXRjaGVzIGFyZSBpbi1mbGlnaHRcblx0XHRpZiAodGhpcy4jYWN0aXZlUmF3RmV0Y2hDb3VudCA+IDApIHJldHVybiBmYWxzZTtcblxuXHRcdC8vIERvIG5vdCBzbGVlcCBpZiB0aGVyZSBhcmUgcmF3IHdlYnNvY2tldHMgb3BlblxuXHRcdGlmICh0aGlzLiNhY3RpdmVSYXdXZWJTb2NrZXRzLnNpemUgPiAwKSByZXR1cm4gZmFsc2U7XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKiBQdXRzIGFuIGFjdG9yIHRvIHNsZWVwLiBUaGlzIHNob3VsZCBqdXN0IHN0YXJ0IHRoZSBzbGVlcCBzZXF1ZW5jZSwgbW9zdCBzaHV0ZG93biBsb2dpYyBzaG91bGQgYmUgaW4gX3N0b3AgKHdoaWNoIGlzIGNhbGxlZCBieSB0aGUgQWN0b3JEcml2ZXIgd2hlbiBzbGVlcGluZykuICovXG5cdGFzeW5jIF9zbGVlcCgpIHtcblx0XHRjb25zdCBzbGVlcCA9IHRoaXMuI2FjdG9yRHJpdmVyLnNsZWVwPy5iaW5kKFxuXHRcdFx0dGhpcy4jYWN0b3JEcml2ZXIsXG5cdFx0XHR0aGlzLiNhY3RvcklkLFxuXHRcdCk7XG5cdFx0aW52YXJpYW50KHRoaXMuI3NsZWVwaW5nU3VwcG9ydGVkLCBcInNsZWVwaW5nIG5vdCBzdXBwb3J0ZWRcIik7XG5cdFx0aW52YXJpYW50KHNsZWVwLCBcIm5vIHNsZWVwIG9uIGRyaXZlclwiKTtcblxuXHRcdGlmICh0aGlzLiNzbGVlcENhbGxlZCkge1xuXHRcdFx0bG9nZ2VyKCkud2FybihcImFscmVhZHkgc2xlZXBpbmcgYWN0b3JcIik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuI3NsZWVwQ2FsbGVkID0gdHJ1ZTtcblxuXHRcdGxvZ2dlcigpLmluZm8oXCJhY3RvciBzbGVlcGluZ1wiKTtcblxuXHRcdC8vIFNjaGVkdWxlIHNsZWVwIHRvIGhhcHBlbiBvbiB0aGUgbmV4dCB0aWNrLiBUaGlzIGFsbG93cyBmb3IgYW55IGFjdGlvbiB0aGF0IGNhbGxzIF9zbGVlcCB0byBjb21wbGV0ZS5cblx0XHRzZXRJbW1lZGlhdGUoYXN5bmMgKCkgPT4ge1xuXHRcdFx0Ly8gVGhlIGFjdG9yIGRyaXZlciBzaG91bGQgY2FsbCBzdG9wIHdoZW4gcmVhZHkgdG8gc3RvcFxuXHRcdFx0Ly9cblx0XHRcdC8vIFRoaXMgd2lsbCBjYWxsIF9zdG9wIG9uY2UgUGVnYm9hcmQgcmVzcG9uZHMgd2l0aCB0aGUgbmV3IHN0YXR1c1xuXHRcdFx0YXdhaXQgc2xlZXAoKTtcblx0XHR9KTtcblx0fVxuXG5cdC8vIE1BUks6IFN0b3Bcblx0YXN5bmMgX3N0b3AoKSB7XG5cdFx0aWYgKHRoaXMuI3N0b3BDYWxsZWQpIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXCJhbHJlYWR5IHN0b3BwaW5nIGFjdG9yXCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLiNzdG9wQ2FsbGVkID0gdHJ1ZTtcblxuXHRcdGxvZ2dlcigpLmluZm8oXCJhY3RvciBzdG9wcGluZ1wiKTtcblxuXHRcdC8vIEFib3J0IGFueSBsaXN0ZW5lcnMgd2FpdGluZyBmb3Igc2h1dGRvd25cblx0XHR0cnkge1xuXHRcdFx0dGhpcy4jYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG5cdFx0fSBjYXRjaCB7fVxuXG5cdFx0Ly8gQ2FsbCBvblN0b3AgbGlmZWN5Y2xlIGhvb2sgaWYgZGVmaW5lZFxuXHRcdGlmICh0aGlzLiNjb25maWcub25TdG9wKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImNhbGxpbmcgb25TdG9wXCIpO1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSB0aGlzLiNjb25maWcub25TdG9wKHRoaXMuYWN0b3JDb250ZXh0KTtcblx0XHRcdFx0aWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcblx0XHRcdFx0XHRhd2FpdCBkZWFkbGluZShyZXN1bHQsIHRoaXMuI2NvbmZpZy5vcHRpb25zLm9uU3RvcFRpbWVvdXQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwib25TdG9wIGNvbXBsZXRlZFwiKTtcblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdGlmIChlcnJvciBpbnN0YW5jZW9mIERlYWRsaW5lRXJyb3IpIHtcblx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcIm9uU3RvcCB0aW1lZCBvdXRcIik7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBvblN0b3BcIiwge1xuXHRcdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIERpc2Nvbm5lY3QgZXhpc3RpbmcgY29ubmVjdGlvbnNcblx0XHRjb25zdCBwcm9taXNlczogUHJvbWlzZTx1bmtub3duPltdID0gW107XG5cdFx0Zm9yIChjb25zdCBjb25uZWN0aW9uIG9mIHRoaXMuI2Nvbm5lY3Rpb25zLnZhbHVlcygpKSB7XG5cdFx0XHRwcm9taXNlcy5wdXNoKGNvbm5lY3Rpb24uZGlzY29ubmVjdCgpKTtcblxuXHRcdFx0Ly8gVE9ETzogRmlndXJlIG91dCBob3cgdG8gYWJvcnQgSFRUUCByZXF1ZXN0cyBvbiBzaHV0ZG93blxuXHRcdH1cblxuXHRcdC8vIFdhaXQgZm9yIGFueSBiYWNrZ3JvdW5kIHRhc2tzIHRvIGZpbmlzaCwgd2l0aCB0aW1lb3V0XG5cdFx0YXdhaXQgdGhpcy4jd2FpdEJhY2tncm91bmRQcm9taXNlcyh0aGlzLiNjb25maWcub3B0aW9ucy53YWl0VW50aWxUaW1lb3V0KTtcblxuXHRcdC8vIENsZWFyIHRpbWVvdXRzXG5cdFx0aWYgKHRoaXMuI3BlbmRpbmdTYXZlVGltZW91dCkgY2xlYXJUaW1lb3V0KHRoaXMuI3BlbmRpbmdTYXZlVGltZW91dCk7XG5cdFx0aWYgKHRoaXMuI3NsZWVwVGltZW91dCkgY2xlYXJUaW1lb3V0KHRoaXMuI3NsZWVwVGltZW91dCk7XG5cdFx0aWYgKHRoaXMuI2NoZWNrQ29ubkxpdmVuZXNzSW50ZXJ2YWwpXG5cdFx0XHRjbGVhckludGVydmFsKHRoaXMuI2NoZWNrQ29ubkxpdmVuZXNzSW50ZXJ2YWwpO1xuXG5cdFx0Ly8gV3JpdGUgc3RhdGVcblx0XHRhd2FpdCB0aGlzLnNhdmVTdGF0ZSh7IGltbWVkaWF0ZTogdHJ1ZSwgYWxsb3dTdG9wcGluZ1N0YXRlOiB0cnVlIH0pO1xuXG5cdFx0Ly8gQXdhaXQgYWxsIGBjbG9zZWAgZXZlbnQgbGlzdGVuZXJzIHdpdGggMS41IHNlY29uZCB0aW1lb3V0XG5cdFx0Y29uc3QgcmVzID0gUHJvbWlzZS5yYWNlKFtcblx0XHRcdFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IGZhbHNlKSxcblx0XHRcdG5ldyBQcm9taXNlPGJvb2xlYW4+KChyZXMpID0+XG5cdFx0XHRcdGdsb2JhbFRoaXMuc2V0VGltZW91dCgoKSA9PiByZXModHJ1ZSksIDE1MDApLFxuXHRcdFx0KSxcblx0XHRdKTtcblxuXHRcdGlmIChhd2FpdCByZXMpIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXG5cdFx0XHRcdFwidGltZWQgb3V0IHdhaXRpbmcgZm9yIGNvbm5lY3Rpb25zIHRvIGNsb3NlLCBzaHV0dGluZyBkb3duIGFueXdheVwiLFxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHQvLyBXYWl0IGZvciBxdWV1ZXMgdG8gZmluaXNoXG5cdFx0aWYgKHRoaXMuI3BlcnNpc3RXcml0ZVF1ZXVlLnJ1bm5pbmdEcmFpbkxvb3ApXG5cdFx0XHRhd2FpdCB0aGlzLiNwZXJzaXN0V3JpdGVRdWV1ZS5ydW5uaW5nRHJhaW5Mb29wO1xuXHRcdGlmICh0aGlzLiNhbGFybVdyaXRlUXVldWUucnVubmluZ0RyYWluTG9vcClcblx0XHRcdGF3YWl0IHRoaXMuI2FsYXJtV3JpdGVRdWV1ZS5ydW5uaW5nRHJhaW5Mb29wO1xuXHR9XG5cblx0LyoqIEFib3J0IHNpZ25hbCB0aGF0IGZpcmVzIHdoZW4gdGhlIGFjdG9yIGlzIHN0b3BwaW5nLiAqL1xuXHRnZXQgYWJvcnRTaWduYWwoKTogQWJvcnRTaWduYWwge1xuXHRcdHJldHVybiB0aGlzLiNhYm9ydENvbnRyb2xsZXIuc2lnbmFsO1xuXHR9XG5cblx0LyoqIFdhaXQgZm9yIGJhY2tncm91bmQgd2FpdFVudGlsIHByb21pc2VzIHdpdGggYSB0aW1lb3V0LiAqL1xuXHRhc3luYyAjd2FpdEJhY2tncm91bmRQcm9taXNlcyh0aW1lb3V0TXM6IG51bWJlcikge1xuXHRcdGNvbnN0IHBlbmRpbmcgPSB0aGlzLiNiYWNrZ3JvdW5kUHJvbWlzZXM7XG5cdFx0aWYgKHBlbmRpbmcubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcIm5vIGJhY2tncm91bmQgcHJvbWlzZXNcIik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmFjZSBwcm9taXNlcyB3aXRoIHRpbWVvdXQgdG8gZGV0ZXJtaW5lIGlmIHBlbmRpbmcgcHJvbWlzZXMgc2V0dGxlZCBmYXN0IGVub3VnaFxuXHRcdGNvbnN0IHRpbWVkT3V0ID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcblx0XHRcdFByb21pc2UuYWxsU2V0dGxlZChwZW5kaW5nKS50aGVuKCgpID0+IGZhbHNlKSxcblx0XHRcdG5ldyBQcm9taXNlPHRydWU+KChyZXNvbHZlKSA9PlxuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUodHJ1ZSksIHRpbWVvdXRNcyksXG5cdFx0XHQpLFxuXHRcdF0pO1xuXG5cdFx0aWYgKHRpbWVkT3V0KSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcblx0XHRcdFx0XCJ0aW1lZCBvdXQgd2FpdGluZyBmb3IgYmFja2dyb3VuZCB0YXNrcywgYmFja2dyb3VuZCBwcm9taXNlcyBtYXkgaGF2ZSBsZWFrZWRcIixcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvdW50OiBwZW5kaW5nLmxlbmd0aCxcblx0XHRcdFx0XHR0aW1lb3V0TXMsXG5cdFx0XHRcdH0sXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImJhY2tncm91bmQgcHJvbWlzZXMgZmluaXNoZWRcIik7XG5cdFx0fVxuXHR9XG5cblx0Ly8gTUFSSzogQkFSRSBDb252ZXJzaW9uIEhlbHBlcnNcblx0I2NvbnZlcnRUb0JhcmVQZXJzaXN0ZWQoXG5cdFx0cGVyc2lzdDogUGVyc2lzdGVkQWN0b3I8UywgQ1AsIENTLCBJPixcblx0KTogYmFyZVNjaGVtYS5QZXJzaXN0ZWRBY3RvciB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGlucHV0OlxuXHRcdFx0XHRwZXJzaXN0LmlucHV0ICE9PSB1bmRlZmluZWRcblx0XHRcdFx0XHQ/IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUocGVyc2lzdC5pbnB1dCkpXG5cdFx0XHRcdFx0OiBudWxsLFxuXHRcdFx0aGFzSW5pdGlhbGl6ZWQ6IHBlcnNpc3QuaGFzSW5pdGlhdGVkLFxuXHRcdFx0c3RhdGU6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUocGVyc2lzdC5zdGF0ZSkpLFxuXHRcdFx0Y29ubmVjdGlvbnM6IHBlcnNpc3QuY29ubmVjdGlvbnMubWFwKChjb25uKSA9PiAoe1xuXHRcdFx0XHRpZDogY29ubi5jb25uSWQsXG5cdFx0XHRcdHRva2VuOiBjb25uLnRva2VuLFxuXHRcdFx0XHRkcml2ZXI6IGNvbm4uY29ubkRyaXZlciBhcyBzdHJpbmcsXG5cdFx0XHRcdGRyaXZlclN0YXRlOiBidWZmZXJUb0FycmF5QnVmZmVyKFxuXHRcdFx0XHRcdGNib3IuZW5jb2RlKGNvbm4uY29ubkRyaXZlclN0YXRlIHx8IHt9KSxcblx0XHRcdFx0KSxcblx0XHRcdFx0cGFyYW1ldGVyczogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShjb25uLnBhcmFtcyB8fCB7fSkpLFxuXHRcdFx0XHRzdGF0ZTogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShjb25uLnN0YXRlIHx8IHt9KSksXG5cdFx0XHRcdGF1dGg6XG5cdFx0XHRcdFx0Y29ubi5hdXRoRGF0YSAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdFx0XHQ/IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUoY29ubi5hdXRoRGF0YSkpXG5cdFx0XHRcdFx0XHQ6IG51bGwsXG5cdFx0XHRcdHN1YnNjcmlwdGlvbnM6IGNvbm4uc3Vic2NyaXB0aW9ucy5tYXAoKHN1YikgPT4gKHtcblx0XHRcdFx0XHRldmVudE5hbWU6IHN1Yi5ldmVudE5hbWUsXG5cdFx0XHRcdH0pKSxcblx0XHRcdFx0bGFzdFNlZW46IEJpZ0ludChjb25uLmxhc3RTZWVuKSxcblx0XHRcdH0pKSxcblx0XHRcdHNjaGVkdWxlZEV2ZW50czogcGVyc2lzdC5zY2hlZHVsZWRFdmVudHMubWFwKChldmVudCkgPT4gKHtcblx0XHRcdFx0ZXZlbnRJZDogZXZlbnQuZXZlbnRJZCxcblx0XHRcdFx0dGltZXN0YW1wOiBCaWdJbnQoZXZlbnQudGltZXN0YW1wKSxcblx0XHRcdFx0a2luZDoge1xuXHRcdFx0XHRcdHRhZzogXCJHZW5lcmljUGVyc2lzdGVkU2NoZWR1bGVFdmVudFwiIGFzIGNvbnN0LFxuXHRcdFx0XHRcdHZhbDoge1xuXHRcdFx0XHRcdFx0YWN0aW9uOiBldmVudC5raW5kLmdlbmVyaWMuYWN0aW9uTmFtZSxcblx0XHRcdFx0XHRcdGFyZ3M6IGV2ZW50LmtpbmQuZ2VuZXJpYy5hcmdzID8/IG51bGwsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fSxcblx0XHRcdH0pKSxcblx0XHR9O1xuXHR9XG5cblx0I2NvbnZlcnRGcm9tQmFyZVBlcnNpc3RlZChcblx0XHRiYXJlRGF0YTogYmFyZVNjaGVtYS5QZXJzaXN0ZWRBY3Rvcixcblx0KTogUGVyc2lzdGVkQWN0b3I8UywgQ1AsIENTLCBJPiB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGlucHV0OiBiYXJlRGF0YS5pbnB1dFxuXHRcdFx0XHQ/IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGJhcmVEYXRhLmlucHV0KSlcblx0XHRcdFx0OiB1bmRlZmluZWQsXG5cdFx0XHRoYXNJbml0aWF0ZWQ6IGJhcmVEYXRhLmhhc0luaXRpYWxpemVkLFxuXHRcdFx0c3RhdGU6IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGJhcmVEYXRhLnN0YXRlKSksXG5cdFx0XHRjb25uZWN0aW9uczogYmFyZURhdGEuY29ubmVjdGlvbnMubWFwKChjb25uKSA9PiAoe1xuXHRcdFx0XHRjb25uSWQ6IGNvbm4uaWQsXG5cdFx0XHRcdHRva2VuOiBjb25uLnRva2VuLFxuXHRcdFx0XHRjb25uRHJpdmVyOiBjb25uLmRyaXZlciBhcyBDb25uZWN0aW9uRHJpdmVyLFxuXHRcdFx0XHRjb25uRHJpdmVyU3RhdGU6IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGNvbm4uZHJpdmVyU3RhdGUpKSxcblx0XHRcdFx0cGFyYW1zOiBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShjb25uLnBhcmFtZXRlcnMpKSxcblx0XHRcdFx0c3RhdGU6IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGNvbm4uc3RhdGUpKSxcblx0XHRcdFx0YXV0aERhdGE6IGNvbm4uYXV0aFxuXHRcdFx0XHRcdD8gY2Jvci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkoY29ubi5hdXRoKSlcblx0XHRcdFx0XHQ6IHVuZGVmaW5lZCxcblx0XHRcdFx0c3Vic2NyaXB0aW9uczogY29ubi5zdWJzY3JpcHRpb25zLm1hcCgoc3ViKSA9PiAoe1xuXHRcdFx0XHRcdGV2ZW50TmFtZTogc3ViLmV2ZW50TmFtZSxcblx0XHRcdFx0fSkpLFxuXHRcdFx0XHRsYXN0U2VlbjogTnVtYmVyKGNvbm4ubGFzdFNlZW4pLFxuXHRcdFx0fSkpLFxuXHRcdFx0c2NoZWR1bGVkRXZlbnRzOiBiYXJlRGF0YS5zY2hlZHVsZWRFdmVudHMubWFwKChldmVudCkgPT4gKHtcblx0XHRcdFx0ZXZlbnRJZDogZXZlbnQuZXZlbnRJZCxcblx0XHRcdFx0dGltZXN0YW1wOiBOdW1iZXIoZXZlbnQudGltZXN0YW1wKSxcblx0XHRcdFx0a2luZDoge1xuXHRcdFx0XHRcdGdlbmVyaWM6IHtcblx0XHRcdFx0XHRcdGFjdGlvbk5hbWU6IGV2ZW50LmtpbmQudmFsLmFjdGlvbixcblx0XHRcdFx0XHRcdGFyZ3M6IGV2ZW50LmtpbmQudmFsLmFyZ3MsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fSxcblx0XHRcdH0pKSxcblx0XHR9O1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvYWN0b3IudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2luc3BlY3Rvci9hY3Rvci50c1wiO2ltcG9ydCB7IHNWYWxpZGF0b3IgfSBmcm9tIFwiQGhvbm8vc3RhbmRhcmQtdmFsaWRhdG9yXCI7XG5pbXBvcnQganNvblBhdGNoIGZyb20gXCJAcml2ZXRraXQvZmFzdC1qc29uLXBhdGNoXCI7XG5pbXBvcnQgeyBIb25vIH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB7IHN0cmVhbVNTRSB9IGZyb20gXCJob25vL3N0cmVhbWluZ1wiO1xuaW1wb3J0IHsgY3JlYXRlTmFub0V2ZW50cywgdHlwZSBVbnN1YnNjcmliZSB9IGZyb20gXCJuYW5vZXZlbnRzXCI7XG5pbXBvcnQgeiBmcm9tIFwiem9kL3Y0XCI7XG5pbXBvcnQgdHlwZSB7XG5cdEFueURhdGFiYXNlUHJvdmlkZXIsXG5cdEluZmVyRGF0YWJhc2VDbGllbnQsXG59IGZyb20gXCJAL2FjdG9yL2RhdGFiYXNlXCI7XG5pbXBvcnQge1xuXHRDb2x1bW5zU2NoZW1hLFxuXHR0eXBlIENvbm5lY3Rpb24sXG5cdEZvcmVpZ25LZXlzU2NoZW1hLFxuXHRQYXRjaFNjaGVtYSxcblx0dHlwZSBSZWFsdGltZUV2ZW50LFxuXHR0eXBlIFJlY29yZGVkUmVhbHRpbWVFdmVudCxcblx0VGFibGVzU2NoZW1hLFxufSBmcm9tIFwiLi9wcm90b2NvbC9jb21tb25cIjtcblxuZXhwb3J0IHR5cGUgQWN0b3JJbnNwZWN0b3JSb3V0ZXJFbnYgPSB7XG5cdFZhcmlhYmxlczoge1xuXHRcdGluc3BlY3RvcjogQWN0b3JJbnNwZWN0b3I7XG5cdH07XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIHJvdXRlciBmb3IgdGhlIEFjdG9yIEluc3BlY3Rvci5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQWN0b3JJbnNwZWN0b3JSb3V0ZXIoKSB7XG5cdHJldHVybiBuZXcgSG9ubzxBY3Rvckluc3BlY3RvclJvdXRlckVudj4oKVxuXHRcdC5nZXQoXCIvcGluZ1wiLCAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IG1lc3NhZ2U6IFwicG9uZ1wiIH0sIDIwMCk7XG5cdFx0fSlcblx0XHQuZ2V0KFwiL3N0YXRlXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRpZiAoYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5pc1N0YXRlRW5hYmxlZCgpKSB7XG5cdFx0XHRcdHJldHVybiBjLmpzb24oXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdHN0YXRlOiBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldFN0YXRlKCksXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHQyMDAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgZW5hYmxlZDogZmFsc2UsIHN0YXRlOiBudWxsIH0sIDIwMCk7XG5cdFx0fSlcblx0XHQucGF0Y2goXG5cdFx0XHRcIi9zdGF0ZVwiLFxuXHRcdFx0c1ZhbGlkYXRvcihcblx0XHRcdFx0XCJqc29uXCIsXG5cdFx0XHRcdHoub2JqZWN0KHsgcGF0Y2g6IFBhdGNoU2NoZW1hIH0pLm9yKHoub2JqZWN0KHsgcmVwbGFjZTogei5hbnkoKSB9KSksXG5cdFx0XHQpLFxuXHRcdFx0YXN5bmMgKGMpID0+IHtcblx0XHRcdFx0aWYgKCEoYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5pc1N0YXRlRW5hYmxlZCgpKSkge1xuXHRcdFx0XHRcdHJldHVybiBjLmpzb24oeyBlbmFibGVkOiBmYWxzZSB9LCAyMDApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3QgYm9keSA9IGMucmVxLnZhbGlkKFwianNvblwiKTtcblx0XHRcdFx0aWYgKFwicmVwbGFjZVwiIGluIGJvZHkpIHtcblx0XHRcdFx0XHRhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLnNldFN0YXRlKGJvZHkucmVwbGFjZSk7XG5cdFx0XHRcdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0c3RhdGU6IGF3YWl0IGMudmFyLmluc3BlY3Rvci5hY2Nlc3NvcnMuZ2V0U3RhdGUoKSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHQyMDAsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCBzdGF0ZSA9IGF3YWl0IGMudmFyLmluc3BlY3Rvci5hY2Nlc3NvcnMuZ2V0U3RhdGUoKTtcblxuXHRcdFx0XHRjb25zdCB7IG5ld0RvY3VtZW50OiBuZXdTdGF0ZSB9ID0ganNvblBhdGNoLmFwcGx5UGF0Y2goXG5cdFx0XHRcdFx0c3RhdGUsXG5cdFx0XHRcdFx0Ym9keS5wYXRjaCxcblx0XHRcdFx0KTtcblx0XHRcdFx0YXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5zZXRTdGF0ZShuZXdTdGF0ZSk7XG5cblx0XHRcdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdFx0XHR7IGVuYWJsZWQ6IHRydWUsIHN0YXRlOiBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldFN0YXRlKCkgfSxcblx0XHRcdFx0XHQyMDAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9LFxuXHRcdClcblx0XHQuZ2V0KFwiL3N0YXRlL3N0cmVhbVwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0aWYgKCEoYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5pc1N0YXRlRW5hYmxlZCgpKSkge1xuXHRcdFx0XHRyZXR1cm4gYy5qc29uKHsgZW5hYmxlZDogZmFsc2UgfSwgMjAwKTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IGlkID0gMDtcblx0XHRcdGxldCB1bnN1YjogVW5zdWJzY3JpYmU7XG5cdFx0XHRyZXR1cm4gc3RyZWFtU1NFKFxuXHRcdFx0XHRjLFxuXHRcdFx0XHRhc3luYyAoc3RyZWFtKSA9PiB7XG5cdFx0XHRcdFx0dW5zdWIgPSBjLnZhci5pbnNwZWN0b3IuZW1pdHRlci5vbihcInN0YXRlVXBkYXRlZFwiLCBhc3luYyAoc3RhdGUpID0+IHtcblx0XHRcdFx0XHRcdHN0cmVhbS53cml0ZVNTRSh7XG5cdFx0XHRcdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHN0YXRlKSB8fCBcIlwiLFxuXHRcdFx0XHRcdFx0XHRldmVudDogXCJzdGF0ZS11cGRhdGVcIixcblx0XHRcdFx0XHRcdFx0aWQ6IFN0cmluZyhpZCsrKSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0Y29uc3QgeyBwcm9taXNlIH0gPSBQcm9taXNlLndpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblxuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0dW5zdWI/LigpO1xuXHRcdFx0XHR9LFxuXHRcdFx0KTtcblx0XHR9KVxuXHRcdC5nZXQoXCIvY29ubmVjdGlvbnNcIiwgYXN5bmMgKGMpID0+IHtcblx0XHRcdGNvbnN0IGNvbm5lY3Rpb25zID0gYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5nZXRDb25uZWN0aW9ucygpO1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IGNvbm5lY3Rpb25zIH0sIDIwMCk7XG5cdFx0fSlcblx0XHQuZ2V0KFwiL2Nvbm5lY3Rpb25zL3N0cmVhbVwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0bGV0IGlkID0gMDtcblx0XHRcdGxldCB1bnN1YjogVW5zdWJzY3JpYmU7XG5cdFx0XHRyZXR1cm4gc3RyZWFtU1NFKFxuXHRcdFx0XHRjLFxuXHRcdFx0XHRhc3luYyAoc3RyZWFtKSA9PiB7XG5cdFx0XHRcdFx0dW5zdWIgPSBjLnZhci5pbnNwZWN0b3IuZW1pdHRlci5vbihcImNvbm5lY3Rpb25VcGRhdGVkXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdHN0cmVhbS53cml0ZVNTRSh7XG5cdFx0XHRcdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KFxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IGMudmFyLmluc3BlY3Rvci5hY2Nlc3NvcnMuZ2V0Q29ubmVjdGlvbnMoKSxcblx0XHRcdFx0XHRcdFx0KSxcblx0XHRcdFx0XHRcdFx0ZXZlbnQ6IFwiY29ubmVjdGlvbi11cGRhdGVcIixcblx0XHRcdFx0XHRcdFx0aWQ6IFN0cmluZyhpZCsrKSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0Y29uc3QgeyBwcm9taXNlIH0gPSBQcm9taXNlLndpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblxuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0dW5zdWI/LigpO1xuXHRcdFx0XHR9LFxuXHRcdFx0KTtcblx0XHR9KVxuXHRcdC5nZXQoXCIvZXZlbnRzXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjb25zdCBldmVudHMgPSBjLnZhci5pbnNwZWN0b3IubGFzdFJlYWx0aW1lRXZlbnRzO1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IGV2ZW50cyB9LCAyMDApO1xuXHRcdH0pXG5cdFx0LnBvc3QoXCIvZXZlbnRzL2NsZWFyXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjLnZhci5pbnNwZWN0b3IubGFzdFJlYWx0aW1lRXZlbnRzLmxlbmd0aCA9IDA7IC8vIENsZWFyIHRoZSBldmVudHNcblx0XHRcdHJldHVybiBjLmpzb24oeyBtZXNzYWdlOiBcIkV2ZW50cyBjbGVhcmVkXCIgfSwgMjAwKTtcblx0XHR9KVxuXHRcdC5nZXQoXCIvZXZlbnRzL3N0cmVhbVwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0bGV0IGlkID0gMDtcblx0XHRcdGxldCB1bnN1YjogVW5zdWJzY3JpYmU7XG5cdFx0XHRyZXR1cm4gc3RyZWFtU1NFKFxuXHRcdFx0XHRjLFxuXHRcdFx0XHRhc3luYyAoc3RyZWFtKSA9PiB7XG5cdFx0XHRcdFx0dW5zdWIgPSBjLnZhci5pbnNwZWN0b3IuZW1pdHRlci5vbihcImV2ZW50RmlyZWRcIiwgKCkgPT4ge1xuXHRcdFx0XHRcdFx0c3RyZWFtLndyaXRlU1NFKHtcblx0XHRcdFx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoYy52YXIuaW5zcGVjdG9yLmxhc3RSZWFsdGltZUV2ZW50cyksXG5cdFx0XHRcdFx0XHRcdGV2ZW50OiBcInJlYWx0aW1lLWV2ZW50XCIsXG5cdFx0XHRcdFx0XHRcdGlkOiBTdHJpbmcoaWQrKyksXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdGNvbnN0IHsgcHJvbWlzZSB9ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzPHZvaWQ+KCk7XG5cblx0XHRcdFx0XHRyZXR1cm4gcHJvbWlzZTtcblx0XHRcdFx0fSxcblx0XHRcdFx0YXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdHVuc3ViPy4oKTtcblx0XHRcdFx0fSxcblx0XHRcdCk7XG5cdFx0fSlcblx0XHQuZ2V0KFwiL3JwY3NcIiwgYXN5bmMgKGMpID0+IHtcblx0XHRcdGNvbnN0IHJwY3MgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldFJwY3MoKTtcblx0XHRcdHJldHVybiBjLmpzb24oeyBycGNzIH0sIDIwMCk7XG5cdFx0fSlcblx0XHQuZ2V0KFwiL2RiXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRpZiAoIShhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmlzRGJFbmFibGVkKCkpKSB7XG5cdFx0XHRcdHJldHVybiBjLmpzb24oeyBlbmFibGVkOiBmYWxzZSwgZGI6IG51bGwgfSwgMjAwKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWNjZXNzIHRoZSBTUUxpdGUgZGF0YWJhc2Vcblx0XHRcdGNvbnN0IGRiID0gYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5nZXREYigpO1xuXG5cdFx0XHQvLyBHZXQgbGlzdCBvZiB0YWJsZXNcblx0XHRcdGNvbnN0IHJvd3MgPSBhd2FpdCBkYi5leGVjdXRlKGBQUkFHTUEgdGFibGVfbGlzdGApO1xuXHRcdFx0Y29uc3QgdGFibGVzID0gVGFibGVzU2NoZW1hLnBhcnNlKHJvd3MpLmZpbHRlcihcblx0XHRcdFx0KHRhYmxlKSA9PiB0YWJsZS5zY2hlbWEgIT09IFwidGVtcFwiICYmICF0YWJsZS5uYW1lLnN0YXJ0c1dpdGgoXCJzcWxpdGVfXCIpLFxuXHRcdFx0KTtcblx0XHRcdC8vIEdldCBjb2x1bW5zIGZvciBlYWNoIHRhYmxlXG5cdFx0XHRjb25zdCB0YWJsZXNJbmZvID0gYXdhaXQgUHJvbWlzZS5hbGwoXG5cdFx0XHRcdHRhYmxlcy5tYXAoKHRhYmxlKSA9PiBkYi5leGVjdXRlKGBQUkFHTUEgdGFibGVfaW5mbygke3RhYmxlLm5hbWV9KWApKSxcblx0XHRcdCk7XG5cdFx0XHRjb25zdCBjb2x1bW5zID0gdGFibGVzSW5mby5tYXAoKGRlZikgPT4gQ29sdW1uc1NjaGVtYS5wYXJzZShkZWYpKTtcblxuXHRcdFx0Ly8gR2V0IGZvcmVpZ24ga2V5cyBmb3IgZWFjaCB0YWJsZVxuXHRcdFx0Y29uc3QgZm9yZWlnbktleXNMaXN0ID0gYXdhaXQgUHJvbWlzZS5hbGwoXG5cdFx0XHRcdHRhYmxlcy5tYXAoKHRhYmxlKSA9PlxuXHRcdFx0XHRcdGRiLmV4ZWN1dGUoYFBSQUdNQSBmb3JlaWduX2tleV9saXN0KCR7dGFibGUubmFtZX0pYCksXG5cdFx0XHRcdCksXG5cdFx0XHQpO1xuXHRcdFx0Y29uc3QgZm9yZWlnbktleXMgPSBmb3JlaWduS2V5c0xpc3QubWFwKChkZWYpID0+XG5cdFx0XHRcdEZvcmVpZ25LZXlzU2NoZW1hLnBhcnNlKGRlZiksXG5cdFx0XHQpO1xuXG5cdFx0XHQvLyBHZXQgcmVjb3JkIGNvdW50cyBmb3IgZWFjaCB0YWJsZVxuXHRcdFx0Y29uc3QgY291bnRJbmZvID0gYXdhaXQgUHJvbWlzZS5hbGwoXG5cdFx0XHRcdHRhYmxlcy5tYXAoKHRhYmxlKSA9PlxuXHRcdFx0XHRcdGRiLmV4ZWN1dGUoYFNFTEVDVCBDT1VOVCgqKSBhcyBjb3VudCBGUk9NICR7dGFibGUubmFtZX1gKSxcblx0XHRcdFx0KSxcblx0XHRcdCk7XG5cdFx0XHRjb25zdCBjb3VudHMgPSBjb3VudEluZm8ubWFwKChkZWYpID0+IHtcblx0XHRcdFx0cmV0dXJuIGRlZlswXS5jb3VudCB8fCAwO1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiBjLmpzb24oXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRlbmFibGVkOiB0cnVlLFxuXHRcdFx0XHRcdGRiOiB0YWJsZXNJbmZvLm1hcCgoXywgaW5kZXgpID0+IHtcblx0XHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHRcdHRhYmxlOiB0YWJsZXNbaW5kZXhdLFxuXHRcdFx0XHRcdFx0XHRjb2x1bW5zOiBjb2x1bW5zW2luZGV4XSxcblx0XHRcdFx0XHRcdFx0Zm9yZWlnbktleXM6IGZvcmVpZ25LZXlzW2luZGV4XSxcblx0XHRcdFx0XHRcdFx0cmVjb3JkczogY291bnRzW2luZGV4XSxcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fSksXG5cdFx0XHRcdH0sXG5cdFx0XHRcdDIwMCxcblx0XHRcdCk7XG5cdFx0fSlcblx0XHQucG9zdChcblx0XHRcdFwiL2RiXCIsXG5cdFx0XHRzVmFsaWRhdG9yKFxuXHRcdFx0XHRcImpzb25cIixcblx0XHRcdFx0ei5vYmplY3QoeyBxdWVyeTogei5zdHJpbmcoKSwgcGFyYW1zOiB6LmFycmF5KHouYW55KCkpLm9wdGlvbmFsKCkgfSksXG5cdFx0XHQpLFxuXHRcdFx0YXN5bmMgKGMpID0+IHtcblx0XHRcdFx0aWYgKCEoYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5pc0RiRW5hYmxlZCgpKSkge1xuXHRcdFx0XHRcdHJldHVybiBjLmpzb24oeyBlbmFibGVkOiBmYWxzZSB9LCAyMDApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnN0IGRiID0gYXdhaXQgYy52YXIuaW5zcGVjdG9yLmFjY2Vzc29ycy5nZXREYigpO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gKGF3YWl0IGRiLmV4ZWN1dGUoXG5cdFx0XHRcdFx0XHRjLnJlcS52YWxpZChcImpzb25cIikucXVlcnksXG5cdFx0XHRcdFx0XHQuLi4oYy5yZXEudmFsaWQoXCJqc29uXCIpLnBhcmFtcyB8fCBbXSksXG5cdFx0XHRcdFx0KSkgYXMgdW5rbm93bjtcblx0XHRcdFx0XHRyZXR1cm4gYy5qc29uKHsgcmVzdWx0IH0sIDIwMCk7XG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0Yztcblx0XHRcdFx0XHRyZXR1cm4gYy5qc29uKHsgZXJyb3I6IChlcnJvciBhcyBFcnJvcikubWVzc2FnZSB9LCA1MDApO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdCk7XG59XG5cbmludGVyZmFjZSBBY3Rvckluc3BlY3RvckFjY2Vzc29ycyB7XG5cdGlzU3RhdGVFbmFibGVkOiAoKSA9PiBQcm9taXNlPGJvb2xlYW4+O1xuXHRnZXRTdGF0ZTogKCkgPT4gUHJvbWlzZTx1bmtub3duPjtcblx0c2V0U3RhdGU6IChzdGF0ZTogdW5rbm93bikgPT4gUHJvbWlzZTx2b2lkPjtcblx0aXNEYkVuYWJsZWQ6ICgpID0+IFByb21pc2U8Ym9vbGVhbj47XG5cdGdldERiOiAoKSA9PiBQcm9taXNlPEluZmVyRGF0YWJhc2VDbGllbnQ8QW55RGF0YWJhc2VQcm92aWRlcj4+O1xuXHRnZXRScGNzOiAoKSA9PiBQcm9taXNlPHN0cmluZ1tdPjtcblx0Z2V0Q29ubmVjdGlvbnM6ICgpID0+IFByb21pc2U8Q29ubmVjdGlvbltdPjtcbn1cblxuaW50ZXJmYWNlIEFjdG9ySW5zcGVjdG9yRW1pdHRlckV2ZW50cyB7XG5cdHN0YXRlVXBkYXRlZDogKHN0YXRlOiB1bmtub3duKSA9PiB2b2lkO1xuXHRjb25uZWN0aW9uVXBkYXRlZDogKCkgPT4gdm9pZDtcblx0ZXZlbnRGaXJlZDogKGV2ZW50OiBSZWFsdGltZUV2ZW50KSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIFByb3ZpZGVzIGEgdW5pZmllZCBpbnRlcmZhY2UgZm9yIGluc3BlY3RpbmcgYWN0b3IgZXh0ZXJuYWwgYW5kIGludGVybmFsIHN0YXRlLlxuICovXG5leHBvcnQgY2xhc3MgQWN0b3JJbnNwZWN0b3Ige1xuXHRwdWJsaWMgcmVhZG9ubHkgYWNjZXNzb3JzOiBBY3Rvckluc3BlY3RvckFjY2Vzc29ycztcblx0cHVibGljIHJlYWRvbmx5IGVtaXR0ZXIgPSBjcmVhdGVOYW5vRXZlbnRzPEFjdG9ySW5zcGVjdG9yRW1pdHRlckV2ZW50cz4oKTtcblxuXHQjbGFzdFJlYWx0aW1lRXZlbnRzOiBSZWNvcmRlZFJlYWx0aW1lRXZlbnRbXSA9IFtdO1xuXG5cdGdldCBsYXN0UmVhbHRpbWVFdmVudHMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuI2xhc3RSZWFsdGltZUV2ZW50cztcblx0fVxuXG5cdGNvbnN0cnVjdG9yKGFjY2Vzc29yczogKCkgPT4gQWN0b3JJbnNwZWN0b3JBY2Nlc3NvcnMpIHtcblx0XHR0aGlzLmFjY2Vzc29ycyA9IGFjY2Vzc29ycygpO1xuXHRcdHRoaXMuZW1pdHRlci5vbihcImV2ZW50RmlyZWRcIiwgKGV2ZW50KSA9PiB7XG5cdFx0XHR0aGlzLiNsYXN0UmVhbHRpbWVFdmVudHMucHVzaCh7XG5cdFx0XHRcdGlkOiBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuXHRcdFx0XHR0aW1lc3RhbXA6IERhdGUubm93KCksXG5cdFx0XHRcdC4uLmV2ZW50LFxuXHRcdFx0fSk7XG5cdFx0XHQvLyBrZWVwIHRoZSBsYXN0IDEwMCBldmVudHNcblx0XHRcdGlmICh0aGlzLiNsYXN0UmVhbHRpbWVFdmVudHMubGVuZ3RoID4gMTAwKSB7XG5cdFx0XHRcdHRoaXMuI2xhc3RSZWFsdGltZUV2ZW50cyA9IHRoaXMuI2xhc3RSZWFsdGltZUV2ZW50cy5zbGljZSgtMTAwKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yL3Byb3RvY29sL2NvbW1vbi50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvcHJvdG9jb2xcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yL3Byb3RvY29sL2NvbW1vbi50c1wiO2ltcG9ydCB6IGZyb20gXCJ6b2QvdjRcIjtcbmltcG9ydCB7IEFjdG9yS2V5U2NoZW1hLCBNQVhfQUNUT1JfS0VZX1NJWkUgfSBmcm9tIFwiQC9tYW5hZ2VyL3Byb3RvY29sL3F1ZXJ5XCI7XG5cbmV4cG9ydCBjb25zdCBBY3RvcklkID0gei5zdHJpbmcoKS5icmFuZChcIkFjdG9ySWRcIik7XG5leHBvcnQgdHlwZSBBY3RvcklkID0gei5pbmZlcjx0eXBlb2YgQWN0b3JJZD47XG5cbmV4cG9ydCBlbnVtIEFjdG9yRmVhdHVyZSB7XG5cdExvZ3MgPSBcImxvZ3NcIixcblx0Q29uZmlnID0gXCJjb25maWdcIixcblx0Q29ubmVjdGlvbnMgPSBcImNvbm5lY3Rpb25zXCIsXG5cdFN0YXRlID0gXCJzdGF0ZVwiLFxuXHRDb25zb2xlID0gXCJjb25zb2xlXCIsXG5cdFJ1bnRpbWUgPSBcInJ1bnRpbWVcIixcblx0TWV0cmljcyA9IFwibWV0cmljc1wiLFxuXHRFdmVudHNNb25pdG9yaW5nID0gXCJldmVudHMtbW9uaXRvcmluZ1wiLFxuXHREYXRhYmFzZSA9IFwiZGF0YWJhc2VcIixcbn1cblxuZXhwb3J0IGNvbnN0IEFjdG9yTG9nRW50cnkgPSB6Lm9iamVjdCh7XG5cdGxldmVsOiB6LnN0cmluZygpLFxuXHRtZXNzYWdlOiB6LnN0cmluZygpLFxuXHR0aW1lc3RhbXA6IHouc3RyaW5nKCksXG5cdG1ldGFkYXRhOiB6LnJlY29yZCh6LnN0cmluZygpLCB6LmFueSgpKS5vcHRpb25hbCgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBBY3RvclNjaGVtYSA9IHoub2JqZWN0KHtcblx0aWQ6IEFjdG9ySWQsXG5cdG5hbWU6IHouc3RyaW5nKCksXG5cdGtleTogei5hcnJheSh6LnN0cmluZygpKSxcblx0dGFnczogei5yZWNvcmQoei5zdHJpbmcoKSwgei5zdHJpbmcoKSkub3B0aW9uYWwoKSxcblx0cmVnaW9uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG5cdGNyZWF0ZWRBdDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuXHRzdGFydGVkQXQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcblx0ZGVzdHJveWVkQXQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcblx0ZmVhdHVyZXM6IHouYXJyYXkoei5lbnVtKEFjdG9yRmVhdHVyZSkpLm9wdGlvbmFsKCksXG59KTtcblxuZXhwb3J0IHR5cGUgQWN0b3IgPSB6LmluZmVyPHR5cGVvZiBBY3RvclNjaGVtYT47XG5leHBvcnQgdHlwZSBBY3RvckxvZ0VudHJ5ID0gei5pbmZlcjx0eXBlb2YgQWN0b3JMb2dFbnRyeT47XG5cbi8vIE1BUks6IFN0YXRlXG5cbmV4cG9ydCBjb25zdCBPcGVyYXRpb25TY2hlbWEgPSB6LmRpc2NyaW1pbmF0ZWRVbmlvbihcIm9wXCIsIFtcblx0ei5vYmplY3Qoe1xuXHRcdG9wOiB6LmxpdGVyYWwoXCJyZW1vdmVcIiksXG5cdFx0cGF0aDogei5zdHJpbmcoKSxcblx0fSksXG5cdHoub2JqZWN0KHtcblx0XHRvcDogei5saXRlcmFsKFwiYWRkXCIpLFxuXHRcdHBhdGg6IHouc3RyaW5nKCksXG5cdFx0dmFsdWU6IHoudW5rbm93bigpLFxuXHR9KSxcblx0ei5vYmplY3Qoe1xuXHRcdG9wOiB6LmxpdGVyYWwoXCJyZXBsYWNlXCIpLFxuXHRcdHBhdGg6IHouc3RyaW5nKCksXG5cdFx0dmFsdWU6IHoudW5rbm93bigpLFxuXHR9KSxcblx0ei5vYmplY3Qoe1xuXHRcdG9wOiB6LmxpdGVyYWwoXCJtb3ZlXCIpLFxuXHRcdHBhdGg6IHouc3RyaW5nKCksXG5cdFx0ZnJvbTogei5zdHJpbmcoKSxcblx0fSksXG5cdHoub2JqZWN0KHtcblx0XHRvcDogei5saXRlcmFsKFwiY29weVwiKSxcblx0XHRwYXRoOiB6LnN0cmluZygpLFxuXHRcdGZyb206IHouc3RyaW5nKCksXG5cdH0pLFxuXHR6Lm9iamVjdCh7XG5cdFx0b3A6IHoubGl0ZXJhbChcInRlc3RcIiksXG5cdFx0cGF0aDogei5zdHJpbmcoKSxcblx0XHR2YWx1ZTogei51bmtub3duKCksXG5cdH0pLFxuXSk7XG5leHBvcnQgdHlwZSBPcGVyYXRpb24gPSB6LmluZmVyPHR5cGVvZiBPcGVyYXRpb25TY2hlbWE+O1xuXG5leHBvcnQgY29uc3QgUGF0Y2hTY2hlbWEgPSB6LmFycmF5KE9wZXJhdGlvblNjaGVtYSk7XG5leHBvcnQgdHlwZSBQYXRjaCA9IHouaW5mZXI8dHlwZW9mIFBhdGNoU2NoZW1hPjtcblxuLy8gTUFSSzogQ29ubmVjdGlvbnNcblxuZXhwb3J0IGNvbnN0IENvbm5lY3Rpb25TY2hlbWEgPSB6Lm9iamVjdCh7XG5cdHBhcmFtczogei5yZWNvcmQoei5zdHJpbmcoKSwgei5hbnkoKSkub3B0aW9uYWwoKSxcblx0aWQ6IHouc3RyaW5nKCksXG5cdHN0YXRlRW5hYmxlZDogei5ib29sZWFuKCkub3B0aW9uYWwoKSxcblx0c3RhdGU6IHouYW55KCkub3B0aW9uYWwoKSxcblx0YXV0aDogei5yZWNvcmQoei5zdHJpbmcoKSwgei5hbnkoKSkub3B0aW9uYWwoKSxcbn0pO1xuZXhwb3J0IHR5cGUgQ29ubmVjdGlvbiA9IHouaW5mZXI8dHlwZW9mIENvbm5lY3Rpb25TY2hlbWE+O1xuXG4vLyBNQVJLOiBSZWFsdGltZSBFdmVudHNcblxuZXhwb3J0IGNvbnN0IFJlYWx0aW1lRXZlbnRTY2hlbWEgPSB6LmRpc2NyaW1pbmF0ZWRVbmlvbihcInR5cGVcIiwgW1xuXHR6Lm9iamVjdCh7XG5cdFx0dHlwZTogei5saXRlcmFsKFwiYWN0aW9uXCIpLFxuXHRcdG5hbWU6IHouc3RyaW5nKCksXG5cdFx0YXJnczogei5hcnJheSh6LmFueSgpKSxcblx0XHRjb25uSWQ6IHouc3RyaW5nKCksXG5cdH0pLFxuXHR6Lm9iamVjdCh7XG5cdFx0dHlwZTogei5saXRlcmFsKFwiYnJvYWRjYXN0XCIpLFxuXHRcdGV2ZW50TmFtZTogei5zdHJpbmcoKSxcblx0XHRhcmdzOiB6LmFycmF5KHouYW55KCkpLFxuXHR9KSxcblx0ei5vYmplY3Qoe1xuXHRcdHR5cGU6IHoubGl0ZXJhbChcInN1YnNjcmliZVwiKSxcblx0XHRldmVudE5hbWU6IHouc3RyaW5nKCksXG5cdFx0Y29ubklkOiB6LnN0cmluZygpLFxuXHR9KSxcblx0ei5vYmplY3Qoe1xuXHRcdHR5cGU6IHoubGl0ZXJhbChcInVuc3Vic2NyaWJlXCIpLFxuXHRcdGV2ZW50TmFtZTogei5zdHJpbmcoKSxcblx0XHRjb25uSWQ6IHouc3RyaW5nKCksXG5cdH0pLFxuXHR6Lm9iamVjdCh7XG5cdFx0dHlwZTogei5saXRlcmFsKFwiZXZlbnRcIiksXG5cdFx0ZXZlbnROYW1lOiB6LnN0cmluZygpLFxuXHRcdGFyZ3M6IHouYXJyYXkoei5hbnkoKSksXG5cdFx0Y29ubklkOiB6LnN0cmluZygpLFxuXHR9KSxcbl0pO1xuZXhwb3J0IHR5cGUgUmVhbHRpbWVFdmVudCA9IHouaW5mZXI8dHlwZW9mIFJlYWx0aW1lRXZlbnRTY2hlbWE+O1xuZXhwb3J0IGNvbnN0IFJlY29yZGVkUmVhbHRpbWVFdmVudFNjaGVtYSA9IFJlYWx0aW1lRXZlbnRTY2hlbWEuYW5kKFxuXHR6Lm9iamVjdCh7XG5cdFx0aWQ6IHouc3RyaW5nKCksXG5cdFx0dGltZXN0YW1wOiB6Lm51bWJlcigpLFxuXHR9KSxcbik7XG5leHBvcnQgdHlwZSBSZWNvcmRlZFJlYWx0aW1lRXZlbnQgPSB6LmluZmVyPHR5cGVvZiBSZWNvcmRlZFJlYWx0aW1lRXZlbnRTY2hlbWE+O1xuXG4vLyBNQVJLOiBEYXRhYmFzZVxuXG5leHBvcnQgY29uc3QgRGF0YWJhc2VRdWVyeVNjaGVtYSA9IHoub2JqZWN0KHtcblx0c3FsOiB6LnN0cmluZygpLFxuXHRhcmdzOiB6LmFycmF5KHouc3RyaW5nKCkub3Ioei5udW1iZXIoKSkpLFxufSk7XG5leHBvcnQgdHlwZSBEYXRhYmFzZVF1ZXJ5ID0gei5pbmZlcjx0eXBlb2YgRGF0YWJhc2VRdWVyeVNjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBUYWJsZVNjaGVtYSA9IHoub2JqZWN0KHtcblx0c2NoZW1hOiB6LnN0cmluZygpLFxuXHRuYW1lOiB6LnN0cmluZygpLFxuXHR0eXBlOiB6LmVudW0oW1widGFibGVcIiwgXCJ2aWV3XCJdKSxcbn0pO1xuZXhwb3J0IHR5cGUgVGFibGUgPSB6LmluZmVyPHR5cGVvZiBUYWJsZVNjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBUYWJsZXNTY2hlbWEgPSB6LmFycmF5KFRhYmxlU2NoZW1hKTtcbmV4cG9ydCB0eXBlIFRhYmxlcyA9IHouaW5mZXI8dHlwZW9mIFRhYmxlc1NjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBDb2x1bW5TY2hlbWEgPSB6Lm9iamVjdCh7XG5cdGNpZDogei5udW1iZXIoKSxcblx0bmFtZTogei5zdHJpbmcoKSxcblx0dHlwZTogelxuXHRcdC5zdHJpbmcoKVxuXHRcdC50b0xvd2VyQ2FzZSgpXG5cdFx0LnRyYW5zZm9ybSgodmFsKSA9PiB7XG5cdFx0XHRyZXR1cm4gelxuXHRcdFx0XHQuZW51bShbXCJpbnRlZ2VyXCIsIFwidGV4dFwiLCBcInJlYWxcIiwgXCJibG9iXCIsIFwibnVtZXJpY1wiLCBcInNlcmlhbFwiXSlcblx0XHRcdFx0LnBhcnNlKHZhbCk7XG5cdFx0fSksXG5cdG5vdG51bGw6IHouY29lcmNlLmJvb2xlYW4oKSxcblx0ZGZsdF92YWx1ZTogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuXHRwazogei5jb2VyY2UuYm9vbGVhbigpLm51bGxhYmxlKCksXG59KTtcbmV4cG9ydCB0eXBlIENvbHVtbiA9IHouaW5mZXI8dHlwZW9mIENvbHVtblNjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBDb2x1bW5zU2NoZW1hID0gei5hcnJheShDb2x1bW5TY2hlbWEpO1xuZXhwb3J0IHR5cGUgQ29sdW1ucyA9IHouaW5mZXI8dHlwZW9mIENvbHVtbnNTY2hlbWE+O1xuXG5leHBvcnQgY29uc3QgRm9yZWlnbktleVNjaGVtYSA9IHoub2JqZWN0KHtcblx0aWQ6IHoubnVtYmVyKCksXG5cdHRhYmxlOiB6LnN0cmluZygpLFxuXHRmcm9tOiB6LnN0cmluZygpLFxuXHR0bzogei5zdHJpbmcoKSxcbn0pO1xuZXhwb3J0IHR5cGUgRm9yZWlnbktleSA9IHouaW5mZXI8dHlwZW9mIEZvcmVpZ25LZXlTY2hlbWE+O1xuXG5leHBvcnQgY29uc3QgRm9yZWlnbktleXNTY2hlbWEgPSB6LmFycmF5KEZvcmVpZ25LZXlTY2hlbWEpO1xuZXhwb3J0IHR5cGUgRm9yZWlnbktleXMgPSB6LmluZmVyPHR5cGVvZiBGb3JlaWduS2V5c1NjaGVtYT47XG5cbi8vIE1BUks6IEJ1aWxkc1xuXG5leHBvcnQgY29uc3QgQnVpbGRTY2hlbWEgPSB6Lm9iamVjdCh7XG5cdG5hbWU6IHouc3RyaW5nKCksXG5cdGNyZWF0ZWRBdDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuXHR0YWdzOiB6LnJlY29yZCh6LnN0cmluZygpLCB6LnN0cmluZygpKS5vcHRpb25hbCgpLFxufSk7XG5leHBvcnQgdHlwZSBCdWlsZCA9IHouaW5mZXI8dHlwZW9mIEJ1aWxkU2NoZW1hPjtcbmV4cG9ydCBjb25zdCBCdWlsZHNTY2hlbWEgPSB6LmFycmF5KEJ1aWxkU2NoZW1hKTtcbmV4cG9ydCB0eXBlIEJ1aWxkcyA9IHouaW5mZXI8dHlwZW9mIEJ1aWxkc1NjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBDcmVhdGVBY3RvclNjaGVtYSA9IHoub2JqZWN0KHtcblx0bmFtZTogei5zdHJpbmcoKSxcblx0Ly8gRklYTUU6IFJlcGxhY2Ugd2l0aCBBY3RvcktleVNjaGVtYSB3aGVuIHJlYWR5XG5cdGtleTogei5hcnJheSh6LnN0cmluZygpLm1heChNQVhfQUNUT1JfS0VZX1NJWkUpKSxcblx0aW5wdXQ6IHouYW55KCksXG59KTtcbmV4cG9ydCB0eXBlIENyZWF0ZUFjdG9yID0gei5pbmZlcjx0eXBlb2YgQ3JlYXRlQWN0b3JTY2hlbWE+O1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvbWFuYWdlci9wcm90b2NvbC9xdWVyeS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9tYW5hZ2VyL3Byb3RvY29sXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL21hbmFnZXIvcHJvdG9jb2wvcXVlcnkudHNcIjtpbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgRW5jb2RpbmdTY2hlbWEgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHtcblx0SEVBREVSX0FDVE9SX0lELFxuXHRIRUFERVJfQUNUT1JfUVVFUlksXG5cdEhFQURFUl9DT05OX0lELFxuXHRIRUFERVJfQ09OTl9QQVJBTVMsXG5cdEhFQURFUl9DT05OX1RPS0VOLFxuXHRIRUFERVJfRU5DT0RJTkcsXG59IGZyb20gXCJAL2FjdG9yL3JvdXRlci1lbmRwb2ludHNcIjtcblxuLy8gTWF4aW11bSBzaXplIG9mIGEga2V5IGNvbXBvbmVudCBpbiBieXRlc1xuLy8gU2V0IHRvIDEyOCBieXRlcyB0byBhbGxvdyBmb3Igc2VwYXJhdG9ycyBhbmQgZXNjYXBlIGNoYXJhY3RlcnMgaW4gdGhlIGZ1bGwga2V5XG4vLyBDbG91ZGZsYXJlJ3MgbWF4aW11bSBrZXkgc2l6ZSBpcyA1MTIgYnl0ZXMsIHNvIHdlIG5lZWQgdG8gYmUgc2lnbmlmaWNhbnRseSBzbWFsbGVyXG5leHBvcnQgY29uc3QgTUFYX0FDVE9SX0tFWV9TSVpFID0gMTI4O1xuXG5leHBvcnQgY29uc3QgQWN0b3JLZXlTY2hlbWEgPSB6LmFycmF5KHouc3RyaW5nKCkubWF4KE1BWF9BQ1RPUl9LRVlfU0laRSkpO1xuXG5leHBvcnQgdHlwZSBBY3RvcktleSA9IHouaW5mZXI8dHlwZW9mIEFjdG9yS2V5U2NoZW1hPjtcblxuZXhwb3J0IGNvbnN0IENyZWF0ZVJlcXVlc3RTY2hlbWEgPSB6Lm9iamVjdCh7XG5cdG5hbWU6IHouc3RyaW5nKCksXG5cdGtleTogQWN0b3JLZXlTY2hlbWEsXG5cdGlucHV0OiB6LnVua25vd24oKS5vcHRpb25hbCgpLFxuXHRyZWdpb246IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgR2V0Rm9yS2V5UmVxdWVzdFNjaGVtYSA9IHoub2JqZWN0KHtcblx0bmFtZTogei5zdHJpbmcoKSxcblx0a2V5OiBBY3RvcktleVNjaGVtYSxcbn0pO1xuXG5leHBvcnQgY29uc3QgR2V0T3JDcmVhdGVSZXF1ZXN0U2NoZW1hID0gei5vYmplY3Qoe1xuXHRuYW1lOiB6LnN0cmluZygpLFxuXHRrZXk6IEFjdG9yS2V5U2NoZW1hLFxuXHRpbnB1dDogei51bmtub3duKCkub3B0aW9uYWwoKSxcblx0cmVnaW9uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IEFjdG9yUXVlcnlTY2hlbWEgPSB6LnVuaW9uKFtcblx0ei5vYmplY3Qoe1xuXHRcdGdldEZvcklkOiB6Lm9iamVjdCh7XG5cdFx0XHRuYW1lOiB6LnN0cmluZygpLFxuXHRcdFx0YWN0b3JJZDogei5zdHJpbmcoKSxcblx0XHR9KSxcblx0fSksXG5cdHoub2JqZWN0KHtcblx0XHRnZXRGb3JLZXk6IEdldEZvcktleVJlcXVlc3RTY2hlbWEsXG5cdH0pLFxuXHR6Lm9iamVjdCh7XG5cdFx0Z2V0T3JDcmVhdGVGb3JLZXk6IEdldE9yQ3JlYXRlUmVxdWVzdFNjaGVtYSxcblx0fSksXG5cdHoub2JqZWN0KHtcblx0XHRjcmVhdGU6IENyZWF0ZVJlcXVlc3RTY2hlbWEsXG5cdH0pLFxuXSk7XG5cbmV4cG9ydCBjb25zdCBDb25uZWN0UmVxdWVzdFNjaGVtYSA9IHoub2JqZWN0KHtcblx0cXVlcnk6IEFjdG9yUXVlcnlTY2hlbWEuZGVzY3JpYmUoSEVBREVSX0FDVE9SX1FVRVJZKSxcblx0ZW5jb2Rpbmc6IEVuY29kaW5nU2NoZW1hLmRlc2NyaWJlKEhFQURFUl9FTkNPRElORyksXG5cdGNvbm5QYXJhbXM6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShIRUFERVJfQ09OTl9QQVJBTVMpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBDb25uZWN0V2ViU29ja2V0UmVxdWVzdFNjaGVtYSA9IHoub2JqZWN0KHtcblx0cXVlcnk6IEFjdG9yUXVlcnlTY2hlbWEuZGVzY3JpYmUoXCJxdWVyeVwiKSxcblx0ZW5jb2Rpbmc6IEVuY29kaW5nU2NoZW1hLmRlc2NyaWJlKFwiZW5jb2RpbmdcIiksXG5cdGNvbm5QYXJhbXM6IHoudW5rbm93bigpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJjb25uX3BhcmFtc1wiKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgQ29ubk1lc3NhZ2VSZXF1ZXN0U2NoZW1hID0gei5vYmplY3Qoe1xuXHRhY3RvcklkOiB6LnN0cmluZygpLmRlc2NyaWJlKEhFQURFUl9BQ1RPUl9JRCksXG5cdGNvbm5JZDogei5zdHJpbmcoKS5kZXNjcmliZShIRUFERVJfQ09OTl9JRCksXG5cdGVuY29kaW5nOiBFbmNvZGluZ1NjaGVtYS5kZXNjcmliZShIRUFERVJfRU5DT0RJTkcpLFxuXHRjb25uVG9rZW46IHouc3RyaW5nKCkuZGVzY3JpYmUoSEVBREVSX0NPTk5fVE9LRU4pLFxufSk7XG5cbmV4cG9ydCBjb25zdCBSZXNvbHZlUmVxdWVzdFNjaGVtYSA9IHoub2JqZWN0KHtcblx0cXVlcnk6IEFjdG9yUXVlcnlTY2hlbWEuZGVzY3JpYmUoSEVBREVSX0FDVE9SX1FVRVJZKSxcblx0Y29ublBhcmFtczogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKEhFQURFUl9DT05OX1BBUkFNUyksXG59KTtcblxuZXhwb3J0IHR5cGUgQWN0b3JRdWVyeSA9IHouaW5mZXI8dHlwZW9mIEFjdG9yUXVlcnlTY2hlbWE+O1xuZXhwb3J0IHR5cGUgR2V0Rm9yS2V5UmVxdWVzdCA9IHouaW5mZXI8dHlwZW9mIEdldEZvcktleVJlcXVlc3RTY2hlbWE+O1xuZXhwb3J0IHR5cGUgR2V0T3JDcmVhdGVSZXF1ZXN0ID0gei5pbmZlcjx0eXBlb2YgR2V0T3JDcmVhdGVSZXF1ZXN0U2NoZW1hPjtcbmV4cG9ydCB0eXBlIENvbm5lY3RRdWVyeSA9IHouaW5mZXI8dHlwZW9mIENvbm5lY3RSZXF1ZXN0U2NoZW1hPjtcbi8qKlxuICogSW50ZXJmYWNlIHJlcHJlc2VudGluZyBhIHJlcXVlc3QgdG8gY3JlYXRlIGEgYWN0b3IuXG4gKi9cbmV4cG9ydCB0eXBlIENyZWF0ZVJlcXVlc3QgPSB6LmluZmVyPHR5cGVvZiBDcmVhdGVSZXF1ZXN0U2NoZW1hPjtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL3JvdXRlci1lbmRwb2ludHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3JcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3Ivcm91dGVyLWVuZHBvaW50cy50c1wiO2ltcG9ydCAqIGFzIGNib3IgZnJvbSBcImNib3IteFwiO1xuaW1wb3J0IHR5cGUgeyBDb250ZXh0IGFzIEhvbm9Db250ZXh0LCBIb25vUmVxdWVzdCB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyB0eXBlIFNTRVN0cmVhbWluZ0FwaSwgc3RyZWFtU1NFIH0gZnJvbSBcImhvbm8vc3RyZWFtaW5nXCI7XG5pbXBvcnQgdHlwZSB7IFdTQ29udGV4dCB9IGZyb20gXCJob25vL3dzXCI7XG5pbXBvcnQgeyBBY3Rpb25Db250ZXh0IH0gZnJvbSBcIkAvYWN0b3IvYWN0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IEFueUNvbm4gfSBmcm9tIFwiQC9hY3Rvci9jb25uZWN0aW9uXCI7XG5pbXBvcnQge1xuXHRDT05ORUNUSU9OX0RSSVZFUl9IVFRQLFxuXHRDT05ORUNUSU9OX0RSSVZFUl9TU0UsXG5cdENPTk5FQ1RJT05fRFJJVkVSX1dFQlNPQ0tFVCxcblx0Z2VuZXJhdGVDb25uSWQsXG5cdGdlbmVyYXRlQ29ublRva2VuLFxufSBmcm9tIFwiQC9hY3Rvci9jb25uZWN0aW9uXCI7XG5pbXBvcnQgKiBhcyBlcnJvcnMgZnJvbSBcIkAvYWN0b3IvZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFjdG9ySW5zdGFuY2UgfSBmcm9tIFwiQC9hY3Rvci9pbnN0YW5jZVwiO1xuaW1wb3J0IHR5cGUgeyBJbnB1dERhdGEgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHsgdHlwZSBFbmNvZGluZywgRW5jb2RpbmdTY2hlbWEgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHR5cGUgeyBVcGdyYWRlV2ViU29ja2V0QXJncyB9IGZyb20gXCJAL2NvbW1vbi9pbmxpbmUtd2Vic29ja2V0LWFkYXB0ZXIyXCI7XG5pbXBvcnQgeyBkZWNvbnN0cnVjdEVycm9yLCBzdHJpbmdpZnlFcnJvciB9IGZyb20gXCJAL2NvbW1vbi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBVbml2ZXJzYWxXZWJTb2NrZXQgfSBmcm9tIFwiQC9jb21tb24vd2Vic29ja2V0LWludGVyZmFjZVwiO1xuaW1wb3J0IHsgSG9ub1dlYlNvY2tldEFkYXB0ZXIgfSBmcm9tIFwiQC9tYW5hZ2VyL2hvbm8td2Vic29ja2V0LWFkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgUnVuQ29uZmlnIH0gZnJvbSBcIkAvcmVnaXN0cnkvcnVuLWNvbmZpZ1wiO1xuaW1wb3J0IHR5cGUgKiBhcyBwcm90b2NvbCBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC9tb2RcIjtcbmltcG9ydCB7XG5cdEhUVFBfQUNUSU9OX1JFUVVFU1RfVkVSU0lPTkVELFxuXHRIVFRQX0FDVElPTl9SRVNQT05TRV9WRVJTSU9ORUQsXG5cdFRPX1NFUlZFUl9WRVJTSU9ORUQsXG59IGZyb20gXCJAL3NjaGVtYXMvY2xpZW50LXByb3RvY29sL3ZlcnNpb25lZFwiO1xuaW1wb3J0IHtcblx0Y29udGVudFR5cGVGb3JFbmNvZGluZyxcblx0ZGVzZXJpYWxpemVXaXRoRW5jb2RpbmcsXG5cdHNlcmlhbGl6ZVdpdGhFbmNvZGluZyxcbn0gZnJvbSBcIkAvc2VyZGVcIjtcbmltcG9ydCB7IGJ1ZmZlclRvQXJyYXlCdWZmZXIgfSBmcm9tIFwiQC91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBBY3RvckRyaXZlciB9IGZyb20gXCIuL2RyaXZlclwiO1xuaW1wb3J0IHR5cGUge1xuXHRHZW5lcmljSHR0cERyaXZlclN0YXRlLFxuXHRHZW5lcmljU3NlRHJpdmVyU3RhdGUsXG5cdEdlbmVyaWNXZWJTb2NrZXREcml2ZXJTdGF0ZSxcbn0gZnJvbSBcIi4vZ2VuZXJpYy1jb25uLWRyaXZlclwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgeyBwYXJzZU1lc3NhZ2UgfSBmcm9tIFwiLi9wcm90b2NvbC9vbGRcIjtcblxuZXhwb3J0IGludGVyZmFjZSBDb25uZWN0V2ViU29ja2V0T3B0cyB7XG5cdHJlcT86IEhvbm9SZXF1ZXN0O1xuXHRlbmNvZGluZzogRW5jb2Rpbmc7XG5cdGFjdG9ySWQ6IHN0cmluZztcblx0cGFyYW1zOiB1bmtub3duO1xuXHRhdXRoRGF0YTogdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb25uZWN0V2ViU29ja2V0T3V0cHV0IHtcblx0b25PcGVuOiAod3M6IFdTQ29udGV4dCkgPT4gdm9pZDtcblx0b25NZXNzYWdlOiAobWVzc2FnZTogcHJvdG9jb2wuVG9TZXJ2ZXIpID0+IHZvaWQ7XG5cdG9uQ2xvc2U6ICgpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdFNzZU9wdHMge1xuXHRyZXE/OiBIb25vUmVxdWVzdDtcblx0ZW5jb2Rpbmc6IEVuY29kaW5nO1xuXHRwYXJhbXM6IHVua25vd247XG5cdGFjdG9ySWQ6IHN0cmluZztcblx0YXV0aERhdGE6IHVua25vd247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdFNzZU91dHB1dCB7XG5cdG9uT3BlbjogKHN0cmVhbTogU1NFU3RyZWFtaW5nQXBpKSA9PiB2b2lkO1xuXHRvbkNsb3NlOiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbk9wdHMge1xuXHRyZXE/OiBIb25vUmVxdWVzdDtcblx0cGFyYW1zOiB1bmtub3duO1xuXHRhY3Rpb25OYW1lOiBzdHJpbmc7XG5cdGFjdGlvbkFyZ3M6IHVua25vd25bXTtcblx0YWN0b3JJZDogc3RyaW5nO1xuXHRhdXRoRGF0YTogdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBY3Rpb25PdXRwdXQge1xuXHRvdXRwdXQ6IHVua25vd247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubnNNZXNzYWdlT3B0cyB7XG5cdHJlcT86IEhvbm9SZXF1ZXN0O1xuXHRjb25uSWQ6IHN0cmluZztcblx0Y29ublRva2VuOiBzdHJpbmc7XG5cdG1lc3NhZ2U6IHByb3RvY29sLlRvU2VydmVyO1xuXHRhY3RvcklkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmV0Y2hPcHRzIHtcblx0cmVxdWVzdDogUmVxdWVzdDtcblx0YWN0b3JJZDogc3RyaW5nO1xuXHRhdXRoRGF0YTogdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRPcHRzIHtcblx0cmVxdWVzdDogUmVxdWVzdDtcblx0d2Vic29ja2V0OiBVbml2ZXJzYWxXZWJTb2NrZXQ7XG5cdGFjdG9ySWQ6IHN0cmluZztcblx0YXV0aERhdGE6IHVua25vd247XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIFdlYlNvY2tldCBjb25uZWN0aW9uIGhhbmRsZXJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVdlYlNvY2tldENvbm5lY3QoXG5cdHJlcTogUmVxdWVzdCB8IHVuZGVmaW5lZCxcblx0cnVuQ29uZmlnOiBSdW5Db25maWcsXG5cdGFjdG9yRHJpdmVyOiBBY3RvckRyaXZlcixcblx0YWN0b3JJZDogc3RyaW5nLFxuXHRlbmNvZGluZzogRW5jb2RpbmcsXG5cdHBhcmFtZXRlcnM6IHVua25vd24sXG5cdGF1dGhEYXRhOiB1bmtub3duLFxuKTogUHJvbWlzZTxVcGdyYWRlV2ViU29ja2V0QXJncz4ge1xuXHRjb25zdCBleHBvc2VJbnRlcm5hbEVycm9yID0gcmVxID8gZ2V0UmVxdWVzdEV4cG9zZUludGVybmFsRXJyb3IocmVxKSA6IGZhbHNlO1xuXG5cdC8vIFNldHVwIHByb21pc2UgZm9yIHRoZSBpbml0IGhhbmRsZXJzIHNpbmNlIGFsbCBvdGhlciBiZWhhdmlvciBkZXBlbmRzIG9uIHRoaXNcblx0Y29uc3Qge1xuXHRcdHByb21pc2U6IGhhbmRsZXJzUHJvbWlzZSxcblx0XHRyZXNvbHZlOiBoYW5kbGVyc1Jlc29sdmUsXG5cdFx0cmVqZWN0OiBoYW5kbGVyc1JlamVjdCxcblx0fSA9IFByb21pc2Uud2l0aFJlc29sdmVyczx7XG5cdFx0Y29ubjogQW55Q29ubjtcblx0XHRhY3RvcjogQW55QWN0b3JJbnN0YW5jZTtcblx0XHRjb25uSWQ6IHN0cmluZztcblx0fT4oKTtcblxuXHQvLyBQcmUtbG9hZCB0aGUgYWN0b3IgdG8gY2F0Y2ggZXJyb3JzIGVhcmx5XG5cdGxldCBhY3RvcjogQW55QWN0b3JJbnN0YW5jZTtcblx0dHJ5IHtcblx0XHRhY3RvciA9IGF3YWl0IGFjdG9yRHJpdmVyLmxvYWRBY3RvcihhY3RvcklkKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHQvLyBSZXR1cm4gaGFuZGxlciB0aGF0IGltbWVkaWF0ZWx5IGNsb3NlcyB3aXRoIGVycm9yXG5cdFx0cmV0dXJuIHtcblx0XHRcdG9uT3BlbjogKF9ldnQ6IGFueSwgd3M6IFdTQ29udGV4dCkgPT4ge1xuXHRcdFx0XHRjb25zdCB7IGNvZGUgfSA9IGRlY29uc3RydWN0RXJyb3IoXG5cdFx0XHRcdFx0ZXJyb3IsXG5cdFx0XHRcdFx0bG9nZ2VyKCksXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0d3NFdmVudDogXCJvcGVuXCIsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRleHBvc2VJbnRlcm5hbEVycm9yLFxuXHRcdFx0XHQpO1xuXHRcdFx0XHR3cy5jbG9zZSgxMDExLCBjb2RlKTtcblx0XHRcdH0sXG5cdFx0XHRvbk1lc3NhZ2U6IChfZXZ0OiB7IGRhdGE6IGFueSB9LCB3czogV1NDb250ZXh0KSA9PiB7XG5cdFx0XHRcdHdzLmNsb3NlKDEwMTEsIFwiQWN0b3Igbm90IGxvYWRlZFwiKTtcblx0XHRcdH0sXG5cdFx0XHRvbkNsb3NlOiAoX2V2ZW50OiBhbnksIF93czogV1NDb250ZXh0KSA9PiB7fSxcblx0XHRcdG9uRXJyb3I6IChfZXJyb3I6IHVua25vd24pID0+IHt9LFxuXHRcdH07XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdG9uT3BlbjogKF9ldnQ6IGFueSwgd3M6IFdTQ29udGV4dCkgPT4ge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ3ZWJzb2NrZXQgb3BlblwiKTtcblxuXHRcdFx0Ly8gUnVuIGFzeW5jIG9wZXJhdGlvbnMgaW4gYmFja2dyb3VuZFxuXHRcdFx0KGFzeW5jICgpID0+IHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBjb25uSWQgPSBnZW5lcmF0ZUNvbm5JZCgpO1xuXHRcdFx0XHRcdGNvbnN0IGNvbm5Ub2tlbiA9IGdlbmVyYXRlQ29ublRva2VuKCk7XG5cdFx0XHRcdFx0Y29uc3QgY29ublN0YXRlID0gYXdhaXQgYWN0b3IucHJlcGFyZUNvbm4ocGFyYW1ldGVycywgcmVxKTtcblxuXHRcdFx0XHRcdC8vIFNhdmUgc29ja2V0XG5cdFx0XHRcdFx0Y29uc3QgY29ubkdsb2JhbFN0YXRlID1cblx0XHRcdFx0XHRcdGFjdG9yRHJpdmVyLmdldEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoYWN0b3JJZCk7XG5cdFx0XHRcdFx0Y29ubkdsb2JhbFN0YXRlLndlYnNvY2tldHMuc2V0KGNvbm5JZCwgd3MpO1xuXHRcdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicmVnaXN0ZXJlZCB3ZWJzb2NrZXQgZm9yIGNvbm5cIiwge1xuXHRcdFx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0XHRcdHRvdGFsQ291bnQ6IGNvbm5HbG9iYWxTdGF0ZS53ZWJzb2NrZXRzLnNpemUsXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHQvLyBDcmVhdGUgY29ubmVjdGlvblxuXHRcdFx0XHRcdGNvbnN0IGNvbm4gPSBhd2FpdCBhY3Rvci5jcmVhdGVDb25uKFxuXHRcdFx0XHRcdFx0Y29ubklkLFxuXHRcdFx0XHRcdFx0Y29ublRva2VuLFxuXHRcdFx0XHRcdFx0cGFyYW1ldGVycyxcblx0XHRcdFx0XHRcdGNvbm5TdGF0ZSxcblx0XHRcdFx0XHRcdENPTk5FQ1RJT05fRFJJVkVSX1dFQlNPQ0tFVCxcblx0XHRcdFx0XHRcdHsgZW5jb2RpbmcgfSBzYXRpc2ZpZXMgR2VuZXJpY1dlYlNvY2tldERyaXZlclN0YXRlLFxuXHRcdFx0XHRcdFx0YXV0aERhdGEsXG5cdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdC8vIFVuYmxvY2sgb3RoZXIgaGFuZGxlcnNcblx0XHRcdFx0XHRoYW5kbGVyc1Jlc29sdmUoeyBjb25uLCBhY3RvciwgY29ubklkIH0pO1xuXHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdGhhbmRsZXJzUmVqZWN0KGVycm9yKTtcblxuXHRcdFx0XHRcdGNvbnN0IHsgY29kZSB9ID0gZGVjb25zdHJ1Y3RFcnJvcihcblx0XHRcdFx0XHRcdGVycm9yLFxuXHRcdFx0XHRcdFx0bG9nZ2VyKCksXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdHdzRXZlbnQ6IFwib3BlblwiLFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGV4cG9zZUludGVybmFsRXJyb3IsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR3cy5jbG9zZSgxMDExLCBjb2RlKTtcblx0XHRcdFx0fVxuXHRcdFx0fSkoKTtcblx0XHR9LFxuXHRcdG9uTWVzc2FnZTogKGV2dDogeyBkYXRhOiBhbnkgfSwgd3M6IFdTQ29udGV4dCkgPT4ge1xuXHRcdFx0Ly8gSGFuZGxlIG1lc3NhZ2UgYXN5bmNocm9ub3VzbHlcblx0XHRcdGhhbmRsZXJzUHJvbWlzZVxuXHRcdFx0XHQudGhlbigoeyBjb25uLCBhY3RvciB9KSA9PiB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJyZWNlaXZlZCBtZXNzYWdlXCIpO1xuXG5cdFx0XHRcdFx0Y29uc3QgdmFsdWUgPSBldnQuZGF0YS52YWx1ZU9mKCkgYXMgSW5wdXREYXRhO1xuXHRcdFx0XHRcdHBhcnNlTWVzc2FnZSh2YWx1ZSwge1xuXHRcdFx0XHRcdFx0ZW5jb2Rpbmc6IGVuY29kaW5nLFxuXHRcdFx0XHRcdFx0bWF4SW5jb21pbmdNZXNzYWdlU2l6ZTogcnVuQ29uZmlnLm1heEluY29taW5nTWVzc2FnZVNpemUsXG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdC50aGVuKChtZXNzYWdlKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGFjdG9yLnByb2Nlc3NNZXNzYWdlKG1lc3NhZ2UsIGNvbm4pLmNhdGNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHsgY29kZSB9ID0gZGVjb25zdHJ1Y3RFcnJvcihcblx0XHRcdFx0XHRcdFx0XHRcdGVycm9yLFxuXHRcdFx0XHRcdFx0XHRcdFx0bG9nZ2VyKCksXG5cdFx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHdzRXZlbnQ6IFwibWVzc2FnZVwiLFxuXHRcdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHRcdGV4cG9zZUludGVybmFsRXJyb3IsXG5cdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0XHR3cy5jbG9zZSgxMDExLCBjb2RlKTtcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdFx0LmNhdGNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHRcdFx0XHRjb25zdCB7IGNvZGUgfSA9IGRlY29uc3RydWN0RXJyb3IoXG5cdFx0XHRcdFx0XHRcdFx0ZXJyb3IsXG5cdFx0XHRcdFx0XHRcdFx0bG9nZ2VyKCksXG5cdFx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdFx0d3NFdmVudDogXCJtZXNzYWdlXCIsXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHRleHBvc2VJbnRlcm5hbEVycm9yLFxuXHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHR3cy5jbG9zZSgxMDExLCBjb2RlKTtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KVxuXHRcdFx0XHQuY2F0Y2goKGVycm9yKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgeyBjb2RlIH0gPSBkZWNvbnN0cnVjdEVycm9yKFxuXHRcdFx0XHRcdFx0ZXJyb3IsXG5cdFx0XHRcdFx0XHRsb2dnZXIoKSxcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0d3NFdmVudDogXCJtZXNzYWdlXCIsXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZXhwb3NlSW50ZXJuYWxFcnJvcixcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdHdzLmNsb3NlKDEwMTEsIGNvZGUpO1xuXHRcdFx0XHR9KTtcblx0XHR9LFxuXHRcdG9uQ2xvc2U6IChcblx0XHRcdGV2ZW50OiB7XG5cdFx0XHRcdHdhc0NsZWFuOiBib29sZWFuO1xuXHRcdFx0XHRjb2RlOiBudW1iZXI7XG5cdFx0XHRcdHJlYXNvbjogc3RyaW5nO1xuXHRcdFx0fSxcblx0XHRcdHdzOiBXU0NvbnRleHQsXG5cdFx0KSA9PiB7XG5cdFx0XHRpZiAoZXZlbnQud2FzQ2xlYW4pIHtcblx0XHRcdFx0bG9nZ2VyKCkuaW5mbyhcIndlYnNvY2tldCBjbG9zZWRcIiwge1xuXHRcdFx0XHRcdGNvZGU6IGV2ZW50LmNvZGUsXG5cdFx0XHRcdFx0cmVhc29uOiBldmVudC5yZWFzb24sXG5cdFx0XHRcdFx0d2FzQ2xlYW46IGV2ZW50Lndhc0NsZWFuLFxuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJ3ZWJzb2NrZXQgY2xvc2VkXCIsIHtcblx0XHRcdFx0XHRjb2RlOiBldmVudC5jb2RlLFxuXHRcdFx0XHRcdHJlYXNvbjogZXZlbnQucmVhc29uLFxuXHRcdFx0XHRcdHdhc0NsZWFuOiBldmVudC53YXNDbGVhbixcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEhBQ0s6IENsb3NlIHNvY2tldCBpbiBvcmRlciB0byBmaXggYnVnIHdpdGggQ2xvdWRmbGFyZSBsZWF2aW5nIFdTIGluIGNsb3Npbmcgc3RhdGVcblx0XHRcdC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jbG91ZGZsYXJlL3dvcmtlcmQvaXNzdWVzLzI1Njlcblx0XHRcdHdzLmNsb3NlKDEwMDAsIFwiaGFja19mb3JjZV9jbG9zZVwiKTtcblxuXHRcdFx0Ly8gSGFuZGxlIGNsZWFudXAgYXN5bmNocm9ub3VzbHlcblx0XHRcdGhhbmRsZXJzUHJvbWlzZVxuXHRcdFx0XHQudGhlbigoeyBjb25uLCBhY3RvciwgY29ubklkIH0pID0+IHtcblx0XHRcdFx0XHRjb25zdCBjb25uR2xvYmFsU3RhdGUgPVxuXHRcdFx0XHRcdFx0YWN0b3JEcml2ZXIuZ2V0R2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZShhY3RvcklkKTtcblx0XHRcdFx0XHRjb25zdCBkaWREZWxldGUgPSBjb25uR2xvYmFsU3RhdGUud2Vic29ja2V0cy5kZWxldGUoY29ubklkKTtcblx0XHRcdFx0XHRpZiAoZGlkRGVsZXRlKSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5pbmZvKFwicmVtb3Zpbmcgd2Vic29ja2V0IGZvciBjb25uXCIsIHtcblx0XHRcdFx0XHRcdFx0dG90YWxDb3VudDogY29ubkdsb2JhbFN0YXRlLndlYnNvY2tldHMuc2l6ZSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS53YXJuKFwid2Vic29ja2V0IGRvZXMgbm90IGV4aXN0IGZvciBjb25uXCIsIHtcblx0XHRcdFx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0XHRcdFx0dG90YWxDb3VudDogY29ubkdsb2JhbFN0YXRlLndlYnNvY2tldHMuc2l6ZSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGFjdG9yLl9fcmVtb3ZlQ29ubihjb25uKTtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHRcdGRlY29uc3RydWN0RXJyb3IoXG5cdFx0XHRcdFx0XHRlcnJvcixcblx0XHRcdFx0XHRcdGxvZ2dlcigpLFxuXHRcdFx0XHRcdFx0eyB3c0V2ZW50OiBcImNsb3NlXCIgfSxcblx0XHRcdFx0XHRcdGV4cG9zZUludGVybmFsRXJyb3IsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSk7XG5cdFx0fSxcblx0XHRvbkVycm9yOiAoX2Vycm9yOiB1bmtub3duKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHQvLyBBY3RvcnMgZG9uJ3QgbmVlZCB0byBrbm93IGFib3V0IHRoaXMsIHNpbmNlIGl0J3MgYWJzdHJhY3RlZCBhd2F5XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJ3ZWJzb2NrZXQgZXJyb3JcIik7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRkZWNvbnN0cnVjdEVycm9yKFxuXHRcdFx0XHRcdGVycm9yLFxuXHRcdFx0XHRcdGxvZ2dlcigpLFxuXHRcdFx0XHRcdHsgd3NFdmVudDogXCJlcnJvclwiIH0sXG5cdFx0XHRcdFx0ZXhwb3NlSW50ZXJuYWxFcnJvcixcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9LFxuXHR9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gU1NFIGNvbm5lY3Rpb24gaGFuZGxlclxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3NlQ29ubmVjdChcblx0YzogSG9ub0NvbnRleHQsXG5cdF9ydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0YWN0b3JEcml2ZXI6IEFjdG9yRHJpdmVyLFxuXHRhY3RvcklkOiBzdHJpbmcsXG5cdGF1dGhEYXRhOiB1bmtub3duLFxuKSB7XG5cdGNvbnN0IGVuY29kaW5nID0gZ2V0UmVxdWVzdEVuY29kaW5nKGMucmVxKTtcblx0Y29uc3QgcGFyYW1ldGVycyA9IGdldFJlcXVlc3RDb25uUGFyYW1zKGMucmVxKTtcblxuXHQvLyBSZXR1cm4gdGhlIG1haW4gaGFuZGxlciB3aXRoIGFsbCBhc3luYyB3b3JrIGluc2lkZVxuXHRyZXR1cm4gc3RyZWFtU1NFKGMsIGFzeW5jIChzdHJlYW0pID0+IHtcblx0XHRsZXQgYWN0b3I6IEFueUFjdG9ySW5zdGFuY2UgfCB1bmRlZmluZWQ7XG5cdFx0bGV0IGNvbm5JZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXHRcdGxldCBjb25uVG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0XHRsZXQgY29ublN0YXRlOiB1bmtub3duO1xuXHRcdGxldCBjb25uOiBBbnlDb25uIHwgdW5kZWZpbmVkO1xuXG5cdFx0dHJ5IHtcblx0XHRcdC8vIERvIGFsbCBhc3luYyB3b3JrIGluc2lkZSB0aGUgaGFuZGxlclxuXHRcdFx0YWN0b3IgPSBhd2FpdCBhY3RvckRyaXZlci5sb2FkQWN0b3IoYWN0b3JJZCk7XG5cdFx0XHRjb25uSWQgPSBnZW5lcmF0ZUNvbm5JZCgpO1xuXHRcdFx0Y29ublRva2VuID0gZ2VuZXJhdGVDb25uVG9rZW4oKTtcblx0XHRcdGNvbm5TdGF0ZSA9IGF3YWl0IGFjdG9yLnByZXBhcmVDb25uKHBhcmFtZXRlcnMsIGMucmVxLnJhdyk7XG5cblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic3NlIG9wZW5cIik7XG5cblx0XHRcdC8vIFNhdmUgc3RyZWFtXG5cdFx0XHRhY3RvckRyaXZlclxuXHRcdFx0XHQuZ2V0R2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZShhY3RvcklkKVxuXHRcdFx0XHQuc3NlU3RyZWFtcy5zZXQoY29ubklkLCBzdHJlYW0pO1xuXG5cdFx0XHQvLyBDcmVhdGUgY29ubmVjdGlvblxuXHRcdFx0Y29ubiA9IGF3YWl0IGFjdG9yLmNyZWF0ZUNvbm4oXG5cdFx0XHRcdGNvbm5JZCxcblx0XHRcdFx0Y29ublRva2VuLFxuXHRcdFx0XHRwYXJhbWV0ZXJzLFxuXHRcdFx0XHRjb25uU3RhdGUsXG5cdFx0XHRcdENPTk5FQ1RJT05fRFJJVkVSX1NTRSxcblx0XHRcdFx0eyBlbmNvZGluZyB9IHNhdGlzZmllcyBHZW5lcmljU3NlRHJpdmVyU3RhdGUsXG5cdFx0XHRcdGF1dGhEYXRhLFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gV2FpdCBmb3IgY2xvc2Vcblx0XHRcdGNvbnN0IGFib3J0UmVzb2x2ZXIgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0cmVhbSBhYm9ydCAod2hlbiBjbGllbnQgY2xvc2VzIHRoZSBjb25uZWN0aW9uKVxuXHRcdFx0c3RyZWFtLm9uQWJvcnQoYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic3NlIHN0cmVhbSBhYm9ydGVkXCIpO1xuXG5cdFx0XHRcdFx0Ly8gQ2xlYW51cFxuXHRcdFx0XHRcdGlmIChjb25uSWQpIHtcblx0XHRcdFx0XHRcdGFjdG9yRHJpdmVyXG5cdFx0XHRcdFx0XHRcdC5nZXRHZW5lcmljQ29ubkdsb2JhbFN0YXRlKGFjdG9ySWQpXG5cdFx0XHRcdFx0XHRcdC5zc2VTdHJlYW1zLmRlbGV0ZShjb25uSWQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoY29ubiAmJiBhY3Rvcikge1xuXHRcdFx0XHRcdFx0YWN0b3IuX19yZW1vdmVDb25uKGNvbm4pO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGFib3J0UmVzb2x2ZXIucmVzb2x2ZSh1bmRlZmluZWQpO1xuXHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgY2xvc2luZyBzc2UgY29ubmVjdGlvblwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdGFib3J0UmVzb2x2ZXIucmVzb2x2ZSh1bmRlZmluZWQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gSEFDSzogV2lsbCB0aHJvdyBpZiBub3QgY29uZmlndXJlZFxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Yy5leGVjdXRpb25DdHgud2FpdFVudGlsKGFib3J0UmVzb2x2ZXIucHJvbWlzZSk7XG5cdFx0XHR9IGNhdGNoIHt9XG5cblx0XHRcdC8vIFdhaXQgdW50aWwgY29ubmVjdGlvbiBhYm9ydGVkXG5cdFx0XHRhd2FpdCBhYm9ydFJlc29sdmVyLnByb21pc2U7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gc3NlIGNvbm5lY3Rpb25cIiwgeyBlcnJvciB9KTtcblxuXHRcdFx0Ly8gQ2xlYW51cCBvbiBlcnJvclxuXHRcdFx0aWYgKGNvbm5JZCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGFjdG9yRHJpdmVyXG5cdFx0XHRcdFx0LmdldEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoYWN0b3JJZClcblx0XHRcdFx0XHQuc3NlU3RyZWFtcy5kZWxldGUoY29ubklkKTtcblx0XHRcdH1cblx0XHRcdGlmIChjb25uICYmIGFjdG9yICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0YWN0b3IuX19yZW1vdmVDb25uKGNvbm4pO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDbG9zZSB0aGUgc3RyZWFtIG9uIGVycm9yXG5cdFx0XHRzdHJlYW0uY2xvc2UoKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gYWN0aW9uIGhhbmRsZXJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUFjdGlvbihcblx0YzogSG9ub0NvbnRleHQsXG5cdF9ydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0YWN0b3JEcml2ZXI6IEFjdG9yRHJpdmVyLFxuXHRhY3Rpb25OYW1lOiBzdHJpbmcsXG5cdGFjdG9ySWQ6IHN0cmluZyxcblx0YXV0aERhdGE6IHVua25vd24sXG4pIHtcblx0Y29uc3QgZW5jb2RpbmcgPSBnZXRSZXF1ZXN0RW5jb2RpbmcoYy5yZXEpO1xuXHRjb25zdCBwYXJhbWV0ZXJzID0gZ2V0UmVxdWVzdENvbm5QYXJhbXMoYy5yZXEpO1xuXG5cdGxvZ2dlcigpLmRlYnVnKFwiaGFuZGxpbmcgYWN0aW9uXCIsIHsgYWN0aW9uTmFtZSwgZW5jb2RpbmcgfSk7XG5cblx0Ly8gVmFsaWRhdGUgaW5jb21pbmcgcmVxdWVzdFxuXHRjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGMucmVxLmFycmF5QnVmZmVyKCk7XG5cdGNvbnN0IHJlcXVlc3QgPSBkZXNlcmlhbGl6ZVdpdGhFbmNvZGluZyhcblx0XHRlbmNvZGluZyxcblx0XHRuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlciksXG5cdFx0SFRUUF9BQ1RJT05fUkVRVUVTVF9WRVJTSU9ORUQsXG5cdCk7XG5cdGNvbnN0IGFjdGlvbkFyZ3MgPSBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShyZXF1ZXN0LmFyZ3MpKTtcblxuXHQvLyBJbnZva2UgdGhlIGFjdGlvblxuXHRsZXQgYWN0b3I6IEFueUFjdG9ySW5zdGFuY2UgfCB1bmRlZmluZWQ7XG5cdGxldCBjb25uOiBBbnlDb25uIHwgdW5kZWZpbmVkO1xuXHRsZXQgb3V0cHV0OiB1bmtub3duIHwgdW5kZWZpbmVkO1xuXHR0cnkge1xuXHRcdGFjdG9yID0gYXdhaXQgYWN0b3JEcml2ZXIubG9hZEFjdG9yKGFjdG9ySWQpO1xuXG5cdFx0Ly8gQ3JlYXRlIGNvbm5cblx0XHRjb25zdCBjb25uU3RhdGUgPSBhd2FpdCBhY3Rvci5wcmVwYXJlQ29ubihwYXJhbWV0ZXJzLCBjLnJlcS5yYXcpO1xuXHRcdGNvbm4gPSBhd2FpdCBhY3Rvci5jcmVhdGVDb25uKFxuXHRcdFx0Z2VuZXJhdGVDb25uSWQoKSxcblx0XHRcdGdlbmVyYXRlQ29ublRva2VuKCksXG5cdFx0XHRwYXJhbWV0ZXJzLFxuXHRcdFx0Y29ublN0YXRlLFxuXHRcdFx0Q09OTkVDVElPTl9EUklWRVJfSFRUUCxcblx0XHRcdHt9IHNhdGlzZmllcyBHZW5lcmljSHR0cERyaXZlclN0YXRlLFxuXHRcdFx0YXV0aERhdGEsXG5cdFx0KTtcblxuXHRcdC8vIENhbGwgYWN0aW9uXG5cdFx0Y29uc3QgY3R4ID0gbmV3IEFjdGlvbkNvbnRleHQoYWN0b3IuYWN0b3JDb250ZXh0ISwgY29ubiEpO1xuXHRcdG91dHB1dCA9IGF3YWl0IGFjdG9yLmV4ZWN1dGVBY3Rpb24oY3R4LCBhY3Rpb25OYW1lLCBhY3Rpb25BcmdzKTtcblx0fSBmaW5hbGx5IHtcblx0XHRpZiAoY29ubikge1xuXHRcdFx0YWN0b3I/Ll9fcmVtb3ZlQ29ubihjb25uKTtcblx0XHR9XG5cdH1cblxuXHQvLyBTZW5kIHJlc3BvbnNlXG5cdGNvbnN0IHJlc3BvbnNlRGF0YTogcHJvdG9jb2wuSHR0cEFjdGlvblJlc3BvbnNlID0ge1xuXHRcdG91dHB1dDogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShvdXRwdXQpKSxcblx0fTtcblx0Y29uc3Qgc2VyaWFsaXplZCA9IHNlcmlhbGl6ZVdpdGhFbmNvZGluZyhcblx0XHRlbmNvZGluZyxcblx0XHRyZXNwb25zZURhdGEsXG5cdFx0SFRUUF9BQ1RJT05fUkVTUE9OU0VfVkVSU0lPTkVELFxuXHQpO1xuXHRyZXR1cm4gYy5ib2R5KHNlcmlhbGl6ZWQgYXMgVWludDhBcnJheSwgMjAwLCB7XG5cdFx0XCJDb250ZW50LVR5cGVcIjogY29udGVudFR5cGVGb3JFbmNvZGluZyhlbmNvZGluZyksXG5cdH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIGNvbm5lY3Rpb24gbWVzc2FnZSBoYW5kbGVyXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVDb25uZWN0aW9uTWVzc2FnZShcblx0YzogSG9ub0NvbnRleHQsXG5cdF9ydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0YWN0b3JEcml2ZXI6IEFjdG9yRHJpdmVyLFxuXHRjb25uSWQ6IHN0cmluZyxcblx0Y29ublRva2VuOiBzdHJpbmcsXG5cdGFjdG9ySWQ6IHN0cmluZyxcbikge1xuXHRjb25zdCBlbmNvZGluZyA9IGdldFJlcXVlc3RFbmNvZGluZyhjLnJlcSk7XG5cblx0Ly8gVmFsaWRhdGUgaW5jb21pbmcgcmVxdWVzdFxuXHRjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGMucmVxLmFycmF5QnVmZmVyKCk7XG5cdGNvbnN0IG1lc3NhZ2UgPSBkZXNlcmlhbGl6ZVdpdGhFbmNvZGluZyhcblx0XHRlbmNvZGluZyxcblx0XHRuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlciksXG5cdFx0VE9fU0VSVkVSX1ZFUlNJT05FRCxcblx0KTtcblxuXHRjb25zdCBhY3RvciA9IGF3YWl0IGFjdG9yRHJpdmVyLmxvYWRBY3RvcihhY3RvcklkKTtcblxuXHQvLyBGaW5kIGNvbm5lY3Rpb25cblx0Y29uc3QgY29ubiA9IGFjdG9yLmNvbm5zLmdldChjb25uSWQpO1xuXHRpZiAoIWNvbm4pIHtcblx0XHR0aHJvdyBuZXcgZXJyb3JzLkNvbm5Ob3RGb3VuZChjb25uSWQpO1xuXHR9XG5cblx0Ly8gQXV0aGVudGljYXRlIGNvbm5lY3Rpb25cblx0aWYgKGNvbm4uX3Rva2VuICE9PSBjb25uVG9rZW4pIHtcblx0XHR0aHJvdyBuZXcgZXJyb3JzLkluY29ycmVjdENvbm5Ub2tlbigpO1xuXHR9XG5cblx0Ly8gUHJvY2VzcyBtZXNzYWdlXG5cdGF3YWl0IGFjdG9yLnByb2Nlc3NNZXNzYWdlKG1lc3NhZ2UsIGNvbm4pO1xuXG5cdHJldHVybiBjLmpzb24oe30pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmF3V2ViU29ja2V0SGFuZGxlcihcblx0cmVxOiBSZXF1ZXN0IHwgdW5kZWZpbmVkLFxuXHRwYXRoOiBzdHJpbmcsXG5cdGFjdG9yRHJpdmVyOiBBY3RvckRyaXZlcixcblx0YWN0b3JJZDogc3RyaW5nLFxuXHRhdXRoRGF0YTogdW5rbm93bixcbik6IFByb21pc2U8VXBncmFkZVdlYlNvY2tldEFyZ3M+IHtcblx0Y29uc3QgYWN0b3IgPSBhd2FpdCBhY3RvckRyaXZlci5sb2FkQWN0b3IoYWN0b3JJZCk7XG5cblx0Ly8gUmV0dXJuIFdlYlNvY2tldCBldmVudCBoYW5kbGVyc1xuXHRyZXR1cm4ge1xuXHRcdG9uT3BlbjogKF9ldnQ6IGFueSwgd3M6IGFueSkgPT4ge1xuXHRcdFx0Ly8gV3JhcCB0aGUgSG9ubyBXZWJTb2NrZXQgaW4gb3VyIGFkYXB0ZXJcblx0XHRcdGNvbnN0IGFkYXB0ZXIgPSBuZXcgSG9ub1dlYlNvY2tldEFkYXB0ZXIod3MpO1xuXG5cdFx0XHQvLyBTdG9yZSBhZGFwdGVyIHJlZmVyZW5jZSBvbiB0aGUgV2ViU29ja2V0IGZvciBldmVudCBoYW5kbGVyc1xuXHRcdFx0KHdzIGFzIGFueSkuX19hZGFwdGVyID0gYWRhcHRlcjtcblxuXHRcdFx0Ly8gRXh0cmFjdCB0aGUgcGF0aCBhZnRlciBwcmVmaXggYW5kIHByZXNlcnZlIHF1ZXJ5IHBhcmFtZXRlcnNcblx0XHRcdC8vIFVzZSBVUkwgQVBJIGZvciBjbGVhbmVyIHBhcnNpbmdcblx0XHRcdGNvbnN0IHVybCA9IG5ldyBVUkwocGF0aCwgXCJodHRwOi8vYWN0b3JcIik7XG5cdFx0XHRjb25zdCBwYXRobmFtZSA9IHVybC5wYXRobmFtZS5yZXBsYWNlKC9eXFwvcmF3XFwvd2Vic29ja2V0LywgXCJcIikgfHwgXCIvXCI7XG5cdFx0XHRjb25zdCBub3JtYWxpemVkUGF0aCA9IHBhdGhuYW1lICsgdXJsLnNlYXJjaDtcblxuXHRcdFx0bGV0IG5ld1JlcXVlc3Q6IFJlcXVlc3Q7XG5cdFx0XHRpZiAocmVxKSB7XG5cdFx0XHRcdG5ld1JlcXVlc3QgPSBuZXcgUmVxdWVzdChgaHR0cDovL2FjdG9yJHtub3JtYWxpemVkUGF0aH1gLCByZXEpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bmV3UmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGBodHRwOi8vYWN0b3Ike25vcm1hbGl6ZWRQYXRofWAsIHtcblx0XHRcdFx0XHRtZXRob2Q6IFwiR0VUXCIsXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJld3JpdGluZyB3ZWJzb2NrZXQgdXJsXCIsIHtcblx0XHRcdFx0ZnJvbTogcGF0aCxcblx0XHRcdFx0dG86IG5ld1JlcXVlc3QudXJsLFxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIENhbGwgdGhlIGFjdG9yJ3Mgb25XZWJTb2NrZXQgaGFuZGxlciB3aXRoIHRoZSBhZGFwdGVkIFdlYlNvY2tldFxuXHRcdFx0YWN0b3IuaGFuZGxlV2ViU29ja2V0KGFkYXB0ZXIsIHtcblx0XHRcdFx0cmVxdWVzdDogbmV3UmVxdWVzdCxcblx0XHRcdFx0YXV0aDogYXV0aERhdGEsXG5cdFx0XHR9KTtcblx0XHR9LFxuXHRcdG9uTWVzc2FnZTogKGV2ZW50OiBhbnksIHdzOiBhbnkpID0+IHtcblx0XHRcdC8vIEZpbmQgdGhlIGFkYXB0ZXIgZm9yIHRoaXMgV2ViU29ja2V0XG5cdFx0XHRjb25zdCBhZGFwdGVyID0gKHdzIGFzIGFueSkuX19hZGFwdGVyO1xuXHRcdFx0aWYgKGFkYXB0ZXIpIHtcblx0XHRcdFx0YWRhcHRlci5faGFuZGxlTWVzc2FnZShldmVudCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRvbkNsb3NlOiAoZXZ0OiBhbnksIHdzOiBhbnkpID0+IHtcblx0XHRcdC8vIEZpbmQgdGhlIGFkYXB0ZXIgZm9yIHRoaXMgV2ViU29ja2V0XG5cdFx0XHRjb25zdCBhZGFwdGVyID0gKHdzIGFzIGFueSkuX19hZGFwdGVyO1xuXHRcdFx0aWYgKGFkYXB0ZXIpIHtcblx0XHRcdFx0YWRhcHRlci5faGFuZGxlQ2xvc2UoZXZ0Py5jb2RlIHx8IDEwMDYsIGV2dD8ucmVhc29uIHx8IFwiXCIpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0b25FcnJvcjogKGVycm9yOiBhbnksIHdzOiBhbnkpID0+IHtcblx0XHRcdC8vIEZpbmQgdGhlIGFkYXB0ZXIgZm9yIHRoaXMgV2ViU29ja2V0XG5cdFx0XHRjb25zdCBhZGFwdGVyID0gKHdzIGFzIGFueSkuX19hZGFwdGVyO1xuXHRcdFx0aWYgKGFkYXB0ZXIpIHtcblx0XHRcdFx0YWRhcHRlci5faGFuZGxlRXJyb3IoZXJyb3IpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdH07XG59XG5cbi8vIEhlbHBlciB0byBnZXQgdGhlIGNvbm5lY3Rpb24gZW5jb2RpbmcgZnJvbSBhIHJlcXVlc3RcbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXF1ZXN0RW5jb2RpbmcocmVxOiBIb25vUmVxdWVzdCk6IEVuY29kaW5nIHtcblx0Y29uc3QgZW5jb2RpbmdQYXJhbSA9IHJlcS5oZWFkZXIoSEVBREVSX0VOQ09ESU5HKTtcblx0aWYgKCFlbmNvZGluZ1BhcmFtKSB7XG5cdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkRW5jb2RpbmcoXCJ1bmRlZmluZWRcIik7XG5cdH1cblxuXHRjb25zdCByZXN1bHQgPSBFbmNvZGluZ1NjaGVtYS5zYWZlUGFyc2UoZW5jb2RpbmdQYXJhbSk7XG5cdGlmICghcmVzdWx0LnN1Y2Nlc3MpIHtcblx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRFbmNvZGluZyhlbmNvZGluZ1BhcmFtIGFzIHN0cmluZyk7XG5cdH1cblxuXHRyZXR1cm4gcmVzdWx0LmRhdGE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXF1ZXN0RXhwb3NlSW50ZXJuYWxFcnJvcihyZXE6IFJlcXVlc3QpOiBib29sZWFuIHtcblx0Y29uc3QgcGFyYW0gPSByZXEuaGVhZGVycy5nZXQoSEVBREVSX0VYUE9TRV9JTlRFUk5BTF9FUlJPUik7XG5cdGlmICghcGFyYW0pIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRyZXR1cm4gcGFyYW0gPT09IFwidHJ1ZVwiO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVxdWVzdFF1ZXJ5KGM6IEhvbm9Db250ZXh0KTogdW5rbm93biB7XG5cdC8vIEdldCBxdWVyeSBwYXJhbWV0ZXJzIGZvciBhY3RvciBsb29rdXBcblx0Y29uc3QgcXVlcnlQYXJhbSA9IGMucmVxLmhlYWRlcihIRUFERVJfQUNUT1JfUVVFUlkpO1xuXHRpZiAoIXF1ZXJ5UGFyYW0pIHtcblx0XHRsb2dnZXIoKS5lcnJvcihcIm1pc3NpbmcgcXVlcnkgcGFyYW1ldGVyXCIpO1xuXHRcdHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFJlcXVlc3QoXCJtaXNzaW5nIHF1ZXJ5XCIpO1xuXHR9XG5cblx0Ly8gUGFyc2UgdGhlIHF1ZXJ5IEpTT04gYW5kIHZhbGlkYXRlIHdpdGggc2NoZW1hXG5cdHRyeSB7XG5cdFx0Y29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShxdWVyeVBhcmFtKTtcblx0XHRyZXR1cm4gcGFyc2VkO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGxvZ2dlcigpLmVycm9yKFwiaW52YWxpZCBxdWVyeSBqc29uXCIsIHsgZXJyb3IgfSk7XG5cdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUXVlcnlKU09OKGVycm9yKTtcblx0fVxufVxuXG5leHBvcnQgY29uc3QgSEVBREVSX0FDVE9SX1FVRVJZID0gXCJYLVJpdmV0S2l0LVF1ZXJ5XCI7XG5cbmV4cG9ydCBjb25zdCBIRUFERVJfRU5DT0RJTkcgPSBcIlgtUml2ZXRLaXQtRW5jb2RpbmdcIjtcblxuLy8gSW50ZXJuYWwgaGVhZGVyXG5leHBvcnQgY29uc3QgSEVBREVSX0VYUE9TRV9JTlRFUk5BTF9FUlJPUiA9IFwiWC1SaXZldEtpdC1FeHBvc2UtSW50ZXJuYWwtRXJyb3JcIjtcblxuLy8gSU1QT1JUQU5UOiBQYXJhbXMgbXVzdCBiZSBpbiBoZWFkZXJzIG9yIGluIGFuIEUyRUUgcGFydCBvZiB0aGUgcmVxdWVzdCAoaS5lLiBOT1QgdGhlIFVSTCBvciBxdWVyeSBzdHJpbmcpIGluIG9yZGVyIHRvIGVuc3VyZSB0aGF0IHRva2VucyBjYW4gYmUgc2VjdXJlbHkgcGFzc2VkIGluIHBhcmFtcy5cbmV4cG9ydCBjb25zdCBIRUFERVJfQ09OTl9QQVJBTVMgPSBcIlgtUml2ZXRLaXQtQ29ubi1QYXJhbXNcIjtcblxuLy8gSW50ZXJuYWwgaGVhZGVyXG5leHBvcnQgY29uc3QgSEVBREVSX0FVVEhfREFUQSA9IFwiWC1SaXZldEtpdC1BdXRoLURhdGFcIjtcblxuZXhwb3J0IGNvbnN0IEhFQURFUl9BQ1RPUl9JRCA9IFwiWC1SaXZldEtpdC1BY3RvclwiO1xuXG5leHBvcnQgY29uc3QgSEVBREVSX0NPTk5fSUQgPSBcIlgtUml2ZXRLaXQtQ29ublwiO1xuXG5leHBvcnQgY29uc3QgSEVBREVSX0NPTk5fVE9LRU4gPSBcIlgtUml2ZXRLaXQtQ29ubi1Ub2tlblwiO1xuXG4vKipcbiAqIEhlYWRlcnMgdGhhdCBwdWJsaWNzIGNhbiBzZW5kIGZyb20gcHVibGljIGNsaWVudHMuXG4gKlxuICogVXNlZCBmb3IgQ09SUy5cbiAqKi9cbmV4cG9ydCBjb25zdCBBTExPV0VEX1BVQkxJQ19IRUFERVJTID0gW1xuXHRcIkNvbnRlbnQtVHlwZVwiLFxuXHRcIlVzZXItQWdlbnRcIixcblx0SEVBREVSX0FDVE9SX1FVRVJZLFxuXHRIRUFERVJfRU5DT0RJTkcsXG5cdEhFQURFUl9DT05OX1BBUkFNUyxcblx0SEVBREVSX0FDVE9SX0lELFxuXHRIRUFERVJfQ09OTl9JRCxcblx0SEVBREVSX0NPTk5fVE9LRU4sXG5dO1xuXG4vLyBIZWxwZXIgdG8gZ2V0IGNvbm5lY3Rpb24gcGFyYW1ldGVycyBmb3IgdGhlIHJlcXVlc3RcbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXF1ZXN0Q29ublBhcmFtcyhyZXE6IEhvbm9SZXF1ZXN0KTogdW5rbm93biB7XG5cdGNvbnN0IHBhcmFtc1BhcmFtID0gcmVxLmhlYWRlcihIRUFERVJfQ09OTl9QQVJBTVMpO1xuXHRpZiAoIXBhcmFtc1BhcmFtKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHR0cnkge1xuXHRcdHJldHVybiBKU09OLnBhcnNlKHBhcmFtc1BhcmFtKTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUGFyYW1zKFxuXHRcdFx0YEludmFsaWQgcGFyYW1zIEpTT046ICR7c3RyaW5naWZ5RXJyb3IoZXJyKX1gLFxuXHRcdCk7XG5cdH1cbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2FjdGlvbi50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3RvclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9hY3Rpb24udHNcIjtpbXBvcnQgdHlwZSB7IEFjdG9yS2V5IH0gZnJvbSBcIkAvYWN0b3IvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSBcIkAvY29tbW9uL2xvZ1wiO1xuaW1wb3J0IHR5cGUgeyBSZWdpc3RyeSB9IGZyb20gXCJAL3JlZ2lzdHJ5L21vZFwiO1xuaW1wb3J0IHR5cGUgeyBDb25uLCBDb25uSWQgfSBmcm9tIFwiLi9jb25uZWN0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yQ29udGV4dCB9IGZyb20gXCIuL2NvbnRleHRcIjtcbmltcG9ydCB0eXBlIHsgQW55RGF0YWJhc2VQcm92aWRlciwgSW5mZXJEYXRhYmFzZUNsaWVudCB9IGZyb20gXCIuL2RhdGFiYXNlXCI7XG5pbXBvcnQgdHlwZSB7IFNhdmVTdGF0ZU9wdGlvbnMgfSBmcm9tIFwiLi9pbnN0YW5jZVwiO1xuaW1wb3J0IHR5cGUgeyBTY2hlZHVsZSB9IGZyb20gXCIuL3NjaGVkdWxlXCI7XG5cbi8qKlxuICogQ29udGV4dCBmb3IgYSByZW1vdGUgcHJvY2VkdXJlIGNhbGwuXG4gKlxuICogQHR5cGVQYXJhbSBBIEFjdG9yIHRoaXMgYWN0aW9uIGJlbG9uZ3MgdG9cbiAqL1xuZXhwb3J0IGNsYXNzIEFjdGlvbkNvbnRleHQ8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlIGV4dGVuZHMgQW55RGF0YWJhc2VQcm92aWRlcixcbj4ge1xuXHQjYWN0b3JDb250ZXh0OiBBY3RvckNvbnRleHQ8XG5cdFx0VFN0YXRlLFxuXHRcdFRDb25uUGFyYW1zLFxuXHRcdFRDb25uU3RhdGUsXG5cdFx0VFZhcnMsXG5cdFx0VElucHV0LFxuXHRcdFRBdXRoRGF0YSxcblx0XHRURGF0YWJhc2Vcblx0PjtcblxuXHQvKipcblx0ICogU2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkuXG5cdCAqXG5cdCAqIEBwYXJhbSBhY3RvckNvbnRleHQgLSBUaGUgYWN0b3IgY29udGV4dFxuXHQgKiBAcGFyYW0gY29ubiAtIFRoZSBjb25uZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgYWN0aW9uXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRhY3RvckNvbnRleHQ6IEFjdG9yQ29udGV4dDxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0XHRwdWJsaWMgcmVhZG9ubHkgY29ubjogQ29ubjxcblx0XHRcdFRTdGF0ZSxcblx0XHRcdFRDb25uUGFyYW1zLFxuXHRcdFx0VENvbm5TdGF0ZSxcblx0XHRcdFRWYXJzLFxuXHRcdFx0VElucHV0LFxuXHRcdFx0VEF1dGhEYXRhLFxuXHRcdFx0VERhdGFiYXNlXG5cdFx0Pixcblx0KSB7XG5cdFx0dGhpcy4jYWN0b3JDb250ZXh0ID0gYWN0b3JDb250ZXh0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgYWN0b3Igc3RhdGVcblx0ICovXG5cdGdldCBzdGF0ZSgpOiBUU3RhdGUge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckNvbnRleHQuc3RhdGU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSBhY3RvciB2YXJpYWJsZXNcblx0ICovXG5cdGdldCB2YXJzKCk6IFRWYXJzIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3JDb250ZXh0LnZhcnM7XG5cdH1cblxuXHQvKipcblx0ICogQnJvYWRjYXN0cyBhbiBldmVudCB0byBhbGwgY29ubmVjdGVkIGNsaWVudHMuXG5cdCAqL1xuXHRicm9hZGNhc3QobmFtZTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSk6IHZvaWQge1xuXHRcdHRoaXMuI2FjdG9yQ29udGV4dC5icm9hZGNhc3QobmFtZSwgLi4uYXJncyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbG9nZ2VyIGluc3RhbmNlLlxuXHQgKi9cblx0Z2V0IGxvZygpOiBMb2dnZXIge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckNvbnRleHQubG9nO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWN0b3IgSUQuXG5cdCAqL1xuXHRnZXQgYWN0b3JJZCgpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckNvbnRleHQuYWN0b3JJZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBhY3RvciBuYW1lLlxuXHQgKi9cblx0Z2V0IG5hbWUoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3JDb250ZXh0Lm5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgYWN0b3Iga2V5LlxuXHQgKi9cblx0Z2V0IGtleSgpOiBBY3RvcktleSB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yQ29udGV4dC5rZXk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcmVnaW9uLlxuXHQgKi9cblx0Z2V0IHJlZ2lvbigpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckNvbnRleHQucmVnaW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNjaGVkdWxlci5cblx0ICovXG5cdGdldCBzY2hlZHVsZSgpOiBTY2hlZHVsZSB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yQ29udGV4dC5zY2hlZHVsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBtYXAgb2YgY29ubmVjdGlvbnMuXG5cdCAqL1xuXHRnZXQgY29ubnMoKTogTWFwPFxuXHRcdENvbm5JZCxcblx0XHRDb25uPFRTdGF0ZSwgVENvbm5QYXJhbXMsIFRDb25uU3RhdGUsIFRWYXJzLCBUSW5wdXQsIFRBdXRoRGF0YSwgVERhdGFiYXNlPlxuXHQ+IHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3JDb250ZXh0LmNvbm5zO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGNsaWVudCBmb3IgdGhlIGdpdmVuIHJlZ2lzdHJ5LlxuXHQgKi9cblx0Y2xpZW50PFIgZXh0ZW5kcyBSZWdpc3RyeTxhbnk+PigpOiBDbGllbnQ8Uj4ge1xuXHRcdHJldHVybiB0aGlzLiNhY3RvckNvbnRleHQuY2xpZW50PFI+KCk7XG5cdH1cblxuXHQvKipcblx0ICogQGV4cGVyaW1lbnRhbFxuXHQgKi9cblx0Z2V0IGRiKCk6IEluZmVyRGF0YWJhc2VDbGllbnQ8VERhdGFiYXNlPiB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yQ29udGV4dC5kYjtcblx0fVxuXG5cdC8qKlxuXHQgKiBGb3JjZXMgdGhlIHN0YXRlIHRvIGdldCBzYXZlZC5cblx0ICovXG5cdGFzeW5jIHNhdmVTdGF0ZShvcHRzOiBTYXZlU3RhdGVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yQ29udGV4dC5zYXZlU3RhdGUob3B0cyk7XG5cdH1cblxuXHQvKipcblx0ICogUHJldmVudHMgdGhlIGFjdG9yIGZyb20gc2xlZXBpbmcgdW50aWwgcHJvbWlzZSBpcyBjb21wbGV0ZS5cblx0ICovXG5cdHdhaXRVbnRpbChwcm9taXNlOiBQcm9taXNlPHZvaWQ+KTogdm9pZCB7XG5cdFx0dGhpcy4jYWN0b3JDb250ZXh0LndhaXRVbnRpbChwcm9taXNlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBYm9ydFNpZ25hbCB0aGF0IGZpcmVzIHdoZW4gdGhlIGFjdG9yIGlzIHN0b3BwaW5nLlxuXHQgKi9cblx0Z2V0IGFib3J0U2lnbmFsKCk6IEFib3J0U2lnbmFsIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3JDb250ZXh0LmFib3J0U2lnbmFsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZvcmNlcyB0aGUgYWN0b3IgdG8gc2xlZXAuXG5cdCAqXG5cdCAqIE5vdCBzdXBwb3J0ZWQgb24gYWxsIGRyaXZlcnMuXG5cdCAqXG5cdCAqIEBleHBlcmltZW50YWxcblx0ICovXG5cdHNsZWVwKCkge1xuXHRcdHRoaXMuI2FjdG9yQ29udGV4dC5zbGVlcCgpO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9tYW5hZ2VyL2xvZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9tYW5hZ2VyXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL21hbmFnZXIvbG9nLnRzXCI7aW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkAvY29tbW9uLy9sb2dcIjtcblxuZXhwb3J0IGNvbnN0IExPR0dFUl9OQU1FID0gXCJhY3Rvci1tYW5hZ2VyXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dnZXIoKSB7XG5cdHJldHVybiBnZXRMb2dnZXIoTE9HR0VSX05BTUUpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvbWFuYWdlci9ob25vLXdlYnNvY2tldC1hZGFwdGVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL21hbmFnZXJcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvbWFuYWdlci9ob25vLXdlYnNvY2tldC1hZGFwdGVyLnRzXCI7aW1wb3J0IHR5cGUgeyBXU0NvbnRleHQgfSBmcm9tIFwiaG9uby93c1wiO1xuaW1wb3J0IHR5cGUge1xuXHRSaXZldENsb3NlRXZlbnQsXG5cdFJpdmV0RXZlbnQsXG5cdFJpdmV0TWVzc2FnZUV2ZW50LFxuXHRVbml2ZXJzYWxXZWJTb2NrZXQsXG59IGZyb20gXCJAL2NvbW1vbi93ZWJzb2NrZXQtaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuLyoqXG4gKiBIb25vV2ViU29ja2V0QWRhcHRlciBwcm92aWRlcyBhIFdlYlNvY2tldC1saWtlIGludGVyZmFjZSBvdmVyIFdTQ29udGV4dFxuICogZm9yIHJhdyBXZWJTb2NrZXQgaGFuZGxpbmcgaW4gYWN0b3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBIb25vV2ViU29ja2V0QWRhcHRlciBpbXBsZW1lbnRzIFVuaXZlcnNhbFdlYlNvY2tldCB7XG5cdC8vIFdlYlNvY2tldCByZWFkeVN0YXRlIHZhbHVlc1xuXHRyZWFkb25seSBDT05ORUNUSU5HID0gMCBhcyBjb25zdDtcblx0cmVhZG9ubHkgT1BFTiA9IDEgYXMgY29uc3Q7XG5cdHJlYWRvbmx5IENMT1NJTkcgPSAyIGFzIGNvbnN0O1xuXHRyZWFkb25seSBDTE9TRUQgPSAzIGFzIGNvbnN0O1xuXG5cdCN3czogV1NDb250ZXh0O1xuXHQjcmVhZHlTdGF0ZTogMCB8IDEgfCAyIHwgMyA9IDE7IC8vIFN0YXJ0IGFzIE9QRU4gc2luY2UgV1NDb250ZXh0IGlzIGFscmVhZHkgY29ubmVjdGVkXG5cdCNldmVudExpc3RlbmVyczogTWFwPHN0cmluZywgU2V0PChldmVudDogYW55KSA9PiB2b2lkPj4gPSBuZXcgTWFwKCk7XG5cdCNjbG9zZUNvZGU/OiBudW1iZXI7XG5cdCNjbG9zZVJlYXNvbj86IHN0cmluZztcblxuXHRjb25zdHJ1Y3Rvcih3czogV1NDb250ZXh0KSB7XG5cdFx0dGhpcy4jd3MgPSB3cztcblxuXHRcdC8vIFRoZSBXU0NvbnRleHQgaXMgYWxyZWFkeSBvcGVuIHdoZW4gd2UgcmVjZWl2ZSBpdFxuXHRcdHRoaXMuI3JlYWR5U3RhdGUgPSB0aGlzLk9QRU47XG5cblx0XHQvLyBJbW1lZGlhdGVseSBmaXJlIHRoZSBvcGVuIGV2ZW50XG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHR0aGlzLiNmaXJlRXZlbnQoXCJvcGVuXCIsIHsgdHlwZTogXCJvcGVuXCIsIHRhcmdldDogdGhpcyB9KTtcblx0XHR9LCAwKTtcblx0fVxuXG5cdGdldCByZWFkeVN0YXRlKCk6IDAgfCAxIHwgMiB8IDMge1xuXHRcdHJldHVybiB0aGlzLiNyZWFkeVN0YXRlO1xuXHR9XG5cblx0Z2V0IGJpbmFyeVR5cGUoKTogXCJhcnJheWJ1ZmZlclwiIHwgXCJibG9iXCIge1xuXHRcdHJldHVybiBcImFycmF5YnVmZmVyXCI7XG5cdH1cblxuXHRzZXQgYmluYXJ5VHlwZSh2YWx1ZTogXCJhcnJheWJ1ZmZlclwiIHwgXCJibG9iXCIpIHtcblx0XHQvLyBJZ25vcmVkIGZvciBub3cgLSBhbHdheXMgdXNlIGFycmF5YnVmZmVyXG5cdH1cblxuXHRnZXQgYnVmZmVyZWRBbW91bnQoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gMDsgLy8gTm90IHRyYWNrZWQgaW4gV1NDb250ZXh0XG5cdH1cblxuXHRnZXQgZXh0ZW5zaW9ucygpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcIlwiOyAvLyBOb3QgYXZhaWxhYmxlIGluIFdTQ29udGV4dFxuXHR9XG5cblx0Z2V0IHByb3RvY29sKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiXCI7IC8vIE5vdCBhdmFpbGFibGUgaW4gV1NDb250ZXh0XG5cdH1cblxuXHRnZXQgdXJsKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiXCI7IC8vIE5vdCBhdmFpbGFibGUgaW4gV1NDb250ZXh0XG5cdH1cblxuXHRzZW5kKGRhdGE6IHN0cmluZyB8IEFycmF5QnVmZmVyTGlrZSB8IEJsb2IgfCBBcnJheUJ1ZmZlclZpZXcpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5yZWFkeVN0YXRlICE9PSB0aGlzLk9QRU4pIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIldlYlNvY2tldCBpcyBub3Qgb3BlblwiKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJicmlkZ2Ugc2VuZGluZyBkYXRhXCIsIHtcblx0XHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBkYXRhLFxuXHRcdFx0XHRpc1N0cmluZzogdHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIsXG5cdFx0XHRcdGlzQXJyYXlCdWZmZXI6IGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcixcblx0XHRcdFx0ZGF0YVN0cjpcblx0XHRcdFx0XHR0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiA/IGRhdGEuc3Vic3RyaW5nKDAsIDEwMCkgOiBcIjxub24tc3RyaW5nPlwiLFxuXHRcdFx0fSk7XG5cblx0XHRcdGlmICh0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHQodGhpcy4jd3MgYXMgYW55KS5zZW5kKGRhdGEpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcblx0XHRcdFx0KHRoaXMuI3dzIGFzIGFueSkuc2VuZChkYXRhKTtcblx0XHRcdH0gZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGRhdGEpKSB7XG5cdFx0XHRcdC8vIENvbnZlcnQgQXJyYXlCdWZmZXJWaWV3IHRvIEFycmF5QnVmZmVyXG5cdFx0XHRcdGNvbnN0IGJ1ZmZlciA9IGRhdGEuYnVmZmVyLnNsaWNlKFxuXHRcdFx0XHRcdGRhdGEuYnl0ZU9mZnNldCxcblx0XHRcdFx0XHRkYXRhLmJ5dGVPZmZzZXQgKyBkYXRhLmJ5dGVMZW5ndGgsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdC8vIENoZWNrIGlmIGl0J3MgYSBTaGFyZWRBcnJheUJ1ZmZlciBhbmQgY29udmVydCB0byBBcnJheUJ1ZmZlclxuXHRcdFx0XHRpZiAoYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpIHtcblx0XHRcdFx0XHRjb25zdCBhcnJheUJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihidWZmZXIuYnl0ZUxlbmd0aCk7XG5cdFx0XHRcdFx0bmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpLnNldChuZXcgVWludDhBcnJheShidWZmZXIpKTtcblx0XHRcdFx0XHQodGhpcy4jd3MgYXMgYW55KS5zZW5kKGFycmF5QnVmZmVyKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQodGhpcy4jd3MgYXMgYW55KS5zZW5kKGJ1ZmZlcik7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIEJsb2IpIHtcblx0XHRcdFx0Ly8gQ29udmVydCBCbG9iIHRvIEFycmF5QnVmZmVyXG5cdFx0XHRcdGRhdGFcblx0XHRcdFx0XHQuYXJyYXlCdWZmZXIoKVxuXHRcdFx0XHRcdC50aGVuKChidWZmZXIpID0+IHtcblx0XHRcdFx0XHRcdCh0aGlzLiN3cyBhcyBhbnkpLnNlbmQoYnVmZmVyKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5jYXRjaCgoZXJyb3IpID0+IHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIGNvbnZlcnQgYmxvYiB0byBhcnJheWJ1ZmZlclwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdFx0dGhpcy4jZmlyZUV2ZW50KFwiZXJyb3JcIiwgeyB0eXBlOiBcImVycm9yXCIsIHRhcmdldDogdGhpcywgZXJyb3IgfSk7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBUcnkgdG8gY29udmVydCB0byBzdHJpbmcgYXMgYSBmYWxsYmFja1xuXHRcdFx0XHRsb2dnZXIoKS53YXJuKFwidW5zdXBwb3J0ZWQgZGF0YSB0eXBlLCBjb252ZXJ0aW5nIHRvIHN0cmluZ1wiLCB7XG5cdFx0XHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBkYXRhLFxuXHRcdFx0XHRcdGRhdGEsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQodGhpcy4jd3MgYXMgYW55KS5zZW5kKFN0cmluZyhkYXRhKSk7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3Igc2VuZGluZyB3ZWJzb2NrZXQgZGF0YVwiLCB7IGVycm9yIH0pO1xuXHRcdFx0dGhpcy4jZmlyZUV2ZW50KFwiZXJyb3JcIiwgeyB0eXBlOiBcImVycm9yXCIsIHRhcmdldDogdGhpcywgZXJyb3IgfSk7XG5cdFx0XHR0aHJvdyBlcnJvcjtcblx0XHR9XG5cdH1cblxuXHRjbG9zZShjb2RlID0gMTAwMCwgcmVhc29uID0gXCJcIik6IHZvaWQge1xuXHRcdGlmICh0aGlzLnJlYWR5U3RhdGUgPT09IHRoaXMuQ0xPU0lORyB8fCB0aGlzLnJlYWR5U3RhdGUgPT09IHRoaXMuQ0xPU0VEKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy4jcmVhZHlTdGF0ZSA9IHRoaXMuQ0xPU0lORztcblx0XHR0aGlzLiNjbG9zZUNvZGUgPSBjb2RlO1xuXHRcdHRoaXMuI2Nsb3NlUmVhc29uID0gcmVhc29uO1xuXG5cdFx0dHJ5IHtcblx0XHRcdCh0aGlzLiN3cyBhcyBhbnkpLmNsb3NlKGNvZGUsIHJlYXNvbik7XG5cblx0XHRcdC8vIFVwZGF0ZSBzdGF0ZSBhbmQgZmlyZSBjbG9zZSBldmVudFxuXHRcdFx0dGhpcy4jcmVhZHlTdGF0ZSA9IHRoaXMuQ0xPU0VEO1xuXHRcdFx0dGhpcy4jZmlyZUV2ZW50KFwiY2xvc2VcIiwge1xuXHRcdFx0XHR0eXBlOiBcImNsb3NlXCIsXG5cdFx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdFx0Y29kZSxcblx0XHRcdFx0cmVhc29uLFxuXHRcdFx0XHR3YXNDbGVhbjogY29kZSA9PT0gMTAwMCxcblx0XHRcdH0pO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGNsb3Npbmcgd2Vic29ja2V0XCIsIHsgZXJyb3IgfSk7XG5cdFx0XHR0aGlzLiNyZWFkeVN0YXRlID0gdGhpcy5DTE9TRUQ7XG5cdFx0XHR0aGlzLiNmaXJlRXZlbnQoXCJjbG9zZVwiLCB7XG5cdFx0XHRcdHR5cGU6IFwiY2xvc2VcIixcblx0XHRcdFx0dGFyZ2V0OiB0aGlzLFxuXHRcdFx0XHRjb2RlOiAxMDA2LFxuXHRcdFx0XHRyZWFzb246IFwiQWJub3JtYWwgY2xvc3VyZVwiLFxuXHRcdFx0XHR3YXNDbGVhbjogZmFsc2UsXG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHRhZGRFdmVudExpc3RlbmVyKHR5cGU6IHN0cmluZywgbGlzdGVuZXI6IChldmVudDogYW55KSA9PiB2b2lkKTogdm9pZCB7XG5cdFx0aWYgKCF0aGlzLiNldmVudExpc3RlbmVycy5oYXModHlwZSkpIHtcblx0XHRcdHRoaXMuI2V2ZW50TGlzdGVuZXJzLnNldCh0eXBlLCBuZXcgU2V0KCkpO1xuXHRcdH1cblx0XHR0aGlzLiNldmVudExpc3RlbmVycy5nZXQodHlwZSkhLmFkZChsaXN0ZW5lcik7XG5cdH1cblxuXHRyZW1vdmVFdmVudExpc3RlbmVyKHR5cGU6IHN0cmluZywgbGlzdGVuZXI6IChldmVudDogYW55KSA9PiB2b2lkKTogdm9pZCB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gdGhpcy4jZXZlbnRMaXN0ZW5lcnMuZ2V0KHR5cGUpO1xuXHRcdGlmIChsaXN0ZW5lcnMpIHtcblx0XHRcdGxpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpO1xuXHRcdH1cblx0fVxuXG5cdGRpc3BhdGNoRXZlbnQoZXZlbnQ6IFJpdmV0RXZlbnQpOiBib29sZWFuIHtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLiNldmVudExpc3RlbmVycy5nZXQoZXZlbnQudHlwZSk7XG5cdFx0aWYgKGxpc3RlbmVycykge1xuXHRcdFx0Zm9yIChjb25zdCBsaXN0ZW5lciBvZiBsaXN0ZW5lcnMpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRsaXN0ZW5lcihldmVudCk7XG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoYGVycm9yIGluICR7ZXZlbnQudHlwZX0gZXZlbnQgbGlzdGVuZXJgLCB7IGVycm9yIH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0Ly8gSW50ZXJuYWwgbWV0aG9kIHRvIGhhbmRsZSBpbmNvbWluZyBtZXNzYWdlcyBmcm9tIFdTQ29udGV4dFxuXHRfaGFuZGxlTWVzc2FnZShkYXRhOiBhbnkpOiB2b2lkIHtcblx0XHQvLyBIb25vIG1heSBwYXNzIGVpdGhlciByYXcgZGF0YSBvciBhIE1lc3NhZ2VFdmVudC1saWtlIG9iamVjdFxuXHRcdGxldCBtZXNzYWdlRGF0YTogc3RyaW5nIHwgQXJyYXlCdWZmZXIgfCBBcnJheUJ1ZmZlclZpZXc7XG5cblx0XHRpZiAodHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIpIHtcblx0XHRcdG1lc3NhZ2VEYXRhID0gZGF0YTtcblx0XHR9IGVsc2UgaWYgKGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlciB8fCBBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkpIHtcblx0XHRcdG1lc3NhZ2VEYXRhID0gZGF0YTtcblx0XHR9IGVsc2UgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09IFwib2JqZWN0XCIgJiYgXCJkYXRhXCIgaW4gZGF0YSkge1xuXHRcdFx0Ly8gSGFuZGxlIE1lc3NhZ2VFdmVudC1saWtlIG9iamVjdHNcblx0XHRcdG1lc3NhZ2VEYXRhID0gZGF0YS5kYXRhO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBGYWxsYmFjayAtIHNob3VsZG4ndCBoYXBwZW4gaW4gbm9ybWFsIG9wZXJhdGlvblxuXHRcdFx0bWVzc2FnZURhdGEgPSBTdHJpbmcoZGF0YSk7XG5cdFx0fVxuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJicmlkZ2UgaGFuZGxpbmcgbWVzc2FnZVwiLCB7XG5cdFx0XHRkYXRhVHlwZTogdHlwZW9mIG1lc3NhZ2VEYXRhLFxuXHRcdFx0aXNBcnJheUJ1ZmZlcjogbWVzc2FnZURhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcixcblx0XHRcdGRhdGFTdHI6IHR5cGVvZiBtZXNzYWdlRGF0YSA9PT0gXCJzdHJpbmdcIiA/IG1lc3NhZ2VEYXRhIDogXCI8YmluYXJ5PlwiLFxuXHRcdH0pO1xuXG5cdFx0dGhpcy4jZmlyZUV2ZW50KFwibWVzc2FnZVwiLCB7XG5cdFx0XHR0eXBlOiBcIm1lc3NhZ2VcIixcblx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdGRhdGE6IG1lc3NhZ2VEYXRhLFxuXHRcdH0pO1xuXHR9XG5cblx0Ly8gSW50ZXJuYWwgbWV0aG9kIHRvIGhhbmRsZSBjbG9zZSBmcm9tIFdTQ29udGV4dFxuXHRfaGFuZGxlQ2xvc2UoY29kZTogbnVtYmVyLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXHRcdC8vIEhBQ0s6IENsb3NlIHNvY2tldCBpbiBvcmRlciB0byBmaXggYnVnIHdpdGggQ2xvdWRmbGFyZSBsZWF2aW5nIFdTIGluIGNsb3Npbmcgc3RhdGVcblx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vY2xvdWRmbGFyZS93b3JrZXJkL2lzc3Vlcy8yNTY5XG5cdFx0KHRoaXMuI3dzIGFzIGFueSkuY2xvc2UoMTAwMCwgXCJoYWNrX2ZvcmNlX2Nsb3NlXCIpO1xuXG5cdFx0aWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHJldHVybjtcblxuXHRcdHRoaXMuI3JlYWR5U3RhdGUgPSB0aGlzLkNMT1NFRDtcblx0XHR0aGlzLiNjbG9zZUNvZGUgPSBjb2RlO1xuXHRcdHRoaXMuI2Nsb3NlUmVhc29uID0gcmVhc29uO1xuXG5cdFx0dGhpcy4jZmlyZUV2ZW50KFwiY2xvc2VcIiwge1xuXHRcdFx0dHlwZTogXCJjbG9zZVwiLFxuXHRcdFx0dGFyZ2V0OiB0aGlzLFxuXHRcdFx0Y29kZSxcblx0XHRcdHJlYXNvbixcblx0XHRcdHdhc0NsZWFuOiBjb2RlID09PSAxMDAwLFxuXHRcdH0pO1xuXHR9XG5cblx0Ly8gSW50ZXJuYWwgbWV0aG9kIHRvIGhhbmRsZSBlcnJvcnMgZnJvbSBXU0NvbnRleHRcblx0X2hhbmRsZUVycm9yKGVycm9yOiBhbnkpOiB2b2lkIHtcblx0XHR0aGlzLiNmaXJlRXZlbnQoXCJlcnJvclwiLCB7XG5cdFx0XHR0eXBlOiBcImVycm9yXCIsXG5cdFx0XHR0YXJnZXQ6IHRoaXMsXG5cdFx0XHRlcnJvcixcblx0XHR9KTtcblx0fVxuXG5cdCNmaXJlRXZlbnQodHlwZTogc3RyaW5nLCBldmVudDogYW55KTogdm9pZCB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gdGhpcy4jZXZlbnRMaXN0ZW5lcnMuZ2V0KHR5cGUpO1xuXHRcdGlmIChsaXN0ZW5lcnMpIHtcblx0XHRcdGZvciAoY29uc3QgbGlzdGVuZXIgb2YgbGlzdGVuZXJzKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0bGlzdGVuZXIoZXZlbnQpO1xuXHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKGBlcnJvciBpbiAke3R5cGV9IGV2ZW50IGxpc3RlbmVyYCwgeyBlcnJvciB9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFsc28gY2hlY2sgZm9yIG9uKiBwcm9wZXJ0aWVzXG5cdFx0c3dpdGNoICh0eXBlKSB7XG5cdFx0XHRjYXNlIFwib3BlblwiOlxuXHRcdFx0XHRpZiAodGhpcy4jb25vcGVuKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHRoaXMuI29ub3BlbihldmVudCk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gb25vcGVuIGhhbmRsZXJcIiwgeyBlcnJvciB9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiY2xvc2VcIjpcblx0XHRcdFx0aWYgKHRoaXMuI29uY2xvc2UpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0dGhpcy4jb25jbG9zZShldmVudCk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gb25jbG9zZSBoYW5kbGVyXCIsIHsgZXJyb3IgfSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcImVycm9yXCI6XG5cdFx0XHRcdGlmICh0aGlzLiNvbmVycm9yKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHRoaXMuI29uZXJyb3IoZXZlbnQpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGluIG9uZXJyb3IgaGFuZGxlclwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJtZXNzYWdlXCI6XG5cdFx0XHRcdGlmICh0aGlzLiNvbm1lc3NhZ2UpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0dGhpcy4jb25tZXNzYWdlKGV2ZW50KTtcblx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBvbm1lc3NhZ2UgaGFuZGxlclwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHQvLyBFdmVudCBoYW5kbGVyIHByb3BlcnRpZXMgd2l0aCBnZXR0ZXJzL3NldHRlcnNcblx0I29ub3BlbjogKChldmVudDogUml2ZXRFdmVudCkgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcblx0I29uY2xvc2U6ICgoZXZlbnQ6IFJpdmV0Q2xvc2VFdmVudCkgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcblx0I29uZXJyb3I6ICgoZXZlbnQ6IFJpdmV0RXZlbnQpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cdCNvbm1lc3NhZ2U6ICgoZXZlbnQ6IFJpdmV0TWVzc2FnZUV2ZW50KSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuXG5cdGdldCBvbm9wZW4oKTogKChldmVudDogUml2ZXRFdmVudCkgPT4gdm9pZCkgfCBudWxsIHtcblx0XHRyZXR1cm4gdGhpcy4jb25vcGVuO1xuXHR9XG5cdHNldCBvbm9wZW4oaGFuZGxlcjogKChldmVudDogUml2ZXRFdmVudCkgPT4gdm9pZCkgfCBudWxsKSB7XG5cdFx0dGhpcy4jb25vcGVuID0gaGFuZGxlcjtcblx0fVxuXG5cdGdldCBvbmNsb3NlKCk6ICgoZXZlbnQ6IFJpdmV0Q2xvc2VFdmVudCkgPT4gdm9pZCkgfCBudWxsIHtcblx0XHRyZXR1cm4gdGhpcy4jb25jbG9zZTtcblx0fVxuXHRzZXQgb25jbG9zZShoYW5kbGVyOiAoKGV2ZW50OiBSaXZldENsb3NlRXZlbnQpID0+IHZvaWQpIHwgbnVsbCkge1xuXHRcdHRoaXMuI29uY2xvc2UgPSBoYW5kbGVyO1xuXHR9XG5cblx0Z2V0IG9uZXJyb3IoKTogKChldmVudDogUml2ZXRFdmVudCkgPT4gdm9pZCkgfCBudWxsIHtcblx0XHRyZXR1cm4gdGhpcy4jb25lcnJvcjtcblx0fVxuXHRzZXQgb25lcnJvcihoYW5kbGVyOiAoKGV2ZW50OiBSaXZldEV2ZW50KSA9PiB2b2lkKSB8IG51bGwpIHtcblx0XHR0aGlzLiNvbmVycm9yID0gaGFuZGxlcjtcblx0fVxuXG5cdGdldCBvbm1lc3NhZ2UoKTogKChldmVudDogUml2ZXRNZXNzYWdlRXZlbnQpID0+IHZvaWQpIHwgbnVsbCB7XG5cdFx0cmV0dXJuIHRoaXMuI29ubWVzc2FnZTtcblx0fVxuXHRzZXQgb25tZXNzYWdlKGhhbmRsZXI6ICgoZXZlbnQ6IFJpdmV0TWVzc2FnZUV2ZW50KSA9PiB2b2lkKSB8IG51bGwpIHtcblx0XHR0aGlzLiNvbm1lc3NhZ2UgPSBoYW5kbGVyO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9wcm90b2NvbC9vbGQudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvcHJvdG9jb2xcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvcHJvdG9jb2wvb2xkLnRzXCI7aW1wb3J0ICogYXMgY2JvciBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBBbnlEYXRhYmFzZVByb3ZpZGVyIH0gZnJvbSBcIkAvYWN0b3IvZGF0YWJhc2VcIjtcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tIFwiQC9hY3Rvci9lcnJvcnNcIjtcbmltcG9ydCB7XG5cdENhY2hlZFNlcmlhbGl6ZXIsXG5cdHR5cGUgRW5jb2RpbmcsXG5cdHR5cGUgSW5wdXREYXRhLFxufSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHsgZGVjb25zdHJ1Y3RFcnJvciB9IGZyb20gXCJAL2NvbW1vbi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgKiBhcyBwcm90b2NvbCBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC9tb2RcIjtcbmltcG9ydCB7XG5cdFRPX0NMSUVOVF9WRVJTSU9ORUQsXG5cdFRPX1NFUlZFUl9WRVJTSU9ORUQsXG59IGZyb20gXCJAL3NjaGVtYXMvY2xpZW50LXByb3RvY29sL3ZlcnNpb25lZFwiO1xuaW1wb3J0IHsgZGVzZXJpYWxpemVXaXRoRW5jb2RpbmcgfSBmcm9tIFwiQC9zZXJkZVwiO1xuaW1wb3J0IHsgYXNzZXJ0VW5yZWFjaGFibGUsIGJ1ZmZlclRvQXJyYXlCdWZmZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmltcG9ydCB7IEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi4vYWN0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IENvbm4gfSBmcm9tIFwiLi4vY29ubmVjdGlvblwiO1xuaW1wb3J0IHR5cGUgeyBBY3Rvckluc3RhbmNlIH0gZnJvbSBcIi4uL2luc3RhbmNlXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi4vbG9nXCI7XG5cbmV4cG9ydCBjb25zdCBUcmFuc3BvcnRTY2hlbWEgPSB6LmVudW0oW1wid2Vic29ja2V0XCIsIFwic3NlXCJdKTtcblxuLyoqXG4gKiBUcmFuc3BvcnQgbWVjaGFuaXNtIHVzZWQgdG8gY29tbXVuaWNhdGUgYmV0d2VlbiBjbGllbnQgJiBhY3Rvci5cbiAqL1xuZXhwb3J0IHR5cGUgVHJhbnNwb3J0ID0gei5pbmZlcjx0eXBlb2YgVHJhbnNwb3J0U2NoZW1hPjtcblxuaW50ZXJmYWNlIE1lc3NhZ2VFdmVudE9wdHMge1xuXHRlbmNvZGluZzogRW5jb2Rpbmc7XG5cdG1heEluY29taW5nTWVzc2FnZVNpemU6IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gZ2V0VmFsdWVMZW5ndGgodmFsdWU6IElucHV0RGF0YSk6IG51bWJlciB7XG5cdGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcblx0XHRyZXR1cm4gdmFsdWUubGVuZ3RoO1xuXHR9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgQmxvYikge1xuXHRcdHJldHVybiB2YWx1ZS5zaXplO1xuXHR9IGVsc2UgaWYgKFxuXHRcdHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcblx0XHR2YWx1ZSBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyIHx8XG5cdFx0dmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5XG5cdCkge1xuXHRcdHJldHVybiB2YWx1ZS5ieXRlTGVuZ3RoO1xuXHR9IGVsc2Uge1xuXHRcdGFzc2VydFVucmVhY2hhYmxlKHZhbHVlKTtcblx0fVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5wdXREYXRhVG9CdWZmZXIoXG5cdGRhdGE6IElucHV0RGF0YSxcbik6IFByb21pc2U8VWludDhBcnJheSB8IHN0cmluZz4ge1xuXHRpZiAodHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIpIHtcblx0XHRyZXR1cm4gZGF0YTtcblx0fSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQmxvYikge1xuXHRcdGNvbnN0IGFycmF5QnVmZmVyID0gYXdhaXQgZGF0YS5hcnJheUJ1ZmZlcigpO1xuXHRcdHJldHVybiBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7XG5cdH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcblx0XHRyZXR1cm4gZGF0YTtcblx0fSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHwgZGF0YSBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSB7XG5cdFx0cmV0dXJuIG5ldyBVaW50OEFycmF5KGRhdGEpO1xuXHR9IGVsc2Uge1xuXHRcdHRocm93IG5ldyBlcnJvcnMuTWFsZm9ybWVkTWVzc2FnZSgpO1xuXHR9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYXJzZU1lc3NhZ2UoXG5cdHZhbHVlOiBJbnB1dERhdGEsXG5cdG9wdHM6IE1lc3NhZ2VFdmVudE9wdHMsXG4pOiBQcm9taXNlPHByb3RvY29sLlRvU2VydmVyPiB7XG5cdC8vIFZhbGlkYXRlIHZhbHVlIGxlbmd0aFxuXHRjb25zdCBsZW5ndGggPSBnZXRWYWx1ZUxlbmd0aCh2YWx1ZSk7XG5cdGlmIChsZW5ndGggPiBvcHRzLm1heEluY29taW5nTWVzc2FnZVNpemUpIHtcblx0XHR0aHJvdyBuZXcgZXJyb3JzLk1lc3NhZ2VUb29Mb25nKCk7XG5cdH1cblxuXHQvLyBQYXJzZSAmIHZhbGlkYXRlIG1lc3NhZ2Vcblx0Y29uc3QgYnVmZmVyID0gYXdhaXQgaW5wdXREYXRhVG9CdWZmZXIodmFsdWUpO1xuXHRyZXR1cm4gZGVzZXJpYWxpemVXaXRoRW5jb2Rpbmcob3B0cy5lbmNvZGluZywgYnVmZmVyLCBUT19TRVJWRVJfVkVSU0lPTkVEKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzTWVzc2FnZUhhbmRsZXI8XG5cdFMsXG5cdENQLFxuXHRDUyxcblx0Vixcblx0SSxcblx0QUQsXG5cdERCIGV4dGVuZHMgQW55RGF0YWJhc2VQcm92aWRlcixcbj4ge1xuXHRvbkV4ZWN1dGVBY3Rpb24/OiAoXG5cdFx0Y3R4OiBBY3Rpb25Db250ZXh0PFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcblx0XHRuYW1lOiBzdHJpbmcsXG5cdFx0YXJnczogdW5rbm93bltdLFxuXHQpID0+IFByb21pc2U8dW5rbm93bj47XG5cdG9uU3Vic2NyaWJlPzogKFxuXHRcdGV2ZW50TmFtZTogc3RyaW5nLFxuXHRcdGNvbm46IENvbm48UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+LFxuXHQpID0+IFByb21pc2U8dm9pZD47XG5cdG9uVW5zdWJzY3JpYmU/OiAoXG5cdFx0ZXZlbnROYW1lOiBzdHJpbmcsXG5cdFx0Y29ubjogQ29ubjxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4sXG5cdCkgPT4gUHJvbWlzZTx2b2lkPjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NNZXNzYWdlPFxuXHRTLFxuXHRDUCxcblx0Q1MsXG5cdFYsXG5cdEksXG5cdEFELFxuXHREQiBleHRlbmRzIEFueURhdGFiYXNlUHJvdmlkZXIsXG4+KFxuXHRtZXNzYWdlOiBwcm90b2NvbC5Ub1NlcnZlcixcblx0YWN0b3I6IEFjdG9ySW5zdGFuY2U8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+LFxuXHRjb25uOiBDb25uPFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcblx0aGFuZGxlcjogUHJvY2Vzc01lc3NhZ2VIYW5kbGVyPFMsIENQLCBDUywgViwgSSwgQUQsIERCPixcbikge1xuXHRsZXQgYWN0aW9uSWQ6IGJpZ2ludCB8IHVuZGVmaW5lZDtcblx0bGV0IGFjdGlvbk5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuXHR0cnkge1xuXHRcdGlmIChtZXNzYWdlLmJvZHkudGFnID09PSBcIkFjdGlvblJlcXVlc3RcIikge1xuXHRcdFx0Ly8gQWN0aW9uIHJlcXVlc3RcblxuXHRcdFx0aWYgKGhhbmRsZXIub25FeGVjdXRlQWN0aW9uID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0dGhyb3cgbmV3IGVycm9ycy5VbnN1cHBvcnRlZChcIkFjdGlvblwiKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgeyBpZCwgbmFtZSwgYXJnczogYXJnc1JhdyB9ID0gbWVzc2FnZS5ib2R5LnZhbDtcblx0XHRcdGFjdGlvbklkID0gaWQ7XG5cdFx0XHRhY3Rpb25OYW1lID0gbmFtZTtcblx0XHRcdGNvbnN0IGFyZ3MgPSBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShhcmdzUmF3KSk7XG5cblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicHJvY2Vzc2luZyBhY3Rpb24gcmVxdWVzdFwiLCB7XG5cdFx0XHRcdGFjdGlvbklkOiBpZCxcblx0XHRcdFx0YWN0aW9uTmFtZTogbmFtZSxcblx0XHRcdH0pO1xuXG5cdFx0XHRjb25zdCBjdHggPSBuZXcgQWN0aW9uQ29udGV4dDxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4oXG5cdFx0XHRcdGFjdG9yLmFjdG9yQ29udGV4dCxcblx0XHRcdFx0Y29ubixcblx0XHRcdCk7XG5cblx0XHRcdC8vIFByb2Nlc3MgdGhlIGFjdGlvbiByZXF1ZXN0IGFuZCB3YWl0IGZvciB0aGUgcmVzdWx0XG5cdFx0XHQvLyBUaGlzIHdpbGwgd2FpdCBmb3IgYXN5bmMgYWN0aW9ucyB0byBjb21wbGV0ZVxuXHRcdFx0Y29uc3Qgb3V0cHV0ID0gYXdhaXQgaGFuZGxlci5vbkV4ZWN1dGVBY3Rpb24oY3R4LCBuYW1lLCBhcmdzKTtcblxuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJzZW5kaW5nIGFjdGlvbiByZXNwb25zZVwiLCB7XG5cdFx0XHRcdGFjdGlvbklkOiBpZCxcblx0XHRcdFx0YWN0aW9uTmFtZTogbmFtZSxcblx0XHRcdFx0b3V0cHV0VHlwZTogdHlwZW9mIG91dHB1dCxcblx0XHRcdFx0aXNQcm9taXNlOiBvdXRwdXQgaW5zdGFuY2VvZiBQcm9taXNlLFxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIFNlbmQgdGhlIHJlc3BvbnNlIGJhY2sgdG8gdGhlIGNsaWVudFxuXHRcdFx0Y29ubi5fc2VuZE1lc3NhZ2UoXG5cdFx0XHRcdG5ldyBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pihcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRib2R5OiB7XG5cdFx0XHRcdFx0XHRcdHRhZzogXCJBY3Rpb25SZXNwb25zZVwiLFxuXHRcdFx0XHRcdFx0XHR2YWw6IHtcblx0XHRcdFx0XHRcdFx0XHRpZDogaWQsXG5cdFx0XHRcdFx0XHRcdFx0b3V0cHV0OiBidWZmZXJUb0FycmF5QnVmZmVyKGNib3IuZW5jb2RlKG91dHB1dCkpLFxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFRPX0NMSUVOVF9WRVJTSU9ORUQsXG5cdFx0XHRcdCksXG5cdFx0XHQpO1xuXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImFjdGlvbiByZXNwb25zZSBzZW50XCIsIHsgaWQsIG5hbWU6IG5hbWUgfSk7XG5cdFx0fSBlbHNlIGlmIChtZXNzYWdlLmJvZHkudGFnID09PSBcIlN1YnNjcmlwdGlvblJlcXVlc3RcIikge1xuXHRcdFx0Ly8gU3Vic2NyaXB0aW9uIHJlcXVlc3RcblxuXHRcdFx0aWYgKFxuXHRcdFx0XHRoYW5kbGVyLm9uU3Vic2NyaWJlID09PSB1bmRlZmluZWQgfHxcblx0XHRcdFx0aGFuZGxlci5vblVuc3Vic2NyaWJlID09PSB1bmRlZmluZWRcblx0XHRcdCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgZXJyb3JzLlVuc3VwcG9ydGVkKFwiU3Vic2NyaXB0aW9uc1wiKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgeyBldmVudE5hbWUsIHN1YnNjcmliZSB9ID0gbWVzc2FnZS5ib2R5LnZhbDtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicHJvY2Vzc2luZyBzdWJzY3JpcHRpb24gcmVxdWVzdFwiLCB7XG5cdFx0XHRcdGV2ZW50TmFtZSxcblx0XHRcdFx0c3Vic2NyaWJlLFxuXHRcdFx0fSk7XG5cblx0XHRcdGlmIChzdWJzY3JpYmUpIHtcblx0XHRcdFx0YXdhaXQgaGFuZGxlci5vblN1YnNjcmliZShldmVudE5hbWUsIGNvbm4pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXdhaXQgaGFuZGxlci5vblVuc3Vic2NyaWJlKGV2ZW50TmFtZSwgY29ubik7XG5cdFx0XHR9XG5cblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic3Vic2NyaXB0aW9uIHJlcXVlc3QgY29tcGxldGVkXCIsIHtcblx0XHRcdFx0ZXZlbnROYW1lLFxuXHRcdFx0XHRzdWJzY3JpYmUsXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YXNzZXJ0VW5yZWFjaGFibGUobWVzc2FnZS5ib2R5KTtcblx0XHR9XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0Y29uc3QgeyBjb2RlLCBtZXNzYWdlLCBtZXRhZGF0YSB9ID0gZGVjb25zdHJ1Y3RFcnJvcihlcnJvciwgbG9nZ2VyKCksIHtcblx0XHRcdGNvbm5lY3Rpb25JZDogY29ubi5pZCxcblx0XHRcdGFjdGlvbklkLFxuXHRcdFx0YWN0aW9uTmFtZSxcblx0XHR9KTtcblxuXHRcdGxvZ2dlcigpLmRlYnVnKFwic2VuZGluZyBlcnJvciByZXNwb25zZVwiLCB7XG5cdFx0XHRhY3Rpb25JZCxcblx0XHRcdGFjdGlvbk5hbWUsXG5cdFx0XHRjb2RlLFxuXHRcdFx0bWVzc2FnZSxcblx0XHR9KTtcblxuXHRcdC8vIEJ1aWxkIHJlc3BvbnNlXG5cdFx0Y29ubi5fc2VuZE1lc3NhZ2UoXG5cdFx0XHRuZXcgQ2FjaGVkU2VyaWFsaXplcjxwcm90b2NvbC5Ub0NsaWVudD4oXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRib2R5OiB7XG5cdFx0XHRcdFx0XHR0YWc6IFwiRXJyb3JcIixcblx0XHRcdFx0XHRcdHZhbDoge1xuXHRcdFx0XHRcdFx0XHRjb2RlLFxuXHRcdFx0XHRcdFx0XHRtZXNzYWdlLFxuXHRcdFx0XHRcdFx0XHRtZXRhZGF0YTogYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShtZXRhZGF0YSkpLFxuXHRcdFx0XHRcdFx0XHRhY3Rpb25JZDogYWN0aW9uSWQgPz8gbnVsbCxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fSxcblx0XHRcdFx0VE9fQ0xJRU5UX1ZFUlNJT05FRCxcblx0XHRcdCksXG5cdFx0KTtcblxuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZXJyb3IgcmVzcG9uc2Ugc2VudFwiLCB7IGFjdGlvbklkLCBhY3Rpb25OYW1lIH0pO1xuXHR9XG59XG5cbi8vLyoqXG4vLyAqIFVzZSBgQ2FjaGVkU2VyaWFsaXplcmAgaWYgc2VyaWFsaXppbmcgdGhlIHNhbWUgZGF0YSByZXBlYXRlZGx5LlxuLy8gKi9cbi8vZXhwb3J0IGZ1bmN0aW9uIHNlcmlhbGl6ZTxUPih2YWx1ZTogVCwgZW5jb2Rpbmc6IEVuY29kaW5nKTogT3V0cHV0RGF0YSB7XG4vL1x0aWYgKGVuY29kaW5nID09PSBcImpzb25cIikge1xuLy9cdFx0cmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbi8vXHR9IGVsc2UgaWYgKGVuY29kaW5nID09PSBcImNib3JcIikge1xuLy9cdFx0Ly8gVE9ETzogUmVtb3ZlIHRoaXMgaGFjaywgYnV0IGNib3IteCBjYW4ndCBoYW5kbGUgYW55dGhpbmcgZXh0cmEgaW4gZGF0YSBzdHJ1Y3R1cmVzXG4vL1x0XHRjb25zdCBjbGVhblZhbHVlID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xuLy9cdFx0cmV0dXJuIGNib3IuZW5jb2RlKGNsZWFuVmFsdWUpO1xuLy9cdH0gZWxzZSB7XG4vL1x0XHRhc3NlcnRVbnJlYWNoYWJsZShlbmNvZGluZyk7XG4vL1x0fVxuLy99XG4vL1xuLy9leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVzZXJpYWxpemUoZGF0YTogSW5wdXREYXRhLCBlbmNvZGluZzogRW5jb2RpbmcpIHtcbi8vXHRpZiAoZW5jb2RpbmcgPT09IFwianNvblwiKSB7XG4vL1x0XHRpZiAodHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpIHtcbi8vXHRcdFx0bG9nZ2VyKCkud2FybihcInJlY2VpdmVkIG5vbi1zdHJpbmcgZm9yIGpzb24gcGFyc2VcIik7XG4vL1x0XHRcdHRocm93IG5ldyBlcnJvcnMuTWFsZm9ybWVkTWVzc2FnZSgpO1xuLy9cdFx0fSBlbHNlIHtcbi8vXHRcdFx0cmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG4vL1x0XHR9XG4vL1x0fSBlbHNlIGlmIChlbmNvZGluZyA9PT0gXCJjYm9yXCIpIHtcbi8vXHRcdGlmIChkYXRhIGluc3RhbmNlb2YgQmxvYikge1xuLy9cdFx0XHRjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGRhdGEuYXJyYXlCdWZmZXIoKTtcbi8vXHRcdFx0cmV0dXJuIGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKSk7XG4vL1x0XHR9IGVsc2UgaWYgKGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4vL1x0XHRcdHJldHVybiBjYm9yLmRlY29kZShkYXRhKTtcbi8vXHRcdH0gZWxzZSBpZiAoXG4vL1x0XHRcdGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlciB8fFxuLy9cdFx0XHRkYXRhIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXJcbi8vXHRcdCkge1xuLy9cdFx0XHRyZXR1cm4gY2Jvci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkoZGF0YSkpO1xuLy9cdFx0fSBlbHNlIHtcbi8vXHRcdFx0bG9nZ2VyKCkud2FybihcInJlY2VpdmVkIG5vbi1iaW5hcnkgdHlwZSBmb3IgY2JvciBwYXJzZVwiKTtcbi8vXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5NYWxmb3JtZWRNZXNzYWdlKCk7XG4vL1x0XHR9XG4vL1x0fSBlbHNlIHtcbi8vXHRcdGFzc2VydFVucmVhY2hhYmxlKGVuY29kaW5nKTtcbi8vXHR9XG4vL31cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZGlzdC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvdjEudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9kaXN0L3NjaGVtYXMvYWN0b3ItcGVyc2lzdFwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2Rpc3Qvc2NoZW1hcy9hY3Rvci1wZXJzaXN0L3YxLnRzXCI7aW1wb3J0ICogYXMgYmFyZSBmcm9tIFwiQGJhcmUtdHMvbGliXCJcblxuY29uc3QgY29uZmlnID0gLyogQF9fUFVSRV9fICovIGJhcmUuQ29uZmlnKHt9KVxuXG5leHBvcnQgdHlwZSB1NjQgPSBiaWdpbnRcblxuZXhwb3J0IHR5cGUgUGVyc2lzdGVkU3Vic2NyaXB0aW9uID0ge1xuICAgIHJlYWRvbmx5IGV2ZW50TmFtZTogc3RyaW5nLFxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZFBlcnNpc3RlZFN1YnNjcmlwdGlvbihiYzogYmFyZS5CeXRlQ3Vyc29yKTogUGVyc2lzdGVkU3Vic2NyaXB0aW9uIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBldmVudE5hbWU6IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVQZXJzaXN0ZWRTdWJzY3JpcHRpb24oYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogUGVyc2lzdGVkU3Vic2NyaXB0aW9uKTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5ldmVudE5hbWUpXG59XG5cbmZ1bmN0aW9uIHJlYWQwKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBBcnJheUJ1ZmZlciB8IG51bGwge1xuICAgIHJldHVybiBiYXJlLnJlYWRCb29sKGJjKVxuICAgICAgICA/IGJhcmUucmVhZERhdGEoYmMpXG4gICAgICAgIDogbnVsbFxufVxuXG5mdW5jdGlvbiB3cml0ZTAoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogQXJyYXlCdWZmZXIgfCBudWxsKTogdm9pZCB7XG4gICAgYmFyZS53cml0ZUJvb2woYmMsIHggIT09IG51bGwpXG4gICAgaWYgKHggIT09IG51bGwpIHtcbiAgICAgICAgYmFyZS53cml0ZURhdGEoYmMsIHgpXG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkMShiYzogYmFyZS5CeXRlQ3Vyc29yKTogcmVhZG9ubHkgUGVyc2lzdGVkU3Vic2NyaXB0aW9uW10ge1xuICAgIGNvbnN0IGxlbiA9IGJhcmUucmVhZFVpbnRTYWZlKGJjKVxuICAgIGlmIChsZW4gPT09IDApIHsgcmV0dXJuIFtdIH1cbiAgICBjb25zdCByZXN1bHQgPSBbcmVhZFBlcnNpc3RlZFN1YnNjcmlwdGlvbihiYyldXG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW47IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSByZWFkUGVyc2lzdGVkU3Vic2NyaXB0aW9uKGJjKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHdyaXRlMShiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiByZWFkb25seSBQZXJzaXN0ZWRTdWJzY3JpcHRpb25bXSk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVVaW50U2FmZShiYywgeC5sZW5ndGgpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHdyaXRlUGVyc2lzdGVkU3Vic2NyaXB0aW9uKGJjLCB4W2ldKVxuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgUGVyc2lzdGVkQ29ubmVjdGlvbiA9IHtcbiAgICByZWFkb25seSBpZDogc3RyaW5nLFxuICAgIHJlYWRvbmx5IHRva2VuOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgZHJpdmVyOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgZHJpdmVyU3RhdGU6IEFycmF5QnVmZmVyLFxuICAgIHJlYWRvbmx5IHBhcmFtZXRlcnM6IEFycmF5QnVmZmVyLFxuICAgIHJlYWRvbmx5IHN0YXRlOiBBcnJheUJ1ZmZlcixcbiAgICByZWFkb25seSBhdXRoOiBBcnJheUJ1ZmZlciB8IG51bGwsXG4gICAgcmVhZG9ubHkgc3Vic2NyaXB0aW9uczogcmVhZG9ubHkgUGVyc2lzdGVkU3Vic2NyaXB0aW9uW10sXG4gICAgcmVhZG9ubHkgbGFzdFNlZW46IHU2NCxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRQZXJzaXN0ZWRDb25uZWN0aW9uKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBQZXJzaXN0ZWRDb25uZWN0aW9uIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBpZDogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICAgICAgdG9rZW46IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIGRyaXZlcjogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICAgICAgZHJpdmVyU3RhdGU6IGJhcmUucmVhZERhdGEoYmMpLFxuICAgICAgICBwYXJhbWV0ZXJzOiBiYXJlLnJlYWREYXRhKGJjKSxcbiAgICAgICAgc3RhdGU6IGJhcmUucmVhZERhdGEoYmMpLFxuICAgICAgICBhdXRoOiByZWFkMChiYyksXG4gICAgICAgIHN1YnNjcmlwdGlvbnM6IHJlYWQxKGJjKSxcbiAgICAgICAgbGFzdFNlZW46IGJhcmUucmVhZFU2NChiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVQZXJzaXN0ZWRDb25uZWN0aW9uKGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IFBlcnNpc3RlZENvbm5lY3Rpb24pOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4LmlkKVxuICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHgudG9rZW4pXG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5kcml2ZXIpXG4gICAgYmFyZS53cml0ZURhdGEoYmMsIHguZHJpdmVyU3RhdGUpXG4gICAgYmFyZS53cml0ZURhdGEoYmMsIHgucGFyYW1ldGVycylcbiAgICBiYXJlLndyaXRlRGF0YShiYywgeC5zdGF0ZSlcbiAgICB3cml0ZTAoYmMsIHguYXV0aClcbiAgICB3cml0ZTEoYmMsIHguc3Vic2NyaXB0aW9ucylcbiAgICBiYXJlLndyaXRlVTY0KGJjLCB4Lmxhc3RTZWVuKVxufVxuXG5leHBvcnQgdHlwZSBHZW5lcmljUGVyc2lzdGVkU2NoZWR1bGVFdmVudCA9IHtcbiAgICByZWFkb25seSBhY3Rpb246IHN0cmluZyxcbiAgICByZWFkb25seSBhcmdzOiBBcnJheUJ1ZmZlciB8IG51bGwsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkR2VuZXJpY1BlcnNpc3RlZFNjaGVkdWxlRXZlbnQoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBhY3Rpb246IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIGFyZ3M6IHJlYWQwKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IEdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5hY3Rpb24pXG4gICAgd3JpdGUwKGJjLCB4LmFyZ3MpXG59XG5cbmV4cG9ydCB0eXBlIFBlcnNpc3RlZFNjaGVkdWxlRXZlbnRLaW5kID1cbiAgICB8IHsgcmVhZG9ubHkgdGFnOiBcIkdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50XCIsIHJlYWRvbmx5IHZhbDogR2VuZXJpY1BlcnNpc3RlZFNjaGVkdWxlRXZlbnQgfVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZFBlcnNpc3RlZFNjaGVkdWxlRXZlbnRLaW5kKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50S2luZCB7XG4gICAgY29uc3Qgb2Zmc2V0ID0gYmMub2Zmc2V0XG4gICAgY29uc3QgdGFnID0gYmFyZS5yZWFkVTgoYmMpXG4gICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIHsgdGFnOiBcIkdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50XCIsIHZhbDogcmVhZEdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KGJjKSB9XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgIGJjLm9mZnNldCA9IG9mZnNldFxuICAgICAgICAgICAgdGhyb3cgbmV3IGJhcmUuQmFyZUVycm9yKG9mZnNldCwgXCJpbnZhbGlkIHRhZ1wiKVxuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50S2luZChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50S2luZCk6IHZvaWQge1xuICAgIHN3aXRjaCAoeC50YWcpIHtcbiAgICAgICAgY2FzZSBcIkdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50XCI6IHtcbiAgICAgICAgICAgIGJhcmUud3JpdGVVOChiYywgMClcbiAgICAgICAgICAgIHdyaXRlR2VuZXJpY1BlcnNpc3RlZFNjaGVkdWxlRXZlbnQoYmMsIHgudmFsKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgUGVyc2lzdGVkU2NoZWR1bGVFdmVudCA9IHtcbiAgICByZWFkb25seSBldmVudElkOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgdGltZXN0YW1wOiB1NjQsXG4gICAgcmVhZG9ubHkga2luZDogUGVyc2lzdGVkU2NoZWR1bGVFdmVudEtpbmQsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkUGVyc2lzdGVkU2NoZWR1bGVFdmVudChiYzogYmFyZS5CeXRlQ3Vyc29yKTogUGVyc2lzdGVkU2NoZWR1bGVFdmVudCB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZXZlbnRJZDogYmFyZS5yZWFkU3RyaW5nKGJjKSxcbiAgICAgICAgdGltZXN0YW1wOiBiYXJlLnJlYWRVNjQoYmMpLFxuICAgICAgICBraW5kOiByZWFkUGVyc2lzdGVkU2NoZWR1bGVFdmVudEtpbmQoYmMpLFxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlUGVyc2lzdGVkU2NoZWR1bGVFdmVudChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiBQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVN0cmluZyhiYywgeC5ldmVudElkKVxuICAgIGJhcmUud3JpdGVVNjQoYmMsIHgudGltZXN0YW1wKVxuICAgIHdyaXRlUGVyc2lzdGVkU2NoZWR1bGVFdmVudEtpbmQoYmMsIHgua2luZClcbn1cblxuZnVuY3Rpb24gcmVhZDIoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IHJlYWRvbmx5IFBlcnNpc3RlZENvbm5lY3Rpb25bXSB7XG4gICAgY29uc3QgbGVuID0gYmFyZS5yZWFkVWludFNhZmUoYmMpXG4gICAgaWYgKGxlbiA9PT0gMCkgeyByZXR1cm4gW10gfVxuICAgIGNvbnN0IHJlc3VsdCA9IFtyZWFkUGVyc2lzdGVkQ29ubmVjdGlvbihiYyldXG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW47IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSByZWFkUGVyc2lzdGVkQ29ubmVjdGlvbihiYylcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiB3cml0ZTIoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogcmVhZG9ubHkgUGVyc2lzdGVkQ29ubmVjdGlvbltdKTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVVpbnRTYWZlKGJjLCB4Lmxlbmd0aClcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgd3JpdGVQZXJzaXN0ZWRDb25uZWN0aW9uKGJjLCB4W2ldKVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVhZDMoYmM6IGJhcmUuQnl0ZUN1cnNvcik6IHJlYWRvbmx5IFBlcnNpc3RlZFNjaGVkdWxlRXZlbnRbXSB7XG4gICAgY29uc3QgbGVuID0gYmFyZS5yZWFkVWludFNhZmUoYmMpXG4gICAgaWYgKGxlbiA9PT0gMCkgeyByZXR1cm4gW10gfVxuICAgIGNvbnN0IHJlc3VsdCA9IFtyZWFkUGVyc2lzdGVkU2NoZWR1bGVFdmVudChiYyldXG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW47IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSByZWFkUGVyc2lzdGVkU2NoZWR1bGVFdmVudChiYylcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiB3cml0ZTMoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogcmVhZG9ubHkgUGVyc2lzdGVkU2NoZWR1bGVFdmVudFtdKTogdm9pZCB7XG4gICAgYmFyZS53cml0ZVVpbnRTYWZlKGJjLCB4Lmxlbmd0aClcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgd3JpdGVQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50KGJjLCB4W2ldKVxuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgUGVyc2lzdGVkQWN0b3IgPSB7XG4gICAgcmVhZG9ubHkgaW5wdXQ6IEFycmF5QnVmZmVyIHwgbnVsbCxcbiAgICByZWFkb25seSBoYXNJbml0aWFsaXplZDogYm9vbGVhbixcbiAgICByZWFkb25seSBzdGF0ZTogQXJyYXlCdWZmZXIsXG4gICAgcmVhZG9ubHkgY29ubmVjdGlvbnM6IHJlYWRvbmx5IFBlcnNpc3RlZENvbm5lY3Rpb25bXSxcbiAgICByZWFkb25seSBzY2hlZHVsZWRFdmVudHM6IHJlYWRvbmx5IFBlcnNpc3RlZFNjaGVkdWxlRXZlbnRbXSxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRQZXJzaXN0ZWRBY3RvcihiYzogYmFyZS5CeXRlQ3Vyc29yKTogUGVyc2lzdGVkQWN0b3Ige1xuICAgIHJldHVybiB7XG4gICAgICAgIGlucHV0OiByZWFkMChiYyksXG4gICAgICAgIGhhc0luaXRpYWxpemVkOiBiYXJlLnJlYWRCb29sKGJjKSxcbiAgICAgICAgc3RhdGU6IGJhcmUucmVhZERhdGEoYmMpLFxuICAgICAgICBjb25uZWN0aW9uczogcmVhZDIoYmMpLFxuICAgICAgICBzY2hlZHVsZWRFdmVudHM6IHJlYWQzKGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVBlcnNpc3RlZEFjdG9yKGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IFBlcnNpc3RlZEFjdG9yKTogdm9pZCB7XG4gICAgd3JpdGUwKGJjLCB4LmlucHV0KVxuICAgIGJhcmUud3JpdGVCb29sKGJjLCB4Lmhhc0luaXRpYWxpemVkKVxuICAgIGJhcmUud3JpdGVEYXRhKGJjLCB4LnN0YXRlKVxuICAgIHdyaXRlMihiYywgeC5jb25uZWN0aW9ucylcbiAgICB3cml0ZTMoYmMsIHguc2NoZWR1bGVkRXZlbnRzKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlUGVyc2lzdGVkQWN0b3IoeDogUGVyc2lzdGVkQWN0b3IpOiBVaW50OEFycmF5IHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoXG4gICAgICAgIG5ldyBVaW50OEFycmF5KGNvbmZpZy5pbml0aWFsQnVmZmVyTGVuZ3RoKSxcbiAgICAgICAgY29uZmlnXG4gICAgKVxuICAgIHdyaXRlUGVyc2lzdGVkQWN0b3IoYmMsIHgpXG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJjLnZpZXcuYnVmZmVyLCBiYy52aWV3LmJ5dGVPZmZzZXQsIGJjLm9mZnNldClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVBlcnNpc3RlZEFjdG9yKGJ5dGVzOiBVaW50OEFycmF5KTogUGVyc2lzdGVkQWN0b3Ige1xuICAgIGNvbnN0IGJjID0gbmV3IGJhcmUuQnl0ZUN1cnNvcihieXRlcywgY29uZmlnKVxuICAgIGNvbnN0IHJlc3VsdCA9IHJlYWRQZXJzaXN0ZWRBY3RvcihiYylcbiAgICBpZiAoYmMub2Zmc2V0IDwgYmMudmlldy5ieXRlTGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBiYXJlLkJhcmVFcnJvcihiYy5vZmZzZXQsIFwicmVtYWluaW5nIGJ5dGVzXCIpXG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3NjaGVtYXMvYWN0b3ItcGVyc2lzdC92ZXJzaW9uZWQudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvc2NoZW1hcy9hY3Rvci1wZXJzaXN0XCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3NjaGVtYXMvYWN0b3ItcGVyc2lzdC92ZXJzaW9uZWQudHNcIjtpbXBvcnQge1xuXHRjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcixcblx0dHlwZSBNaWdyYXRpb25Gbixcbn0gZnJvbSBcIkAvY29tbW9uL3ZlcnNpb25lZC1kYXRhXCI7XG5pbXBvcnQgKiBhcyB2MSBmcm9tIFwiLi4vLi4vLi4vZGlzdC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvdjFcIjtcblxuZXhwb3J0IGNvbnN0IENVUlJFTlRfVkVSU0lPTiA9IDE7XG5cbmV4cG9ydCB0eXBlIEN1cnJlbnRQZXJzaXN0ZWRBY3RvciA9IHYxLlBlcnNpc3RlZEFjdG9yO1xuZXhwb3J0IHR5cGUgQ3VycmVudFBlcnNpc3RlZENvbm5lY3Rpb24gPSB2MS5QZXJzaXN0ZWRDb25uZWN0aW9uO1xuZXhwb3J0IHR5cGUgQ3VycmVudFBlcnNpc3RlZFN1YnNjcmlwdGlvbiA9IHYxLlBlcnNpc3RlZFN1YnNjcmlwdGlvbjtcbmV4cG9ydCB0eXBlIEN1cnJlbnRHZW5lcmljUGVyc2lzdGVkU2NoZWR1bGVFdmVudCA9XG5cdHYxLkdlbmVyaWNQZXJzaXN0ZWRTY2hlZHVsZUV2ZW50O1xuZXhwb3J0IHR5cGUgQ3VycmVudFBlcnNpc3RlZFNjaGVkdWxlRXZlbnRLaW5kID0gdjEuUGVyc2lzdGVkU2NoZWR1bGVFdmVudEtpbmQ7XG5leHBvcnQgdHlwZSBDdXJyZW50UGVyc2lzdGVkU2NoZWR1bGVFdmVudCA9IHYxLlBlcnNpc3RlZFNjaGVkdWxlRXZlbnQ7XG5cbmNvbnN0IG1pZ3JhdGlvbnMgPSBuZXcgTWFwPG51bWJlciwgTWlncmF0aW9uRm48YW55LCBhbnk+PigpO1xuXG5leHBvcnQgY29uc3QgUEVSU0lTVEVEX0FDVE9SX1ZFUlNJT05FRCA9XG5cdGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPEN1cnJlbnRQZXJzaXN0ZWRBY3Rvcj4oe1xuXHRcdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdFx0bWlncmF0aW9ucyxcblx0XHRzZXJpYWxpemVWZXJzaW9uOiAoZGF0YSkgPT4gdjEuZW5jb2RlUGVyc2lzdGVkQWN0b3IoZGF0YSksXG5cdFx0ZGVzZXJpYWxpemVWZXJzaW9uOiAoYnl0ZXMpID0+IHYxLmRlY29kZVBlcnNpc3RlZEFjdG9yKGJ5dGVzKSxcblx0fSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9jb250ZXh0LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2NvbnRleHQudHNcIjtpbXBvcnQgdHlwZSB7IEFjdG9yS2V5IH0gZnJvbSBcIkAvYWN0b3IvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSBcIkAvY29tbW9uL2xvZ1wiO1xuaW1wb3J0IHR5cGUgeyBSZWdpc3RyeSB9IGZyb20gXCJAL3JlZ2lzdHJ5L21vZFwiO1xuaW1wb3J0IHR5cGUgeyBDb25uLCBDb25uSWQgfSBmcm9tIFwiLi9jb25uZWN0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IEFueURhdGFiYXNlUHJvdmlkZXIsIEluZmVyRGF0YWJhc2VDbGllbnQgfSBmcm9tIFwiLi9kYXRhYmFzZVwiO1xuaW1wb3J0IHR5cGUgeyBBY3Rvckluc3RhbmNlLCBTYXZlU3RhdGVPcHRpb25zIH0gZnJvbSBcIi4vaW5zdGFuY2VcIjtcbmltcG9ydCB0eXBlIHsgU2NoZWR1bGUgfSBmcm9tIFwiLi9zY2hlZHVsZVwiO1xuXG4vKipcbiAqIEFjdG9yQ29udGV4dCBjbGFzcyB0aGF0IHByb3ZpZGVzIGFjY2VzcyB0byBhY3RvciBtZXRob2RzIGFuZCBzdGF0ZVxuICovXG5leHBvcnQgY2xhc3MgQWN0b3JDb250ZXh0PFxuXHRUU3RhdGUsXG5cdFRDb25uUGFyYW1zLFxuXHRUQ29ublN0YXRlLFxuXHRUVmFycyxcblx0VElucHV0LFxuXHRUQXV0aERhdGEsXG5cdFREYXRhYmFzZSBleHRlbmRzIEFueURhdGFiYXNlUHJvdmlkZXIsXG4+IHtcblx0I2FjdG9yOiBBY3Rvckluc3RhbmNlPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD47XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0YWN0b3I6IEFjdG9ySW5zdGFuY2U8XG5cdFx0XHRUU3RhdGUsXG5cdFx0XHRUQ29ublBhcmFtcyxcblx0XHRcdFRDb25uU3RhdGUsXG5cdFx0XHRUVmFycyxcblx0XHRcdFRJbnB1dCxcblx0XHRcdFRBdXRoRGF0YSxcblx0XHRcdFREYXRhYmFzZVxuXHRcdD4sXG5cdCkge1xuXHRcdHRoaXMuI2FjdG9yID0gYWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSBhY3RvciBzdGF0ZVxuXHQgKi9cblx0Z2V0IHN0YXRlKCk6IFRTdGF0ZSB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yLnN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgYWN0b3IgdmFyaWFibGVzXG5cdCAqL1xuXHRnZXQgdmFycygpOiBUVmFycyB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yLnZhcnM7XG5cdH1cblxuXHQvKipcblx0ICogQnJvYWRjYXN0cyBhbiBldmVudCB0byBhbGwgY29ubmVjdGVkIGNsaWVudHMuXG5cdCAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50LlxuXHQgKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gc2VuZCB3aXRoIHRoZSBldmVudC5cblx0ICovXG5cdGJyb2FkY2FzdDxBcmdzIGV4dGVuZHMgQXJyYXk8dW5rbm93bj4+KG5hbWU6IHN0cmluZywgLi4uYXJnczogQXJncyk6IHZvaWQge1xuXHRcdHRoaXMuI2FjdG9yLl9icm9hZGNhc3QobmFtZSwgLi4uYXJncyk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGxvZ2dlciBpbnN0YW5jZS5cblx0ICovXG5cdGdldCBsb2coKTogTG9nZ2VyIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3IubG9nO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWN0b3IgSUQuXG5cdCAqL1xuXHRnZXQgYWN0b3JJZCgpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLiNhY3Rvci5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBhY3RvciBuYW1lLlxuXHQgKi9cblx0Z2V0IG5hbWUoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3IubmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBhY3RvciBrZXkuXG5cdCAqL1xuXHRnZXQga2V5KCk6IEFjdG9yS2V5IHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3Iua2V5O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHJlZ2lvbi5cblx0ICovXG5cdGdldCByZWdpb24oKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3IucmVnaW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNjaGVkdWxlci5cblx0ICovXG5cdGdldCBzY2hlZHVsZSgpOiBTY2hlZHVsZSB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yLnNjaGVkdWxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIG1hcCBvZiBjb25uZWN0aW9ucy5cblx0ICovXG5cdGdldCBjb25ucygpOiBNYXA8XG5cdFx0Q29ubklkLFxuXHRcdENvbm48VFN0YXRlLCBUQ29ublBhcmFtcywgVENvbm5TdGF0ZSwgVFZhcnMsIFRJbnB1dCwgVEF1dGhEYXRhLCBURGF0YWJhc2U+XG5cdD4ge1xuXHRcdHJldHVybiB0aGlzLiNhY3Rvci5jb25ucztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjbGllbnQgZm9yIHRoZSBnaXZlbiByZWdpc3RyeS5cblx0ICovXG5cdGNsaWVudDxSIGV4dGVuZHMgUmVnaXN0cnk8YW55Pj4oKTogQ2xpZW50PFI+IHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3IuaW5saW5lQ2xpZW50IGFzIENsaWVudDxSPjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBkYXRhYmFzZS5cblx0ICogQGV4cGVyaW1lbnRhbFxuXHQgKiBAdGhyb3dzIHtEYXRhYmFzZU5vdEVuYWJsZWR9IElmIHRoZSBkYXRhYmFzZSBpcyBub3QgZW5hYmxlZC5cblx0ICovXG5cdGdldCBkYigpOiBJbmZlckRhdGFiYXNlQ2xpZW50PFREYXRhYmFzZT4ge1xuXHRcdHJldHVybiB0aGlzLiNhY3Rvci5kYjtcblx0fVxuXG5cdC8qKlxuXHQgKiBGb3JjZXMgdGhlIHN0YXRlIHRvIGdldCBzYXZlZC5cblx0ICpcblx0ICogQHBhcmFtIG9wdHMgLSBPcHRpb25zIGZvciBzYXZpbmcgdGhlIHN0YXRlLlxuXHQgKi9cblx0YXN5bmMgc2F2ZVN0YXRlKG9wdHM6IFNhdmVTdGF0ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3Iuc2F2ZVN0YXRlKG9wdHMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZXZlbnRzIHRoZSBhY3RvciBmcm9tIHNsZWVwaW5nIHVudGlsIHByb21pc2UgaXMgY29tcGxldGUuXG5cdCAqL1xuXHR3YWl0VW50aWwocHJvbWlzZTogUHJvbWlzZTx2b2lkPik6IHZvaWQge1xuXHRcdHRoaXMuI2FjdG9yLl93YWl0VW50aWwocHJvbWlzZSk7XG5cdH1cblxuXHQvKipcblx0ICogQWJvcnRTaWduYWwgdGhhdCBmaXJlcyB3aGVuIHRoZSBhY3RvciBpcyBzdG9wcGluZy5cblx0ICovXG5cdGdldCBhYm9ydFNpZ25hbCgpOiBBYm9ydFNpZ25hbCB7XG5cdFx0cmV0dXJuIHRoaXMuI2FjdG9yLmFib3J0U2lnbmFsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZvcmNlcyB0aGUgYWN0b3IgdG8gc2xlZXAuXG5cdCAqXG5cdCAqIE5vdCBzdXBwb3J0ZWQgb24gYWxsIGRyaXZlcnMuXG5cdCAqXG5cdCAqIEBleHBlcmltZW50YWxcblx0ICovXG5cdHNsZWVwKCkge1xuXHRcdHRoaXMuI2FjdG9yLl9zbGVlcCgpO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9zY2hlZHVsZS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3RvclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9zY2hlZHVsZS50c1wiO2ltcG9ydCB0eXBlIHsgQW55QWN0b3JJbnN0YW5jZSB9IGZyb20gXCIuL2luc3RhbmNlXCI7XG5cbmV4cG9ydCBjbGFzcyBTY2hlZHVsZSB7XG5cdCNhY3RvcjogQW55QWN0b3JJbnN0YW5jZTtcblxuXHRjb25zdHJ1Y3RvcihhY3RvcjogQW55QWN0b3JJbnN0YW5jZSkge1xuXHRcdHRoaXMuI2FjdG9yID0gYWN0b3I7XG5cdH1cblxuXHRhc3luYyBhZnRlcihkdXJhdGlvbjogbnVtYmVyLCBmbjogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pIHtcblx0XHRhd2FpdCB0aGlzLiNhY3Rvci5zY2hlZHVsZUV2ZW50KERhdGUubm93KCkgKyBkdXJhdGlvbiwgZm4sIGFyZ3MpO1xuXHR9XG5cblx0YXN5bmMgYXQodGltZXN0YW1wOiBudW1iZXIsIGZuOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSkge1xuXHRcdGF3YWl0IHRoaXMuI2FjdG9yLnNjaGVkdWxlRXZlbnQodGltZXN0YW1wLCBmbiwgYXJncyk7XG5cdH1cbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2RlZmluaXRpb24udHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3JcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvZGVmaW5pdGlvbi50c1wiO2ltcG9ydCB0eXBlIHsgUmVnaXN0cnlDb25maWcgfSBmcm9tIFwiQC9yZWdpc3RyeS9jb25maWdcIjtcbmltcG9ydCB0eXBlIHsgQWN0aW9uQ29udGV4dCB9IGZyb20gXCIuL2FjdGlvblwiO1xuaW1wb3J0IHR5cGUgeyBBY3Rpb25zLCBBY3RvckNvbmZpZyB9IGZyb20gXCIuL2NvbmZpZ1wiO1xuaW1wb3J0IHR5cGUgeyBBY3RvckNvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCI7XG5pbXBvcnQgdHlwZSB7IEFueURhdGFiYXNlUHJvdmlkZXIgfSBmcm9tIFwiLi9kYXRhYmFzZVwiO1xuaW1wb3J0IHsgQWN0b3JJbnN0YW5jZSB9IGZyb20gXCIuL2luc3RhbmNlXCI7XG5cbmV4cG9ydCB0eXBlIEFueUFjdG9yRGVmaW5pdGlvbiA9IEFjdG9yRGVmaW5pdGlvbjxcblx0YW55LFxuXHRhbnksXG5cdGFueSxcblx0YW55LFxuXHRhbnksXG5cdGFueSxcblx0YW55LFxuXHRhbnlcbj47XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIGNvbnRleHQgdHlwZSBmcm9tIGFuIEFjdG9yRGVmaW5pdGlvblxuICovXG5leHBvcnQgdHlwZSBBY3RvckNvbnRleHRPZjxBRCBleHRlbmRzIEFueUFjdG9yRGVmaW5pdGlvbj4gPVxuXHRBRCBleHRlbmRzIEFjdG9yRGVmaW5pdGlvbjxcblx0XHRpbmZlciBTLFxuXHRcdGluZmVyIENQLFxuXHRcdGluZmVyIENTLFxuXHRcdGluZmVyIFYsXG5cdFx0aW5mZXIgSSxcblx0XHRpbmZlciBBRCxcblx0XHRpbmZlciBEQixcblx0XHRhbnlcblx0PlxuXHRcdD8gQWN0b3JDb250ZXh0PFMsIENQLCBDUywgViwgSSwgQUQsIERCPlxuXHRcdDogbmV2ZXI7XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIGNvbnRleHQgdHlwZSBmcm9tIGFuIEFjdG9yRGVmaW5pdGlvblxuICovXG5leHBvcnQgdHlwZSBBY3Rpb25Db250ZXh0T2Y8QUQgZXh0ZW5kcyBBbnlBY3RvckRlZmluaXRpb24+ID1cblx0QUQgZXh0ZW5kcyBBY3RvckRlZmluaXRpb248XG5cdFx0aW5mZXIgUyxcblx0XHRpbmZlciBDUCxcblx0XHRpbmZlciBDUyxcblx0XHRpbmZlciBWLFxuXHRcdGluZmVyIEksXG5cdFx0aW5mZXIgQUQsXG5cdFx0aW5mZXIgREIsXG5cdFx0YW55XG5cdD5cblx0XHQ/IEFjdGlvbkNvbnRleHQ8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+XG5cdFx0OiBuZXZlcjtcblxuZXhwb3J0IGNsYXNzIEFjdG9yRGVmaW5pdGlvbjxcblx0Uyxcblx0Q1AsXG5cdENTLFxuXHRWLFxuXHRJLFxuXHRBRCxcblx0REIgZXh0ZW5kcyBBbnlEYXRhYmFzZVByb3ZpZGVyLFxuXHRSIGV4dGVuZHMgQWN0aW9uczxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4sXG4+IHtcblx0I2NvbmZpZzogQWN0b3JDb25maWc8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+O1xuXG5cdGNvbnN0cnVjdG9yKGNvbmZpZzogQWN0b3JDb25maWc8UywgQ1AsIENTLCBWLCBJLCBBRCwgREI+KSB7XG5cdFx0dGhpcy4jY29uZmlnID0gY29uZmlnO1xuXHR9XG5cblx0Z2V0IGNvbmZpZygpOiBBY3RvckNvbmZpZzxTLCBDUCwgQ1MsIFYsIEksIEFELCBEQj4ge1xuXHRcdHJldHVybiB0aGlzLiNjb25maWc7XG5cdH1cblxuXHRpbnN0YW50aWF0ZSgpOiBBY3Rvckluc3RhbmNlPFMsIENQLCBDUywgViwgSSwgQUQsIERCPiB7XG5cdFx0cmV0dXJuIG5ldyBBY3Rvckluc3RhbmNlKHRoaXMuI2NvbmZpZyk7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvb2t1cEluUmVnaXN0cnkoXG5cdHJlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZyxcblx0bmFtZTogc3RyaW5nLFxuKTogQW55QWN0b3JEZWZpbml0aW9uIHtcblx0Ly8gQnVpbGQgYWN0b3Jcblx0Y29uc3QgZGVmaW5pdGlvbiA9IHJlZ2lzdHJ5Q29uZmlnLnVzZVtuYW1lXTtcblx0aWYgKCFkZWZpbml0aW9uKSB0aHJvdyBuZXcgRXJyb3IoYG5vIGFjdG9yIGluIHJlZ2lzdHJ5IGZvciBuYW1lICR7bmFtZX1gKTtcblx0cmV0dXJuIGRlZmluaXRpb247XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9hY3Rvci9nZW5lcmljLWNvbm4tZHJpdmVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL2dlbmVyaWMtY29ubi1kcml2ZXIudHNcIjtpbXBvcnQgdHlwZSB7IFNTRVN0cmVhbWluZ0FwaSB9IGZyb20gXCJob25vL3N0cmVhbWluZ1wiO1xuaW1wb3J0IHR5cGUgeyBXU0NvbnRleHQgfSBmcm9tIFwiaG9uby93c1wiO1xuaW1wb3J0IHR5cGUgeyBXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCB7XG5cdHR5cGUgQW55Q29ubixcblx0Q09OTkVDVElPTl9EUklWRVJfSFRUUCxcblx0Q09OTkVDVElPTl9EUklWRVJfU1NFLFxuXHRDT05ORUNUSU9OX0RSSVZFUl9XRUJTT0NLRVQsXG59IGZyb20gXCJAL2FjdG9yL2Nvbm5lY3Rpb25cIjtcbmltcG9ydCB7XG5cdHR5cGUgQ29ubkRyaXZlcixcblx0dHlwZSBDb25uZWN0aW9uRHJpdmVyc01hcCxcblx0Q29ubmVjdGlvblJlYWR5U3RhdGUsXG59IGZyb20gXCJAL2FjdG9yL2RyaXZlclwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBY3Rvckluc3RhbmNlIH0gZnJvbSBcIkAvYWN0b3IvaW5zdGFuY2VcIjtcbmltcG9ydCB0eXBlIHsgQ2FjaGVkU2VyaWFsaXplciwgRW5jb2RpbmcgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHsgZW5jb2RlRGF0YVRvU3RyaW5nIH0gZnJvbSBcIkAvYWN0b3IvcHJvdG9jb2wvc2VyZGVcIjtcbmltcG9ydCB0eXBlICogYXMgcHJvdG9jb2wgZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvbW9kXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuLy8gVGhpcyBzdGF0ZSBpcyBkaWZmZXJlbnQgdGhhbiBgUGVyc2lzdGVkQ29ubmAgc3RhdGUgc2luY2UgdGhlIGNvbm5lY3Rpb24tc3BlY2lmaWMgc3RhdGUgaXMgcGVyc2lzdGVkICYgbXVzdCBiZSBzZXJpYWxpemFibGUuIFRoaXMgaXMgYWxzbyBwYXJ0IG9mIHRoZSBjb25uZWN0aW9uIGRyaXZlciwgbm90IHBhcnQgb2YgdGhlIGNvcmUgYWN0b3IuXG4vL1xuLy8gVGhpcyBob2xkcyB0aGUgYWN0dWFsIGNvbm5lY3Rpb25zLCB3aGljaCBhcmUgbm90IHNlcmlhbGl6YWJsZS5cbi8vXG4vLyBUaGlzIGlzIHNjb3BlZCB0byBlYWNoIGFjdG9yLiBEbyBub3Qgc2hhcmUgYmV0d2VlbiBtdWx0aXBsZSBhY3RvcnMuXG5leHBvcnQgY2xhc3MgR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSB7XG5cdHdlYnNvY2tldHMgPSBuZXcgTWFwPHN0cmluZywgV1NDb250ZXh0PigpO1xuXHRzc2VTdHJlYW1zID0gbmV3IE1hcDxzdHJpbmcsIFNTRVN0cmVhbWluZ0FwaT4oKTtcbn1cblxuLyoqXG4gKiBFeHBvc2VzIGNvbm5lY3Rpb24gZHJpdmVycyBmb3IgcGxhdGZvcm1zIHRoYXQgc3VwcG9ydCB2YW5pbGxhIFdlYlNvY2tldCwgU1NFLCBhbmQgSFRUUC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUdlbmVyaWNDb25uRHJpdmVycyhcblx0Z2xvYmFsU3RhdGU6IEdlbmVyaWNDb25uR2xvYmFsU3RhdGUsXG4pOiBDb25uZWN0aW9uRHJpdmVyc01hcCB7XG5cdHJldHVybiB7XG5cdFx0W0NPTk5FQ1RJT05fRFJJVkVSX1dFQlNPQ0tFVF06IGNyZWF0ZUdlbmVyaWNXZWJTb2NrZXREcml2ZXIoZ2xvYmFsU3RhdGUpLFxuXHRcdFtDT05ORUNUSU9OX0RSSVZFUl9TU0VdOiBjcmVhdGVHZW5lcmljU3NlRHJpdmVyKGdsb2JhbFN0YXRlKSxcblx0XHRbQ09OTkVDVElPTl9EUklWRVJfSFRUUF06IGNyZWF0ZUdlbmVyaWNIdHRwRHJpdmVyKCksXG5cdH07XG59XG5cbi8vIE1BUks6IFdlYlNvY2tldFxuZXhwb3J0IGludGVyZmFjZSBHZW5lcmljV2ViU29ja2V0RHJpdmVyU3RhdGUge1xuXHRlbmNvZGluZzogRW5jb2Rpbmc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVHZW5lcmljV2ViU29ja2V0RHJpdmVyKFxuXHRnbG9iYWxTdGF0ZTogR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSxcbik6IENvbm5Ecml2ZXI8R2VuZXJpY1dlYlNvY2tldERyaXZlclN0YXRlPiB7XG5cdHJldHVybiB7XG5cdFx0c2VuZE1lc3NhZ2U6IChcblx0XHRcdGFjdG9yOiBBbnlBY3Rvckluc3RhbmNlLFxuXHRcdFx0Y29ubjogQW55Q29ubixcblx0XHRcdHN0YXRlOiBHZW5lcmljV2ViU29ja2V0RHJpdmVyU3RhdGUsXG5cdFx0XHRtZXNzYWdlOiBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pixcblx0XHQpID0+IHtcblx0XHRcdGNvbnN0IHdzID0gZ2xvYmFsU3RhdGUud2Vic29ja2V0cy5nZXQoY29ubi5pZCk7XG5cdFx0XHRpZiAoIXdzKSB7XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJtaXNzaW5nIHdzIGZvciBzZW5kTWVzc2FnZVwiLCB7XG5cdFx0XHRcdFx0YWN0b3JJZDogYWN0b3IuaWQsXG5cdFx0XHRcdFx0Y29ubklkOiBjb25uLmlkLFxuXHRcdFx0XHRcdHRvdGFsQ291bnQ6IGdsb2JhbFN0YXRlLndlYnNvY2tldHMuc2l6ZSxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3Qgc2VyaWFsaXplZCA9IG1lc3NhZ2Uuc2VyaWFsaXplKHN0YXRlLmVuY29kaW5nKTtcblxuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJzZW5kaW5nIHdlYnNvY2tldCBtZXNzYWdlXCIsIHtcblx0XHRcdFx0ZW5jb2Rpbmc6IHN0YXRlLmVuY29kaW5nLFxuXHRcdFx0XHRkYXRhVHlwZTogdHlwZW9mIHNlcmlhbGl6ZWQsXG5cdFx0XHRcdGlzVWludDhBcnJheTogc2VyaWFsaXplZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXksXG5cdFx0XHRcdGlzQXJyYXlCdWZmZXI6IHNlcmlhbGl6ZWQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcixcblx0XHRcdFx0ZGF0YUxlbmd0aDpcblx0XHRcdFx0XHQoc2VyaWFsaXplZCBhcyBhbnkpLmJ5dGVMZW5ndGggfHwgKHNlcmlhbGl6ZWQgYXMgYW55KS5sZW5ndGgsXG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gQ29udmVydCBVaW50OEFycmF5IHRvIEFycmF5QnVmZmVyIGZvciBwcm9wZXIgdHJhbnNtaXNzaW9uXG5cdFx0XHRpZiAoc2VyaWFsaXplZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcblx0XHRcdFx0Y29uc3QgYnVmZmVyID0gc2VyaWFsaXplZC5idWZmZXIuc2xpY2UoXG5cdFx0XHRcdFx0c2VyaWFsaXplZC5ieXRlT2Zmc2V0LFxuXHRcdFx0XHRcdHNlcmlhbGl6ZWQuYnl0ZU9mZnNldCArIHNlcmlhbGl6ZWQuYnl0ZUxlbmd0aCxcblx0XHRcdFx0KTtcblx0XHRcdFx0Ly8gSGFuZGxlIFNoYXJlZEFycmF5QnVmZmVyIGNhc2Vcblx0XHRcdFx0aWYgKGJ1ZmZlciBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSB7XG5cdFx0XHRcdFx0Y29uc3QgYXJyYXlCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoYnVmZmVyLmJ5dGVMZW5ndGgpO1xuXHRcdFx0XHRcdG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKS5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSk7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjb252ZXJ0ZWQgU2hhcmVkQXJyYXlCdWZmZXIgdG8gQXJyYXlCdWZmZXJcIiwge1xuXHRcdFx0XHRcdFx0Ynl0ZUxlbmd0aDogYXJyYXlCdWZmZXIuYnl0ZUxlbmd0aCxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR3cy5zZW5kKGFycmF5QnVmZmVyKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInNlbmRpbmcgQXJyYXlCdWZmZXJcIiwge1xuXHRcdFx0XHRcdFx0Ynl0ZUxlbmd0aDogYnVmZmVyLmJ5dGVMZW5ndGgsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0d3Muc2VuZChidWZmZXIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInNlbmRpbmcgc3RyaW5nIGRhdGFcIiwge1xuXHRcdFx0XHRcdGxlbmd0aDogKHNlcmlhbGl6ZWQgYXMgc3RyaW5nKS5sZW5ndGgsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHR3cy5zZW5kKHNlcmlhbGl6ZWQpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRkaXNjb25uZWN0OiBhc3luYyAoXG5cdFx0XHRhY3RvcjogQW55QWN0b3JJbnN0YW5jZSxcblx0XHRcdGNvbm46IEFueUNvbm4sXG5cdFx0XHRfc3RhdGU6IEdlbmVyaWNXZWJTb2NrZXREcml2ZXJTdGF0ZSxcblx0XHRcdHJlYXNvbj86IHN0cmluZyxcblx0XHQpID0+IHtcblx0XHRcdGNvbnN0IHdzID0gZ2xvYmFsU3RhdGUud2Vic29ja2V0cy5nZXQoY29ubi5pZCk7XG5cdFx0XHRpZiAoIXdzKSB7XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJtaXNzaW5nIHdzIGZvciBkaXNjb25uZWN0XCIsIHtcblx0XHRcdFx0XHRhY3RvcklkOiBhY3Rvci5pZCxcblx0XHRcdFx0XHRjb25uSWQ6IGNvbm4uaWQsXG5cdFx0XHRcdFx0dG90YWxDb3VudDogZ2xvYmFsU3RhdGUud2Vic29ja2V0cy5zaXplLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgcmF3ID0gd3MucmF3IGFzIFdlYlNvY2tldDtcblx0XHRcdGlmICghcmF3KSB7XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJ3cy5yYXcgZG9lcyBub3QgZXhpc3RcIik7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ3JlYXRlIHByb21pc2UgdG8gd2FpdCBmb3Igc29ja2V0IHRvIGNsb3NlIGdyYWNlZnVsbHlcblx0XHRcdGNvbnN0IHsgcHJvbWlzZSwgcmVzb2x2ZSB9ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzPHZvaWQ+KCk7XG5cdFx0XHRyYXcuYWRkRXZlbnRMaXN0ZW5lcihcImNsb3NlXCIsICgpID0+IHJlc29sdmUoKSk7XG5cblx0XHRcdC8vIENsb3NlIHNvY2tldFxuXHRcdFx0d3MuY2xvc2UoMTAwMCwgcmVhc29uKTtcblxuXHRcdFx0YXdhaXQgcHJvbWlzZTtcblx0XHR9LFxuXG5cdFx0Z2V0Q29ubmVjdGlvblJlYWR5U3RhdGU6IChcblx0XHRcdF9hY3RvcjogQW55QWN0b3JJbnN0YW5jZSxcblx0XHRcdGNvbm46IEFueUNvbm4sXG5cdFx0KTogQ29ubmVjdGlvblJlYWR5U3RhdGUgfCB1bmRlZmluZWQgPT4ge1xuXHRcdFx0Y29uc3Qgd3MgPSBnbG9iYWxTdGF0ZS53ZWJzb2NrZXRzLmdldChjb25uLmlkKTtcblx0XHRcdGlmICghd3MpIHtcblx0XHRcdFx0bG9nZ2VyKCkud2FybihcIm1pc3Npbmcgd3MgZm9yIGdldENvbm5lY3Rpb25SZWFkeVN0YXRlXCIsIHtcblx0XHRcdFx0XHRjb25uSWQ6IGNvbm4uaWQsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCByYXcgPSB3cy5yYXcgYXMgV2ViU29ja2V0O1xuXG5cdFx0XHRyZXR1cm4gcmF3LnJlYWR5U3RhdGUgYXMgQ29ubmVjdGlvblJlYWR5U3RhdGU7XG5cdFx0fSxcblx0fTtcbn1cblxuLy8gTUFSSzogU1NFXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyaWNTc2VEcml2ZXJTdGF0ZSB7XG5cdGVuY29kaW5nOiBFbmNvZGluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUdlbmVyaWNTc2VEcml2ZXIoXG5cdGdsb2JhbFN0YXRlOiBHZW5lcmljQ29ubkdsb2JhbFN0YXRlLFxuKTogQ29ubkRyaXZlcjxHZW5lcmljU3NlRHJpdmVyU3RhdGU+IHtcblx0cmV0dXJuIHtcblx0XHRzZW5kTWVzc2FnZTogKFxuXHRcdFx0X2FjdG9yOiBBbnlBY3Rvckluc3RhbmNlLFxuXHRcdFx0Y29ubjogQW55Q29ubixcblx0XHRcdHN0YXRlOiBHZW5lcmljU3NlRHJpdmVyU3RhdGUsXG5cdFx0XHRtZXNzYWdlOiBDYWNoZWRTZXJpYWxpemVyPHByb3RvY29sLlRvQ2xpZW50Pixcblx0XHQpID0+IHtcblx0XHRcdGNvbnN0IHN0cmVhbSA9IGdsb2JhbFN0YXRlLnNzZVN0cmVhbXMuZ2V0KGNvbm4uaWQpO1xuXHRcdFx0aWYgKCFzdHJlYW0pIHtcblx0XHRcdFx0bG9nZ2VyKCkud2FybihcIm1pc3Npbmcgc3NlIHN0cmVhbSBmb3Igc2VuZE1lc3NhZ2VcIiwge1xuXHRcdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHN0cmVhbS53cml0ZVNTRSh7XG5cdFx0XHRcdGRhdGE6IGVuY29kZURhdGFUb1N0cmluZyhtZXNzYWdlLnNlcmlhbGl6ZShzdGF0ZS5lbmNvZGluZykpLFxuXHRcdFx0fSk7XG5cdFx0fSxcblxuXHRcdGRpc2Nvbm5lY3Q6IGFzeW5jIChcblx0XHRcdF9hY3RvcjogQW55QWN0b3JJbnN0YW5jZSxcblx0XHRcdGNvbm46IEFueUNvbm4sXG5cdFx0XHRfc3RhdGU6IEdlbmVyaWNTc2VEcml2ZXJTdGF0ZSxcblx0XHRcdF9yZWFzb24/OiBzdHJpbmcsXG5cdFx0KSA9PiB7XG5cdFx0XHRjb25zdCBzdHJlYW0gPSBnbG9iYWxTdGF0ZS5zc2VTdHJlYW1zLmdldChjb25uLmlkKTtcblx0XHRcdGlmICghc3RyZWFtKSB7XG5cdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJtaXNzaW5nIHNzZSBzdHJlYW0gZm9yIGRpc2Nvbm5lY3RcIiwgeyBjb25uSWQ6IGNvbm4uaWQgfSk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0c3RyZWFtLmNsb3NlKCk7XG5cdFx0fSxcblxuXHRcdGdldENvbm5lY3Rpb25SZWFkeVN0YXRlOiAoXG5cdFx0XHRfYWN0b3I6IEFueUFjdG9ySW5zdGFuY2UsXG5cdFx0XHRjb25uOiBBbnlDb25uLFxuXHRcdCk6IENvbm5lY3Rpb25SZWFkeVN0YXRlIHwgdW5kZWZpbmVkID0+IHtcblx0XHRcdGNvbnN0IHN0cmVhbSA9IGdsb2JhbFN0YXRlLnNzZVN0cmVhbXMuZ2V0KGNvbm4uaWQpO1xuXHRcdFx0aWYgKCFzdHJlYW0pIHtcblx0XHRcdFx0bG9nZ2VyKCkud2FybihcIm1pc3Npbmcgc3NlIHN0cmVhbSBmb3IgZ2V0Q29ubmVjdGlvblJlYWR5U3RhdGVcIiwge1xuXHRcdFx0XHRcdGNvbm5JZDogY29ubi5pZCxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzdHJlYW0uYWJvcnRlZCB8fCBzdHJlYW0uY2xvc2VkKSB7XG5cdFx0XHRcdHJldHVybiBDb25uZWN0aW9uUmVhZHlTdGF0ZS5DTE9TRUQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBDb25uZWN0aW9uUmVhZHlTdGF0ZS5PUEVOO1xuXHRcdH0sXG5cdH07XG59XG5cbi8vIE1BUks6IEhUVFBcbmV4cG9ydCB0eXBlIEdlbmVyaWNIdHRwRHJpdmVyU3RhdGUgPSBSZWNvcmQ8bmV2ZXIsIG5ldmVyPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUdlbmVyaWNIdHRwRHJpdmVyKCk6IENvbm5Ecml2ZXI8R2VuZXJpY0h0dHBEcml2ZXJTdGF0ZT4ge1xuXHRyZXR1cm4ge1xuXHRcdGdldENvbm5lY3Rpb25SZWFkeVN0YXRlKF9hY3RvciwgX2Nvbm4pIHtcblx0XHRcdC8vIFRPRE86IFRoaXMgbWlnaHQgbm90IGJlIHRoZSBjb3JyZWN0IGxvZ2ljXG5cdFx0XHRyZXR1cm4gQ29ubmVjdGlvblJlYWR5U3RhdGUuT1BFTjtcblx0XHR9LFxuXHRcdGRpc2Nvbm5lY3Q6IGFzeW5jICgpID0+IHtcblx0XHRcdC8vIE5vb3Bcblx0XHR9LFxuXHR9O1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3Ivcm91dGVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL3JvdXRlci50c1wiO2ltcG9ydCB7IEhvbm8sIHR5cGUgQ29udGV4dCBhcyBIb25vQ29udGV4dCB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgaW52YXJpYW50IGZyb20gXCJpbnZhcmlhbnRcIjtcbmltcG9ydCB7IEVuY29kaW5nU2NoZW1hIH0gZnJvbSBcIkAvYWN0b3IvcHJvdG9jb2wvc2VyZGVcIjtcbmltcG9ydCB7XG5cdHR5cGUgQWN0aW9uT3B0cyxcblx0dHlwZSBBY3Rpb25PdXRwdXQsXG5cdHR5cGUgQ29ubmVjdFNzZU9wdHMsXG5cdHR5cGUgQ29ubmVjdFNzZU91dHB1dCxcblx0dHlwZSBDb25uZWN0V2ViU29ja2V0T3B0cyxcblx0dHlwZSBDb25uZWN0V2ViU29ja2V0T3V0cHV0LFxuXHR0eXBlIENvbm5zTWVzc2FnZU9wdHMsXG5cdEhFQURFUl9BVVRIX0RBVEEsXG5cdEhFQURFUl9DT05OX0lELFxuXHRIRUFERVJfQ09OTl9QQVJBTVMsXG5cdEhFQURFUl9DT05OX1RPS0VOLFxuXHRIRUFERVJfRU5DT0RJTkcsXG5cdGhhbmRsZUFjdGlvbixcblx0aGFuZGxlQ29ubmVjdGlvbk1lc3NhZ2UsXG5cdGhhbmRsZVJhd1dlYlNvY2tldEhhbmRsZXIsXG5cdGhhbmRsZVNzZUNvbm5lY3QsXG5cdGhhbmRsZVdlYlNvY2tldENvbm5lY3QsXG59IGZyb20gXCJAL2FjdG9yL3JvdXRlci1lbmRwb2ludHNcIjtcbmltcG9ydCB7XG5cdGhhbmRsZVJvdXRlRXJyb3IsXG5cdGhhbmRsZVJvdXRlTm90Rm91bmQsXG5cdGxvZ2dlck1pZGRsZXdhcmUsXG59IGZyb20gXCJAL2NvbW1vbi9yb3V0ZXJcIjtcbmltcG9ydCB7IG5vb3BOZXh0IH0gZnJvbSBcIkAvY29tbW9uL3V0aWxzXCI7XG5pbXBvcnQge1xuXHR0eXBlIEFjdG9ySW5zcGVjdG9yUm91dGVyRW52LFxuXHRjcmVhdGVBY3Rvckluc3BlY3RvclJvdXRlcixcbn0gZnJvbSBcIkAvaW5zcGVjdG9yL2FjdG9yXCI7XG5pbXBvcnQgeyBzZWN1cmVJbnNwZWN0b3IgfSBmcm9tIFwiQC9pbnNwZWN0b3IvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgUnVuQ29uZmlnIH0gZnJvbSBcIkAvcmVnaXN0cnkvcnVuLWNvbmZpZ1wiO1xuaW1wb3J0IHR5cGUgeyBBY3RvckRyaXZlciB9IGZyb20gXCIuL2RyaXZlclwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5cbmV4cG9ydCBjb25zdCBQQVRIX0NPTk5FQ1RfV0VCU09DS0VUID0gXCIvY29ubmVjdC93ZWJzb2NrZXRcIjtcbmV4cG9ydCBjb25zdCBQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYID0gXCIvcmF3L3dlYnNvY2tldC9cIjtcblxuZXhwb3J0IHR5cGUge1xuXHRDb25uZWN0V2ViU29ja2V0T3B0cyxcblx0Q29ubmVjdFdlYlNvY2tldE91dHB1dCxcblx0Q29ubmVjdFNzZU9wdHMsXG5cdENvbm5lY3RTc2VPdXRwdXQsXG5cdEFjdGlvbk9wdHMsXG5cdEFjdGlvbk91dHB1dCxcblx0Q29ubnNNZXNzYWdlT3B0cyxcbn07XG5cbmludGVyZmFjZSBBY3RvclJvdXRlckJpbmRpbmdzIHtcblx0YWN0b3JJZDogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBBY3RvclJvdXRlciA9IEhvbm88eyBCaW5kaW5nczogQWN0b3JSb3V0ZXJCaW5kaW5ncyB9PjtcblxuLyoqXG4gKiBDcmVhdGVzIGEgcm91dGVyIHRoYXQgcnVucyBvbiB0aGUgcGFydGl0aW9uZWQgaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVBY3RvclJvdXRlcihcblx0cnVuQ29uZmlnOiBSdW5Db25maWcsXG5cdGFjdG9yRHJpdmVyOiBBY3RvckRyaXZlcixcbik6IEFjdG9yUm91dGVyIHtcblx0Y29uc3Qgcm91dGVyID0gbmV3IEhvbm88eyBCaW5kaW5nczogQWN0b3JSb3V0ZXJCaW5kaW5ncyB9Pih7IHN0cmljdDogZmFsc2UgfSk7XG5cblx0cm91dGVyLnVzZShcIipcIiwgbG9nZ2VyTWlkZGxld2FyZShsb2dnZXIoKSkpO1xuXG5cdHJvdXRlci5nZXQoXCIvXCIsIChjKSA9PiB7XG5cdFx0cmV0dXJuIGMudGV4dChcblx0XHRcdFwiVGhpcyBpcyBhbiBSaXZldEtpdCBhY3Rvci5cXG5cXG5MZWFybiBtb3JlIGF0IGh0dHBzOi8vcml2ZXRraXQub3JnXCIsXG5cdFx0KTtcblx0fSk7XG5cblx0cm91dGVyLmdldChcIi9oZWFsdGhcIiwgKGMpID0+IHtcblx0XHRyZXR1cm4gYy50ZXh0KFwib2tcIik7XG5cdH0pO1xuXG5cdHJvdXRlci5nZXQoUEFUSF9DT05ORUNUX1dFQlNPQ0tFVCwgYXN5bmMgKGMpID0+IHtcblx0XHRjb25zdCB1cGdyYWRlV2ViU29ja2V0ID0gcnVuQ29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQ/LigpO1xuXHRcdGlmICh1cGdyYWRlV2ViU29ja2V0KSB7XG5cdFx0XHRyZXR1cm4gdXBncmFkZVdlYlNvY2tldChhc3luYyAoYykgPT4ge1xuXHRcdFx0XHRjb25zdCBlbmNvZGluZ1JhdyA9IGMucmVxLmhlYWRlcihIRUFERVJfRU5DT0RJTkcpO1xuXHRcdFx0XHRjb25zdCBjb25uUGFyYW1zUmF3ID0gYy5yZXEuaGVhZGVyKEhFQURFUl9DT05OX1BBUkFNUyk7XG5cdFx0XHRcdGNvbnN0IGF1dGhEYXRhUmF3ID0gYy5yZXEuaGVhZGVyKEhFQURFUl9BVVRIX0RBVEEpO1xuXG5cdFx0XHRcdGNvbnN0IGVuY29kaW5nID0gRW5jb2RpbmdTY2hlbWEucGFyc2UoZW5jb2RpbmdSYXcpO1xuXHRcdFx0XHRjb25zdCBjb25uUGFyYW1zID0gY29ublBhcmFtc1Jhd1xuXHRcdFx0XHRcdD8gSlNPTi5wYXJzZShjb25uUGFyYW1zUmF3KVxuXHRcdFx0XHRcdDogdW5kZWZpbmVkO1xuXHRcdFx0XHRjb25zdCBhdXRoRGF0YSA9IGF1dGhEYXRhUmF3ID8gSlNPTi5wYXJzZShhdXRoRGF0YVJhdykgOiB1bmRlZmluZWQ7XG5cblx0XHRcdFx0cmV0dXJuIGF3YWl0IGhhbmRsZVdlYlNvY2tldENvbm5lY3QoXG5cdFx0XHRcdFx0Yy5yZXEucmF3LFxuXHRcdFx0XHRcdHJ1bkNvbmZpZyxcblx0XHRcdFx0XHRhY3RvckRyaXZlcixcblx0XHRcdFx0XHRjLmVudi5hY3RvcklkLFxuXHRcdFx0XHRcdGVuY29kaW5nLFxuXHRcdFx0XHRcdGNvbm5QYXJhbXMsXG5cdFx0XHRcdFx0YXV0aERhdGEsXG5cdFx0XHRcdCk7XG5cdFx0XHR9KShjLCBub29wTmV4dCgpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGMudGV4dChcblx0XHRcdFx0XCJXZWJTb2NrZXRzIGFyZSBub3QgZW5hYmxlZCBmb3IgdGhpcyBkcml2ZXIuIFVzZSBTU0UgaW5zdGVhZC5cIixcblx0XHRcdFx0NDAwLFxuXHRcdFx0KTtcblx0XHR9XG5cdH0pO1xuXG5cdHJvdXRlci5nZXQoXCIvY29ubmVjdC9zc2VcIiwgYXN5bmMgKGMpID0+IHtcblx0XHRjb25zdCBhdXRoRGF0YVJhdyA9IGMucmVxLmhlYWRlcihIRUFERVJfQVVUSF9EQVRBKTtcblx0XHRsZXQgYXV0aERhdGE6IHVua25vd247XG5cdFx0aWYgKGF1dGhEYXRhUmF3KSB7XG5cdFx0XHRhdXRoRGF0YSA9IEpTT04ucGFyc2UoYXV0aERhdGFSYXcpO1xuXHRcdH1cblxuXHRcdHJldHVybiBoYW5kbGVTc2VDb25uZWN0KGMsIHJ1bkNvbmZpZywgYWN0b3JEcml2ZXIsIGMuZW52LmFjdG9ySWQsIGF1dGhEYXRhKTtcblx0fSk7XG5cblx0cm91dGVyLnBvc3QoXCIvYWN0aW9uLzphY3Rpb25cIiwgYXN5bmMgKGMpID0+IHtcblx0XHRjb25zdCBhY3Rpb25OYW1lID0gYy5yZXEucGFyYW0oXCJhY3Rpb25cIik7XG5cblx0XHRjb25zdCBhdXRoRGF0YVJhdyA9IGMucmVxLmhlYWRlcihIRUFERVJfQVVUSF9EQVRBKTtcblx0XHRsZXQgYXV0aERhdGE6IHVua25vd247XG5cdFx0aWYgKGF1dGhEYXRhUmF3KSB7XG5cdFx0XHRhdXRoRGF0YSA9IEpTT04ucGFyc2UoYXV0aERhdGFSYXcpO1xuXHRcdH1cblxuXHRcdHJldHVybiBoYW5kbGVBY3Rpb24oXG5cdFx0XHRjLFxuXHRcdFx0cnVuQ29uZmlnLFxuXHRcdFx0YWN0b3JEcml2ZXIsXG5cdFx0XHRhY3Rpb25OYW1lLFxuXHRcdFx0Yy5lbnYuYWN0b3JJZCxcblx0XHRcdGF1dGhEYXRhLFxuXHRcdCk7XG5cdH0pO1xuXG5cdHJvdXRlci5wb3N0KFwiL2Nvbm5lY3Rpb25zL21lc3NhZ2VcIiwgYXN5bmMgKGMpID0+IHtcblx0XHRjb25zdCBjb25uSWQgPSBjLnJlcS5oZWFkZXIoSEVBREVSX0NPTk5fSUQpO1xuXHRcdGNvbnN0IGNvbm5Ub2tlbiA9IGMucmVxLmhlYWRlcihIRUFERVJfQ09OTl9UT0tFTik7XG5cdFx0aWYgKCFjb25uSWQgfHwgIWNvbm5Ub2tlbikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXJzXCIpO1xuXHRcdH1cblx0XHRyZXR1cm4gaGFuZGxlQ29ubmVjdGlvbk1lc3NhZ2UoXG5cdFx0XHRjLFxuXHRcdFx0cnVuQ29uZmlnLFxuXHRcdFx0YWN0b3JEcml2ZXIsXG5cdFx0XHRjb25uSWQsXG5cdFx0XHRjb25uVG9rZW4sXG5cdFx0XHRjLmVudi5hY3RvcklkLFxuXHRcdCk7XG5cdH0pO1xuXG5cdC8vIFJhdyBIVFRQIGVuZHBvaW50cyAtIC9odHRwLypcblx0cm91dGVyLmFsbChcIi9yYXcvaHR0cC8qXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0Y29uc3QgYXV0aERhdGFSYXcgPSBjLnJlcS5oZWFkZXIoSEVBREVSX0FVVEhfREFUQSk7XG5cdFx0bGV0IGF1dGhEYXRhOiB1bmtub3duO1xuXHRcdGlmIChhdXRoRGF0YVJhdykge1xuXHRcdFx0YXV0aERhdGEgPSBKU09OLnBhcnNlKGF1dGhEYXRhUmF3KTtcblx0XHR9XG5cblx0XHRjb25zdCBhY3RvciA9IGF3YWl0IGFjdG9yRHJpdmVyLmxvYWRBY3RvcihjLmVudi5hY3RvcklkKTtcblxuXHRcdC8vIFRPRE86IFRoaXMgaXMgbm90IGEgY2xlYW4gd2F5IG9mIGRvaW5nIHRoaXMgc2luY2UgYC9odHRwL2AgbWlnaHQgZXhpc3QgbWlkLXBhdGhcblx0XHQvLyBTdHJpcCB0aGUgL2h0dHAgcHJlZml4IGZyb20gdGhlIFVSTCB0byBnZXQgdGhlIG9yaWdpbmFsIHBhdGhcblx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKGMucmVxLnVybCk7XG5cdFx0Y29uc3Qgb3JpZ2luYWxQYXRoID0gdXJsLnBhdGhuYW1lLnJlcGxhY2UoL15cXC9yYXdcXC9odHRwLywgXCJcIikgfHwgXCIvXCI7XG5cblx0XHQvLyBDcmVhdGUgYSBuZXcgcmVxdWVzdCB3aXRoIHRoZSBjb3JyZWN0ZWQgVVJMXG5cdFx0Y29uc3QgY29ycmVjdGVkVXJsID0gbmV3IFVSTChvcmlnaW5hbFBhdGggKyB1cmwuc2VhcmNoLCB1cmwub3JpZ2luKTtcblx0XHRjb25zdCBjb3JyZWN0ZWRSZXF1ZXN0ID0gbmV3IFJlcXVlc3QoY29ycmVjdGVkVXJsLCB7XG5cdFx0XHRtZXRob2Q6IGMucmVxLm1ldGhvZCxcblx0XHRcdGhlYWRlcnM6IGMucmVxLnJhdy5oZWFkZXJzLFxuXHRcdFx0Ym9keTogYy5yZXEucmF3LmJvZHksXG5cdFx0fSk7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJld3JpdGluZyBodHRwIHVybFwiLCB7XG5cdFx0XHRmcm9tOiBjLnJlcS51cmwsXG5cdFx0XHR0bzogY29ycmVjdGVkUmVxdWVzdC51cmwsXG5cdFx0fSk7XG5cblx0XHQvLyBDYWxsIHRoZSBhY3RvcidzIG9uRmV0Y2ggaGFuZGxlciAtIGl0IHdpbGwgdGhyb3cgYXBwcm9wcmlhdGUgZXJyb3JzXG5cdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhY3Rvci5oYW5kbGVGZXRjaChjb3JyZWN0ZWRSZXF1ZXN0LCB7XG5cdFx0XHRhdXRoOiBhdXRoRGF0YSxcblx0XHR9KTtcblxuXHRcdC8vIFRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlbiBub3cgc2luY2UgaGFuZGxlRmV0Y2ggdGhyb3dzIGVycm9yc1xuXHRcdGlmICghcmVzcG9uc2UpIHtcblx0XHRcdHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiaGFuZGxlRmV0Y2ggcmV0dXJuZWQgdm9pZCB1bmV4cGVjdGVkbHlcIik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3BvbnNlO1xuXHR9KTtcblxuXHQvLyBSYXcgV2ViU29ja2V0IGVuZHBvaW50IC0gL3dlYnNvY2tldC8qXG5cdHJvdXRlci5nZXQoYCR7UEFUSF9SQVdfV0VCU09DS0VUX1BSRUZJWH0qYCwgYXN5bmMgKGMpID0+IHtcblx0XHRjb25zdCB1cGdyYWRlV2ViU29ja2V0ID0gcnVuQ29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQ/LigpO1xuXHRcdGlmICh1cGdyYWRlV2ViU29ja2V0KSB7XG5cdFx0XHRyZXR1cm4gdXBncmFkZVdlYlNvY2tldChhc3luYyAoYykgPT4ge1xuXHRcdFx0XHRjb25zdCBlbmNvZGluZ1JhdyA9IGMucmVxLmhlYWRlcihIRUFERVJfRU5DT0RJTkcpO1xuXHRcdFx0XHRjb25zdCBjb25uUGFyYW1zUmF3ID0gYy5yZXEuaGVhZGVyKEhFQURFUl9DT05OX1BBUkFNUyk7XG5cdFx0XHRcdGNvbnN0IGF1dGhEYXRhUmF3ID0gYy5yZXEuaGVhZGVyKEhFQURFUl9BVVRIX0RBVEEpO1xuXG5cdFx0XHRcdGNvbnN0IGVuY29kaW5nID0gRW5jb2RpbmdTY2hlbWEucGFyc2UoZW5jb2RpbmdSYXcpO1xuXHRcdFx0XHRjb25zdCBjb25uUGFyYW1zID0gY29ublBhcmFtc1Jhd1xuXHRcdFx0XHRcdD8gSlNPTi5wYXJzZShjb25uUGFyYW1zUmF3KVxuXHRcdFx0XHRcdDogdW5kZWZpbmVkO1xuXHRcdFx0XHRjb25zdCBhdXRoRGF0YSA9IGF1dGhEYXRhUmF3ID8gSlNPTi5wYXJzZShhdXRoRGF0YVJhdykgOiB1bmRlZmluZWQ7XG5cblx0XHRcdFx0Y29uc3QgdXJsID0gbmV3IFVSTChjLnJlcS51cmwpO1xuXHRcdFx0XHRjb25zdCBwYXRoV2l0aFF1ZXJ5ID0gYy5yZXEucGF0aCArIHVybC5zZWFyY2g7XG5cblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJhY3RvciByb3V0ZXIgcmF3IHdlYnNvY2tldFwiLCB7XG5cdFx0XHRcdFx0cGF0aDogYy5yZXEucGF0aCxcblx0XHRcdFx0XHR1cmw6IGMucmVxLnVybCxcblx0XHRcdFx0XHRzZWFyY2g6IHVybC5zZWFyY2gsXG5cdFx0XHRcdFx0cGF0aFdpdGhRdWVyeSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmV0dXJuIGF3YWl0IGhhbmRsZVJhd1dlYlNvY2tldEhhbmRsZXIoXG5cdFx0XHRcdFx0Yy5yZXEucmF3LFxuXHRcdFx0XHRcdHBhdGhXaXRoUXVlcnksXG5cdFx0XHRcdFx0YWN0b3JEcml2ZXIsXG5cdFx0XHRcdFx0Yy5lbnYuYWN0b3JJZCxcblx0XHRcdFx0XHRhdXRoRGF0YSxcblx0XHRcdFx0KTtcblx0XHRcdH0pKGMsIG5vb3BOZXh0KCkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gYy50ZXh0KFxuXHRcdFx0XHRcIldlYlNvY2tldHMgYXJlIG5vdCBlbmFibGVkIGZvciB0aGlzIGRyaXZlci4gVXNlIFNTRSBpbnN0ZWFkLlwiLFxuXHRcdFx0XHQ0MDAsXG5cdFx0XHQpO1xuXHRcdH1cblx0fSk7XG5cblx0aWYgKHJ1bkNvbmZpZy5pbnNwZWN0b3IuZW5hYmxlZCkge1xuXHRcdHJvdXRlci5yb3V0ZShcblx0XHRcdFwiL2luc3BlY3RcIixcblx0XHRcdG5ldyBIb25vPEFjdG9ySW5zcGVjdG9yUm91dGVyRW52ICYgeyBCaW5kaW5nczogQWN0b3JSb3V0ZXJCaW5kaW5ncyB9PigpXG5cdFx0XHRcdC51c2Uoc2VjdXJlSW5zcGVjdG9yKHJ1bkNvbmZpZyksIGFzeW5jIChjLCBuZXh0KSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgaW5zcGVjdG9yID0gKGF3YWl0IGFjdG9yRHJpdmVyLmxvYWRBY3RvcihjLmVudi5hY3RvcklkKSlcblx0XHRcdFx0XHRcdC5pbnNwZWN0b3I7XG5cdFx0XHRcdFx0aW52YXJpYW50KGluc3BlY3RvciwgXCJpbnNwZWN0b3Igbm90IHN1cHBvcnRlZCBvbiB0aGlzIHBsYXRmb3JtXCIpO1xuXG5cdFx0XHRcdFx0Yy5zZXQoXCJpbnNwZWN0b3JcIiwgaW5zcGVjdG9yKTtcblx0XHRcdFx0XHRhd2FpdCBuZXh0KCk7XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC5yb3V0ZShcIi9cIiwgY3JlYXRlQWN0b3JJbnNwZWN0b3JSb3V0ZXIoKSksXG5cdFx0KTtcblx0fVxuXG5cdHJvdXRlci5ub3RGb3VuZChoYW5kbGVSb3V0ZU5vdEZvdW5kKTtcblx0cm91dGVyLm9uRXJyb3IoXG5cdFx0aGFuZGxlUm91dGVFcnJvci5iaW5kKHVuZGVmaW5lZCwge1xuXHRcdFx0Ly8gQWxsIGhlYWRlcnMgdG8gdGhpcyBlbmRwb2ludCBhcmUgY29uc2lkZXJlZCBzZWN1cmUsIHNvIHdlIGNhbiBlbmFibGUgdGhlIGV4cG9zZSBpbnRlcm5hbCBlcnJvciBoZWFkZXIgZm9yIHJlcXVlc3RzIGZyb20gdGhlIGludGVybmFsIGNsaWVudFxuXHRcdFx0ZW5hYmxlRXhwb3NlSW50ZXJuYWxFcnJvcjogdHJ1ZSxcblx0XHR9KSxcblx0KTtcblxuXHRyZXR1cm4gcm91dGVyO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL3JvdXRlci50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb25cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL3JvdXRlci50c1wiO2ltcG9ydCAqIGFzIGNib3IgZnJvbSBcImNib3IteFwiO1xuaW1wb3J0IHR5cGUgeyBDb250ZXh0IGFzIEhvbm9Db250ZXh0LCBOZXh0IH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB0eXBlIHsgRW5jb2RpbmcgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHtcblx0Z2V0UmVxdWVzdEVuY29kaW5nLFxuXHRnZXRSZXF1ZXN0RXhwb3NlSW50ZXJuYWxFcnJvcixcbn0gZnJvbSBcIkAvYWN0b3Ivcm91dGVyLWVuZHBvaW50c1wiO1xuaW1wb3J0IHsgSHR0cFJlc3BvbnNlRXJyb3IgfSBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC9tb2RcIjtcbmltcG9ydCB7IEhUVFBfUkVTUE9OU0VfRVJST1JfVkVSU0lPTkVEIH0gZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdmVyc2lvbmVkXCI7XG5pbXBvcnQgeyBzZXJpYWxpemVXaXRoRW5jb2RpbmcgfSBmcm9tIFwiQC9zZXJkZVwiO1xuaW1wb3J0IHsgYnVmZmVyVG9BcnJheUJ1ZmZlciB9IGZyb20gXCJAL3V0aWxzXCI7XG5pbXBvcnQgeyBnZXRMb2dnZXIsIHR5cGUgTG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgeyBkZWNvbnN0cnVjdEVycm9yLCBzdHJpbmdpZnlFcnJvciB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dnZXIoKSB7XG5cdHJldHVybiBnZXRMb2dnZXIoXCJyb3V0ZXJcIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dnZXJNaWRkbGV3YXJlKGxvZ2dlcjogTG9nZ2VyKSB7XG5cdHJldHVybiBhc3luYyAoYzogSG9ub0NvbnRleHQsIG5leHQ6IE5leHQpID0+IHtcblx0XHRjb25zdCBtZXRob2QgPSBjLnJlcS5tZXRob2Q7XG5cdFx0Y29uc3QgcGF0aCA9IGMucmVxLnBhdGg7XG5cdFx0Y29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuXHRcdGF3YWl0IG5leHQoKTtcblxuXHRcdGNvbnN0IGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcblx0XHRsb2dnZXIuZGVidWcoXCJodHRwIHJlcXVlc3RcIiwge1xuXHRcdFx0bWV0aG9kLFxuXHRcdFx0cGF0aCxcblx0XHRcdHN0YXR1czogYy5yZXMuc3RhdHVzLFxuXHRcdFx0ZHQ6IGAke2R1cmF0aW9ufW1zYCxcblx0XHRcdHJlcVNpemU6IGMucmVxLmhlYWRlcihcImNvbnRlbnQtbGVuZ3RoXCIpLFxuXHRcdFx0cmVzU2l6ZTogYy5yZXMuaGVhZGVycy5nZXQoXCJjb250ZW50LWxlbmd0aFwiKSxcblx0XHRcdHVzZXJBZ2VudDogYy5yZXEuaGVhZGVyKFwidXNlci1hZ2VudFwiKSxcblx0XHR9KTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVJvdXRlTm90Rm91bmQoYzogSG9ub0NvbnRleHQpIHtcblx0cmV0dXJuIGMudGV4dChcIk5vdCBGb3VuZCAoUml2ZXRLaXQpXCIsIDQwNCk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGFuZGxlUm91dGVyRXJyb3JPcHRzIHtcblx0ZW5hYmxlRXhwb3NlSW50ZXJuYWxFcnJvcj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVSb3V0ZUVycm9yKFxuXHRvcHRzOiBIYW5kbGVSb3V0ZXJFcnJvck9wdHMsXG5cdGVycm9yOiB1bmtub3duLFxuXHRjOiBIb25vQ29udGV4dCxcbikge1xuXHRjb25zdCBleHBvc2VJbnRlcm5hbEVycm9yID1cblx0XHRvcHRzLmVuYWJsZUV4cG9zZUludGVybmFsRXJyb3IgJiYgZ2V0UmVxdWVzdEV4cG9zZUludGVybmFsRXJyb3IoYy5yZXEucmF3KTtcblxuXHRjb25zdCB7IHN0YXR1c0NvZGUsIGNvZGUsIG1lc3NhZ2UsIG1ldGFkYXRhIH0gPSBkZWNvbnN0cnVjdEVycm9yKFxuXHRcdGVycm9yLFxuXHRcdGxvZ2dlcigpLFxuXHRcdHtcblx0XHRcdG1ldGhvZDogYy5yZXEubWV0aG9kLFxuXHRcdFx0cGF0aDogYy5yZXEucGF0aCxcblx0XHR9LFxuXHRcdGV4cG9zZUludGVybmFsRXJyb3IsXG5cdCk7XG5cblx0bGV0IGVuY29kaW5nOiBFbmNvZGluZztcblx0dHJ5IHtcblx0XHRlbmNvZGluZyA9IGdldFJlcXVlc3RFbmNvZGluZyhjLnJlcSk7XG5cdH0gY2F0Y2ggKGVycikge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZmFpbGVkIHRvIGV4dHJhY3QgZW5jb2RpbmdcIiwge1xuXHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVyciksXG5cdFx0fSk7XG5cdFx0ZW5jb2RpbmcgPSBcImpzb25cIjtcblx0fVxuXG5cdGNvbnN0IG91dHB1dCA9IHNlcmlhbGl6ZVdpdGhFbmNvZGluZyhcblx0XHRlbmNvZGluZyxcblx0XHR7XG5cdFx0XHRjb2RlLFxuXHRcdFx0bWVzc2FnZSxcblx0XHRcdG1ldGFkYXRhOiBidWZmZXJUb0FycmF5QnVmZmVyKGNib3IuZW5jb2RlKG1ldGFkYXRhKSksXG5cdFx0fSxcblx0XHRIVFRQX1JFU1BPTlNFX0VSUk9SX1ZFUlNJT05FRCxcblx0KTtcblxuXHRyZXR1cm4gYy5ib2R5KG91dHB1dCwgeyBzdGF0dXM6IHN0YXR1c0NvZGUgfSk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvdXRpbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2luc3BlY3Rvci91dGlscy50c1wiO2ltcG9ydCBjcnlwdG8gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5pbXBvcnQgeyBjcmVhdGVNaWRkbGV3YXJlIH0gZnJvbSBcImhvbm8vZmFjdG9yeVwiO1xuaW1wb3J0IHR5cGUgeyBSdW5Db25maWcgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB0eXBlIHsgUnVuQ29uZmlnSW5wdXQgfSBmcm9tIFwiQC9yZWdpc3RyeS9ydW4tY29uZmlnXCI7XG5pbXBvcnQgeyBpbnNwZWN0b3JMb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmVTZWNyZXRzKHByb3ZpZGVkU2VjcmV0OiBzdHJpbmcsIHZhbGlkU2VjcmV0OiBzdHJpbmcpIHtcblx0Ly8gRWFybHkgbGVuZ3RoIGNoZWNrIHRvIGF2b2lkIHVubmVjZXNzYXJ5IHByb2Nlc3Npbmdcblx0aWYgKHByb3ZpZGVkU2VjcmV0Lmxlbmd0aCAhPT0gdmFsaWRTZWNyZXQubGVuZ3RoKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpO1xuXG5cdGNvbnN0IGEgPSBlbmNvZGVyLmVuY29kZShwcm92aWRlZFNlY3JldCk7XG5cdGNvbnN0IGIgPSBlbmNvZGVyLmVuY29kZSh2YWxpZFNlY3JldCk7XG5cblx0aWYgKGEuYnl0ZUxlbmd0aCAhPT0gYi5ieXRlTGVuZ3RoKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Ly8gUGVyZm9ybSB0aW1pbmctc2FmZSBjb21wYXJpc29uXG5cdGlmICghY3J5cHRvLnRpbWluZ1NhZmVFcXVhbChhLCBiKSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGNvbnN0IHNlY3VyZUluc3BlY3RvciA9IChydW5Db25maWc6IFJ1bkNvbmZpZykgPT5cblx0Y3JlYXRlTWlkZGxld2FyZShhc3luYyAoYywgbmV4dCkgPT4ge1xuXHRcdGlmICghcnVuQ29uZmlnLmluc3BlY3Rvci5lbmFibGVkKSB7XG5cdFx0XHRyZXR1cm4gYy50ZXh0KFwiSW5zcGVjdG9yIGlzIG5vdCBlbmFibGVkXCIsIDUwMyk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgdXNlclRva2VuID0gYy5yZXEuaGVhZGVyKFwiQXV0aG9yaXphdGlvblwiKT8ucmVwbGFjZShcIkJlYXJlciBcIiwgXCJcIik7XG5cdFx0aWYgKCF1c2VyVG9rZW4pIHtcblx0XHRcdHJldHVybiBjLnRleHQoXCJVbmF1dGhvcml6ZWRcIiwgNDAxKTtcblx0XHR9XG5cblx0XHRjb25zdCBpbnNwZWN0b3JUb2tlbiA9IHJ1bkNvbmZpZy5pbnNwZWN0b3IudG9rZW4/LigpO1xuXHRcdGlmICghaW5zcGVjdG9yVG9rZW4pIHtcblx0XHRcdHJldHVybiBjLnRleHQoXCJVbmF1dGhvcml6ZWRcIiwgNDAxKTtcblx0XHR9XG5cblx0XHRjb25zdCBpc1ZhbGlkID0gY29tcGFyZVNlY3JldHModXNlclRva2VuLCBpbnNwZWN0b3JUb2tlbik7XG5cblx0XHRpZiAoIWlzVmFsaWQpIHtcblx0XHRcdHJldHVybiBjLnRleHQoXCJVbmF1dGhvcml6ZWRcIiwgNDAxKTtcblx0XHR9XG5cdFx0YXdhaXQgbmV4dCgpO1xuXHR9KTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEluc3BlY3RvclVybChydW5Db25maWc6IFJ1bkNvbmZpZ0lucHV0IHwgdW5kZWZpbmVkKSB7XG5cdGlmICghcnVuQ29uZmlnPy5pbnNwZWN0b3I/LmVuYWJsZWQpIHtcblx0XHRyZXR1cm4gXCJkaXNhYmxlZFwiO1xuXHR9XG5cblx0Y29uc3QgYWNjZXNzVG9rZW4gPSBydW5Db25maWc/Lmluc3BlY3Rvcj8udG9rZW4/LigpO1xuXG5cdGlmICghYWNjZXNzVG9rZW4pIHtcblx0XHRpbnNwZWN0b3JMb2dnZXIoKS53YXJuKFxuXHRcdFx0XCJJbnNwZWN0b3IgVG9rZW4gaXMgbm90IHNldCwgYnV0IEluc3BlY3RvciBpcyBlbmFibGVkLiBQbGVhc2Ugc2V0IGl0IGluIHRoZSBydW4gY29uZmlndXJhdGlvbiBgaW5zcGVjdG9yLnRva2VuYCBvciB2aWEgYFJJVkVUS0lUX0lOU1BFQ1RPUl9UT0tFTmAgZW52aXJvbm1lbnQgdmFyaWFibGUuIEluc3BlY3RvciB3aWxsIG5vdCBiZSBhY2Nlc3NpYmxlLlwiLFxuXHRcdCk7XG5cdFx0cmV0dXJuIFwiZGlzYWJsZWRcIjtcblx0fVxuXG5cdGNvbnN0IHVybCA9IG5ldyBVUkwoXCJodHRwczovL3N0dWRpby5yaXZldC5nZ1wiKTtcblxuXHR1cmwuc2VhcmNoUGFyYW1zLnNldChcInRcIiwgYWNjZXNzVG9rZW4pO1xuXG5cdGlmIChydW5Db25maWc/Lmluc3BlY3Rvcj8uZGVmYXVsdEVuZHBvaW50KSB7XG5cdFx0dXJsLnNlYXJjaFBhcmFtcy5zZXQoXCJ1XCIsIHJ1bkNvbmZpZy5pbnNwZWN0b3IuZGVmYXVsdEVuZHBvaW50KTtcblx0fVxuXG5cdHJldHVybiB1cmwuaHJlZjtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2luc3BlY3Rvci9sb2cudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2luc3BlY3Rvci9sb2cudHNcIjtpbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQC9jb21tb24vL2xvZ1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gaW5zcGVjdG9yTG9nZ2VyKCkge1xuXHRyZXR1cm4gZ2V0TG9nZ2VyKFwiaW5zcGVjdG9yXCIpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvYWN0b3IvbW9kLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2FjdG9yL21vZC50c1wiO2ltcG9ydCB7XG5cdHR5cGUgQWN0aW9ucyxcblx0dHlwZSBBY3RvckNvbmZpZyxcblx0dHlwZSBBY3RvckNvbmZpZ0lucHV0LFxuXHRBY3RvckNvbmZpZ1NjaGVtYSxcblx0QWN0b3JUeXBlcyxcbn0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IEFueURhdGFiYXNlUHJvdmlkZXIgfSBmcm9tIFwiLi9kYXRhYmFzZVwiO1xuaW1wb3J0IHsgQWN0b3JEZWZpbml0aW9uIH0gZnJvbSBcIi4vZGVmaW5pdGlvblwiO1xuXG5leHBvcnQgZnVuY3Rpb24gYWN0b3I8XG5cdFRTdGF0ZSxcblx0VENvbm5QYXJhbXMsXG5cdFRDb25uU3RhdGUsXG5cdFRWYXJzLFxuXHRUSW5wdXQsXG5cdFRBdXRoRGF0YSxcblx0VERhdGFiYXNlIGV4dGVuZHMgQW55RGF0YWJhc2VQcm92aWRlcixcblx0VEFjdGlvbnMgZXh0ZW5kcyBBY3Rpb25zPFxuXHRcdFRTdGF0ZSxcblx0XHRUQ29ublBhcmFtcyxcblx0XHRUQ29ublN0YXRlLFxuXHRcdFRWYXJzLFxuXHRcdFRJbnB1dCxcblx0XHRUQXV0aERhdGEsXG5cdFx0VERhdGFiYXNlXG5cdD4sXG4+KFxuXHRpbnB1dDogQWN0b3JDb25maWdJbnB1dDxcblx0XHRUU3RhdGUsXG5cdFx0VENvbm5QYXJhbXMsXG5cdFx0VENvbm5TdGF0ZSxcblx0XHRUVmFycyxcblx0XHRUSW5wdXQsXG5cdFx0VEF1dGhEYXRhLFxuXHRcdFREYXRhYmFzZSxcblx0XHRUQWN0aW9uc1xuXHQ+LFxuKTogQWN0b3JEZWZpbml0aW9uPFxuXHRUU3RhdGUsXG5cdFRDb25uUGFyYW1zLFxuXHRUQ29ublN0YXRlLFxuXHRUVmFycyxcblx0VElucHV0LFxuXHRUQXV0aERhdGEsXG5cdFREYXRhYmFzZSxcblx0VEFjdGlvbnNcbj4ge1xuXHRjb25zdCBjb25maWcgPSBBY3RvckNvbmZpZ1NjaGVtYS5wYXJzZShpbnB1dCkgYXMgQWN0b3JDb25maWc8XG5cdFx0VFN0YXRlLFxuXHRcdFRDb25uUGFyYW1zLFxuXHRcdFRDb25uU3RhdGUsXG5cdFx0VFZhcnMsXG5cdFx0VElucHV0LFxuXHRcdFRBdXRoRGF0YSxcblx0XHRURGF0YWJhc2Vcblx0Pjtcblx0cmV0dXJuIG5ldyBBY3RvckRlZmluaXRpb24oY29uZmlnKTtcbn1cbmV4cG9ydCB0eXBlIHsgRW5jb2RpbmcgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuZXhwb3J0IHR5cGUge1xuXHRVbml2ZXJzYWxFcnJvckV2ZW50LFxuXHRVbml2ZXJzYWxFdmVudCxcblx0VW5pdmVyc2FsRXZlbnRTb3VyY2UsXG5cdFVuaXZlcnNhbE1lc3NhZ2VFdmVudCxcbn0gZnJvbSBcIkAvY29tbW9uL2V2ZW50c291cmNlLWludGVyZmFjZVwiO1xuZXhwb3J0IHR5cGUgeyBVcGdyYWRlV2ViU29ja2V0QXJncyB9IGZyb20gXCJAL2NvbW1vbi9pbmxpbmUtd2Vic29ja2V0LWFkYXB0ZXIyXCI7XG5leHBvcnQgdHlwZSB7XG5cdFJpdmV0Q2xvc2VFdmVudCxcblx0Uml2ZXRFdmVudCxcblx0Uml2ZXRNZXNzYWdlRXZlbnQsXG5cdFVuaXZlcnNhbFdlYlNvY2tldCxcbn0gZnJvbSBcIkAvY29tbW9uL3dlYnNvY2tldC1pbnRlcmZhY2VcIjtcbmV4cG9ydCB0eXBlIHsgQWN0b3JLZXkgfSBmcm9tIFwiQC9tYW5hZ2VyL3Byb3RvY29sL3F1ZXJ5XCI7XG5leHBvcnQgdHlwZSB7IEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi9hY3Rpb25cIjtcbmV4cG9ydCB0eXBlICogZnJvbSBcIi4vY29uZmlnXCI7XG5leHBvcnQgdHlwZSB7XG5cdENvbm4sXG5cdENvbm5lY3Rpb25Ecml2ZXIsXG5cdENvbm5lY3Rpb25TdGF0dXMsXG5cdGdlbmVyYXRlQ29ubklkLFxuXHRnZW5lcmF0ZUNvbm5Ub2tlbixcbn0gZnJvbSBcIi4vY29ubmVjdGlvblwiO1xuZXhwb3J0IHtcblx0Q09OTkVDVElPTl9EUklWRVJfSFRUUCxcblx0Q09OTkVDVElPTl9EUklWRVJfU1NFLFxuXHRDT05ORUNUSU9OX0RSSVZFUl9XRUJTT0NLRVQsXG59IGZyb20gXCIuL2Nvbm5lY3Rpb25cIjtcbmV4cG9ydCB0eXBlIHsgQWN0b3JDb250ZXh0IH0gZnJvbSBcIi4vY29udGV4dFwiO1xuZXhwb3J0IHR5cGUge1xuXHRBY3Rpb25Db250ZXh0T2YsXG5cdEFjdG9yQ29udGV4dE9mLFxuXHRBY3RvckRlZmluaXRpb24sXG5cdEFueUFjdG9yRGVmaW5pdGlvbixcbn0gZnJvbSBcIi4vZGVmaW5pdGlvblwiO1xuZXhwb3J0IHsgbG9va3VwSW5SZWdpc3RyeSB9IGZyb20gXCIuL2RlZmluaXRpb25cIjtcbmV4cG9ydCB7IFVzZXJFcnJvciwgdHlwZSBVc2VyRXJyb3JPcHRpb25zIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5leHBvcnQge1xuXHRjcmVhdGVHZW5lcmljQ29ubkRyaXZlcnMsXG5cdEdlbmVyaWNDb25uR2xvYmFsU3RhdGUsXG59IGZyb20gXCIuL2dlbmVyaWMtY29ubi1kcml2ZXJcIjtcbmV4cG9ydCB0eXBlIHsgQW55QWN0b3JJbnN0YW5jZSB9IGZyb20gXCIuL2luc3RhbmNlXCI7XG5leHBvcnQge1xuXHR0eXBlIEFjdG9yUm91dGVyLFxuXHRjcmVhdGVBY3RvclJvdXRlcixcblx0UEFUSF9DT05ORUNUX1dFQlNPQ0tFVCxcblx0UEFUSF9SQVdfV0VCU09DS0VUX1BSRUZJWCxcbn0gZnJvbSBcIi4vcm91dGVyXCI7XG5leHBvcnQge1xuXHRBTExPV0VEX1BVQkxJQ19IRUFERVJTLFxuXHRoYW5kbGVSYXdXZWJTb2NrZXRIYW5kbGVyLFxuXHRoYW5kbGVXZWJTb2NrZXRDb25uZWN0LFxufSBmcm9tIFwiLi9yb3V0ZXItZW5kcG9pbnRzXCI7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvYWN0b3ItY29ubi50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnRcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY2xpZW50L2FjdG9yLWNvbm4udHNcIjtpbXBvcnQgKiBhcyBjYm9yIGZyb20gXCJjYm9yLXhcIjtcbmltcG9ydCBpbnZhcmlhbnQgZnJvbSBcImludmFyaWFudFwiO1xuaW1wb3J0IHBSZXRyeSBmcm9tIFwicC1yZXRyeVwiO1xuaW1wb3J0IHR5cGUgeyBDbG9zZUV2ZW50LCBXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCB0eXBlIHsgQW55QWN0b3JEZWZpbml0aW9uIH0gZnJvbSBcIkAvYWN0b3IvZGVmaW5pdGlvblwiO1xuaW1wb3J0IHsgaW5wdXREYXRhVG9CdWZmZXIgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9vbGRcIjtcbmltcG9ydCB7IHR5cGUgRW5jb2RpbmcsIGpzb25TdHJpbmdpZnlDb21wYXQgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHR5cGUge1xuXHRVbml2ZXJzYWxFcnJvckV2ZW50LFxuXHRVbml2ZXJzYWxFdmVudFNvdXJjZSxcblx0VW5pdmVyc2FsTWVzc2FnZUV2ZW50LFxufSBmcm9tIFwiQC9jb21tb24vZXZlbnRzb3VyY2UtaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBhc3NlcnRVbnJlYWNoYWJsZSwgc3RyaW5naWZ5RXJyb3IgfSBmcm9tIFwiQC9jb21tb24vdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JRdWVyeSB9IGZyb20gXCJAL21hbmFnZXIvcHJvdG9jb2wvcXVlcnlcIjtcbmltcG9ydCB0eXBlICogYXMgcHJvdG9jb2wgZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvbW9kXCI7XG5pbXBvcnQge1xuXHRUT19DTElFTlRfVkVSU0lPTkVELFxuXHRUT19TRVJWRVJfVkVSU0lPTkVELFxufSBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWRcIjtcbmltcG9ydCB7XG5cdGRlc2VyaWFsaXplV2l0aEVuY29kaW5nLFxuXHRlbmNvZGluZ0lzQmluYXJ5LFxuXHRzZXJpYWxpemVXaXRoRW5jb2RpbmcsXG59IGZyb20gXCJAL3NlcmRlXCI7XG5pbXBvcnQgeyBidWZmZXJUb0FycmF5QnVmZmVyLCBnZXRFbnZVbml2ZXJzYWwgfSBmcm9tIFwiQC91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBBY3RvckRlZmluaXRpb25BY3Rpb25zIH0gZnJvbSBcIi4vYWN0b3ItY29tbW9uXCI7XG5pbXBvcnQge1xuXHRBQ1RPUl9DT05OU19TWU1CT0wsXG5cdHR5cGUgQ2xpZW50RHJpdmVyLFxuXHR0eXBlIENsaWVudFJhdyxcblx0VFJBTlNQT1JUX1NZTUJPTCxcbn0gZnJvbSBcIi4vY2xpZW50XCI7XG5pbXBvcnQgKiBhcyBlcnJvcnMgZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0TWVzc2FnZSBhcyBDb25uTWVzc2FnZSwgbWVzc2FnZUxlbmd0aCB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmludGVyZmFjZSBBY3Rpb25JbkZsaWdodCB7XG5cdG5hbWU6IHN0cmluZztcblx0cmVzb2x2ZTogKHJlc3BvbnNlOiBwcm90b2NvbC5BY3Rpb25SZXNwb25zZSkgPT4gdm9pZDtcblx0cmVqZWN0OiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgRXZlbnRTdWJzY3JpcHRpb25zPEFyZ3MgZXh0ZW5kcyBBcnJheTx1bmtub3duPj4ge1xuXHRjYWxsYmFjazogKC4uLmFyZ3M6IEFyZ3MpID0+IHZvaWQ7XG5cdG9uY2U6IGJvb2xlYW47XG59XG5cbi8qKlxuICogQSBmdW5jdGlvbiB0aGF0IHVuc3Vic2NyaWJlcyBmcm9tIGFuIGV2ZW50LlxuICpcbiAqIEB0eXBlZGVmIHtGdW5jdGlvbn0gRXZlbnRVbnN1YnNjcmliZVxuICovXG5leHBvcnQgdHlwZSBFdmVudFVuc3Vic2NyaWJlID0gKCkgPT4gdm9pZDtcblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyBjb25uZWN0aW9uIGVycm9ycy5cbiAqXG4gKiBAdHlwZWRlZiB7RnVuY3Rpb259IEFjdG9yRXJyb3JDYWxsYmFja1xuICovXG5leHBvcnQgdHlwZSBBY3RvckVycm9yQ2FsbGJhY2sgPSAoZXJyb3I6IGVycm9ycy5BY3RvckVycm9yKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlbmRIdHRwTWVzc2FnZU9wdHMge1xuXHRlcGhlbWVyYWw6IGJvb2xlYW47XG5cdHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG5leHBvcnQgdHlwZSBDb25uVHJhbnNwb3J0ID1cblx0fCB7IHdlYnNvY2tldDogV2ViU29ja2V0IH1cblx0fCB7IHNzZTogVW5pdmVyc2FsRXZlbnRTb3VyY2UgfTtcblxuZXhwb3J0IGNvbnN0IENPTk5FQ1RfU1lNQk9MID0gU3ltYm9sKFwiY29ubmVjdFwiKTtcblxuLyoqXG4gKiBQcm92aWRlcyB1bmRlcmx5aW5nIGZ1bmN0aW9ucyBmb3Ige0BsaW5rIEFjdG9yQ29ubn0uIFNlZSB7QGxpbmsgQWN0b3JDb25ufSBmb3IgdXNpbmcgdHlwZS1zYWZlIHJlbW90ZSBwcm9jZWR1cmUgY2FsbHMuXG4gKlxuICogQHNlZSB7QGxpbmsgQWN0b3JDb25ufVxuICovXG5leHBvcnQgY2xhc3MgQWN0b3JDb25uUmF3IHtcblx0I2Rpc3Bvc2VkID0gZmFsc2U7XG5cblx0LyogV2lsbCBiZSBhYm9ydGVkIG9uIGRpc3Bvc2UuICovXG5cdCNhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cblx0LyoqIElmIGF0dGVtcHRpbmcgdG8gY29ubmVjdC4gSGVscGZ1bCBmb3Iga25vd2luZyBpZiBpbiBhIHJldHJ5IGxvb3Agd2hlbiByZWNvbm5lY3RpbmcuICovXG5cdCNjb25uZWN0aW5nID0gZmFsc2U7XG5cblx0Ly8gVGhlc2Ugd2lsbCBvbmx5IGJlIHNldCBvbiBTU0UgZHJpdmVyXG5cdCNhY3RvcklkPzogc3RyaW5nO1xuXHQjY29ubmVjdGlvbklkPzogc3RyaW5nO1xuXHQjY29ubmVjdGlvblRva2VuPzogc3RyaW5nO1xuXG5cdCN0cmFuc3BvcnQ/OiBDb25uVHJhbnNwb3J0O1xuXG5cdCNtZXNzYWdlUXVldWU6IHByb3RvY29sLlRvU2VydmVyW10gPSBbXTtcblx0I2FjdGlvbnNJbkZsaWdodCA9IG5ldyBNYXA8bnVtYmVyLCBBY3Rpb25JbkZsaWdodD4oKTtcblxuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFVua25vd24gc3Vic2NyaXB0aW9uIHR5cGVcblx0I2V2ZW50U3Vic2NyaXB0aW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8RXZlbnRTdWJzY3JpcHRpb25zPGFueVtdPj4+KCk7XG5cblx0I2Vycm9ySGFuZGxlcnMgPSBuZXcgU2V0PEFjdG9yRXJyb3JDYWxsYmFjaz4oKTtcblxuXHQjYWN0aW9uSWRDb3VudGVyID0gMDtcblxuXHQvKipcblx0ICogSW50ZXJ2YWwgdGhhdCBrZWVwcyB0aGUgTm9kZUpTIHByb2Nlc3MgYWxpdmUgaWYgdGhpcyBpcyB0aGUgb25seSB0aGluZyBydW5uaW5nLlxuXHQgKlxuXHQgKiBTZWUgdHRwczovL2dpdGh1Yi5jb20vbm9kZWpzL25vZGUvaXNzdWVzLzIyMDg4XG5cdCAqL1xuXHQja2VlcE5vZGVBbGl2ZUludGVydmFsOiBOb2RlSlMuVGltZW91dDtcblxuXHQvKiogUHJvbWlzZSB1c2VkIHRvIGluZGljYXRlIHRoZSBzb2NrZXQgaGFzIGNvbm5lY3RlZCBzdWNjZXNzZnVsbHkuIFRoaXMgd2lsbCBiZSByZWplY3RlZCBpZiB0aGUgY29ubmVjdGlvbiBmYWlscy4gKi9cblx0I29uT3BlblByb21pc2U/OiBQcm9taXNlV2l0aFJlc29sdmVyczx1bmRlZmluZWQ+O1xuXG5cdCNjbGllbnQ6IENsaWVudFJhdztcblx0I2RyaXZlcjogQ2xpZW50RHJpdmVyO1xuXHQjcGFyYW1zOiB1bmtub3duO1xuXHQjZW5jb2RpbmdLaW5kOiBFbmNvZGluZztcblx0I2FjdG9yUXVlcnk6IEFjdG9yUXVlcnk7XG5cblx0Ly8gVE9ETzogd3MgbWVzc2FnZSBxdWV1ZVxuXG5cdC8qKlxuXHQgKiBEbyBub3QgY2FsbCB0aGlzIGRpcmVjdGx5LlxuXHQgKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEFjdG9yQ29ublJhdy5cblx0ICpcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdGNsaWVudDogQ2xpZW50UmF3LFxuXHRcdGRyaXZlcjogQ2xpZW50RHJpdmVyLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRlbmNvZGluZ0tpbmQ6IEVuY29kaW5nLFxuXHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdCkge1xuXHRcdHRoaXMuI2NsaWVudCA9IGNsaWVudDtcblx0XHR0aGlzLiNkcml2ZXIgPSBkcml2ZXI7XG5cdFx0dGhpcy4jcGFyYW1zID0gcGFyYW1zO1xuXHRcdHRoaXMuI2VuY29kaW5nS2luZCA9IGVuY29kaW5nS2luZDtcblx0XHR0aGlzLiNhY3RvclF1ZXJ5ID0gYWN0b3JRdWVyeTtcblxuXHRcdHRoaXMuI2tlZXBOb2RlQWxpdmVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IDYwXzAwMCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbCBhIHJhdyBhY3Rpb24gY29ubmVjdGlvbi4gU2VlIHtAbGluayBBY3RvckNvbm59IGZvciB0eXBlLXNhZmUgYWN0aW9uIGNhbGxzLlxuXHQgKlxuXHQgKiBAc2VlIHtAbGluayBBY3RvckNvbm59XG5cdCAqIEB0ZW1wbGF0ZSBBcmdzIC0gVGhlIHR5cGUgb2YgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGFjdGlvbiBmdW5jdGlvbi5cblx0ICogQHRlbXBsYXRlIFJlc3BvbnNlIC0gVGhlIHR5cGUgb2YgdGhlIHJlc3BvbnNlIHJldHVybmVkIGJ5IHRoZSBhY3Rpb24gZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGFjdGlvbiBmdW5jdGlvbiB0byBjYWxsLlxuXHQgKiBAcGFyYW0gey4uLkFyZ3N9IGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGFjdGlvbiBmdW5jdGlvbi5cblx0ICogQHJldHVybnMge1Byb21pc2U8UmVzcG9uc2U+fSAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSByZXNwb25zZSBvZiB0aGUgYWN0aW9uIGZ1bmN0aW9uLlxuXHQgKi9cblx0YXN5bmMgYWN0aW9uPFxuXHRcdEFyZ3MgZXh0ZW5kcyBBcnJheTx1bmtub3duPiA9IHVua25vd25bXSxcblx0XHRSZXNwb25zZSA9IHVua25vd24sXG5cdD4ob3B0czoge1xuXHRcdG5hbWU6IHN0cmluZztcblx0XHRhcmdzOiBBcmdzO1xuXHRcdHNpZ25hbD86IEFib3J0U2lnbmFsO1xuXHR9KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiYWN0aW9uXCIsIHsgbmFtZTogb3B0cy5uYW1lLCBhcmdzOiBvcHRzLmFyZ3MgfSk7XG5cblx0XHQvLyBJZiB3ZSBoYXZlIGFuIGFjdGl2ZSBjb25uZWN0aW9uLCB1c2UgdGhlIHdlYnNvY2thY3Rpb25JZFxuXHRcdGNvbnN0IGFjdGlvbklkID0gdGhpcy4jYWN0aW9uSWRDb3VudGVyO1xuXHRcdHRoaXMuI2FjdGlvbklkQ291bnRlciArPSAxO1xuXG5cdFx0Y29uc3QgeyBwcm9taXNlLCByZXNvbHZlLCByZWplY3QgfSA9XG5cdFx0XHRQcm9taXNlLndpdGhSZXNvbHZlcnM8cHJvdG9jb2wuQWN0aW9uUmVzcG9uc2U+KCk7XG5cdFx0dGhpcy4jYWN0aW9uc0luRmxpZ2h0LnNldChhY3Rpb25JZCwgeyBuYW1lOiBvcHRzLm5hbWUsIHJlc29sdmUsIHJlamVjdCB9KTtcblxuXHRcdHRoaXMuI3NlbmRNZXNzYWdlKHtcblx0XHRcdGJvZHk6IHtcblx0XHRcdFx0dGFnOiBcIkFjdGlvblJlcXVlc3RcIixcblx0XHRcdFx0dmFsOiB7XG5cdFx0XHRcdFx0aWQ6IEJpZ0ludChhY3Rpb25JZCksXG5cdFx0XHRcdFx0bmFtZTogb3B0cy5uYW1lLFxuXHRcdFx0XHRcdGFyZ3M6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUob3B0cy5hcmdzKSksXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdH0gc2F0aXNmaWVzIHByb3RvY29sLlRvU2VydmVyKTtcblxuXHRcdC8vIFRPRE86IFRocm93IGVycm9yIGlmIGRpc2Nvbm5lY3QgaXMgY2FsbGVkXG5cblx0XHRjb25zdCB7IGlkOiByZXNwb25zZUlkLCBvdXRwdXQgfSA9IGF3YWl0IHByb21pc2U7XG5cdFx0aWYgKHJlc3BvbnNlSWQgIT09IEJpZ0ludChhY3Rpb25JZCkpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBSZXF1ZXN0IElEICR7YWN0aW9uSWR9IGRvZXMgbm90IG1hdGNoIHJlc3BvbnNlIElEICR7cmVzcG9uc2VJZH1gLFxuXHRcdFx0KTtcblxuXHRcdHJldHVybiBjYm9yLmRlY29kZShuZXcgVWludDhBcnJheShvdXRwdXQpKSBhcyBSZXNwb25zZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEbyBub3QgY2FsbCB0aGlzIGRpcmVjdGx5LlxuZW5jXG5cdCAqIEVzdGFibGlzaGVzIGEgY29ubmVjdGlvbiB0byB0aGUgc2VydmVyIHVzaW5nIHRoZSBzcGVjaWZpZWQgZW5kcG9pbnQgJiBlbmNvZGluZyAmIGRyaXZlci5cblx0ICpcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cHVibGljIFtDT05ORUNUX1NZTUJPTF0oKSB7XG5cdFx0dGhpcy4jY29ubmVjdFdpdGhSZXRyeSgpO1xuXHR9XG5cblx0YXN5bmMgI2Nvbm5lY3RXaXRoUmV0cnkoKSB7XG5cdFx0dGhpcy4jY29ubmVjdGluZyA9IHRydWU7XG5cblx0XHQvLyBBdHRlbXB0IHRvIHJlY29ubmVjdCBpbmRlZmluaXRlbHlcblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgcFJldHJ5KHRoaXMuI2Nvbm5lY3RBbmRXYWl0LmJpbmQodGhpcyksIHtcblx0XHRcdFx0Zm9yZXZlcjogdHJ1ZSxcblx0XHRcdFx0bWluVGltZW91dDogMjUwLFxuXHRcdFx0XHRtYXhUaW1lb3V0OiAzMF8wMDAsXG5cblx0XHRcdFx0b25GYWlsZWRBdHRlbXB0OiAoZXJyb3IpID0+IHtcblx0XHRcdFx0XHRsb2dnZXIoKS53YXJuKFwiZmFpbGVkIHRvIHJlY29ubmVjdFwiLCB7XG5cdFx0XHRcdFx0XHRhdHRlbXB0OiBlcnJvci5hdHRlbXB0TnVtYmVyLFxuXHRcdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBDYW5jZWwgcmV0cnkgaWYgYWJvcnRlZFxuXHRcdFx0XHRzaWduYWw6IHRoaXMuI2Fib3J0Q29udHJvbGxlci5zaWduYWwsXG5cdFx0XHR9KTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGlmICgoZXJyIGFzIEVycm9yKS5uYW1lID09PSBcIkFib3J0RXJyb3JcIikge1xuXHRcdFx0XHQvLyBJZ25vcmUgYWJvcnRpb25zXG5cdFx0XHRcdGxvZ2dlcigpLmluZm8oXCJjb25uZWN0aW9uIHJldHJ5IGFib3J0ZWRcIik7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIFVua25vd24gZXJyb3Jcblx0XHRcdFx0dGhyb3cgZXJyO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuI2Nvbm5lY3RpbmcgPSBmYWxzZTtcblx0fVxuXG5cdGFzeW5jICNjb25uZWN0QW5kV2FpdCgpIHtcblx0XHR0cnkge1xuXHRcdFx0Ly8gQ3JlYXRlIHByb21pc2UgZm9yIG9wZW5cblx0XHRcdGlmICh0aGlzLiNvbk9wZW5Qcm9taXNlKVxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCIjb25PcGVuUHJvbWlzZSBhbHJlYWR5IGRlZmluZWRcIik7XG5cdFx0XHR0aGlzLiNvbk9wZW5Qcm9taXNlID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7XG5cblx0XHRcdC8vIENvbm5lY3QgdHJhbnNwb3J0XG5cdFx0XHRpZiAodGhpcy4jY2xpZW50W1RSQU5TUE9SVF9TWU1CT0xdID09PSBcIndlYnNvY2tldFwiKSB7XG5cdFx0XHRcdGF3YWl0IHRoaXMuI2Nvbm5lY3RXZWJTb2NrZXQoKTtcblx0XHRcdH0gZWxzZSBpZiAodGhpcy4jY2xpZW50W1RSQU5TUE9SVF9TWU1CT0xdID09PSBcInNzZVwiKSB7XG5cdFx0XHRcdGF3YWl0IHRoaXMuI2Nvbm5lY3RTc2UoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFzc2VydFVucmVhY2hhYmxlKHRoaXMuI2NsaWVudFtUUkFOU1BPUlRfU1lNQk9MXSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdhaXQgZm9yIHJlc3VsdFxuXHRcdFx0YXdhaXQgdGhpcy4jb25PcGVuUHJvbWlzZS5wcm9taXNlO1xuXHRcdH0gZmluYWxseSB7XG5cdFx0XHR0aGlzLiNvbk9wZW5Qcm9taXNlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jICNjb25uZWN0V2ViU29ja2V0KHsgc2lnbmFsIH06IHsgc2lnbmFsPzogQWJvcnRTaWduYWwgfSA9IHt9KSB7XG5cdFx0Y29uc3Qgd3MgPSBhd2FpdCB0aGlzLiNkcml2ZXIuY29ubmVjdFdlYlNvY2tldChcblx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdHRoaXMuI2FjdG9yUXVlcnksXG5cdFx0XHR0aGlzLiNlbmNvZGluZ0tpbmQsXG5cdFx0XHR0aGlzLiNwYXJhbXMsXG5cdFx0XHRzaWduYWwgPyB7IHNpZ25hbCB9IDogdW5kZWZpbmVkLFxuXHRcdCk7XG5cdFx0dGhpcy4jdHJhbnNwb3J0ID0geyB3ZWJzb2NrZXQ6IHdzIH07XG5cdFx0d3MuYWRkRXZlbnRMaXN0ZW5lcihcIm9wZW5cIiwgKCkgPT4ge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ3ZWJzb2NrZXQgb3BlblwiKTtcblx0XHR9KTtcblx0XHR3cy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBhc3luYyAoZXYpID0+IHtcblx0XHRcdHRoaXMuI2hhbmRsZU9uTWVzc2FnZShldi5kYXRhKTtcblx0XHR9KTtcblx0XHR3cy5hZGRFdmVudExpc3RlbmVyKFwiY2xvc2VcIiwgKGV2KSA9PiB7XG5cdFx0XHR0aGlzLiNoYW5kbGVPbkNsb3NlKGV2KTtcblx0XHR9KTtcblx0XHR3cy5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgKF9ldikgPT4ge1xuXHRcdFx0dGhpcy4jaGFuZGxlT25FcnJvcigpO1xuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgI2Nvbm5lY3RTc2UoeyBzaWduYWwgfTogeyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9ID0ge30pIHtcblx0XHRjb25zdCBldmVudFNvdXJjZSA9IGF3YWl0IHRoaXMuI2RyaXZlci5jb25uZWN0U3NlKFxuXHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0dGhpcy4jYWN0b3JRdWVyeSxcblx0XHRcdHRoaXMuI2VuY29kaW5nS2luZCxcblx0XHRcdHRoaXMuI3BhcmFtcyxcblx0XHRcdHNpZ25hbCA/IHsgc2lnbmFsIH0gOiB1bmRlZmluZWQsXG5cdFx0KTtcblx0XHR0aGlzLiN0cmFuc3BvcnQgPSB7IHNzZTogZXZlbnRTb3VyY2UgfTtcblx0XHRldmVudFNvdXJjZS5vbm9wZW4gPSAoKSA9PiB7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImV2ZW50c291cmNlIG9wZW5cIik7XG5cdFx0XHQvLyAjaGFuZGxlT25PcGVuIGlzIGNhbGxlZCBvbiBcImlcIiBldmVudFxuXHRcdH07XG5cdFx0ZXZlbnRTb3VyY2Uub25tZXNzYWdlID0gKGV2OiBVbml2ZXJzYWxNZXNzYWdlRXZlbnQpID0+IHtcblx0XHRcdHRoaXMuI2hhbmRsZU9uTWVzc2FnZShldi5kYXRhKTtcblx0XHR9O1xuXHRcdGV2ZW50U291cmNlLm9uZXJyb3IgPSAoX2V2OiBVbml2ZXJzYWxFcnJvckV2ZW50KSA9PiB7XG5cdFx0XHRpZiAoZXZlbnRTb3VyY2UucmVhZHlTdGF0ZSA9PT0gZXZlbnRTb3VyY2UuQ0xPU0VEKSB7XG5cdFx0XHRcdC8vIFRoaXMgZXJyb3IgaW5kaWNhdGVzIGEgY2xvc2UgZXZlbnRcblx0XHRcdFx0dGhpcy4jaGFuZGxlT25DbG9zZShuZXcgRXZlbnQoXCJlcnJvclwiKSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBMb2cgZXJyb3Igc2luY2UgZXZlbnQgc291cmNlIGlzIHN0aWxsIG9wZW5cblx0XHRcdFx0dGhpcy4jaGFuZGxlT25FcnJvcigpO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvKiogQ2FsbGVkIGJ5IHRoZSBvbm9wZW4gZXZlbnQgZnJvbSBkcml2ZXJzLiAqL1xuXHQjaGFuZGxlT25PcGVuKCkge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwic29ja2V0IG9wZW5cIiwge1xuXHRcdFx0bWVzc2FnZVF1ZXVlTGVuZ3RoOiB0aGlzLiNtZXNzYWdlUXVldWUubGVuZ3RoLFxuXHRcdH0pO1xuXG5cdFx0Ly8gUmVzb2x2ZSBvcGVuIHByb21pc2Vcblx0XHRpZiAodGhpcy4jb25PcGVuUHJvbWlzZSkge1xuXHRcdFx0dGhpcy4jb25PcGVuUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXCIjb25PcGVuUHJvbWlzZSBpcyB1bmRlZmluZWRcIik7XG5cdFx0fVxuXG5cdFx0Ly8gUmVzdWJzY3JpYmUgdG8gYWxsIGFjdGl2ZSBldmVudHNcblx0XHRmb3IgKGNvbnN0IGV2ZW50TmFtZSBvZiB0aGlzLiNldmVudFN1YnNjcmlwdGlvbnMua2V5cygpKSB7XG5cdFx0XHR0aGlzLiNzZW5kU3Vic2NyaXB0aW9uKGV2ZW50TmFtZSwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0Ly8gRmx1c2ggcXVldWVcblx0XHQvL1xuXHRcdC8vIElmIHRoZSBtZXNzYWdlIGZhaWxzIHRvIHNlbmQsIHRoZSBtZXNzYWdlIHdpbGwgYmUgcmUtcXVldWVkXG5cdFx0Y29uc3QgcXVldWUgPSB0aGlzLiNtZXNzYWdlUXVldWU7XG5cdFx0dGhpcy4jbWVzc2FnZVF1ZXVlID0gW107XG5cdFx0Zm9yIChjb25zdCBtc2cgb2YgcXVldWUpIHtcblx0XHRcdHRoaXMuI3NlbmRNZXNzYWdlKG1zZyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIENhbGxlZCBieSB0aGUgb25tZXNzYWdlIGV2ZW50IGZyb20gZHJpdmVycy4gKi9cblx0YXN5bmMgI2hhbmRsZU9uTWVzc2FnZShkYXRhOiBhbnkpIHtcblx0XHRsb2dnZXIoKS50cmFjZShcInJlY2VpdmVkIG1lc3NhZ2VcIiwge1xuXHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBkYXRhLFxuXHRcdFx0aXNCbG9iOiBkYXRhIGluc3RhbmNlb2YgQmxvYixcblx0XHRcdGlzQXJyYXlCdWZmZXI6IGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcixcblx0XHR9KTtcblxuXHRcdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy4jcGFyc2VNZXNzYWdlKGRhdGEgYXMgQ29ubk1lc3NhZ2UpO1xuXHRcdGxvZ2dlcigpLnRyYWNlKFxuXHRcdFx0XCJwYXJzZWQgbWVzc2FnZVwiLFxuXHRcdFx0Z2V0RW52VW5pdmVyc2FsKFwiX1JJVkVUS0lUX0xPR19NRVNTQUdFXCIpXG5cdFx0XHRcdD8ge1xuXHRcdFx0XHRcdFx0bWVzc2FnZToganNvblN0cmluZ2lmeUNvbXBhdChyZXNwb25zZSkuc3Vic3RyaW5nKDAsIDEwMCkgKyBcIi4uLlwiLFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0OiB7fSxcblx0XHQpO1xuXG5cdFx0aWYgKHJlc3BvbnNlLmJvZHkudGFnID09PSBcIkluaXRcIikge1xuXHRcdFx0Ly8gVGhpcyBpcyBvbmx5IGNhbGxlZCBmb3IgU1NFXG5cdFx0XHR0aGlzLiNhY3RvcklkID0gcmVzcG9uc2UuYm9keS52YWwuYWN0b3JJZDtcblx0XHRcdHRoaXMuI2Nvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmJvZHkudmFsLmNvbm5lY3Rpb25JZDtcblx0XHRcdHRoaXMuI2Nvbm5lY3Rpb25Ub2tlbiA9IHJlc3BvbnNlLmJvZHkudmFsLmNvbm5lY3Rpb25Ub2tlbjtcblx0XHRcdGxvZ2dlcigpLnRyYWNlKFwicmVjZWl2ZWQgaW5pdCBtZXNzYWdlXCIsIHtcblx0XHRcdFx0YWN0b3JJZDogdGhpcy4jYWN0b3JJZCxcblx0XHRcdFx0Y29ubmVjdGlvbklkOiB0aGlzLiNjb25uZWN0aW9uSWQsXG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuI2hhbmRsZU9uT3BlbigpO1xuXHRcdH0gZWxzZSBpZiAocmVzcG9uc2UuYm9keS50YWcgPT09IFwiRXJyb3JcIikge1xuXHRcdFx0Ly8gQ29ubmVjdGlvbiBlcnJvclxuXHRcdFx0Y29uc3QgeyBjb2RlLCBtZXNzYWdlLCBtZXRhZGF0YSwgYWN0aW9uSWQgfSA9IHJlc3BvbnNlLmJvZHkudmFsO1xuXG5cdFx0XHRpZiAoYWN0aW9uSWQpIHtcblx0XHRcdFx0Y29uc3QgaW5GbGlnaHQgPSB0aGlzLiN0YWtlQWN0aW9uSW5GbGlnaHQoTnVtYmVyKGFjdGlvbklkKSk7XG5cblx0XHRcdFx0bG9nZ2VyKCkud2FybihcImFjdGlvbiBlcnJvclwiLCB7XG5cdFx0XHRcdFx0YWN0aW9uSWQ6IGFjdGlvbklkLFxuXHRcdFx0XHRcdGFjdGlvbk5hbWU6IGluRmxpZ2h0Py5uYW1lLFxuXHRcdFx0XHRcdGNvZGUsXG5cdFx0XHRcdFx0bWVzc2FnZSxcblx0XHRcdFx0XHRtZXRhZGF0YSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aW5GbGlnaHQucmVqZWN0KG5ldyBlcnJvcnMuQWN0b3JFcnJvcihjb2RlLCBtZXNzYWdlLCBtZXRhZGF0YSkpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bG9nZ2VyKCkud2FybihcImNvbm5lY3Rpb24gZXJyb3JcIiwge1xuXHRcdFx0XHRcdGNvZGUsXG5cdFx0XHRcdFx0bWVzc2FnZSxcblx0XHRcdFx0XHRtZXRhZGF0YSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gQ3JlYXRlIGEgY29ubmVjdGlvbiBlcnJvclxuXHRcdFx0XHRjb25zdCBhY3RvckVycm9yID0gbmV3IGVycm9ycy5BY3RvckVycm9yKGNvZGUsIG1lc3NhZ2UsIG1ldGFkYXRhKTtcblxuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGFuIG9uT3BlblByb21pc2UsIHJlamVjdCBpdCB3aXRoIHRoZSBlcnJvclxuXHRcdFx0XHRpZiAodGhpcy4jb25PcGVuUHJvbWlzZSkge1xuXHRcdFx0XHRcdHRoaXMuI29uT3BlblByb21pc2UucmVqZWN0KGFjdG9yRXJyb3IpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUmVqZWN0IGFueSBpbi1mbGlnaHQgcmVxdWVzdHNcblx0XHRcdFx0Zm9yIChjb25zdCBbaWQsIGluRmxpZ2h0XSBvZiB0aGlzLiNhY3Rpb25zSW5GbGlnaHQuZW50cmllcygpKSB7XG5cdFx0XHRcdFx0aW5GbGlnaHQucmVqZWN0KGFjdG9yRXJyb3IpO1xuXHRcdFx0XHRcdHRoaXMuI2FjdGlvbnNJbkZsaWdodC5kZWxldGUoaWQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gRGlzcGF0Y2ggdG8gZXJyb3IgaGFuZGxlciBpZiByZWdpc3RlcmVkXG5cdFx0XHRcdHRoaXMuI2Rpc3BhdGNoQWN0b3JFcnJvcihhY3RvckVycm9yKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHJlc3BvbnNlLmJvZHkudGFnID09PSBcIkFjdGlvblJlc3BvbnNlXCIpIHtcblx0XHRcdC8vIEFjdGlvbiByZXNwb25zZSBPS1xuXHRcdFx0Y29uc3QgeyBpZDogYWN0aW9uSWQgfSA9IHJlc3BvbnNlLmJvZHkudmFsO1xuXHRcdFx0bG9nZ2VyKCkudHJhY2UoXCJyZWNlaXZlZCBhY3Rpb24gcmVzcG9uc2VcIiwge1xuXHRcdFx0XHRhY3Rpb25JZCxcblx0XHRcdH0pO1xuXG5cdFx0XHRjb25zdCBpbkZsaWdodCA9IHRoaXMuI3Rha2VBY3Rpb25JbkZsaWdodChOdW1iZXIoYWN0aW9uSWQpKTtcblx0XHRcdGxvZ2dlcigpLnRyYWNlKFwicmVzb2x2aW5nIGFjdGlvbiBwcm9taXNlXCIsIHtcblx0XHRcdFx0YWN0aW9uSWQsXG5cdFx0XHRcdGFjdGlvbk5hbWU6IGluRmxpZ2h0Py5uYW1lLFxuXHRcdFx0fSk7XG5cdFx0XHRpbkZsaWdodC5yZXNvbHZlKHJlc3BvbnNlLmJvZHkudmFsKTtcblx0XHR9IGVsc2UgaWYgKHJlc3BvbnNlLmJvZHkudGFnID09PSBcIkV2ZW50XCIpIHtcblx0XHRcdGxvZ2dlcigpLnRyYWNlKFwicmVjZWl2ZWQgZXZlbnRcIiwgeyBuYW1lOiByZXNwb25zZS5ib2R5LnZhbC5uYW1lIH0pO1xuXHRcdFx0dGhpcy4jZGlzcGF0Y2hFdmVudChyZXNwb25zZS5ib2R5LnZhbCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFzc2VydFVucmVhY2hhYmxlKHJlc3BvbnNlLmJvZHkpO1xuXHRcdH1cblx0fVxuXG5cdC8qKiBDYWxsZWQgYnkgdGhlIG9uY2xvc2UgZXZlbnQgZnJvbSBkcml2ZXJzLiAqL1xuXHQjaGFuZGxlT25DbG9zZShldmVudDogRXZlbnQgfCBDbG9zZUV2ZW50KSB7XG5cdFx0Ly8gVE9ETzogSGFuZGxlIHF1ZXVlXG5cdFx0Ly8gVE9ETzogUmVjb25uZWN0IHdpdGggYmFja29mZlxuXG5cdFx0Ly8gUmVqZWN0IG9wZW4gcHJvbWlzZVxuXHRcdGlmICh0aGlzLiNvbk9wZW5Qcm9taXNlKSB7XG5cdFx0XHR0aGlzLiNvbk9wZW5Qcm9taXNlLnJlamVjdChuZXcgRXJyb3IoXCJDbG9zZWRcIikpO1xuXHRcdH1cblxuXHRcdC8vIFdlIGNhbid0IHVzZSBgZXZlbnQgaW5zdGFuY2VvZiBDbG9zZUV2ZW50YCBiZWNhdXNlIGl0J3Mgbm90IGRlZmluZWQgaW4gTm9kZUpTXG5cdFx0Ly9cblx0XHQvLyBUaGVzZSBwcm9wZXJ0aWVzIHdpbGwgYmUgdW5kZWZpbmVkXG5cdFx0Y29uc3QgY2xvc2VFdmVudCA9IGV2ZW50IGFzIENsb3NlRXZlbnQ7XG5cdFx0aWYgKGNsb3NlRXZlbnQud2FzQ2xlYW4pIHtcblx0XHRcdGxvZ2dlcigpLmluZm8oXCJzb2NrZXQgY2xvc2VkXCIsIHtcblx0XHRcdFx0Y29kZTogY2xvc2VFdmVudC5jb2RlLFxuXHRcdFx0XHRyZWFzb246IGNsb3NlRXZlbnQucmVhc29uLFxuXHRcdFx0XHR3YXNDbGVhbjogY2xvc2VFdmVudC53YXNDbGVhbixcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsb2dnZXIoKS53YXJuKFwic29ja2V0IGNsb3NlZFwiLCB7XG5cdFx0XHRcdGNvZGU6IGNsb3NlRXZlbnQuY29kZSxcblx0XHRcdFx0cmVhc29uOiBjbG9zZUV2ZW50LnJlYXNvbixcblx0XHRcdFx0d2FzQ2xlYW46IGNsb3NlRXZlbnQud2FzQ2xlYW4sXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHR0aGlzLiN0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHQvLyBBdXRvbWF0aWNhbGx5IHJlY29ubmVjdC4gU2tpcCBpZiBhbHJlYWR5IGF0dGVtcHRpbmcgdG8gY29ubmVjdC5cblx0XHRpZiAoIXRoaXMuI2Rpc3Bvc2VkICYmICF0aGlzLiNjb25uZWN0aW5nKSB7XG5cdFx0XHQvLyBUT0RPOiBGZXRjaCBhY3RvciB0byBjaGVjayBpZiBpdCdzIGRlc3Ryb3llZFxuXHRcdFx0Ly8gVE9ETzogQWRkIGJhY2tvZmYgZm9yIHJlY29ubmVjdFxuXHRcdFx0Ly8gVE9ETzogQWRkIGEgd2F5IG9mIHByZXNlcnZpbmcgY29ubmVjdGlvbiBJRCBmb3IgY29ubmVjdGlvbiBzdGF0ZVxuXG5cdFx0XHQvLyBBdHRlbXB0IHRvIGNvbm5lY3QgYWdhaW5cblx0XHRcdHRoaXMuI2Nvbm5lY3RXaXRoUmV0cnkoKTtcblx0XHR9XG5cdH1cblxuXHQvKiogQ2FsbGVkIGJ5IHRoZSBvbmVycm9yIGV2ZW50IGZyb20gZHJpdmVycy4gKi9cblx0I2hhbmRsZU9uRXJyb3IoKSB7XG5cdFx0aWYgKHRoaXMuI2Rpc3Bvc2VkKSByZXR1cm47XG5cblx0XHQvLyBNb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIHdpbGwgYmUgbG9nZ2VkIGluIG9uY2xvc2Vcblx0XHRsb2dnZXIoKS53YXJuKFwic29ja2V0IGVycm9yXCIpO1xuXHR9XG5cblx0I3Rha2VBY3Rpb25JbkZsaWdodChpZDogbnVtYmVyKTogQWN0aW9uSW5GbGlnaHQge1xuXHRcdGNvbnN0IGluRmxpZ2h0ID0gdGhpcy4jYWN0aW9uc0luRmxpZ2h0LmdldChpZCk7XG5cdFx0aWYgKCFpbkZsaWdodCkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnRlcm5hbEVycm9yKGBObyBpbiBmbGlnaHQgcmVzcG9uc2UgZm9yICR7aWR9YCk7XG5cdFx0fVxuXHRcdHRoaXMuI2FjdGlvbnNJbkZsaWdodC5kZWxldGUoaWQpO1xuXHRcdHJldHVybiBpbkZsaWdodDtcblx0fVxuXG5cdCNkaXNwYXRjaEV2ZW50KGV2ZW50OiBwcm90b2NvbC5FdmVudCkge1xuXHRcdGNvbnN0IHsgbmFtZSwgYXJnczogYXJnc1JhdyB9ID0gZXZlbnQ7XG5cdFx0Y29uc3QgYXJncyA9IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGFyZ3NSYXcpKTtcblxuXHRcdGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuI2V2ZW50U3Vic2NyaXB0aW9ucy5nZXQobmFtZSk7XG5cdFx0aWYgKCFsaXN0ZW5lcnMpIHJldHVybjtcblxuXHRcdC8vIENyZWF0ZSBhIG5ldyBhcnJheSB0byBhdm9pZCBpc3N1ZXMgd2l0aCBsaXN0ZW5lcnMgYmVpbmcgcmVtb3ZlZCBkdXJpbmcgaXRlcmF0aW9uXG5cdFx0Zm9yIChjb25zdCBsaXN0ZW5lciBvZiBbLi4ubGlzdGVuZXJzXSkge1xuXHRcdFx0bGlzdGVuZXIuY2FsbGJhY2soLi4uYXJncyk7XG5cblx0XHRcdC8vIFJlbW92ZSBpZiB0aGlzIHdhcyBhIG9uZS10aW1lIGxpc3RlbmVyXG5cdFx0XHRpZiAobGlzdGVuZXIub25jZSkge1xuXHRcdFx0XHRsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDbGVhbiB1cCBlbXB0eSBsaXN0ZW5lciBzZXRzXG5cdFx0aWYgKGxpc3RlbmVycy5zaXplID09PSAwKSB7XG5cdFx0XHR0aGlzLiNldmVudFN1YnNjcmlwdGlvbnMuZGVsZXRlKG5hbWUpO1xuXHRcdH1cblx0fVxuXG5cdCNkaXNwYXRjaEFjdG9yRXJyb3IoZXJyb3I6IGVycm9ycy5BY3RvckVycm9yKSB7XG5cdFx0Ly8gQ2FsbCBhbGwgcmVnaXN0ZXJlZCBlcnJvciBoYW5kbGVyc1xuXHRcdGZvciAoY29uc3QgaGFuZGxlciBvZiBbLi4udGhpcy4jZXJyb3JIYW5kbGVyc10pIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGhhbmRsZXIoZXJyb3IpO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiRXJyb3IgaW4gY29ubmVjdGlvbiBlcnJvciBoYW5kbGVyXCIsIHtcblx0XHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyKSxcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0I2FkZEV2ZW50U3Vic2NyaXB0aW9uPEFyZ3MgZXh0ZW5kcyBBcnJheTx1bmtub3duPj4oXG5cdFx0ZXZlbnROYW1lOiBzdHJpbmcsXG5cdFx0Y2FsbGJhY2s6ICguLi5hcmdzOiBBcmdzKSA9PiB2b2lkLFxuXHRcdG9uY2U6IGJvb2xlYW4sXG5cdCk6IEV2ZW50VW5zdWJzY3JpYmUge1xuXHRcdGNvbnN0IGxpc3RlbmVyOiBFdmVudFN1YnNjcmlwdGlvbnM8QXJncz4gPSB7XG5cdFx0XHRjYWxsYmFjayxcblx0XHRcdG9uY2UsXG5cdFx0fTtcblxuXHRcdGxldCBzdWJzY3JpcHRpb25TZXQgPSB0aGlzLiNldmVudFN1YnNjcmlwdGlvbnMuZ2V0KGV2ZW50TmFtZSk7XG5cdFx0aWYgKHN1YnNjcmlwdGlvblNldCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRzdWJzY3JpcHRpb25TZXQgPSBuZXcgU2V0KCk7XG5cdFx0XHR0aGlzLiNldmVudFN1YnNjcmlwdGlvbnMuc2V0KGV2ZW50TmFtZSwgc3Vic2NyaXB0aW9uU2V0KTtcblx0XHRcdHRoaXMuI3NlbmRTdWJzY3JpcHRpb24oZXZlbnROYW1lLCB0cnVlKTtcblx0XHR9XG5cdFx0c3Vic2NyaXB0aW9uU2V0LmFkZChsaXN0ZW5lcik7XG5cblx0XHQvLyBSZXR1cm4gdW5zdWJzY3JpYmUgZnVuY3Rpb25cblx0XHRyZXR1cm4gKCkgPT4ge1xuXHRcdFx0Y29uc3QgbGlzdGVuZXJzID0gdGhpcy4jZXZlbnRTdWJzY3JpcHRpb25zLmdldChldmVudE5hbWUpO1xuXHRcdFx0aWYgKGxpc3RlbmVycykge1xuXHRcdFx0XHRsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcblx0XHRcdFx0aWYgKGxpc3RlbmVycy5zaXplID09PSAwKSB7XG5cdFx0XHRcdFx0dGhpcy4jZXZlbnRTdWJzY3JpcHRpb25zLmRlbGV0ZShldmVudE5hbWUpO1xuXHRcdFx0XHRcdHRoaXMuI3NlbmRTdWJzY3JpcHRpb24oZXZlbnROYW1lLCBmYWxzZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZXMgdG8gYW4gZXZlbnQgdGhhdCB3aWxsIGhhcHBlbiByZXBlYXRlZGx5LlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQXJncyAtIFRoZSB0eXBlIG9mIGFyZ3VtZW50cyB0aGUgZXZlbnQgY2FsbGJhY2sgd2lsbCByZWNlaXZlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHN1YnNjcmliZSB0by5cblx0ICogQHBhcmFtIHsoLi4uYXJnczogQXJncykgPT4gdm9pZH0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG5cdCAqIEByZXR1cm5zIHtFdmVudFVuc3Vic2NyaWJlfSAtIEEgZnVuY3Rpb24gdG8gdW5zdWJzY3JpYmUgZnJvbSB0aGUgZXZlbnQuXG5cdCAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9ldmVudHN8RXZlbnRzIERvY3VtZW50YXRpb259XG5cdCAqL1xuXHRvbjxBcmdzIGV4dGVuZHMgQXJyYXk8dW5rbm93bj4gPSB1bmtub3duW10+KFxuXHRcdGV2ZW50TmFtZTogc3RyaW5nLFxuXHRcdGNhbGxiYWNrOiAoLi4uYXJnczogQXJncykgPT4gdm9pZCxcblx0KTogRXZlbnRVbnN1YnNjcmliZSB7XG5cdFx0cmV0dXJuIHRoaXMuI2FkZEV2ZW50U3Vic2NyaXB0aW9uPEFyZ3M+KGV2ZW50TmFtZSwgY2FsbGJhY2ssIGZhbHNlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdWJzY3JpYmVzIHRvIGFuIGV2ZW50IHRoYXQgd2lsbCBiZSB0cmlnZ2VyZWQgb25seSBvbmNlLlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQXJncyAtIFRoZSB0eXBlIG9mIGFyZ3VtZW50cyB0aGUgZXZlbnQgY2FsbGJhY2sgd2lsbCByZWNlaXZlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHN1YnNjcmliZSB0by5cblx0ICogQHBhcmFtIHsoLi4uYXJnczogQXJncykgPT4gdm9pZH0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG5cdCAqIEByZXR1cm5zIHtFdmVudFVuc3Vic2NyaWJlfSAtIEEgZnVuY3Rpb24gdG8gdW5zdWJzY3JpYmUgZnJvbSB0aGUgZXZlbnQuXG5cdCAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9ldmVudHN8RXZlbnRzIERvY3VtZW50YXRpb259XG5cdCAqL1xuXHRvbmNlPEFyZ3MgZXh0ZW5kcyBBcnJheTx1bmtub3duPiA9IHVua25vd25bXT4oXG5cdFx0ZXZlbnROYW1lOiBzdHJpbmcsXG5cdFx0Y2FsbGJhY2s6ICguLi5hcmdzOiBBcmdzKSA9PiB2b2lkLFxuXHQpOiBFdmVudFVuc3Vic2NyaWJlIHtcblx0XHRyZXR1cm4gdGhpcy4jYWRkRXZlbnRTdWJzY3JpcHRpb248QXJncz4oZXZlbnROYW1lLCBjYWxsYmFjaywgdHJ1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU3Vic2NyaWJlcyB0byBjb25uZWN0aW9uIGVycm9ycy5cblx0ICpcblx0ICogQHBhcmFtIHtBY3RvckVycm9yQ2FsbGJhY2t9IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgd2hlbiBhIGNvbm5lY3Rpb24gZXJyb3Igb2NjdXJzLlxuXHQgKiBAcmV0dXJucyB7KCkgPT4gdm9pZH0gLSBBIGZ1bmN0aW9uIHRvIHVuc3Vic2NyaWJlIGZyb20gdGhlIGVycm9yIGhhbmRsZXIuXG5cdCAqL1xuXHRvbkVycm9yKGNhbGxiYWNrOiBBY3RvckVycm9yQ2FsbGJhY2spOiAoKSA9PiB2b2lkIHtcblx0XHR0aGlzLiNlcnJvckhhbmRsZXJzLmFkZChjYWxsYmFjayk7XG5cblx0XHQvLyBSZXR1cm4gdW5zdWJzY3JpYmUgZnVuY3Rpb25cblx0XHRyZXR1cm4gKCkgPT4ge1xuXHRcdFx0dGhpcy4jZXJyb3JIYW5kbGVycy5kZWxldGUoY2FsbGJhY2spO1xuXHRcdH07XG5cdH1cblxuXHQjc2VuZE1lc3NhZ2UobWVzc2FnZTogcHJvdG9jb2wuVG9TZXJ2ZXIsIG9wdHM/OiBTZW5kSHR0cE1lc3NhZ2VPcHRzKSB7XG5cdFx0aWYgKHRoaXMuI2Rpc3Bvc2VkKSB7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkFjdG9yQ29ubkRpc3Bvc2VkKCk7XG5cdFx0fVxuXG5cdFx0bGV0IHF1ZXVlTWVzc2FnZSA9IGZhbHNlO1xuXHRcdGlmICghdGhpcy4jdHJhbnNwb3J0KSB7XG5cdFx0XHQvLyBObyB0cmFuc3BvcnQgY29ubmVjdGVkIHlldFxuXHRcdFx0cXVldWVNZXNzYWdlID0gdHJ1ZTtcblx0XHR9IGVsc2UgaWYgKFwid2Vic29ja2V0XCIgaW4gdGhpcy4jdHJhbnNwb3J0KSB7XG5cdFx0XHRpZiAodGhpcy4jdHJhbnNwb3J0LndlYnNvY2tldC5yZWFkeVN0YXRlID09PSAxKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29uc3QgbWVzc2FnZVNlcmlhbGl6ZWQgPSBzZXJpYWxpemVXaXRoRW5jb2RpbmcoXG5cdFx0XHRcdFx0XHR0aGlzLiNlbmNvZGluZ0tpbmQsXG5cdFx0XHRcdFx0XHRtZXNzYWdlLFxuXHRcdFx0XHRcdFx0VE9fU0VSVkVSX1ZFUlNJT05FRCxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdHRoaXMuI3RyYW5zcG9ydC53ZWJzb2NrZXQuc2VuZChtZXNzYWdlU2VyaWFsaXplZCk7XG5cdFx0XHRcdFx0bG9nZ2VyKCkudHJhY2UoXCJzZW50IHdlYnNvY2tldCBtZXNzYWdlXCIsIHtcblx0XHRcdFx0XHRcdGxlbjogbWVzc2FnZUxlbmd0aChtZXNzYWdlU2VyaWFsaXplZCksXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkud2FybihcImZhaWxlZCB0byBzZW5kIG1lc3NhZ2UsIGFkZGVkIHRvIHF1ZXVlXCIsIHtcblx0XHRcdFx0XHRcdGVycm9yLFxuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0Ly8gQXNzdW1pbmcgdGhlIHNvY2tldCBpcyBkaXNjb25uZWN0ZWQgYW5kIHdpbGwgYmUgcmVjb25uZWN0ZWQgc29vblxuXHRcdFx0XHRcdHF1ZXVlTWVzc2FnZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHF1ZXVlTWVzc2FnZSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChcInNzZVwiIGluIHRoaXMuI3RyYW5zcG9ydCkge1xuXHRcdFx0aWYgKHRoaXMuI3RyYW5zcG9ydC5zc2UucmVhZHlTdGF0ZSA9PT0gMSkge1xuXHRcdFx0XHQvLyBTcGF3biBpbiBiYWNrZ3JvdW5kIHNpbmNlICNzZW5kTWVzc2FnZSBjYW5ub3QgYmUgYXN5bmNcblx0XHRcdFx0dGhpcy4jc2VuZEh0dHBNZXNzYWdlKG1lc3NhZ2UsIG9wdHMpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cXVldWVNZXNzYWdlID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0YXNzZXJ0VW5yZWFjaGFibGUodGhpcy4jdHJhbnNwb3J0KTtcblx0XHR9XG5cblx0XHRpZiAoIW9wdHM/LmVwaGVtZXJhbCAmJiBxdWV1ZU1lc3NhZ2UpIHtcblx0XHRcdHRoaXMuI21lc3NhZ2VRdWV1ZS5wdXNoKG1lc3NhZ2UpO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJxdWV1ZWQgY29ubmVjdGlvbiBtZXNzYWdlXCIpO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jICNzZW5kSHR0cE1lc3NhZ2UoXG5cdFx0bWVzc2FnZTogcHJvdG9jb2wuVG9TZXJ2ZXIsXG5cdFx0b3B0cz86IFNlbmRIdHRwTWVzc2FnZU9wdHMsXG5cdCkge1xuXHRcdHRyeSB7XG5cdFx0XHRpZiAoIXRoaXMuI2FjdG9ySWQgfHwgIXRoaXMuI2Nvbm5lY3Rpb25JZCB8fCAhdGhpcy4jY29ubmVjdGlvblRva2VuKVxuXHRcdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludGVybmFsRXJyb3IoXCJNaXNzaW5nIGNvbm5lY3Rpb24gSUQgb3IgdG9rZW4uXCIpO1xuXG5cdFx0XHRsb2dnZXIoKS50cmFjZShcblx0XHRcdFx0XCJzZW50IGh0dHAgbWVzc2FnZVwiLFxuXHRcdFx0XHRnZXRFbnZVbml2ZXJzYWwoXCJfUklWRVRLSVRfTE9HX01FU1NBR0VcIilcblx0XHRcdFx0XHQ/IHtcblx0XHRcdFx0XHRcdFx0bWVzc2FnZToganNvblN0cmluZ2lmeUNvbXBhdChtZXNzYWdlKS5zdWJzdHJpbmcoMCwgMTAwKSArIFwiLi4uXCIsXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0OiB7fSxcblx0XHRcdCk7XG5cblx0XHRcdGF3YWl0IHRoaXMuI2RyaXZlci5zZW5kSHR0cE1lc3NhZ2UoXG5cdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0dGhpcy4jYWN0b3JJZCxcblx0XHRcdFx0dGhpcy4jZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHR0aGlzLiNjb25uZWN0aW9uSWQsXG5cdFx0XHRcdHRoaXMuI2Nvbm5lY3Rpb25Ub2tlbixcblx0XHRcdFx0bWVzc2FnZSxcblx0XHRcdFx0b3B0cz8uc2lnbmFsID8geyBzaWduYWw6IG9wdHMuc2lnbmFsIH0gOiB1bmRlZmluZWQsXG5cdFx0XHQpO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHQvLyBUT0RPOiBUaGlzIHdpbGwgbm90IGF1dG9tYXRpY2FsbHkgdHJpZ2dlciBhIHJlLWJyb2FkY2FzdCBvZiBIVFRQIGV2ZW50cyBzaW5jZSBTU0UgaXMgc2VwYXJhdGUgZnJvbSB0aGUgSFRUUCBhY3Rpb25cblxuXHRcdFx0bG9nZ2VyKCkud2FybihcImZhaWxlZCB0byBzZW5kIG1lc3NhZ2UsIGFkZGVkIHRvIHF1ZXVlXCIsIHtcblx0XHRcdFx0ZXJyb3IsXG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gQXNzdW1pbmcgdGhlIHNvY2tldCBpcyBkaXNjb25uZWN0ZWQgYW5kIHdpbGwgYmUgcmVjb25uZWN0ZWQgc29vblxuXHRcdFx0Ly9cblx0XHRcdC8vIFdpbGwgYXR0ZW1wdCB0byByZXNlbmQgc29vblxuXHRcdFx0aWYgKCFvcHRzPy5lcGhlbWVyYWwpIHtcblx0XHRcdFx0dGhpcy4jbWVzc2FnZVF1ZXVlLnVuc2hpZnQobWVzc2FnZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgI3BhcnNlTWVzc2FnZShkYXRhOiBDb25uTWVzc2FnZSk6IFByb21pc2U8cHJvdG9jb2wuVG9DbGllbnQ+IHtcblx0XHRpbnZhcmlhbnQodGhpcy4jdHJhbnNwb3J0LCBcInRyYW5zcG9ydCBtdXN0IGJlIGRlZmluZWRcIik7XG5cblx0XHQvLyBEZWNvZGUgYmFzZTY0IHNpbmNlIFNTRSBzZW5kcyByYXcgc3RyaW5nc1xuXHRcdGlmIChlbmNvZGluZ0lzQmluYXJ5KHRoaXMuI2VuY29kaW5nS2luZCkgJiYgXCJzc2VcIiBpbiB0aGlzLiN0cmFuc3BvcnQpIHtcblx0XHRcdGlmICh0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHRjb25zdCBiaW5hcnlTdHJpbmcgPSBhdG9iKGRhdGEpO1xuXHRcdFx0XHRkYXRhID0gbmV3IFVpbnQ4QXJyYXkoXG5cdFx0XHRcdFx0Wy4uLmJpbmFyeVN0cmluZ10ubWFwKChjaGFyKSA9PiBjaGFyLmNoYXJDb2RlQXQoMCkpLFxuXHRcdFx0XHQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnRlcm5hbEVycm9yKFxuXHRcdFx0XHRcdGBFeHBlY3RlZCBkYXRhIHRvIGJlIGEgc3RyaW5nIGZvciBTU0UsIGdvdCAke2RhdGF9LmAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3QgYnVmZmVyID0gYXdhaXQgaW5wdXREYXRhVG9CdWZmZXIoZGF0YSk7XG5cblx0XHRyZXR1cm4gZGVzZXJpYWxpemVXaXRoRW5jb2RpbmcoXG5cdFx0XHR0aGlzLiNlbmNvZGluZ0tpbmQsXG5cdFx0XHRidWZmZXIsXG5cdFx0XHRUT19DTElFTlRfVkVSU0lPTkVELFxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzY29ubmVjdHMgZnJvbSB0aGUgYWN0b3IuXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzb2NrZXQgaXMgZ3JhY2VmdWxseSBjbG9zZWQuXG5cdCAqL1xuXHRhc3luYyBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdC8vIEludGVybmFsbHksIHRoaXMgXCJkaXNwb3Nlc1wiIHRoZSBjb25uZWN0aW9uXG5cblx0XHRpZiAodGhpcy4jZGlzcG9zZWQpIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXCJjb25uZWN0aW9uIGFscmVhZHkgZGlzY29ubmVjdGVkXCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLiNkaXNwb3NlZCA9IHRydWU7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImRpc3Bvc2luZyBhY3RvciBjb25uXCIpO1xuXG5cdFx0Ly8gQ2xlYXIgaW50ZXJ2YWwgc28gTm9kZUpTIHByb2Nlc3MgY2FuIGV4aXRcblx0XHRjbGVhckludGVydmFsKHRoaXMuI2tlZXBOb2RlQWxpdmVJbnRlcnZhbCk7XG5cblx0XHQvLyBBYm9ydFxuXHRcdHRoaXMuI2Fib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGZyb20gcmVnaXN0cnlcblx0XHR0aGlzLiNjbGllbnRbQUNUT1JfQ09OTlNfU1lNQk9MXS5kZWxldGUodGhpcyk7XG5cblx0XHQvLyBEaXNjb25uZWN0IHRyYW5zcG9ydCBjbGVhbmx5XG5cdFx0aWYgKCF0aGlzLiN0cmFuc3BvcnQpIHtcblx0XHRcdC8vIE5vdGhpbmcgdG8gZG9cblx0XHR9IGVsc2UgaWYgKFwid2Vic29ja2V0XCIgaW4gdGhpcy4jdHJhbnNwb3J0KSB7XG5cdFx0XHRjb25zdCB3cyA9IHRoaXMuI3RyYW5zcG9ydC53ZWJzb2NrZXQ7XG5cdFx0XHQvLyBDaGVjayBpZiBXZWJTb2NrZXQgaXMgYWxyZWFkeSBjbG9zZWQgb3IgY2xvc2luZ1xuXHRcdFx0aWYgKFxuXHRcdFx0XHR3cy5yZWFkeVN0YXRlID09PSAyIC8qIENMT1NJTkcgKi8gfHxcblx0XHRcdFx0d3MucmVhZHlTdGF0ZSA9PT0gMyAvKiBDTE9TRUQgKi9cblx0XHRcdCkge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcIndzIGFscmVhZHkgY2xvc2VkIG9yIGNsb3NpbmdcIik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCB7IHByb21pc2UsIHJlc29sdmUgfSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpO1xuXHRcdFx0XHR3cy5hZGRFdmVudExpc3RlbmVyKFwiY2xvc2VcIiwgKCkgPT4ge1xuXHRcdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwid3MgY2xvc2VkXCIpO1xuXHRcdFx0XHRcdHJlc29sdmUodW5kZWZpbmVkKTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHdzLmNsb3NlKCk7XG5cdFx0XHRcdGF3YWl0IHByb21pc2U7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChcInNzZVwiIGluIHRoaXMuI3RyYW5zcG9ydCkge1xuXHRcdFx0dGhpcy4jdHJhbnNwb3J0LnNzZS5jbG9zZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhc3NlcnRVbnJlYWNoYWJsZSh0aGlzLiN0cmFuc3BvcnQpO1xuXHRcdH1cblx0XHR0aGlzLiN0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cdH1cblxuXHQjc2VuZFN1YnNjcmlwdGlvbihldmVudE5hbWU6IHN0cmluZywgc3Vic2NyaWJlOiBib29sZWFuKSB7XG5cdFx0dGhpcy4jc2VuZE1lc3NhZ2UoXG5cdFx0XHR7XG5cdFx0XHRcdGJvZHk6IHtcblx0XHRcdFx0XHR0YWc6IFwiU3Vic2NyaXB0aW9uUmVxdWVzdFwiLFxuXHRcdFx0XHRcdHZhbDoge1xuXHRcdFx0XHRcdFx0ZXZlbnROYW1lLFxuXHRcdFx0XHRcdFx0c3Vic2NyaWJlLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdFx0eyBlcGhlbWVyYWw6IHRydWUgfSxcblx0XHQpO1xuXHR9XG59XG5cbi8qKlxuICogQ29ubmVjdGlvbiB0byBhIGFjdG9yLiBBbGxvd3MgY2FsbGluZyBhY3RvcidzIHJlbW90ZSBwcm9jZWR1cmUgY2FsbHMgd2l0aCBpbmZlcnJlZCB0eXBlcy4gU2VlIHtAbGluayBBY3RvckNvbm5SYXd9IGZvciB1bmRlcmx5aW5nIG1ldGhvZHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYFxuICogY29uc3Qgcm9vbSA9IGNsaWVudC5jb25uZWN0PENoYXRSb29tPiguLi5ldGMuLi4pO1xuICogLy8gVGhpcyBjYWxscyB0aGUgYWN0aW9uIG5hbWVkIGBzZW5kTWVzc2FnZWAgb24gdGhlIGBDaGF0Um9vbWAgYWN0b3IuXG4gKiBhd2FpdCByb29tLnNlbmRNZXNzYWdlKCdIZWxsbywgd29ybGQhJyk7XG4gKiBgYGBcbiAqXG4gKiBQcml2YXRlIG1ldGhvZHMgKGUuZy4gdGhvc2Ugc3RhcnRpbmcgd2l0aCBgX2ApIGFyZSBhdXRvbWF0aWNhbGx5IGV4Y2x1ZGVkLlxuICpcbiAqIEB0ZW1wbGF0ZSBBRCBUaGUgYWN0b3IgY2xhc3MgdGhhdCB0aGlzIGNvbm5lY3Rpb24gaXMgZm9yLlxuICogQHNlZSB7QGxpbmsgQWN0b3JDb25uUmF3fVxuICovXG5leHBvcnQgdHlwZSBBY3RvckNvbm48QUQgZXh0ZW5kcyBBbnlBY3RvckRlZmluaXRpb24+ID0gQWN0b3JDb25uUmF3ICZcblx0QWN0b3JEZWZpbml0aW9uQWN0aW9uczxBRD47XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvZXJyb3JzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudFwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvZXJyb3JzLnRzXCI7aW1wb3J0IHsgTUFYX0NPTk5fUEFSQU1TX1NJWkUgfSBmcm9tIFwiQC9jb21tb24vL25ldHdvcmtcIjtcblxuZXhwb3J0IGNsYXNzIEFjdG9yQ2xpZW50RXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG5leHBvcnQgY2xhc3MgSW50ZXJuYWxFcnJvciBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige31cblxuZXhwb3J0IGNsYXNzIE1hbmFnZXJFcnJvciBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihlcnJvcjogc3RyaW5nLCBvcHRzPzogRXJyb3JPcHRpb25zKSB7XG5cdFx0c3VwZXIoYE1hbmFnZXIgZXJyb3I6ICR7ZXJyb3J9YCwgb3B0cyk7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIE1hbGZvcm1lZFJlc3BvbnNlTWVzc2FnZSBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihjYXVzZT86IHVua25vd24pIHtcblx0XHRzdXBlcihgTWFsZm9ybWVkIHJlc3BvbnNlIG1lc3NhZ2U6ICR7Y2F1c2V9YCwgeyBjYXVzZSB9KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQWN0b3JFcnJvciBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige1xuXHRfX3R5cGUgPSBcIkFjdG9yRXJyb3JcIjtcblxuXHRjb25zdHJ1Y3Rvcihcblx0XHRwdWJsaWMgcmVhZG9ubHkgY29kZTogc3RyaW5nLFxuXHRcdG1lc3NhZ2U6IHN0cmluZyxcblx0XHRwdWJsaWMgcmVhZG9ubHkgbWV0YWRhdGE/OiB1bmtub3duLFxuXHQpIHtcblx0XHRzdXBlcihtZXNzYWdlKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSHR0cFJlcXVlc3RFcnJvciBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcsIG9wdHM/OiB7IGNhdXNlPzogdW5rbm93biB9KSB7XG5cdFx0c3VwZXIoYEhUVFAgcmVxdWVzdCBlcnJvcjogJHttZXNzYWdlfWAsIHsgY2F1c2U6IG9wdHM/LmNhdXNlIH0pO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBBY3RvckNvbm5EaXNwb3NlZCBleHRlbmRzIEFjdG9yQ2xpZW50RXJyb3Ige1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcihcIkF0dGVtcHRpbmcgdG8gaW50ZXJhY3Qgd2l0aCBhIGRpc3Bvc2VkIGFjdG9yIGNvbm5lY3Rpb24uXCIpO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvbG9nLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudFwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvbG9nLnRzXCI7aW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkAvY29tbW9uLy9sb2dcIjtcblxuZXhwb3J0IGNvbnN0IExPR0dFUl9OQU1FID0gXCJhY3Rvci1jbGllbnRcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2dlcigpIHtcblx0cmV0dXJuIGdldExvZ2dlcihMT0dHRVJfTkFNRSk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvdXRpbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY2xpZW50XCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudC91dGlscy50c1wiO2ltcG9ydCAqIGFzIGNib3IgZnJvbSBcImNib3IteFwiO1xuaW1wb3J0IGludmFyaWFudCBmcm9tIFwiaW52YXJpYW50XCI7XG5pbXBvcnQgeyBhc3NlcnRVbnJlYWNoYWJsZSB9IGZyb20gXCJAL2NvbW1vbi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBWZXJzaW9uZWREYXRhSGFuZGxlciB9IGZyb20gXCJAL2NvbW1vbi92ZXJzaW9uZWQtZGF0YVwiO1xuaW1wb3J0IHR5cGUgeyBFbmNvZGluZyB9IGZyb20gXCJAL21vZFwiO1xuaW1wb3J0IHR5cGUgeyBIdHRwUmVzcG9uc2VFcnJvciB9IGZyb20gXCJAL3NjaGVtYXMvY2xpZW50LXByb3RvY29sL21vZFwiO1xuaW1wb3J0IHsgSFRUUF9SRVNQT05TRV9FUlJPUl9WRVJTSU9ORUQgfSBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWRcIjtcbmltcG9ydCB7XG5cdGNvbnRlbnRUeXBlRm9yRW5jb2RpbmcsXG5cdGRlc2VyaWFsaXplV2l0aEVuY29kaW5nLFxuXHRzZXJpYWxpemVXaXRoRW5jb2RpbmcsXG59IGZyb20gXCJAL3NlcmRlXCI7XG5pbXBvcnQgeyBodHRwVXNlckFnZW50IH0gZnJvbSBcIkAvdXRpbHNcIjtcbmltcG9ydCB7IEFjdG9yRXJyb3IsIEh0dHBSZXF1ZXN0RXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCIuL2xvZ1wiO1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRNZXNzYWdlID0gc3RyaW5nIHwgQmxvYiB8IEFycmF5QnVmZmVyIHwgVWludDhBcnJheTtcblxuZXhwb3J0IGZ1bmN0aW9uIG1lc3NhZ2VMZW5ndGgobWVzc2FnZTogV2ViU29ja2V0TWVzc2FnZSk6IG51bWJlciB7XG5cdGlmIChtZXNzYWdlIGluc3RhbmNlb2YgQmxvYikge1xuXHRcdHJldHVybiBtZXNzYWdlLnNpemU7XG5cdH1cblx0aWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuXHRcdHJldHVybiBtZXNzYWdlLmJ5dGVMZW5ndGg7XG5cdH1cblx0aWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG5cdFx0cmV0dXJuIG1lc3NhZ2UuYnl0ZUxlbmd0aDtcblx0fVxuXHRpZiAodHlwZW9mIG1lc3NhZ2UgPT09IFwic3RyaW5nXCIpIHtcblx0XHRyZXR1cm4gbWVzc2FnZS5sZW5ndGg7XG5cdH1cblx0YXNzZXJ0VW5yZWFjaGFibGUobWVzc2FnZSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlcXVlc3RPcHRzPFJlcXVlc3RCb2R5LCBSZXNwb25zZUJvZHk+IHtcblx0bWV0aG9kOiBzdHJpbmc7XG5cdHVybDogc3RyaW5nO1xuXHRoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRib2R5PzogUmVxdWVzdEJvZHk7XG5cdGVuY29kaW5nOiBFbmNvZGluZztcblx0c2tpcFBhcnNlUmVzcG9uc2U/OiBib29sZWFuO1xuXHRzaWduYWw/OiBBYm9ydFNpZ25hbDtcblx0Y3VzdG9tRmV0Y2g/OiAocmVxOiBSZXF1ZXN0KSA9PiBQcm9taXNlPFJlc3BvbnNlPjtcblx0cmVxdWVzdFZlcnNpb25lZERhdGFIYW5kbGVyOiBWZXJzaW9uZWREYXRhSGFuZGxlcjxSZXF1ZXN0Qm9keT47XG5cdHJlc3BvbnNlVmVyc2lvbmVkRGF0YUhhbmRsZXI6IFZlcnNpb25lZERhdGFIYW5kbGVyPFJlc3BvbnNlQm9keT47XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kSHR0cFJlcXVlc3Q8XG5cdFJlcXVlc3RCb2R5ID0gdW5rbm93bixcblx0UmVzcG9uc2VCb2R5ID0gdW5rbm93bixcbj4ob3B0czogSHR0cFJlcXVlc3RPcHRzPFJlcXVlc3RCb2R5LCBSZXNwb25zZUJvZHk+KTogUHJvbWlzZTxSZXNwb25zZUJvZHk+IHtcblx0bG9nZ2VyKCkuZGVidWcoXCJzZW5kaW5nIGh0dHAgcmVxdWVzdFwiLCB7XG5cdFx0dXJsOiBvcHRzLnVybCxcblx0XHRlbmNvZGluZzogb3B0cy5lbmNvZGluZyxcblx0fSk7XG5cblx0Ly8gU2VyaWFsaXplIGJvZHlcblx0bGV0IGNvbnRlbnRUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cdGxldCBib2R5RGF0YTogc3RyaW5nIHwgVWludDhBcnJheSB8IHVuZGVmaW5lZDtcblx0aWYgKG9wdHMubWV0aG9kID09PSBcIlBPU1RcIiB8fCBvcHRzLm1ldGhvZCA9PT0gXCJQVVRcIikge1xuXHRcdGludmFyaWFudChvcHRzLmJvZHkgIT09IHVuZGVmaW5lZCwgXCJtaXNzaW5nIGJvZHlcIik7XG5cdFx0Y29udGVudFR5cGUgPSBjb250ZW50VHlwZUZvckVuY29kaW5nKG9wdHMuZW5jb2RpbmcpO1xuXHRcdGJvZHlEYXRhID0gc2VyaWFsaXplV2l0aEVuY29kaW5nPFJlcXVlc3RCb2R5Pihcblx0XHRcdG9wdHMuZW5jb2RpbmcsXG5cdFx0XHRvcHRzLmJvZHksXG5cdFx0XHRvcHRzLnJlcXVlc3RWZXJzaW9uZWREYXRhSGFuZGxlcixcblx0XHQpO1xuXHR9XG5cblx0Ly8gU2VuZCByZXF1ZXN0XG5cdGxldCByZXNwb25zZTogUmVzcG9uc2U7XG5cdHRyeSB7XG5cdFx0Ly8gTWFrZSB0aGUgSFRUUCByZXF1ZXN0XG5cdFx0cmVzcG9uc2UgPSBhd2FpdCAob3B0cy5jdXN0b21GZXRjaCA/PyBmZXRjaCkoXG5cdFx0XHRuZXcgUmVxdWVzdChvcHRzLnVybCwge1xuXHRcdFx0XHRtZXRob2Q6IG9wdHMubWV0aG9kLFxuXHRcdFx0XHRoZWFkZXJzOiB7XG5cdFx0XHRcdFx0Li4ub3B0cy5oZWFkZXJzLFxuXHRcdFx0XHRcdC4uLihjb250ZW50VHlwZVxuXHRcdFx0XHRcdFx0PyB7XG5cdFx0XHRcdFx0XHRcdFx0XCJDb250ZW50LVR5cGVcIjogY29udGVudFR5cGUsXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdDoge30pLFxuXHRcdFx0XHRcdFwiVXNlci1BZ2VudFwiOiBodHRwVXNlckFnZW50KCksXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGJvZHk6IGJvZHlEYXRhLFxuXHRcdFx0XHRjcmVkZW50aWFsczogXCJpbmNsdWRlXCIsXG5cdFx0XHRcdHNpZ25hbDogb3B0cy5zaWduYWwsXG5cdFx0XHR9KSxcblx0XHQpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdHRocm93IG5ldyBIdHRwUmVxdWVzdEVycm9yKGBSZXF1ZXN0IGZhaWxlZDogJHtlcnJvcn1gLCB7XG5cdFx0XHRjYXVzZTogZXJyb3IsXG5cdFx0fSk7XG5cdH1cblxuXHQvLyBQYXJzZSByZXNwb25zZSBlcnJvclxuXHRpZiAoIXJlc3BvbnNlLm9rKSB7XG5cdFx0Ly8gQXR0ZW1wdCB0byBwYXJzZSBzdHJ1Y3R1cmVkIGRhdGFcblx0XHRjb25zdCBidWZmZXJSZXNwb25zZSA9IGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7XG5cdFx0bGV0IHJlc3BvbnNlRGF0YTogSHR0cFJlc3BvbnNlRXJyb3I7XG5cdFx0dHJ5IHtcblx0XHRcdHJlc3BvbnNlRGF0YSA9IGRlc2VyaWFsaXplV2l0aEVuY29kaW5nKFxuXHRcdFx0XHRvcHRzLmVuY29kaW5nLFxuXHRcdFx0XHRuZXcgVWludDhBcnJheShidWZmZXJSZXNwb25zZSksXG5cdFx0XHRcdEhUVFBfUkVTUE9OU0VfRVJST1JfVkVSU0lPTkVELFxuXHRcdFx0KTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0Ly9sb2dnZXIoKS53YXJuKFwiZmFpbGVkIHRvIGNsZWFubHkgcGFyc2UgZXJyb3IsIHRoaXMgaXMgbGlrZWx5IGJlY2F1c2UgYSBub24tc3RydWN0dXJlZCByZXNwb25zZSBpcyBiZWluZyBzZXJ2ZWRcIiwge1xuXHRcdFx0Ly9cdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvciksXG5cdFx0XHQvL30pO1xuXG5cdFx0XHQvLyBFcnJvciBpcyBub3Qgc3RydWN0dXJlZFxuXHRcdFx0Y29uc3QgdGV4dFJlc3BvbnNlID0gbmV3IFRleHREZWNvZGVyKFwidXRmLThcIiwgeyBmYXRhbDogZmFsc2UgfSkuZGVjb2RlKFxuXHRcdFx0XHRidWZmZXJSZXNwb25zZSxcblx0XHRcdCk7XG5cdFx0XHR0aHJvdyBuZXcgSHR0cFJlcXVlc3RFcnJvcihcblx0XHRcdFx0YCR7cmVzcG9uc2Uuc3RhdHVzVGV4dH0gKCR7cmVzcG9uc2Uuc3RhdHVzfSk6XFxuJHt0ZXh0UmVzcG9uc2V9YCxcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Ly8gVGhyb3cgc3RydWN0dXJlZCBlcnJvclxuXHRcdHRocm93IG5ldyBBY3RvckVycm9yKFxuXHRcdFx0cmVzcG9uc2VEYXRhLmNvZGUsXG5cdFx0XHRyZXNwb25zZURhdGEubWVzc2FnZSxcblx0XHRcdHJlc3BvbnNlRGF0YS5tZXRhZGF0YVxuXHRcdFx0XHQ/IGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KHJlc3BvbnNlRGF0YS5tZXRhZGF0YSkpXG5cdFx0XHRcdDogdW5kZWZpbmVkLFxuXHRcdCk7XG5cdH1cblxuXHQvLyBTb21lIHJlcXVlc3RzIGRvbid0IG5lZWQgdGhlIHN1Y2Nlc3MgcmVzcG9uc2UgdG8gYmUgcGFyc2VkLCBzbyB0aGlzIGNhbiBzcGVlZCB0aGluZ3MgdXBcblx0aWYgKG9wdHMuc2tpcFBhcnNlUmVzcG9uc2UpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkIGFzIFJlc3BvbnNlQm9keTtcblx0fVxuXG5cdC8vIFBhcnNlIHRoZSByZXNwb25zZSBiYXNlZCBvbiBlbmNvZGluZ1xuXHR0cnkge1xuXHRcdGNvbnN0IGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCkpO1xuXHRcdHJldHVybiBkZXNlcmlhbGl6ZVdpdGhFbmNvZGluZyhcblx0XHRcdG9wdHMuZW5jb2RpbmcsXG5cdFx0XHRidWZmZXIsXG5cdFx0XHRvcHRzLnJlc3BvbnNlVmVyc2lvbmVkRGF0YUhhbmRsZXIsXG5cdFx0KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHR0aHJvdyBuZXcgSHR0cFJlcXVlc3RFcnJvcihgRmFpbGVkIHRvIHBhcnNlIHJlc3BvbnNlOiAke2Vycm9yfWAsIHtcblx0XHRcdGNhdXNlOiBlcnJvcixcblx0XHR9KTtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY2xpZW50L2FjdG9yLWhhbmRsZS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnRcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY2xpZW50L2FjdG9yLWhhbmRsZS50c1wiO2ltcG9ydCBpbnZhcmlhbnQgZnJvbSBcImludmFyaWFudFwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBY3RvckRlZmluaXRpb24gfSBmcm9tIFwiQC9hY3Rvci9kZWZpbml0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IEVuY29kaW5nIH0gZnJvbSBcIkAvYWN0b3IvcHJvdG9jb2wvc2VyZGVcIjtcbmltcG9ydCB7IGFzc2VydFVucmVhY2hhYmxlIH0gZnJvbSBcIkAvYWN0b3IvdXRpbHNcIjtcbmltcG9ydCB7IGltcG9ydFdlYlNvY2tldCB9IGZyb20gXCJAL2NvbW1vbi93ZWJzb2NrZXRcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JRdWVyeSB9IGZyb20gXCJAL21hbmFnZXIvcHJvdG9jb2wvcXVlcnlcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JEZWZpbml0aW9uQWN0aW9ucyB9IGZyb20gXCIuL2FjdG9yLWNvbW1vblwiO1xuaW1wb3J0IHsgdHlwZSBBY3RvckNvbm4sIEFjdG9yQ29ublJhdyB9IGZyb20gXCIuL2FjdG9yLWNvbm5cIjtcbmltcG9ydCB7XG5cdHR5cGUgQ2xpZW50RHJpdmVyLFxuXHR0eXBlIENsaWVudFJhdyxcblx0Q1JFQVRFX0FDVE9SX0NPTk5fUFJPWFksXG59IGZyb20gXCIuL2NsaWVudFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgeyByYXdIdHRwRmV0Y2gsIHJhd1dlYlNvY2tldCB9IGZyb20gXCIuL3Jhdy11dGlsc1wiO1xuXG4vKipcbiAqIFByb3ZpZGVzIHVuZGVybHlpbmcgZnVuY3Rpb25zIGZvciBzdGF0ZWxlc3Mge0BsaW5rIEFjdG9ySGFuZGxlfSBmb3IgYWN0aW9uIGNhbGxzLlxuICogU2ltaWxhciB0byBBY3RvckNvbm5SYXcgYnV0IGRvZXNuJ3QgbWFpbnRhaW4gYSBjb25uZWN0aW9uLlxuICpcbiAqIEBzZWUge0BsaW5rIEFjdG9ySGFuZGxlfVxuICovXG5leHBvcnQgY2xhc3MgQWN0b3JIYW5kbGVSYXcge1xuXHQjY2xpZW50OiBDbGllbnRSYXc7XG5cdCNkcml2ZXI6IENsaWVudERyaXZlcjtcblx0I2VuY29kaW5nS2luZDogRW5jb2Rpbmc7XG5cdCNhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5O1xuXHQjcGFyYW1zOiB1bmtub3duO1xuXG5cdC8qKlxuXHQgKiBEbyBub3QgY2FsbCB0aGlzIGRpcmVjdGx5LlxuXHQgKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEFjdG9ySGFuZGxlUmF3LlxuXHQgKlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0Y2xpZW50OiBhbnksXG5cdFx0ZHJpdmVyOiBDbGllbnREcml2ZXIsXG5cdFx0cGFyYW1zOiB1bmtub3duLFxuXHRcdGVuY29kaW5nS2luZDogRW5jb2RpbmcsXG5cdFx0YWN0b3JRdWVyeTogQWN0b3JRdWVyeSxcblx0KSB7XG5cdFx0dGhpcy4jY2xpZW50ID0gY2xpZW50O1xuXHRcdHRoaXMuI2RyaXZlciA9IGRyaXZlcjtcblx0XHR0aGlzLiNlbmNvZGluZ0tpbmQgPSBlbmNvZGluZ0tpbmQ7XG5cdFx0dGhpcy4jYWN0b3JRdWVyeSA9IGFjdG9yUXVlcnk7XG5cdFx0dGhpcy4jcGFyYW1zID0gcGFyYW1zO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGwgYSByYXcgYWN0aW9uLiBUaGlzIG1ldGhvZCBzZW5kcyBhbiBIVFRQIHJlcXVlc3QgdG8gaW52b2tlIHRoZSBuYW1lZCBhY3Rpb24uXG5cdCAqXG5cdCAqIEBzZWUge0BsaW5rIEFjdG9ySGFuZGxlfVxuXHQgKiBAdGVtcGxhdGUgQXJncyAtIFRoZSB0eXBlIG9mIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhY3Rpb24gZnVuY3Rpb24uXG5cdCAqIEB0ZW1wbGF0ZSBSZXNwb25zZSAtIFRoZSB0eXBlIG9mIHRoZSByZXNwb25zZSByZXR1cm5lZCBieSB0aGUgYWN0aW9uIGZ1bmN0aW9uLlxuXHQgKi9cblx0YXN5bmMgYWN0aW9uPFxuXHRcdEFyZ3MgZXh0ZW5kcyBBcnJheTx1bmtub3duPiA9IHVua25vd25bXSxcblx0XHRSZXNwb25zZSA9IHVua25vd24sXG5cdD4ob3B0czoge1xuXHRcdG5hbWU6IHN0cmluZztcblx0XHRhcmdzOiBBcmdzO1xuXHRcdHNpZ25hbD86IEFib3J0U2lnbmFsO1xuXHR9KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdHJldHVybiBhd2FpdCB0aGlzLiNkcml2ZXIuYWN0aW9uPEFyZ3MsIFJlc3BvbnNlPihcblx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdHRoaXMuI2FjdG9yUXVlcnksXG5cdFx0XHR0aGlzLiNlbmNvZGluZ0tpbmQsXG5cdFx0XHR0aGlzLiNwYXJhbXMsXG5cdFx0XHRvcHRzLm5hbWUsXG5cdFx0XHRvcHRzLmFyZ3MsXG5cdFx0XHR7IHNpZ25hbDogb3B0cy5zaWduYWwgfSxcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVzdGFibGlzaGVzIGEgcGVyc2lzdGVudCBjb25uZWN0aW9uIHRvIHRoZSBhY3Rvci5cblx0ICpcblx0ICogQHRlbXBsYXRlIEFEIFRoZSBhY3RvciBjbGFzcyB0aGF0IHRoaXMgY29ubmVjdGlvbiBpcyBmb3IuXG5cdCAqIEByZXR1cm5zIHtBY3RvckNvbm48QUQ+fSBBIGNvbm5lY3Rpb24gdG8gdGhlIGFjdG9yLlxuXHQgKi9cblx0Y29ubmVjdCgpOiBBY3RvckNvbm48QW55QWN0b3JEZWZpbml0aW9uPiB7XG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJlc3RhYmxpc2hpbmcgY29ubmVjdGlvbiBmcm9tIGhhbmRsZVwiLCB7XG5cdFx0XHRxdWVyeTogdGhpcy4jYWN0b3JRdWVyeSxcblx0XHR9KTtcblxuXHRcdGNvbnN0IGNvbm4gPSBuZXcgQWN0b3JDb25uUmF3KFxuXHRcdFx0dGhpcy4jY2xpZW50LFxuXHRcdFx0dGhpcy4jZHJpdmVyLFxuXHRcdFx0dGhpcy4jcGFyYW1zLFxuXHRcdFx0dGhpcy4jZW5jb2RpbmdLaW5kLFxuXHRcdFx0dGhpcy4jYWN0b3JRdWVyeSxcblx0XHQpO1xuXG5cdFx0cmV0dXJuIHRoaXMuI2NsaWVudFtDUkVBVEVfQUNUT1JfQ09OTl9QUk9YWV0oXG5cdFx0XHRjb25uLFxuXHRcdCkgYXMgQWN0b3JDb25uPEFueUFjdG9yRGVmaW5pdGlvbj47XG5cdH1cblxuXHQvKipcblx0ICogTWFrZXMgYSByYXcgSFRUUCByZXF1ZXN0IHRvIHRoZSBhY3Rvci5cblx0ICpcblx0ICogQHBhcmFtIGlucHV0IC0gVGhlIFVSTCwgcGF0aCwgb3IgUmVxdWVzdCBvYmplY3Rcblx0ICogQHBhcmFtIGluaXQgLSBTdGFuZGFyZCBmZXRjaCBSZXF1ZXN0SW5pdCBvcHRpb25zXG5cdCAqIEByZXR1cm5zIFByb21pc2U8UmVzcG9uc2U+IC0gVGhlIHJhdyBIVFRQIHJlc3BvbnNlXG5cdCAqL1xuXHRhc3luYyBmZXRjaChcblx0XHRpbnB1dDogc3RyaW5nIHwgVVJMIHwgUmVxdWVzdCxcblx0XHRpbml0PzogUmVxdWVzdEluaXQsXG5cdCk6IFByb21pc2U8UmVzcG9uc2U+IHtcblx0XHRyZXR1cm4gcmF3SHR0cEZldGNoKFxuXHRcdFx0dGhpcy4jZHJpdmVyLFxuXHRcdFx0dGhpcy4jYWN0b3JRdWVyeSxcblx0XHRcdHRoaXMuI3BhcmFtcyxcblx0XHRcdGlucHV0LFxuXHRcdFx0aW5pdCxcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSByYXcgV2ViU29ja2V0IGNvbm5lY3Rpb24gdG8gdGhlIGFjdG9yLlxuXHQgKlxuXHQgKiBAcGFyYW0gcGF0aCAtIFRoZSBwYXRoIGZvciB0aGUgV2ViU29ja2V0IGNvbm5lY3Rpb24gKGUuZy4sIFwic3RyZWFtXCIpXG5cdCAqIEBwYXJhbSBwcm90b2NvbHMgLSBPcHRpb25hbCBXZWJTb2NrZXQgc3VicHJvdG9jb2xzXG5cdCAqIEByZXR1cm5zIFdlYlNvY2tldCAtIEEgcmF3IFdlYlNvY2tldCBjb25uZWN0aW9uXG5cdCAqL1xuXHRhc3luYyB3ZWJzb2NrZXQoXG5cdFx0cGF0aD86IHN0cmluZyxcblx0XHRwcm90b2NvbHM/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0KTogUHJvbWlzZTxXZWJTb2NrZXQ+IHtcblx0XHRyZXR1cm4gcmF3V2ViU29ja2V0KFxuXHRcdFx0dGhpcy4jZHJpdmVyLFxuXHRcdFx0dGhpcy4jYWN0b3JRdWVyeSxcblx0XHRcdHRoaXMuI3BhcmFtcyxcblx0XHRcdHBhdGgsXG5cdFx0XHRwcm90b2NvbHMsXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNvbHZlcyB0aGUgYWN0b3IgdG8gZ2V0IGl0cyB1bmlxdWUgYWN0b3IgSURcblx0ICpcblx0ICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYWN0b3IncyBJRFxuXHQgKi9cblx0YXN5bmMgcmVzb2x2ZSh7IHNpZ25hbCB9OiB7IHNpZ25hbD86IEFib3J0U2lnbmFsIH0gPSB7fSk6IFByb21pc2U8c3RyaW5nPiB7XG5cdFx0aWYgKFxuXHRcdFx0XCJnZXRGb3JLZXlcIiBpbiB0aGlzLiNhY3RvclF1ZXJ5IHx8XG5cdFx0XHRcImdldE9yQ3JlYXRlRm9yS2V5XCIgaW4gdGhpcy4jYWN0b3JRdWVyeVxuXHRcdCkge1xuXHRcdFx0Ly8gVE9ETzpcblx0XHRcdGxldCBuYW1lOiBzdHJpbmc7XG5cdFx0XHRpZiAoXCJnZXRGb3JLZXlcIiBpbiB0aGlzLiNhY3RvclF1ZXJ5KSB7XG5cdFx0XHRcdG5hbWUgPSB0aGlzLiNhY3RvclF1ZXJ5LmdldEZvcktleS5uYW1lO1xuXHRcdFx0fSBlbHNlIGlmIChcImdldE9yQ3JlYXRlRm9yS2V5XCIgaW4gdGhpcy4jYWN0b3JRdWVyeSkge1xuXHRcdFx0XHRuYW1lID0gdGhpcy4jYWN0b3JRdWVyeS5nZXRPckNyZWF0ZUZvcktleS5uYW1lO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXNzZXJ0VW5yZWFjaGFibGUodGhpcy4jYWN0b3JRdWVyeSk7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGFjdG9ySWQgPSBhd2FpdCB0aGlzLiNkcml2ZXIucmVzb2x2ZUFjdG9ySWQoXG5cdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0dGhpcy4jYWN0b3JRdWVyeSxcblx0XHRcdFx0dGhpcy4jZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHR0aGlzLiNwYXJhbXMsXG5cdFx0XHRcdHNpZ25hbCA/IHsgc2lnbmFsIH0gOiB1bmRlZmluZWQsXG5cdFx0XHQpO1xuXG5cdFx0XHR0aGlzLiNhY3RvclF1ZXJ5ID0geyBnZXRGb3JJZDogeyBhY3RvcklkLCBuYW1lIH0gfTtcblxuXHRcdFx0cmV0dXJuIGFjdG9ySWQ7XG5cdFx0fSBlbHNlIGlmIChcImdldEZvcklkXCIgaW4gdGhpcy4jYWN0b3JRdWVyeSkge1xuXHRcdFx0Ly8gU0tpcCBzaW5jZSBpdCdzIGFscmVhZHkgcmVzb2x2ZWRcblx0XHRcdHJldHVybiB0aGlzLiNhY3RvclF1ZXJ5LmdldEZvcklkLmFjdG9ySWQ7XG5cdFx0fSBlbHNlIGlmIChcImNyZWF0ZVwiIGluIHRoaXMuI2FjdG9yUXVlcnkpIHtcblx0XHRcdC8vIENhbm5vdCBjcmVhdGUgYSBoYW5kbGUgd2l0aCB0aGlzIHF1ZXJ5XG5cdFx0XHRpbnZhcmlhbnQoZmFsc2UsIFwiYWN0b3JRdWVyeSBjYW5ub3QgYmUgY3JlYXRlXCIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhc3NlcnRVbnJlYWNoYWJsZSh0aGlzLiNhY3RvclF1ZXJ5KTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBTdGF0ZWxlc3MgaGFuZGxlIHRvIGEgYWN0b3IuIEFsbG93cyBjYWxsaW5nIGFjdG9yJ3MgcmVtb3RlIHByb2NlZHVyZSBjYWxscyB3aXRoIGluZmVycmVkIHR5cGVzXG4gKiB3aXRob3V0IGVzdGFibGlzaGluZyBhIHBlcnNpc3RlbnQgY29ubmVjdGlvbi5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgXG4gKiBjb25zdCByb29tID0gY2xpZW50LmdldDxDaGF0Um9vbT4oLi4uZXRjLi4uKTtcbiAqIC8vIFRoaXMgY2FsbHMgdGhlIGFjdGlvbiBuYW1lZCBgc2VuZE1lc3NhZ2VgIG9uIHRoZSBgQ2hhdFJvb21gIGFjdG9yIHdpdGhvdXQgYSBjb25uZWN0aW9uLlxuICogYXdhaXQgcm9vbS5zZW5kTWVzc2FnZSgnSGVsbG8sIHdvcmxkIScpO1xuICogYGBgXG4gKlxuICogUHJpdmF0ZSBtZXRob2RzIChlLmcuIHRob3NlIHN0YXJ0aW5nIHdpdGggYF9gKSBhcmUgYXV0b21hdGljYWxseSBleGNsdWRlZC5cbiAqXG4gKiBAdGVtcGxhdGUgQUQgVGhlIGFjdG9yIGNsYXNzIHRoYXQgdGhpcyBoYW5kbGUgaXMgZm9yLlxuICogQHNlZSB7QGxpbmsgQWN0b3JIYW5kbGVSYXd9XG4gKi9cbmV4cG9ydCB0eXBlIEFjdG9ySGFuZGxlPEFEIGV4dGVuZHMgQW55QWN0b3JEZWZpbml0aW9uPiA9IE9taXQ8XG5cdEFjdG9ySGFuZGxlUmF3LFxuXHRcImNvbm5lY3RcIlxuPiAmIHtcblx0Ly8gQWRkIHR5cGVkIHZlcnNpb24gb2YgQWN0b3JDb25uIChpbnN0ZWFkIG9mIHVzaW5nIEFueUFjdG9yRGVmaW5pdGlvbilcblx0Y29ubmVjdCgpOiBBY3RvckNvbm48QUQ+O1xuXHQvLyBSZXNvbHZlIG1ldGhvZCByZXR1cm5zIHRoZSBhY3RvciBJRFxuXHRyZXNvbHZlKCk6IFByb21pc2U8c3RyaW5nPjtcbn0gJiBBY3RvckRlZmluaXRpb25BY3Rpb25zPEFEPjtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudC9yYXctdXRpbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY2xpZW50XCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudC9yYXctdXRpbHMudHNcIjtpbXBvcnQgdHlwZSB7IEFjdG9yUXVlcnkgfSBmcm9tIFwiQC9tYW5hZ2VyL3Byb3RvY29sL3F1ZXJ5XCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudERyaXZlciB9IGZyb20gXCIuL2NsaWVudFwiO1xuXG4vKipcbiAqIFNoYXJlZCBpbXBsZW1lbnRhdGlvbiBmb3IgcmF3IEhUVFAgZmV0Y2ggcmVxdWVzdHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJhd0h0dHBGZXRjaChcblx0ZHJpdmVyOiBDbGllbnREcml2ZXIsXG5cdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdHBhcmFtczogdW5rbm93bixcblx0aW5wdXQ6IHN0cmluZyB8IFVSTCB8IFJlcXVlc3QsXG5cdGluaXQ/OiBSZXF1ZXN0SW5pdCxcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcblx0Ly8gRXh0cmFjdCBwYXRoIGFuZCBtZXJnZSBpbml0IG9wdGlvbnNcblx0bGV0IHBhdGg6IHN0cmluZztcblx0bGV0IG1lcmdlZEluaXQ6IFJlcXVlc3RJbml0ID0gaW5pdCB8fCB7fTtcblxuXHRpZiAodHlwZW9mIGlucHV0ID09PSBcInN0cmluZ1wiKSB7XG5cdFx0cGF0aCA9IGlucHV0O1xuXHR9IGVsc2UgaWYgKGlucHV0IGluc3RhbmNlb2YgVVJMKSB7XG5cdFx0cGF0aCA9IGlucHV0LnBhdGhuYW1lICsgaW5wdXQuc2VhcmNoO1xuXHR9IGVsc2UgaWYgKGlucHV0IGluc3RhbmNlb2YgUmVxdWVzdCkge1xuXHRcdC8vIEV4dHJhY3QgcGF0aCBmcm9tIFJlcXVlc3QgVVJMXG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChpbnB1dC51cmwpO1xuXHRcdHBhdGggPSB1cmwucGF0aG5hbWUgKyB1cmwuc2VhcmNoO1xuXHRcdC8vIE1lcmdlIFJlcXVlc3QgcHJvcGVydGllcyB3aXRoIGluaXRcblx0XHRjb25zdCByZXF1ZXN0SGVhZGVycyA9IG5ldyBIZWFkZXJzKGlucHV0LmhlYWRlcnMpO1xuXHRcdGNvbnN0IGluaXRIZWFkZXJzID0gbmV3IEhlYWRlcnMoaW5pdD8uaGVhZGVycyB8fCB7fSk7XG5cblx0XHQvLyBNZXJnZSBoZWFkZXJzIC0gaW5pdCBoZWFkZXJzIG92ZXJyaWRlIHJlcXVlc3QgaGVhZGVyc1xuXHRcdGNvbnN0IG1lcmdlZEhlYWRlcnMgPSBuZXcgSGVhZGVycyhyZXF1ZXN0SGVhZGVycyk7XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgaW5pdEhlYWRlcnMpIHtcblx0XHRcdG1lcmdlZEhlYWRlcnMuc2V0KGtleSwgdmFsdWUpO1xuXHRcdH1cblxuXHRcdG1lcmdlZEluaXQgPSB7XG5cdFx0XHRtZXRob2Q6IGlucHV0Lm1ldGhvZCxcblx0XHRcdGJvZHk6IGlucHV0LmJvZHksXG5cdFx0XHRtb2RlOiBpbnB1dC5tb2RlLFxuXHRcdFx0Y3JlZGVudGlhbHM6IGlucHV0LmNyZWRlbnRpYWxzLFxuXHRcdFx0cmVkaXJlY3Q6IGlucHV0LnJlZGlyZWN0LFxuXHRcdFx0cmVmZXJyZXI6IGlucHV0LnJlZmVycmVyLFxuXHRcdFx0cmVmZXJyZXJQb2xpY3k6IGlucHV0LnJlZmVycmVyUG9saWN5LFxuXHRcdFx0aW50ZWdyaXR5OiBpbnB1dC5pbnRlZ3JpdHksXG5cdFx0XHRrZWVwYWxpdmU6IGlucHV0LmtlZXBhbGl2ZSxcblx0XHRcdHNpZ25hbDogaW5wdXQuc2lnbmFsLFxuXHRcdFx0Li4ubWVyZ2VkSW5pdCwgLy8gaW5pdCBvdmVycmlkZXMgUmVxdWVzdCBwcm9wZXJ0aWVzXG5cdFx0XHRoZWFkZXJzOiBtZXJnZWRIZWFkZXJzLCAvLyBoZWFkZXJzIG11c3QgYmUgc2V0IGFmdGVyIHNwcmVhZCB0byBlbnN1cmUgcHJvcGVyIG1lcmdlXG5cdFx0fTtcblx0XHQvLyBBZGQgZHVwbGV4IGlmIGJvZHkgaXMgcHJlc2VudFxuXHRcdGlmIChtZXJnZWRJbml0LmJvZHkpIHtcblx0XHRcdChtZXJnZWRJbml0IGFzIGFueSkuZHVwbGV4ID0gXCJoYWxmXCI7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGlucHV0IHR5cGUgZm9yIGZldGNoXCIpO1xuXHR9XG5cblx0Ly8gVXNlIHRoZSBkcml2ZXIncyByYXcgSFRUUCBtZXRob2QgLSBqdXN0IHBhc3MgdGhlIHN1Yi1wYXRoXG5cdHJldHVybiBhd2FpdCBkcml2ZXIucmF3SHR0cFJlcXVlc3QoXG5cdFx0dW5kZWZpbmVkLFxuXHRcdGFjdG9yUXVlcnksXG5cdFx0Ly8gRm9yY2UgSlNPTiBzbyBpdCdzIHJlYWRhYmxlIGJ5IHRoZSB1c2VyXG5cdFx0XCJqc29uXCIsXG5cdFx0cGFyYW1zLFxuXHRcdHBhdGgsXG5cdFx0bWVyZ2VkSW5pdCxcblx0XHR1bmRlZmluZWQsXG5cdCk7XG59XG5cbi8qKlxuICogU2hhcmVkIGltcGxlbWVudGF0aW9uIGZvciByYXcgV2ViU29ja2V0IGNvbm5lY3Rpb25zXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByYXdXZWJTb2NrZXQoXG5cdGRyaXZlcjogQ2xpZW50RHJpdmVyLFxuXHRhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRwYXJhbXM6IHVua25vd24sXG5cdHBhdGg/OiBzdHJpbmcsXG5cdHByb3RvY29scz86IHN0cmluZyB8IHN0cmluZ1tdLFxuKTogUHJvbWlzZTxhbnk+IHtcblx0Ly8gVXNlIHRoZSBkcml2ZXIncyByYXcgV2ViU29ja2V0IG1ldGhvZFxuXHRyZXR1cm4gYXdhaXQgZHJpdmVyLnJhd1dlYlNvY2tldChcblx0XHR1bmRlZmluZWQsXG5cdFx0YWN0b3JRdWVyeSxcblx0XHQvLyBGb3JjZSBKU09OIHNvIGl0J3MgcmVhZGFibGUgYnkgdGhlIHVzZXJcblx0XHRcImpzb25cIixcblx0XHRwYXJhbXMsXG5cdFx0cGF0aCB8fCBcIlwiLFxuXHRcdHByb3RvY29scyxcblx0XHR1bmRlZmluZWQsXG5cdCk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvY2xpZW50LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NsaWVudFwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jbGllbnQvY2xpZW50LnRzXCI7aW1wb3J0IHR5cGUgeyBDb250ZXh0IGFzIEhvbm9Db250ZXh0IH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB0eXBlIHsgV2ViU29ja2V0IH0gZnJvbSBcIndzXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFjdG9yRGVmaW5pdGlvbiB9IGZyb20gXCJAL2FjdG9yL2RlZmluaXRpb25cIjtcbmltcG9ydCB0eXBlIHsgVHJhbnNwb3J0IH0gZnJvbSBcIkAvYWN0b3IvcHJvdG9jb2wvb2xkXCI7XG5pbXBvcnQgdHlwZSB7IEVuY29kaW5nIH0gZnJvbSBcIkAvYWN0b3IvcHJvdG9jb2wvc2VyZGVcIjtcbmltcG9ydCB0eXBlIHsgVW5pdmVyc2FsRXZlbnRTb3VyY2UgfSBmcm9tIFwiQC9jb21tb24vZXZlbnRzb3VyY2UtaW50ZXJmYWNlXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yUXVlcnkgfSBmcm9tIFwiQC9tYW5hZ2VyL3Byb3RvY29sL3F1ZXJ5XCI7XG5pbXBvcnQgdHlwZSB7IFJlZ2lzdHJ5IH0gZnJvbSBcIkAvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IFRvU2VydmVyIH0gZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yQWN0aW9uRnVuY3Rpb24gfSBmcm9tIFwiLi9hY3Rvci1jb21tb25cIjtcbmltcG9ydCB7XG5cdHR5cGUgQWN0b3JDb25uLFxuXHR0eXBlIEFjdG9yQ29ublJhdyxcblx0Q09OTkVDVF9TWU1CT0wsXG59IGZyb20gXCIuL2FjdG9yLWNvbm5cIjtcbmltcG9ydCB7IHR5cGUgQWN0b3JIYW5kbGUsIEFjdG9ySGFuZGxlUmF3IH0gZnJvbSBcIi4vYWN0b3ItaGFuZGxlXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuLyoqIEV4dHJhY3QgdGhlIGFjdG9yIHJlZ2lzdHJ5IGZyb20gdGhlIHJlZ2lzdHJ5IGRlZmluaXRpb24uICovXG5leHBvcnQgdHlwZSBFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEEgZXh0ZW5kcyBSZWdpc3RyeTxhbnk+PiA9XG5cdEEgZXh0ZW5kcyBSZWdpc3RyeTxpbmZlciBBY3RvcnM+ID8gQWN0b3JzIDogbmV2ZXI7XG5cbi8qKiBFeHRyYWN0IHRoZSByZWdpc3RyeSBkZWZpbml0aW9uIGZyb20gdGhlIGNsaWVudC4gKi9cbmV4cG9ydCB0eXBlIEV4dHJhY3RSZWdpc3RyeUZyb21DbGllbnQ8QyBleHRlbmRzIENsaWVudDxSZWdpc3RyeTx7fT4+PiA9XG5cdEMgZXh0ZW5kcyBDbGllbnQ8aW5mZXIgQT4gPyBBIDogbmV2ZXI7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGFjdG9yIGFjY2Vzc29yIHRoYXQgcHJvdmlkZXMgbWV0aG9kcyB0byBpbnRlcmFjdCB3aXRoIGEgc3BlY2lmaWMgYWN0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3JBY2Nlc3NvcjxBRCBleHRlbmRzIEFueUFjdG9yRGVmaW5pdGlvbj4ge1xuXHQvKipcblx0ICogR2V0cyBhIHN0YXRlbGVzcyBoYW5kbGUgdG8gYSBhY3RvciBieSBpdHMga2V5LCBidXQgZG9lcyBub3QgY3JlYXRlIHRoZSBhY3RvciBpZiBpdCBkb2Vzbid0IGV4aXN0LlxuXHQgKiBUaGUgYWN0b3IgbmFtZSBpcyBhdXRvbWF0aWNhbGx5IGluamVjdGVkIGZyb20gdGhlIHByb3BlcnR5IGFjY2Vzc29yLlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQUQgVGhlIGFjdG9yIGNsYXNzIHRoYXQgdGhpcyBoYW5kbGUgaXMgZm9yLlxuXHQgKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSBba2V5PVtdXSAtIFRoZSBrZXkgdG8gaWRlbnRpZnkgdGhlIGFjdG9yLiBDYW4gYmUgYSBzaW5nbGUgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXG5cdCAqIEBwYXJhbSB7R2V0V2l0aElkT3B0aW9uc30gW29wdHNdIC0gT3B0aW9ucyBmb3IgZ2V0dGluZyB0aGUgYWN0b3IuXG5cdCAqIEByZXR1cm5zIHtBY3RvckhhbmRsZTxBRD59IC0gQSBoYW5kbGUgdG8gdGhlIGFjdG9yLlxuXHQgKi9cblx0Z2V0KGtleT86IHN0cmluZyB8IHN0cmluZ1tdLCBvcHRzPzogR2V0V2l0aElkT3B0aW9ucyk6IEFjdG9ySGFuZGxlPEFEPjtcblxuXHQvKipcblx0ICogR2V0cyBhIHN0YXRlbGVzcyBoYW5kbGUgdG8gYSBhY3RvciBieSBpdHMga2V5LCBjcmVhdGluZyBpdCBpZiBuZWNlc3NhcnkuXG5cdCAqIFRoZSBhY3RvciBuYW1lIGlzIGF1dG9tYXRpY2FsbHkgaW5qZWN0ZWQgZnJvbSB0aGUgcHJvcGVydHkgYWNjZXNzb3IuXG5cdCAqXG5cdCAqIEB0ZW1wbGF0ZSBBRCBUaGUgYWN0b3IgY2xhc3MgdGhhdCB0aGlzIGhhbmRsZSBpcyBmb3IuXG5cdCAqIEBwYXJhbSB7c3RyaW5nIHwgc3RyaW5nW119IFtrZXk9W11dIC0gVGhlIGtleSB0byBpZGVudGlmeSB0aGUgYWN0b3IuIENhbiBiZSBhIHNpbmdsZSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncy5cblx0ICogQHBhcmFtIHtHZXRPcHRpb25zfSBbb3B0c10gLSBPcHRpb25zIGZvciBnZXR0aW5nIHRoZSBhY3Rvci5cblx0ICogQHJldHVybnMge0FjdG9ySGFuZGxlPEFEPn0gLSBBIGhhbmRsZSB0byB0aGUgYWN0b3IuXG5cdCAqL1xuXHRnZXRPckNyZWF0ZShcblx0XHRrZXk/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0XHRvcHRzPzogR2V0T3JDcmVhdGVPcHRpb25zLFxuXHQpOiBBY3RvckhhbmRsZTxBRD47XG5cblx0LyoqXG5cdCAqIEdldHMgYSBzdGF0ZWxlc3MgaGFuZGxlIHRvIGEgYWN0b3IgYnkgaXRzIElELlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQUQgVGhlIGFjdG9yIGNsYXNzIHRoYXQgdGhpcyBoYW5kbGUgaXMgZm9yLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gYWN0b3JJZCAtIFRoZSBJRCBvZiB0aGUgYWN0b3IuXG5cdCAqIEBwYXJhbSB7R2V0V2l0aElkT3B0aW9uc30gW29wdHNdIC0gT3B0aW9ucyBmb3IgZ2V0dGluZyB0aGUgYWN0b3IuXG5cdCAqIEByZXR1cm5zIHtBY3RvckhhbmRsZTxBRD59IC0gQSBoYW5kbGUgdG8gdGhlIGFjdG9yLlxuXHQgKi9cblx0Z2V0Rm9ySWQoYWN0b3JJZDogc3RyaW5nLCBvcHRzPzogR2V0V2l0aElkT3B0aW9ucyk6IEFjdG9ySGFuZGxlPEFEPjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBhY3RvciB3aXRoIHRoZSBuYW1lIGF1dG9tYXRpY2FsbHkgaW5qZWN0ZWQgZnJvbSB0aGUgcHJvcGVydHkgYWNjZXNzb3IsXG5cdCAqIGFuZCByZXR1cm5zIGEgc3RhdGVsZXNzIGhhbmRsZSB0byBpdCB3aXRoIHRoZSBhY3RvciBJRCByZXNvbHZlZC5cblx0ICpcblx0ICogQHRlbXBsYXRlIEFEIFRoZSBhY3RvciBjbGFzcyB0aGF0IHRoaXMgaGFuZGxlIGlzIGZvci5cblx0ICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0ga2V5IC0gVGhlIGtleSB0byBpZGVudGlmeSB0aGUgYWN0b3IuIENhbiBiZSBhIHNpbmdsZSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncy5cblx0ICogQHBhcmFtIHtDcmVhdGVPcHRpb25zfSBbb3B0c10gLSBPcHRpb25zIGZvciBjcmVhdGluZyB0aGUgYWN0b3IgKGV4Y2x1ZGluZyBuYW1lIGFuZCBrZXkpLlxuXHQgKiBAcmV0dXJucyB7UHJvbWlzZTxBY3RvckhhbmRsZTxBRD4+fSAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgaGFuZGxlIHRvIHRoZSBhY3Rvci5cblx0ICovXG5cdGNyZWF0ZShcblx0XHRrZXk/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0XHRvcHRzPzogQ3JlYXRlT3B0aW9ucyxcblx0KTogUHJvbWlzZTxBY3RvckhhbmRsZTxBRD4+O1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNvbmZpZ3VyaW5nIHRoZSBjbGllbnQuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDbGllbnRPcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpZW50T3B0aW9ucyB7XG5cdGVuY29kaW5nPzogRW5jb2Rpbmc7XG5cdHRyYW5zcG9ydD86IFRyYW5zcG9ydDtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBxdWVyeWluZyBhY3RvcnMuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBRdWVyeU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7dW5rbm93bn0gW3BhcmFtZXRlcnNdIC0gUGFyYW1ldGVycyB0byBwYXNzIHRvIHRoZSBjb25uZWN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5T3B0aW9ucyB7XG5cdC8qKiBQYXJhbWV0ZXJzIHRvIHBhc3MgdG8gdGhlIGNvbm5lY3Rpb24uICovXG5cdHBhcmFtcz86IHVua25vd247XG5cdC8qKiBTaWduYWwgdG8gYWJvcnQgdGhlIHJlcXVlc3QuICovXG5cdHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGdldHRpbmcgYSBhY3RvciBieSBJRC5cbiAqIEB0eXBlZGVmIHtRdWVyeU9wdGlvbnN9IEdldFdpdGhJZE9wdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRXaXRoSWRPcHRpb25zIGV4dGVuZHMgUXVlcnlPcHRpb25zIHt9XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgZ2V0dGluZyBhIGFjdG9yLlxuICogQHR5cGVkZWYge1F1ZXJ5T3B0aW9uc30gR2V0T3B0aW9uc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIEdldE9wdGlvbnMgZXh0ZW5kcyBRdWVyeU9wdGlvbnMge31cblxuLyoqXG4gKiBPcHRpb25zIGZvciBnZXR0aW5nIG9yIGNyZWF0aW5nIGEgYWN0b3IuXG4gKiBAdHlwZWRlZiB7UXVlcnlPcHRpb25zfSBHZXRPckNyZWF0ZU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY3JlYXRlSW5SZWdpb25dIC0gUmVnaW9uIHRvIGNyZWF0ZSB0aGUgYWN0b3IgaW4gaWYgaXQgZG9lc24ndCBleGlzdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRPckNyZWF0ZU9wdGlvbnMgZXh0ZW5kcyBRdWVyeU9wdGlvbnMge1xuXHQvKiogUmVnaW9uIHRvIGNyZWF0ZSB0aGUgYWN0b3IgaW4gaWYgaXQgZG9lc24ndCBleGlzdC4gKi9cblx0Y3JlYXRlSW5SZWdpb24/OiBzdHJpbmc7XG5cdC8qKiBJbnB1dCBkYXRhIHRvIHBhc3MgdG8gdGhlIGFjdG9yLiAqL1xuXHRjcmVhdGVXaXRoSW5wdXQ/OiB1bmtub3duO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNyZWF0aW5nIGEgYWN0b3IuXG4gKiBAdHlwZWRlZiB7UXVlcnlPcHRpb25zfSBDcmVhdGVPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3JlZ2lvbl0gLSBUaGUgcmVnaW9uIHRvIGNyZWF0ZSB0aGUgYWN0b3IgaW4uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlT3B0aW9ucyBleHRlbmRzIFF1ZXJ5T3B0aW9ucyB7XG5cdC8qKiBUaGUgcmVnaW9uIHRvIGNyZWF0ZSB0aGUgYWN0b3IgaW4uICovXG5cdHJlZ2lvbj86IHN0cmluZztcblx0LyoqIElucHV0IGRhdGEgdG8gcGFzcyB0byB0aGUgYWN0b3IuICovXG5cdGlucHV0PzogdW5rbm93bjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgcmVnaW9uIHRvIGNvbm5lY3QgdG8uXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWdpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBpZCAtIFRoZSByZWdpb24gSUQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbmFtZSAtIFRoZSByZWdpb24gbmFtZS5cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9lZGdlfEVkZ2UgTmV0d29ya2luZ31cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9yZWdpb25zfEF2YWlsYWJsZSBSZWdpb25zfVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvbiB7XG5cdC8qKlxuXHQgKiBUaGUgcmVnaW9uIHNsdWcuXG5cdCAqL1xuXHRpZDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgaHVtYW4tZnJpZW5kbHkgcmVnaW9uIG5hbWUuXG5cdCAqL1xuXHRuYW1lOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBBQ1RPUl9DT05OU19TWU1CT0wgPSBTeW1ib2woXCJhY3RvckNvbm5zXCIpO1xuZXhwb3J0IGNvbnN0IENSRUFURV9BQ1RPUl9DT05OX1BST1hZID0gU3ltYm9sKFwiY3JlYXRlQWN0b3JDb25uUHJveHlcIik7XG5leHBvcnQgY29uc3QgVFJBTlNQT1JUX1NZTUJPTCA9IFN5bWJvbChcInRyYW5zcG9ydFwiKTtcblxuZXhwb3J0IGludGVyZmFjZSBDbGllbnREcml2ZXIge1xuXHRhY3Rpb248QXJncyBleHRlbmRzIEFycmF5PHVua25vd24+ID0gdW5rbm93bltdLCBSZXNwb25zZSA9IHVua25vd24+KFxuXHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRuYW1lOiBzdHJpbmcsXG5cdFx0YXJnczogQXJncyxcblx0XHRvcHRzOiB7IHNpZ25hbD86IEFib3J0U2lnbmFsIH0gfCB1bmRlZmluZWQsXG5cdCk6IFByb21pc2U8UmVzcG9uc2U+O1xuXHRyZXNvbHZlQWN0b3JJZChcblx0XHRjOiBIb25vQ29udGV4dCB8IHVuZGVmaW5lZCxcblx0XHRhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRcdGVuY29kaW5nS2luZDogRW5jb2RpbmcsXG5cdFx0cGFyYW1zOiB1bmtub3duLFxuXHRcdG9wdHM6IHsgc2lnbmFsPzogQWJvcnRTaWduYWwgfSB8IHVuZGVmaW5lZCxcblx0KTogUHJvbWlzZTxzdHJpbmc+O1xuXHRjb25uZWN0V2ViU29ja2V0KFxuXHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0ZW5jb2RpbmdLaW5kOiBFbmNvZGluZyxcblx0XHRwYXJhbXM6IHVua25vd24sXG5cdFx0b3B0czogeyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9IHwgdW5kZWZpbmVkLFxuXHQpOiBQcm9taXNlPFdlYlNvY2tldD47XG5cdGNvbm5lY3RTc2UoXG5cdFx0YzogSG9ub0NvbnRleHQgfCB1bmRlZmluZWQsXG5cdFx0YWN0b3JRdWVyeTogQWN0b3JRdWVyeSxcblx0XHRlbmNvZGluZ0tpbmQ6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRvcHRzOiB7IHNpZ25hbD86IEFib3J0U2lnbmFsIH0gfCB1bmRlZmluZWQsXG5cdCk6IFByb21pc2U8VW5pdmVyc2FsRXZlbnRTb3VyY2U+O1xuXHRzZW5kSHR0cE1lc3NhZ2UoXG5cdFx0YzogSG9ub0NvbnRleHQgfCB1bmRlZmluZWQsXG5cdFx0YWN0b3JJZDogc3RyaW5nLFxuXHRcdGVuY29kaW5nOiBFbmNvZGluZyxcblx0XHRjb25uZWN0aW9uSWQ6IHN0cmluZyxcblx0XHRjb25uZWN0aW9uVG9rZW46IHN0cmluZyxcblx0XHRtZXNzYWdlOiBUb1NlcnZlcixcblx0XHRvcHRzOiB7IHNpZ25hbD86IEFib3J0U2lnbmFsIH0gfCB1bmRlZmluZWQsXG5cdCk6IFByb21pc2U8dm9pZD47XG5cdHJhd0h0dHBSZXF1ZXN0KFxuXHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0aW5pdDogUmVxdWVzdEluaXQsXG5cdFx0b3B0czogeyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9IHwgdW5kZWZpbmVkLFxuXHQpOiBQcm9taXNlPFJlc3BvbnNlPjtcblx0cmF3V2ViU29ja2V0KFxuXHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0cHJvdG9jb2xzOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZCxcblx0XHRvcHRzOiB7IHNpZ25hbD86IEFib3J0U2lnbmFsIH0gfCB1bmRlZmluZWQsXG5cdCk6IFByb21pc2U8V2ViU29ja2V0Pjtcbn1cblxuLyoqXG4gKiBDbGllbnQgZm9yIG1hbmFnaW5nICYgY29ubmVjdGluZyB0byBhY3RvcnMuXG4gKlxuICogQHRlbXBsYXRlIEEgVGhlIGFjdG9ycyBtYXAgdHlwZSB0aGF0IGRlZmluZXMgdGhlIGF2YWlsYWJsZSBhY3RvcnMuXG4gKiBAc2VlIHtAbGluayBodHRwczovL3JpdmV0LmdnL2RvY3MvbWFuYWdlfENyZWF0ZSAmIE1hbmFnZSBBY3RvcnN9XG4gKi9cbmV4cG9ydCBjbGFzcyBDbGllbnRSYXcge1xuXHQjZGlzcG9zZWQgPSBmYWxzZTtcblxuXHRbQUNUT1JfQ09OTlNfU1lNQk9MXSA9IG5ldyBTZXQ8QWN0b3JDb25uUmF3PigpO1xuXG5cdCNkcml2ZXI6IENsaWVudERyaXZlcjtcblx0I2VuY29kaW5nS2luZDogRW5jb2Rpbmc7XG5cdFtUUkFOU1BPUlRfU1lNQk9MXTogVHJhbnNwb3J0O1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIENsaWVudC5cblx0ICpcblx0ICogQHBhcmFtIHtzdHJpbmd9IG1hbmFnZXJFbmRwb2ludCAtIFRoZSBtYW5hZ2VyIGVuZHBvaW50LiBTZWUge0BsaW5rIGh0dHBzOi8vcml2ZXQuZ2cvZG9jcy9zZXR1cHxJbml0aWFsIFNldHVwfSBmb3IgaW5zdHJ1Y3Rpb25zIG9uIGdldHRpbmcgdGhlIG1hbmFnZXIgZW5kcG9pbnQuXG5cdCAqIEBwYXJhbSB7Q2xpZW50T3B0aW9uc30gW29wdHNdIC0gT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgdGhlIGNsaWVudC5cblx0ICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9yaXZldC5nZy9kb2NzL3NldHVwfEluaXRpYWwgU2V0dXB9XG5cdCAqL1xuXHRwdWJsaWMgY29uc3RydWN0b3IoZHJpdmVyOiBDbGllbnREcml2ZXIsIG9wdHM/OiBDbGllbnRPcHRpb25zKSB7XG5cdFx0dGhpcy4jZHJpdmVyID0gZHJpdmVyO1xuXG5cdFx0dGhpcy4jZW5jb2RpbmdLaW5kID0gb3B0cz8uZW5jb2RpbmcgPz8gXCJiYXJlXCI7XG5cdFx0dGhpc1tUUkFOU1BPUlRfU1lNQk9MXSA9IG9wdHM/LnRyYW5zcG9ydCA/PyBcIndlYnNvY2tldFwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYSBzdGF0ZWxlc3MgaGFuZGxlIHRvIGEgYWN0b3IgYnkgaXRzIElELlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQUQgVGhlIGFjdG9yIGNsYXNzIHRoYXQgdGhpcyBoYW5kbGUgaXMgZm9yLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBhY3Rvci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGFjdG9ySWQgLSBUaGUgSUQgb2YgdGhlIGFjdG9yLlxuXHQgKiBAcGFyYW0ge0dldFdpdGhJZE9wdGlvbnN9IFtvcHRzXSAtIE9wdGlvbnMgZm9yIGdldHRpbmcgdGhlIGFjdG9yLlxuXHQgKiBAcmV0dXJucyB7QWN0b3JIYW5kbGU8QUQ+fSAtIEEgaGFuZGxlIHRvIHRoZSBhY3Rvci5cblx0ICovXG5cdGdldEZvcklkPEFEIGV4dGVuZHMgQW55QWN0b3JEZWZpbml0aW9uPihcblx0XHRuYW1lOiBzdHJpbmcsXG5cdFx0YWN0b3JJZDogc3RyaW5nLFxuXHRcdG9wdHM/OiBHZXRXaXRoSWRPcHRpb25zLFxuXHQpOiBBY3RvckhhbmRsZTxBRD4ge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZ2V0IGhhbmRsZSB0byBhY3RvciB3aXRoIGlkXCIsIHtcblx0XHRcdG5hbWUsXG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0cGFyYW1zOiBvcHRzPy5wYXJhbXMsXG5cdFx0fSk7XG5cblx0XHRjb25zdCBhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5ID0ge1xuXHRcdFx0Z2V0Rm9ySWQ6IHtcblx0XHRcdFx0bmFtZSxcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdH0sXG5cdFx0fTtcblxuXHRcdGNvbnN0IGhhbmRsZSA9IHRoaXMuI2NyZWF0ZUhhbmRsZShvcHRzPy5wYXJhbXMsIGFjdG9yUXVlcnkpO1xuXHRcdHJldHVybiBjcmVhdGVBY3RvclByb3h5KGhhbmRsZSkgYXMgQWN0b3JIYW5kbGU8QUQ+O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYSBzdGF0ZWxlc3MgaGFuZGxlIHRvIGEgYWN0b3IgYnkgaXRzIGtleSwgYnV0IGRvZXMgbm90IGNyZWF0ZSB0aGUgYWN0b3IgaWYgaXQgZG9lc24ndCBleGlzdC5cblx0ICpcblx0ICogQHRlbXBsYXRlIEFEIFRoZSBhY3RvciBjbGFzcyB0aGF0IHRoaXMgaGFuZGxlIGlzIGZvci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgYWN0b3IuXG5cdCAqIEBwYXJhbSB7c3RyaW5nIHwgc3RyaW5nW119IFtrZXk9W11dIC0gVGhlIGtleSB0byBpZGVudGlmeSB0aGUgYWN0b3IuIENhbiBiZSBhIHNpbmdsZSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncy5cblx0ICogQHBhcmFtIHtHZXRXaXRoSWRPcHRpb25zfSBbb3B0c10gLSBPcHRpb25zIGZvciBnZXR0aW5nIHRoZSBhY3Rvci5cblx0ICogQHJldHVybnMge0FjdG9ySGFuZGxlPEFEPn0gLSBBIGhhbmRsZSB0byB0aGUgYWN0b3IuXG5cdCAqL1xuXHRnZXQ8QUQgZXh0ZW5kcyBBbnlBY3RvckRlZmluaXRpb24+KFxuXHRcdG5hbWU6IHN0cmluZyxcblx0XHRrZXk/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0XHRvcHRzPzogR2V0V2l0aElkT3B0aW9ucyxcblx0KTogQWN0b3JIYW5kbGU8QUQ+IHtcblx0XHQvLyBDb252ZXJ0IHN0cmluZyB0byBhcnJheSBvZiBzdHJpbmdzXG5cdFx0Y29uc3Qga2V5QXJyYXk6IHN0cmluZ1tdID0gdHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIiA/IFtrZXldIDoga2V5IHx8IFtdO1xuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJnZXQgaGFuZGxlIHRvIGFjdG9yXCIsIHtcblx0XHRcdG5hbWUsXG5cdFx0XHRrZXk6IGtleUFycmF5LFxuXHRcdFx0cGFyYW1ldGVyczogb3B0cz8ucGFyYW1zLFxuXHRcdH0pO1xuXG5cdFx0Y29uc3QgYWN0b3JRdWVyeTogQWN0b3JRdWVyeSA9IHtcblx0XHRcdGdldEZvcktleToge1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRrZXk6IGtleUFycmF5LFxuXHRcdFx0fSxcblx0XHR9O1xuXG5cdFx0Y29uc3QgaGFuZGxlID0gdGhpcy4jY3JlYXRlSGFuZGxlKG9wdHM/LnBhcmFtcywgYWN0b3JRdWVyeSk7XG5cdFx0cmV0dXJuIGNyZWF0ZUFjdG9yUHJveHkoaGFuZGxlKSBhcyBBY3RvckhhbmRsZTxBRD47XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBhIHN0YXRlbGVzcyBoYW5kbGUgdG8gYSBhY3RvciBieSBpdHMga2V5LCBjcmVhdGluZyBpdCBpZiBuZWNlc3NhcnkuXG5cdCAqXG5cdCAqIEB0ZW1wbGF0ZSBBRCBUaGUgYWN0b3IgY2xhc3MgdGhhdCB0aGlzIGhhbmRsZSBpcyBmb3IuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGFjdG9yLlxuXHQgKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSBba2V5PVtdXSAtIFRoZSBrZXkgdG8gaWRlbnRpZnkgdGhlIGFjdG9yLiBDYW4gYmUgYSBzaW5nbGUgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXG5cdCAqIEBwYXJhbSB7R2V0T3B0aW9uc30gW29wdHNdIC0gT3B0aW9ucyBmb3IgZ2V0dGluZyB0aGUgYWN0b3IuXG5cdCAqIEByZXR1cm5zIHtBY3RvckhhbmRsZTxBRD59IC0gQSBoYW5kbGUgdG8gdGhlIGFjdG9yLlxuXHQgKi9cblx0Z2V0T3JDcmVhdGU8QUQgZXh0ZW5kcyBBbnlBY3RvckRlZmluaXRpb24+KFxuXHRcdG5hbWU6IHN0cmluZyxcblx0XHRrZXk/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0XHRvcHRzPzogR2V0T3JDcmVhdGVPcHRpb25zLFxuXHQpOiBBY3RvckhhbmRsZTxBRD4ge1xuXHRcdC8vIENvbnZlcnQgc3RyaW5nIHRvIGFycmF5IG9mIHN0cmluZ3Ncblx0XHRjb25zdCBrZXlBcnJheTogc3RyaW5nW10gPSB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiID8gW2tleV0gOiBrZXkgfHwgW107XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImdldCBvciBjcmVhdGUgaGFuZGxlIHRvIGFjdG9yXCIsIHtcblx0XHRcdG5hbWUsXG5cdFx0XHRrZXk6IGtleUFycmF5LFxuXHRcdFx0cGFyYW1ldGVyczogb3B0cz8ucGFyYW1zLFxuXHRcdFx0Y3JlYXRlSW5SZWdpb246IG9wdHM/LmNyZWF0ZUluUmVnaW9uLFxuXHRcdH0pO1xuXG5cdFx0Y29uc3QgYWN0b3JRdWVyeTogQWN0b3JRdWVyeSA9IHtcblx0XHRcdGdldE9yQ3JlYXRlRm9yS2V5OiB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGtleToga2V5QXJyYXksXG5cdFx0XHRcdGlucHV0OiBvcHRzPy5jcmVhdGVXaXRoSW5wdXQsXG5cdFx0XHRcdHJlZ2lvbjogb3B0cz8uY3JlYXRlSW5SZWdpb24sXG5cdFx0XHR9LFxuXHRcdH07XG5cblx0XHRjb25zdCBoYW5kbGUgPSB0aGlzLiNjcmVhdGVIYW5kbGUob3B0cz8ucGFyYW1zLCBhY3RvclF1ZXJ5KTtcblx0XHRyZXR1cm4gY3JlYXRlQWN0b3JQcm94eShoYW5kbGUpIGFzIEFjdG9ySGFuZGxlPEFEPjtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IGFjdG9yIHdpdGggdGhlIHByb3ZpZGVkIGtleSBhbmQgcmV0dXJucyBhIHN0YXRlbGVzcyBoYW5kbGUgdG8gaXQuXG5cdCAqIFJlc29sdmVzIHRoZSBhY3RvciBJRCBhbmQgcmV0dXJucyBhIGhhbmRsZSB3aXRoIGdldEZvcklkIHF1ZXJ5LlxuXHQgKlxuXHQgKiBAdGVtcGxhdGUgQUQgVGhlIGFjdG9yIGNsYXNzIHRoYXQgdGhpcyBoYW5kbGUgaXMgZm9yLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBhY3Rvci5cblx0ICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0ga2V5IC0gVGhlIGtleSB0byBpZGVudGlmeSB0aGUgYWN0b3IuIENhbiBiZSBhIHNpbmdsZSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncy5cblx0ICogQHBhcmFtIHtDcmVhdGVPcHRpb25zfSBbb3B0c10gLSBPcHRpb25zIGZvciBjcmVhdGluZyB0aGUgYWN0b3IgKGV4Y2x1ZGluZyBuYW1lIGFuZCBrZXkpLlxuXHQgKiBAcmV0dXJucyB7UHJvbWlzZTxBY3RvckhhbmRsZTxBRD4+fSAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgaGFuZGxlIHRvIHRoZSBhY3Rvci5cblx0ICovXG5cdGFzeW5jIGNyZWF0ZTxBRCBleHRlbmRzIEFueUFjdG9yRGVmaW5pdGlvbj4oXG5cdFx0bmFtZTogc3RyaW5nLFxuXHRcdGtleT86IHN0cmluZyB8IHN0cmluZ1tdLFxuXHRcdG9wdHM/OiBDcmVhdGVPcHRpb25zLFxuXHQpOiBQcm9taXNlPEFjdG9ySGFuZGxlPEFEPj4ge1xuXHRcdC8vIENvbnZlcnQgc3RyaW5nIHRvIGFycmF5IG9mIHN0cmluZ3Ncblx0XHRjb25zdCBrZXlBcnJheTogc3RyaW5nW10gPSB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiID8gW2tleV0gOiBrZXkgfHwgW107XG5cblx0XHRjb25zdCBjcmVhdGVRdWVyeSA9IHtcblx0XHRcdGNyZWF0ZToge1xuXHRcdFx0XHQuLi5vcHRzLFxuXHRcdFx0XHQvLyBEbyB0aGVzZSBsYXN0IHRvIG92ZXJyaWRlIGBvcHRzYFxuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRrZXk6IGtleUFycmF5LFxuXHRcdFx0fSxcblx0XHR9IHNhdGlzZmllcyBBY3RvclF1ZXJ5O1xuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJjcmVhdGUgYWN0b3IgaGFuZGxlXCIsIHtcblx0XHRcdG5hbWUsXG5cdFx0XHRrZXk6IGtleUFycmF5LFxuXHRcdFx0cGFyYW1ldGVyczogb3B0cz8ucGFyYW1zLFxuXHRcdFx0Y3JlYXRlOiBjcmVhdGVRdWVyeS5jcmVhdGUsXG5cdFx0fSk7XG5cblx0XHQvLyBDcmVhdGUgdGhlIGFjdG9yXG5cdFx0Y29uc3QgYWN0b3JJZCA9IGF3YWl0IHRoaXMuI2RyaXZlci5yZXNvbHZlQWN0b3JJZChcblx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdGNyZWF0ZVF1ZXJ5LFxuXHRcdFx0dGhpcy4jZW5jb2RpbmdLaW5kLFxuXHRcdFx0b3B0cz8ucGFyYW1zLFxuXHRcdFx0b3B0cz8uc2lnbmFsID8geyBzaWduYWw6IG9wdHMuc2lnbmFsIH0gOiB1bmRlZmluZWQsXG5cdFx0KTtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImNyZWF0ZWQgYWN0b3Igd2l0aCBJRFwiLCB7XG5cdFx0XHRuYW1lLFxuXHRcdFx0a2V5OiBrZXlBcnJheSxcblx0XHRcdGFjdG9ySWQsXG5cdFx0fSk7XG5cblx0XHQvLyBDcmVhdGUgaGFuZGxlIHdpdGggYWN0b3IgSURcblx0XHRjb25zdCBnZXRGb3JJZFF1ZXJ5ID0ge1xuXHRcdFx0Z2V0Rm9ySWQ6IHtcblx0XHRcdFx0bmFtZSxcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdH0sXG5cdFx0fSBzYXRpc2ZpZXMgQWN0b3JRdWVyeTtcblx0XHRjb25zdCBoYW5kbGUgPSB0aGlzLiNjcmVhdGVIYW5kbGUob3B0cz8ucGFyYW1zLCBnZXRGb3JJZFF1ZXJ5KTtcblxuXHRcdGNvbnN0IHByb3h5ID0gY3JlYXRlQWN0b3JQcm94eShoYW5kbGUpIGFzIEFjdG9ySGFuZGxlPEFEPjtcblxuXHRcdHJldHVybiBwcm94eTtcblx0fVxuXG5cdCNjcmVhdGVIYW5kbGUocGFyYW1zOiB1bmtub3duLCBhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5KTogQWN0b3JIYW5kbGVSYXcge1xuXHRcdHJldHVybiBuZXcgQWN0b3JIYW5kbGVSYXcoXG5cdFx0XHR0aGlzLFxuXHRcdFx0dGhpcy4jZHJpdmVyLFxuXHRcdFx0cGFyYW1zLFxuXHRcdFx0dGhpcy4jZW5jb2RpbmdLaW5kLFxuXHRcdFx0YWN0b3JRdWVyeSxcblx0XHQpO1xuXHR9XG5cblx0W0NSRUFURV9BQ1RPUl9DT05OX1BST1hZXTxBRCBleHRlbmRzIEFueUFjdG9yRGVmaW5pdGlvbj4oXG5cdFx0Y29ubjogQWN0b3JDb25uUmF3LFxuXHQpOiBBY3RvckNvbm48QUQ+IHtcblx0XHQvLyBTYXZlIHRvIGNvbm5lY3Rpb24gbGlzdFxuXHRcdHRoaXNbQUNUT1JfQ09OTlNfU1lNQk9MXS5hZGQoY29ubik7XG5cblx0XHQvLyBTdGFydCBjb25uZWN0aW9uXG5cdFx0Y29ubltDT05ORUNUX1NZTUJPTF0oKTtcblxuXHRcdHJldHVybiBjcmVhdGVBY3RvclByb3h5KGNvbm4pIGFzIEFjdG9yQ29ubjxBRD47XG5cdH1cblxuXHQvKipcblx0ICogRGlzY29ubmVjdHMgZnJvbSBhbGwgYWN0b3JzLlxuXHQgKlxuXHQgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgY29ubmVjdGlvbnMgYXJlIGNsb3NlZC5cblx0ICovXG5cdGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuI2Rpc3Bvc2VkKSB7XG5cdFx0XHRsb2dnZXIoKS53YXJuKFwiY2xpZW50IGFscmVhZHkgZGlzY29ubmVjdGVkXCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLiNkaXNwb3NlZCA9IHRydWU7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImRpc3Bvc2luZyBjbGllbnRcIik7XG5cblx0XHRjb25zdCBkaXNwb3NlUHJvbWlzZXMgPSBbXTtcblxuXHRcdC8vIERpc3Bvc2UgYWxsIGNvbm5lY3Rpb25zXG5cdFx0Zm9yIChjb25zdCBjb25uIG9mIHRoaXNbQUNUT1JfQ09OTlNfU1lNQk9MXS52YWx1ZXMoKSkge1xuXHRcdFx0ZGlzcG9zZVByb21pc2VzLnB1c2goY29ubi5kaXNwb3NlKCkpO1xuXHRcdH1cblxuXHRcdGF3YWl0IFByb21pc2UuYWxsKGRpc3Bvc2VQcm9taXNlcyk7XG5cdH1cbn1cblxuLyoqXG4gKiBDbGllbnQgdHlwZSB3aXRoIGFjdG9yIGFjY2Vzc29ycy5cbiAqIFRoaXMgYWRkcyBwcm9wZXJ0eSBhY2Nlc3NvcnMgZm9yIGFjdG9yIG5hbWVzIHRvIHRoZSBDbGllbnRSYXcgYmFzZSBjbGFzcy5cbiAqXG4gKiBAdGVtcGxhdGUgQSBUaGUgYWN0b3IgcmVnaXN0cnkgdHlwZS5cbiAqL1xuZXhwb3J0IHR5cGUgQ2xpZW50PEEgZXh0ZW5kcyBSZWdpc3RyeTxhbnk+PiA9IENsaWVudFJhdyAmIHtcblx0W0sgaW4ga2V5b2YgRXh0cmFjdEFjdG9yc0Zyb21SZWdpc3RyeTxBPl06IEFjdG9yQWNjZXNzb3I8XG5cdFx0RXh0cmFjdEFjdG9yc0Zyb21SZWdpc3RyeTxBPltLXVxuXHQ+O1xufTtcblxuZXhwb3J0IHR5cGUgQW55Q2xpZW50ID0gQ2xpZW50PFJlZ2lzdHJ5PGFueT4+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2xpZW50V2l0aERyaXZlcjxBIGV4dGVuZHMgUmVnaXN0cnk8YW55Pj4oXG5cdGRyaXZlcjogQ2xpZW50RHJpdmVyLFxuXHRvcHRzPzogQ2xpZW50T3B0aW9ucyxcbik6IENsaWVudDxBPiB7XG5cdGNvbnN0IGNsaWVudCA9IG5ldyBDbGllbnRSYXcoZHJpdmVyLCBvcHRzKTtcblxuXHQvLyBDcmVhdGUgcHJveHkgZm9yIGFjY2Vzc2luZyBhY3RvcnMgYnkgbmFtZVxuXHRyZXR1cm4gbmV3IFByb3h5KGNsaWVudCwge1xuXHRcdGdldDogKHRhcmdldDogQ2xpZW50UmF3LCBwcm9wOiBzdHJpbmcgfCBzeW1ib2wsIHJlY2VpdmVyOiB1bmtub3duKSA9PiB7XG5cdFx0XHQvLyBHZXQgdGhlIHJlYWwgcHJvcGVydHkgaWYgaXQgZXhpc3RzXG5cdFx0XHRpZiAodHlwZW9mIHByb3AgPT09IFwic3ltYm9sXCIgfHwgcHJvcCBpbiB0YXJnZXQpIHtcblx0XHRcdFx0Y29uc3QgdmFsdWUgPSBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcblx0XHRcdFx0Ly8gUHJlc2VydmUgbWV0aG9kIGJpbmRpbmdcblx0XHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHZhbHVlLmJpbmQodGFyZ2V0KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEhhbmRsZSBhY3RvciBhY2Nlc3NvciBmb3Igc3RyaW5nIHByb3BlcnRpZXMgKGFjdG9yIG5hbWVzKVxuXHRcdFx0aWYgKHR5cGVvZiBwcm9wID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdC8vIFJldHVybiBhY3RvciBhY2Nlc3NvciBvYmplY3Qgd2l0aCBtZXRob2RzXG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0Ly8gSGFuZGxlIG1ldGhvZHMgKHN0YXRlbGVzcyBhY3Rpb24pXG5cdFx0XHRcdFx0Z2V0OiAoXG5cdFx0XHRcdFx0XHRrZXk/OiBzdHJpbmcgfCBzdHJpbmdbXSxcblx0XHRcdFx0XHRcdG9wdHM/OiBHZXRXaXRoSWRPcHRpb25zLFxuXHRcdFx0XHRcdCk6IEFjdG9ySGFuZGxlPEV4dHJhY3RBY3RvcnNGcm9tUmVnaXN0cnk8QT5bdHlwZW9mIHByb3BdPiA9PiB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdGFyZ2V0LmdldDxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT4oXG5cdFx0XHRcdFx0XHRcdHByb3AsXG5cdFx0XHRcdFx0XHRcdGtleSxcblx0XHRcdFx0XHRcdFx0b3B0cyxcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRnZXRPckNyZWF0ZTogKFxuXHRcdFx0XHRcdFx0a2V5Pzogc3RyaW5nIHwgc3RyaW5nW10sXG5cdFx0XHRcdFx0XHRvcHRzPzogR2V0T3B0aW9ucyxcblx0XHRcdFx0XHQpOiBBY3RvckhhbmRsZTxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT4gPT4ge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRhcmdldC5nZXRPckNyZWF0ZTxcblx0XHRcdFx0XHRcdFx0RXh0cmFjdEFjdG9yc0Zyb21SZWdpc3RyeTxBPlt0eXBlb2YgcHJvcF1cblx0XHRcdFx0XHRcdD4ocHJvcCwga2V5LCBvcHRzKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGdldEZvcklkOiAoXG5cdFx0XHRcdFx0XHRhY3RvcklkOiBzdHJpbmcsXG5cdFx0XHRcdFx0XHRvcHRzPzogR2V0V2l0aElkT3B0aW9ucyxcblx0XHRcdFx0XHQpOiBBY3RvckhhbmRsZTxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT4gPT4ge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRhcmdldC5nZXRGb3JJZDxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT4oXG5cdFx0XHRcdFx0XHRcdHByb3AsXG5cdFx0XHRcdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdFx0XHRcdG9wdHMsXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0Y3JlYXRlOiBhc3luYyAoXG5cdFx0XHRcdFx0XHRrZXk6IHN0cmluZyB8IHN0cmluZ1tdLFxuXHRcdFx0XHRcdFx0b3B0czogQ3JlYXRlT3B0aW9ucyA9IHt9LFxuXHRcdFx0XHRcdCk6IFByb21pc2U8XG5cdFx0XHRcdFx0XHRBY3RvckhhbmRsZTxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT5cblx0XHRcdFx0XHQ+ID0+IHtcblx0XHRcdFx0XHRcdHJldHVybiBhd2FpdCB0YXJnZXQuY3JlYXRlPFxuXHRcdFx0XHRcdFx0XHRFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXVxuXHRcdFx0XHRcdFx0Pihwcm9wLCBrZXksIG9wdHMpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0gYXMgQWN0b3JBY2Nlc3NvcjxFeHRyYWN0QWN0b3JzRnJvbVJlZ2lzdHJ5PEE+W3R5cGVvZiBwcm9wXT47XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0fSkgYXMgQ2xpZW50PEE+O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBwcm94eSBmb3IgYSBhY3RvciB0aGF0IGVuYWJsZXMgY2FsbGluZyBhY3Rpb25zIHdpdGhvdXQgZXhwbGljaXRseSB1c2luZyBgLmFjdGlvbmAuXG4gKiovXG5mdW5jdGlvbiBjcmVhdGVBY3RvclByb3h5PEFEIGV4dGVuZHMgQW55QWN0b3JEZWZpbml0aW9uPihcblx0aGFuZGxlOiBBY3RvckhhbmRsZVJhdyB8IEFjdG9yQ29ublJhdyxcbik6IEFjdG9ySGFuZGxlPEFEPiB8IEFjdG9yQ29ubjxBRD4ge1xuXHQvLyBTdG9yZXMgcmV0dXJuZWQgYWN0aW9uIGZ1bmN0aW9ucyBmb3IgZmFzdGVyIGNhbGxzXG5cdGNvbnN0IG1ldGhvZENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIEFjdG9yQWN0aW9uRnVuY3Rpb24+KCk7XG5cdHJldHVybiBuZXcgUHJveHkoaGFuZGxlLCB7XG5cdFx0Z2V0KHRhcmdldDogQWN0b3JIYW5kbGVSYXcsIHByb3A6IHN0cmluZyB8IHN5bWJvbCwgcmVjZWl2ZXI6IHVua25vd24pIHtcblx0XHRcdC8vIEhhbmRsZSBidWlsdC1pbiBTeW1ib2wgcHJvcGVydGllc1xuXHRcdFx0aWYgKHR5cGVvZiBwcm9wID09PSBcInN5bWJvbFwiKSB7XG5cdFx0XHRcdHJldHVybiBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSGFuZGxlIGJ1aWx0LWluIFByb21pc2UgbWV0aG9kcyBhbmQgZXhpc3RpbmcgcHJvcGVydGllc1xuXHRcdFx0aWYgKHByb3AgPT09IFwiY29uc3RydWN0b3JcIiB8fCBwcm9wIGluIHRhcmdldCkge1xuXHRcdFx0XHRjb25zdCB2YWx1ZSA9IFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpO1xuXHRcdFx0XHQvLyBQcmVzZXJ2ZSBtZXRob2QgYmluZGluZ1xuXHRcdFx0XHRpZiAodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUuYmluZCh0YXJnZXQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ3JlYXRlIGFjdGlvbiBmdW5jdGlvbiB0aGF0IHByZXNlcnZlcyAndGhpcycgY29udGV4dFxuXHRcdFx0aWYgKHR5cGVvZiBwcm9wID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdC8vIElmIEpTIGlzIGF0dGVtcHRpbmcgdG8gY2FsbGluZyB0aGlzIGFzIGEgcHJvbWlzZSwgaWdub3JlIGl0XG5cdFx0XHRcdGlmIChwcm9wID09PSBcInRoZW5cIikgcmV0dXJuIHVuZGVmaW5lZDtcblxuXHRcdFx0XHRsZXQgbWV0aG9kID0gbWV0aG9kQ2FjaGUuZ2V0KHByb3ApO1xuXHRcdFx0XHRpZiAoIW1ldGhvZCkge1xuXHRcdFx0XHRcdG1ldGhvZCA9ICguLi5hcmdzOiB1bmtub3duW10pID0+IHRhcmdldC5hY3Rpb24oeyBuYW1lOiBwcm9wLCBhcmdzIH0pO1xuXHRcdFx0XHRcdG1ldGhvZENhY2hlLnNldChwcm9wLCBtZXRob2QpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBtZXRob2Q7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8vIFN1cHBvcnQgZm9yICdpbicgb3BlcmF0b3Jcblx0XHRoYXModGFyZ2V0OiBBY3RvckhhbmRsZVJhdywgcHJvcDogc3RyaW5nIHwgc3ltYm9sKSB7XG5cdFx0XHQvLyBBbGwgc3RyaW5nIHByb3BlcnRpZXMgYXJlIHBvdGVudGlhbGx5IGFjdGlvbiBmdW5jdGlvbnNcblx0XHRcdGlmICh0eXBlb2YgcHJvcCA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdC8vIEZvciBzeW1ib2xzLCBkZWZlciB0byB0aGUgdGFyZ2V0J3Mgb3duIGhhcyBiZWhhdmlvclxuXHRcdFx0cmV0dXJuIFJlZmxlY3QuaGFzKHRhcmdldCwgcHJvcCk7XG5cdFx0fSxcblxuXHRcdC8vIFN1cHBvcnQgaW5zdGFuY2VvZiBjaGVja3Ncblx0XHRnZXRQcm90b3R5cGVPZih0YXJnZXQ6IEFjdG9ySGFuZGxlUmF3KSB7XG5cdFx0XHRyZXR1cm4gUmVmbGVjdC5nZXRQcm90b3R5cGVPZih0YXJnZXQpO1xuXHRcdH0sXG5cblx0XHQvLyBQcmV2ZW50IHByb3BlcnR5IGVudW1lcmF0aW9uIG9mIG5vbi1leGlzdGVudCBhY3Rpb24gbWV0aG9kc1xuXHRcdG93bktleXModGFyZ2V0OiBBY3RvckhhbmRsZVJhdykge1xuXHRcdFx0cmV0dXJuIFJlZmxlY3Qub3duS2V5cyh0YXJnZXQpO1xuXHRcdH0sXG5cblx0XHQvLyBTdXBwb3J0IHByb3BlciBwcm9wZXJ0eSBkZXNjcmlwdG9yc1xuXHRcdGdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQ6IEFjdG9ySGFuZGxlUmF3LCBwcm9wOiBzdHJpbmcgfCBzeW1ib2wpIHtcblx0XHRcdGNvbnN0IHRhcmdldERlc2NyaXB0b3IgPSBSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIHByb3ApO1xuXHRcdFx0aWYgKHRhcmdldERlc2NyaXB0b3IpIHtcblx0XHRcdFx0cmV0dXJuIHRhcmdldERlc2NyaXB0b3I7XG5cdFx0XHR9XG5cdFx0XHRpZiAodHlwZW9mIHByb3AgPT09IFwic3RyaW5nXCIpIHtcblx0XHRcdFx0Ly8gTWFrZSBhY3Rpb24gbWV0aG9kcyBhcHBlYXIgbm9uLWVudW1lcmFibGVcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0XHRcdFx0ZW51bWVyYWJsZTogZmFsc2UsXG5cdFx0XHRcdFx0d3JpdGFibGU6IGZhbHNlLFxuXHRcdFx0XHRcdHZhbHVlOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiB0YXJnZXQuYWN0aW9uKHsgbmFtZTogcHJvcCwgYXJncyB9KSxcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0fSkgYXMgQWN0b3JIYW5kbGU8QUQ+IHwgQWN0b3JDb25uPEFEPjtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi9pbmxpbmUtd2Vic29ja2V0LWFkYXB0ZXIyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vblwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb24vaW5saW5lLXdlYnNvY2tldC1hZGFwdGVyMi50c1wiO2ltcG9ydCB7IFdTQ29udGV4dCB9IGZyb20gXCJob25vL3dzXCI7XG5pbXBvcnQgdHlwZSB7XG5cdFJpdmV0Q2xvc2VFdmVudCxcblx0Uml2ZXRFdmVudCxcblx0Uml2ZXRNZXNzYWdlRXZlbnQsXG5cdFVuaXZlcnNhbFdlYlNvY2tldCxcbn0gZnJvbSBcIkAvY29tbW9uL3dlYnNvY2tldC1pbnRlcmZhY2VcIjtcbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCIuL2xvZ1wiO1xuXG5leHBvcnQgY29uc3QgTE9HR0VSX05BTUUgPSBcImZha2UtZXZlbnQtc291cmNlMlwiO1xuXG5leHBvcnQgZnVuY3Rpb24gbG9nZ2VyKCkge1xuXHRyZXR1cm4gZ2V0TG9nZ2VyKExPR0dFUl9OQU1FKTtcbn1cblxuLy8gVE9ETzogTWVyZ2Ugd2l0aCBDb25uZWN0V2ViU29ja2V0T3V0cHV0IGludGVyZmFjZVxuZXhwb3J0IGludGVyZmFjZSBVcGdyYWRlV2ViU29ja2V0QXJncyB7XG5cdG9uT3BlbjogKGV2ZW50OiBhbnksIHdzOiBXU0NvbnRleHQpID0+IHZvaWQ7XG5cdG9uTWVzc2FnZTogKGV2ZW50OiBhbnksIHdzOiBXU0NvbnRleHQpID0+IHZvaWQ7XG5cdG9uQ2xvc2U6IChldmVudDogYW55LCB3czogV1NDb250ZXh0KSA9PiB2b2lkO1xuXHRvbkVycm9yOiAoZXJyb3I6IGFueSwgd3M6IFdTQ29udGV4dCkgPT4gdm9pZDtcbn1cblxuLy8gVE9ETzogUmVtb3ZlIGAyYCBzdWZmaXhcbi8qKlxuICogSW5saW5lV2ViU29ja2V0QWRhcHRlciBpbXBsZW1lbnRzIGEgV2ViU29ja2V0LWxpa2UgaW50ZXJmYWNlXG4gKiB0aGF0IGNvbm5lY3RzIHRvIGEgVXBncmFkZVdlYlNvY2tldEFyZ3MgaGFuZGxlclxuICovXG5leHBvcnQgY2xhc3MgSW5saW5lV2ViU29ja2V0QWRhcHRlcjIgaW1wbGVtZW50cyBVbml2ZXJzYWxXZWJTb2NrZXQge1xuXHQvLyBXZWJTb2NrZXQgcmVhZHlTdGF0ZSB2YWx1ZXNcblx0cmVhZG9ubHkgQ09OTkVDVElORyA9IDAgYXMgY29uc3Q7XG5cdHJlYWRvbmx5IE9QRU4gPSAxIGFzIGNvbnN0O1xuXHRyZWFkb25seSBDTE9TSU5HID0gMiBhcyBjb25zdDtcblx0cmVhZG9ubHkgQ0xPU0VEID0gMyBhcyBjb25zdDtcblxuXHQvLyBQcml2YXRlIHByb3BlcnRpZXNcblx0I2hhbmRsZXI6IFVwZ3JhZGVXZWJTb2NrZXRBcmdzO1xuXHQjd3NDb250ZXh0OiBXU0NvbnRleHQ7XG5cdCNyZWFkeVN0YXRlOiAwIHwgMSB8IDIgfCAzID0gMDsgLy8gU3RhcnQgaW4gQ09OTkVDVElORyBzdGF0ZVxuXHQjcXVldWVkTWVzc2FnZXM6IEFycmF5PHN0cmluZyB8IEFycmF5QnVmZmVyIHwgVWludDhBcnJheT4gPSBbXTtcblx0Ly8gRXZlbnQgYnVmZmVyaW5nIGlzIG5lZWRlZCBzaW5jZSBldmVudHMgY2FuIGJlIGZpcmVkXG5cdC8vIGJlZm9yZSBKYXZhU2NyaXB0IGhhcyBhIGNoYW5jZSB0byBhZGQgZXZlbnQgbGlzdGVuZXJzIChlLmcuIHdpdGhpbiB0aGUgc2FtZSB0aWNrKVxuXHQjYnVmZmVyZWRFdmVudHM6IEFycmF5PHtcblx0XHR0eXBlOiBzdHJpbmc7XG5cdFx0ZXZlbnQ6IGFueTtcblx0fT4gPSBbXTtcblxuXHQvLyBFdmVudCBsaXN0ZW5lcnMgd2l0aCBidWZmZXJpbmdcblx0I2V2ZW50TGlzdGVuZXJzOiBNYXA8c3RyaW5nLCAoKGV2OiBhbnkpID0+IHZvaWQpW10+ID0gbmV3IE1hcCgpO1xuXG5cdGNvbnN0cnVjdG9yKGhhbmRsZXI6IFVwZ3JhZGVXZWJTb2NrZXRBcmdzKSB7XG5cdFx0dGhpcy4jaGFuZGxlciA9IGhhbmRsZXI7XG5cblx0XHQvLyBDcmVhdGUgYSBmYWtlIFdTQ29udGV4dCB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG5cdFx0dGhpcy4jd3NDb250ZXh0ID0gbmV3IFdTQ29udGV4dCh7XG5cdFx0XHRyYXc6IHRoaXMsXG5cdFx0XHRzZW5kOiAoZGF0YTogc3RyaW5nIHwgQXJyYXlCdWZmZXIgfCBVaW50OEFycmF5KSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiV1NDb250ZXh0LnNlbmQgY2FsbGVkXCIpO1xuXHRcdFx0XHR0aGlzLiNoYW5kbGVNZXNzYWdlKGRhdGEpO1xuXHRcdFx0fSxcblx0XHRcdGNsb3NlOiAoY29kZT86IG51bWJlciwgcmVhc29uPzogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiV1NDb250ZXh0LmNsb3NlIGNhbGxlZFwiLCB7IGNvZGUsIHJlYXNvbiB9KTtcblx0XHRcdFx0dGhpcy4jaGFuZGxlQ2xvc2UoY29kZSB8fCAxMDAwLCByZWFzb24gfHwgXCJcIik7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGUgdG8gMSAoT1BFTikgc2luY2UgaGFuZGxlcnMgZXhwZWN0IGFuIG9wZW4gY29ubmVjdGlvblxuXHRcdFx0cmVhZHlTdGF0ZTogMSxcblx0XHR9KTtcblxuXHRcdC8vIEluaXRpYWxpemUgdGhlIGNvbm5lY3Rpb25cblx0XHR0aGlzLiNpbml0aWFsaXplKCk7XG5cdH1cblxuXHRnZXQgcmVhZHlTdGF0ZSgpOiAwIHwgMSB8IDIgfCAzIHtcblx0XHRyZXR1cm4gdGhpcy4jcmVhZHlTdGF0ZTtcblx0fVxuXG5cdGdldCBiaW5hcnlUeXBlKCk6IFwiYXJyYXlidWZmZXJcIiB8IFwiYmxvYlwiIHtcblx0XHRyZXR1cm4gXCJhcnJheWJ1ZmZlclwiO1xuXHR9XG5cblx0c2V0IGJpbmFyeVR5cGUodmFsdWU6IFwiYXJyYXlidWZmZXJcIiB8IFwiYmxvYlwiKSB7XG5cdFx0Ly8gSWdub3JlZCBmb3Igbm93IC0gYWx3YXlzIHVzZSBhcnJheWJ1ZmZlclxuXHR9XG5cblx0Z2V0IGJ1ZmZlcmVkQW1vdW50KCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIDA7IC8vIE5vdCB0cmFja2VkIGluIElubGluZVdlYlNvY2tldEFkYXB0ZXJcblx0fVxuXG5cdGdldCBleHRlbnNpb25zKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiXCI7IC8vIE5vdCBhdmFpbGFibGUgaW4gSW5saW5lV2ViU29ja2V0QWRhcHRlclxuXHR9XG5cblx0Z2V0IHByb3RvY29sKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiXCI7IC8vIE5vdCBhdmFpbGFibGUgaW4gSW5saW5lV2ViU29ja2V0QWRhcHRlclxuXHR9XG5cblx0Z2V0IHVybCgpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcIlwiOyAvLyBOb3QgYXZhaWxhYmxlIGluIElubGluZVdlYlNvY2tldEFkYXB0ZXJcblx0fVxuXG5cdHNlbmQoZGF0YTogc3RyaW5nIHwgQXJyYXlCdWZmZXJMaWtlIHwgQmxvYiB8IEFycmF5QnVmZmVyVmlldyk6IHZvaWQge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwic2VuZCBjYWxsZWRcIiwgeyByZWFkeVN0YXRlOiB0aGlzLnJlYWR5U3RhdGUgfSk7XG5cblx0XHRpZiAodGhpcy5yZWFkeVN0YXRlICE9PSB0aGlzLk9QRU4pIHtcblx0XHRcdGNvbnN0IGVycm9yID0gbmV3IEVycm9yKFwiV2ViU29ja2V0IGlzIG5vdCBvcGVuXCIpO1xuXHRcdFx0bG9nZ2VyKCkud2FybihcImNhbm5vdCBzZW5kIG1lc3NhZ2UsIHdlYnNvY2tldCBub3Qgb3BlblwiLCB7XG5cdFx0XHRcdHJlYWR5U3RhdGU6IHRoaXMucmVhZHlTdGF0ZSxcblx0XHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBkYXRhLFxuXHRcdFx0XHRkYXRhTGVuZ3RoOiB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiA/IGRhdGEubGVuZ3RoIDogXCJiaW5hcnlcIixcblx0XHRcdFx0ZXJyb3IsXG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuI2ZpcmVFcnJvcihlcnJvcik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy4jaGFuZGxlci5vbk1lc3NhZ2UoeyBkYXRhIH0sIHRoaXMuI3dzQ29udGV4dCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uXG5cdCAqL1xuXHRjbG9zZShjb2RlID0gMTAwMCwgcmVhc29uID0gXCJcIik6IHZvaWQge1xuXHRcdGlmICh0aGlzLnJlYWR5U3RhdGUgPT09IHRoaXMuQ0xPU0VEIHx8IHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TSU5HKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJjbG9zaW5nIGZha2Ugd2Vic29ja2V0XCIsIHsgY29kZSwgcmVhc29uIH0pO1xuXG5cdFx0dGhpcy4jcmVhZHlTdGF0ZSA9IHRoaXMuQ0xPU0lORztcblxuXHRcdC8vIENhbGwgdGhlIGhhbmRsZXIncyBvbkNsb3NlIG1ldGhvZFxuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLiNoYW5kbGVyLm9uQ2xvc2UoeyBjb2RlLCByZWFzb24sIHdhc0NsZWFuOiB0cnVlIH0sIHRoaXMuI3dzQ29udGV4dCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGNsb3Npbmcgd2Vic29ja2V0XCIsIHsgZXJyb3I6IGVyciB9KTtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dGhpcy4jcmVhZHlTdGF0ZSA9IHRoaXMuQ0xPU0VEO1xuXG5cdFx0XHQvLyBGaXJlIHRoZSBjbG9zZSBldmVudFxuXHRcdFx0Ly8gQ3JlYXRlIGEgY2xvc2UgZXZlbnQgb2JqZWN0IHNpbmNlIENsb3NlRXZlbnQgaXMgbm90IGF2YWlsYWJsZSBpbiBOb2RlLmpzXG5cdFx0XHRjb25zdCBjbG9zZUV2ZW50ID0ge1xuXHRcdFx0XHR0eXBlOiBcImNsb3NlXCIsXG5cdFx0XHRcdHdhc0NsZWFuOiBjb2RlID09PSAxMDAwLFxuXHRcdFx0XHRjb2RlLFxuXHRcdFx0XHRyZWFzb24sXG5cdFx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdFx0Y3VycmVudFRhcmdldDogdGhpcyxcblx0XHRcdH0gYXMgdW5rbm93biBhcyBSaXZldENsb3NlRXZlbnQ7XG5cblx0XHRcdHRoaXMuI2ZpcmVDbG9zZShjbG9zZUV2ZW50KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSW5pdGlhbGl6ZSB0aGUgY29ubmVjdGlvbiB3aXRoIHRoZSBoYW5kbGVyXG5cdCAqL1xuXHRhc3luYyAjaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHR0cnkge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmYWtlIHdlYnNvY2tldCBpbml0aWFsaXppbmdcIik7XG5cblx0XHRcdC8vIENhbGwgdGhlIGhhbmRsZXIncyBvbk9wZW4gbWV0aG9kXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImNhbGxpbmcgaGFuZGxlci5vbk9wZW4gd2l0aCBXU0NvbnRleHRcIik7XG5cdFx0XHR0aGlzLiNoYW5kbGVyLm9uT3Blbih1bmRlZmluZWQsIHRoaXMuI3dzQ29udGV4dCk7XG5cblx0XHRcdC8vIFVwZGF0ZSB0aGUgcmVhZHkgc3RhdGUgYW5kIGZpcmUgZXZlbnRzXG5cdFx0XHR0aGlzLiNyZWFkeVN0YXRlID0gdGhpcy5PUEVOO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmYWtlIHdlYnNvY2tldCBpbml0aWFsaXplZCBhbmQgbm93IE9QRU5cIik7XG5cblx0XHRcdC8vIEZpcmUgdGhlIG9wZW4gZXZlbnRcblx0XHRcdHRoaXMuI2ZpcmVPcGVuKCk7XG5cblx0XHRcdC8vIERlbGF5IHByb2Nlc3NpbmcgcXVldWVkIG1lc3NhZ2VzIHNsaWdodGx5IHRvIGFsbG93IGV2ZW50IGhhbmRsZXJzIHRvIGJlIHNldCB1cFxuXHRcdFx0aWYgKHRoaXMuI3F1ZXVlZE1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0aWYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5PUEVOKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkud2FybihcInNvY2tldCBubyBsb25nZXIgb3BlbiwgZHJvcHBpbmcgcXVldWVkIG1lc3NhZ2VzXCIpO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFxuXHRcdFx0XHRcdGBub3cgcHJvY2Vzc2luZyAke3RoaXMuI3F1ZXVlZE1lc3NhZ2VzLmxlbmd0aH0gcXVldWVkIG1lc3NhZ2VzYCxcblx0XHRcdFx0KTtcblxuXHRcdFx0XHQvLyBDcmVhdGUgYSBjb3B5IHRvIGF2b2lkIGlzc3VlcyBpZiBuZXcgbWVzc2FnZXMgYXJyaXZlIGR1cmluZyBwcm9jZXNzaW5nXG5cdFx0XHRcdGNvbnN0IG1lc3NhZ2VzVG9Qcm9jZXNzID0gWy4uLnRoaXMuI3F1ZXVlZE1lc3NhZ2VzXTtcblx0XHRcdFx0dGhpcy4jcXVldWVkTWVzc2FnZXMgPSBbXTtcblxuXHRcdFx0XHQvLyBQcm9jZXNzIGVhY2ggcXVldWVkIG1lc3NhZ2Vcblx0XHRcdFx0Zm9yIChjb25zdCBtZXNzYWdlIG9mIG1lc3NhZ2VzVG9Qcm9jZXNzKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJwcm9jZXNzaW5nIHF1ZXVlZCBtZXNzYWdlXCIpO1xuXHRcdFx0XHRcdHRoaXMuI2hhbmRsZU1lc3NhZ2UobWVzc2FnZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3Igb3BlbmluZyBmYWtlIHdlYnNvY2tldFwiLCB7XG5cdFx0XHRcdGVycm9yOiBlcnIsXG5cdFx0XHRcdGVycm9yTWVzc2FnZTogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuXHRcdFx0XHRzdGFjazogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIuc3RhY2sgOiB1bmRlZmluZWQsXG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuI2ZpcmVFcnJvcihlcnIpO1xuXHRcdFx0dGhpcy5jbG9zZSgxMDExLCBcIkludGVybmFsIGVycm9yIGR1cmluZyBpbml0aWFsaXphdGlvblwiKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlIG1lc3NhZ2VzIHJlY2VpdmVkIGZyb20gdGhlIHNlcnZlciB2aWEgdGhlIFdTQ29udGV4dFxuXHQgKi9cblx0I2hhbmRsZU1lc3NhZ2UoZGF0YTogc3RyaW5nIHwgQXJyYXlCdWZmZXIgfCBVaW50OEFycmF5KTogdm9pZCB7XG5cdFx0Ly8gU3RvcmUgbWVzc2FnZXMgdGhhdCBhcnJpdmUgYmVmb3JlIHRoZSBzb2NrZXQgaXMgZnVsbHkgaW5pdGlhbGl6ZWRcblx0XHRpZiAodGhpcy5yZWFkeVN0YXRlICE9PSB0aGlzLk9QRU4pIHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwibWVzc2FnZSByZWNlaXZlZCBiZWZvcmUgc29ja2V0IGlzIE9QRU4sIHF1ZXVpbmdcIiwge1xuXHRcdFx0XHRyZWFkeVN0YXRlOiB0aGlzLnJlYWR5U3RhdGUsXG5cdFx0XHRcdGRhdGFUeXBlOiB0eXBlb2YgZGF0YSxcblx0XHRcdFx0ZGF0YUxlbmd0aDpcblx0XHRcdFx0XHR0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIlxuXHRcdFx0XHRcdFx0PyBkYXRhLmxlbmd0aFxuXHRcdFx0XHRcdFx0OiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXJcblx0XHRcdFx0XHRcdFx0PyBkYXRhLmJ5dGVMZW5ndGhcblx0XHRcdFx0XHRcdFx0OiBkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheVxuXHRcdFx0XHRcdFx0XHRcdD8gZGF0YS5ieXRlTGVuZ3RoXG5cdFx0XHRcdFx0XHRcdFx0OiBcInVua25vd25cIixcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBRdWV1ZSB0aGUgbWVzc2FnZSB0byBiZSBwcm9jZXNzZWQgb25jZSB0aGUgc29ja2V0IGlzIG9wZW5cblx0XHRcdHRoaXMuI3F1ZXVlZE1lc3NhZ2VzLnB1c2goZGF0YSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTG9nIG1lc3NhZ2UgcmVjZWl2ZWQgZnJvbSBzZXJ2ZXJcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZha2Ugd2Vic29ja2V0IHJlY2VpdmVkIG1lc3NhZ2UgZnJvbSBzZXJ2ZXJcIiwge1xuXHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBkYXRhLFxuXHRcdFx0ZGF0YUxlbmd0aDpcblx0XHRcdFx0dHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCJcblx0XHRcdFx0XHQ/IGRhdGEubGVuZ3RoXG5cdFx0XHRcdFx0OiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXJcblx0XHRcdFx0XHRcdD8gZGF0YS5ieXRlTGVuZ3RoXG5cdFx0XHRcdFx0XHQ6IGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5XG5cdFx0XHRcdFx0XHRcdD8gZGF0YS5ieXRlTGVuZ3RoXG5cdFx0XHRcdFx0XHRcdDogXCJ1bmtub3duXCIsXG5cdFx0fSk7XG5cblx0XHQvLyBDcmVhdGUgYSBNZXNzYWdlRXZlbnQtbGlrZSBvYmplY3Rcblx0XHRjb25zdCBldmVudCA9IHtcblx0XHRcdHR5cGU6IFwibWVzc2FnZVwiLFxuXHRcdFx0ZGF0YSxcblx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdGN1cnJlbnRUYXJnZXQ6IHRoaXMsXG5cdFx0fSBhcyB1bmtub3duIGFzIFJpdmV0TWVzc2FnZUV2ZW50O1xuXG5cdFx0Ly8gRGlzcGF0Y2ggdGhlIGV2ZW50XG5cdFx0dGhpcy4jZGlzcGF0Y2hFdmVudChcIm1lc3NhZ2VcIiwgZXZlbnQpO1xuXHR9XG5cblx0I2hhbmRsZUNsb3NlKGNvZGU6IG51bWJlciwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5yZWFkeVN0YXRlID09PSB0aGlzLkNMT1NFRCkgcmV0dXJuO1xuXG5cdFx0dGhpcy4jcmVhZHlTdGF0ZSA9IHRoaXMuQ0xPU0VEO1xuXG5cdFx0Ly8gQ3JlYXRlIGEgQ2xvc2VFdmVudC1saWtlIG9iamVjdFxuXHRcdGNvbnN0IGV2ZW50ID0ge1xuXHRcdFx0dHlwZTogXCJjbG9zZVwiLFxuXHRcdFx0Y29kZSxcblx0XHRcdHJlYXNvbixcblx0XHRcdHdhc0NsZWFuOiBjb2RlID09PSAxMDAwLFxuXHRcdFx0dGFyZ2V0OiB0aGlzLFxuXHRcdFx0Y3VycmVudFRhcmdldDogdGhpcyxcblx0XHR9IGFzIHVua25vd24gYXMgUml2ZXRDbG9zZUV2ZW50O1xuXG5cdFx0Ly8gRGlzcGF0Y2ggdGhlIGV2ZW50XG5cdFx0dGhpcy4jZGlzcGF0Y2hFdmVudChcImNsb3NlXCIsIGV2ZW50KTtcblx0fVxuXG5cdGFkZEV2ZW50TGlzdGVuZXIodHlwZTogc3RyaW5nLCBsaXN0ZW5lcjogKGV2OiBhbnkpID0+IHZvaWQpOiB2b2lkIHtcblx0XHRpZiAoIXRoaXMuI2V2ZW50TGlzdGVuZXJzLmhhcyh0eXBlKSkge1xuXHRcdFx0dGhpcy4jZXZlbnRMaXN0ZW5lcnMuc2V0KHR5cGUsIFtdKTtcblx0XHR9XG5cdFx0dGhpcy4jZXZlbnRMaXN0ZW5lcnMuZ2V0KHR5cGUpIS5wdXNoKGxpc3RlbmVyKTtcblxuXHRcdC8vIEZsdXNoIGFueSBidWZmZXJlZCBldmVudHMgZm9yIHRoaXMgdHlwZVxuXHRcdHRoaXMuI2ZsdXNoQnVmZmVyZWRFdmVudHModHlwZSk7XG5cdH1cblxuXHRyZW1vdmVFdmVudExpc3RlbmVyKHR5cGU6IHN0cmluZywgbGlzdGVuZXI6IChldjogYW55KSA9PiB2b2lkKTogdm9pZCB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gdGhpcy4jZXZlbnRMaXN0ZW5lcnMuZ2V0KHR5cGUpO1xuXHRcdGlmIChsaXN0ZW5lcnMpIHtcblx0XHRcdGNvbnN0IGluZGV4ID0gbGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuXHRcdFx0aWYgKGluZGV4ICE9PSAtMSkge1xuXHRcdFx0XHRsaXN0ZW5lcnMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQjZGlzcGF0Y2hFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50OiBhbnkpOiB2b2lkIHtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLiNldmVudExpc3RlbmVycy5nZXQodHlwZSk7XG5cdFx0aWYgKGxpc3RlbmVycyAmJiBsaXN0ZW5lcnMubGVuZ3RoID4gMCkge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXG5cdFx0XHRcdGBkaXNwYXRjaGluZyAke3R5cGV9IGV2ZW50IHRvICR7bGlzdGVuZXJzLmxlbmd0aH0gbGlzdGVuZXJzYCxcblx0XHRcdCk7XG5cdFx0XHRmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIGxpc3RlbmVycykge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGxpc3RlbmVyKGV2ZW50KTtcblx0XHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoYGVycm9yIGluICR7dHlwZX0gZXZlbnQgbGlzdGVuZXJgLCB7IGVycm9yOiBlcnIgfSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoYG5vICR7dHlwZX0gbGlzdGVuZXJzIHJlZ2lzdGVyZWQsIGJ1ZmZlcmluZyBldmVudGApO1xuXHRcdFx0dGhpcy4jYnVmZmVyZWRFdmVudHMucHVzaCh7IHR5cGUsIGV2ZW50IH0pO1xuXHRcdH1cblxuXHRcdC8vIEFsc28gY2hlY2sgZm9yIG9uKiBwcm9wZXJ0aWVzXG5cdFx0c3dpdGNoICh0eXBlKSB7XG5cdFx0XHRjYXNlIFwib3BlblwiOlxuXHRcdFx0XHRpZiAodGhpcy4jb25vcGVuKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHRoaXMuI29ub3BlbihldmVudCk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gb25vcGVuIGhhbmRsZXJcIiwgeyBlcnJvciB9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiY2xvc2VcIjpcblx0XHRcdFx0aWYgKHRoaXMuI29uY2xvc2UpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0dGhpcy4jb25jbG9zZShldmVudCk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gb25jbG9zZSBoYW5kbGVyXCIsIHsgZXJyb3IgfSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcImVycm9yXCI6XG5cdFx0XHRcdGlmICh0aGlzLiNvbmVycm9yKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHRoaXMuI29uZXJyb3IoZXZlbnQpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGluIG9uZXJyb3IgaGFuZGxlclwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJtZXNzYWdlXCI6XG5cdFx0XHRcdGlmICh0aGlzLiNvbm1lc3NhZ2UpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0dGhpcy4jb25tZXNzYWdlKGV2ZW50KTtcblx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBvbm1lc3NhZ2UgaGFuZGxlclwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRkaXNwYXRjaEV2ZW50KGV2ZW50OiBSaXZldEV2ZW50KTogYm9vbGVhbiB7XG5cdFx0dGhpcy4jZGlzcGF0Y2hFdmVudChldmVudC50eXBlLCBldmVudCk7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQjZmx1c2hCdWZmZXJlZEV2ZW50cyh0eXBlOiBzdHJpbmcpOiB2b2lkIHtcblx0XHRjb25zdCBldmVudHNUb0ZsdXNoID0gdGhpcy4jYnVmZmVyZWRFdmVudHMuZmlsdGVyKFxuXHRcdFx0KGJ1ZmZlcmVkKSA9PiBidWZmZXJlZC50eXBlID09PSB0eXBlLFxuXHRcdCk7XG5cdFx0dGhpcy4jYnVmZmVyZWRFdmVudHMgPSB0aGlzLiNidWZmZXJlZEV2ZW50cy5maWx0ZXIoXG5cdFx0XHQoYnVmZmVyZWQpID0+IGJ1ZmZlcmVkLnR5cGUgIT09IHR5cGUsXG5cdFx0KTtcblxuXHRcdGZvciAoY29uc3QgeyBldmVudCB9IG9mIGV2ZW50c1RvRmx1c2gpIHtcblx0XHRcdHRoaXMuI2Rpc3BhdGNoRXZlbnQodHlwZSwgZXZlbnQpO1xuXHRcdH1cblx0fVxuXG5cdCNmaXJlT3BlbigpOiB2b2lkIHtcblx0XHR0cnkge1xuXHRcdFx0Ly8gQ3JlYXRlIGFuIEV2ZW50LWxpa2Ugb2JqZWN0IHNpbmNlIEV2ZW50IGNvbnN0cnVjdG9yIG1heSBub3QgYmUgYXZhaWxhYmxlXG5cdFx0XHRjb25zdCBldmVudCA9IHtcblx0XHRcdFx0dHlwZTogXCJvcGVuXCIsXG5cdFx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdFx0Y3VycmVudFRhcmdldDogdGhpcyxcblx0XHRcdH0gYXMgdW5rbm93biBhcyBSaXZldEV2ZW50O1xuXG5cdFx0XHR0aGlzLiNkaXNwYXRjaEV2ZW50KFwib3BlblwiLCBldmVudCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGluIG9wZW4gZXZlbnRcIiwgeyBlcnJvcjogZXJyIH0pO1xuXHRcdH1cblx0fVxuXG5cdCNmaXJlQ2xvc2UoZXZlbnQ6IFJpdmV0Q2xvc2VFdmVudCk6IHZvaWQge1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLiNkaXNwYXRjaEV2ZW50KFwiY2xvc2VcIiwgZXZlbnQpO1xuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBjbG9zZSBldmVudFwiLCB7IGVycm9yOiBlcnIgfSk7XG5cdFx0fVxuXHR9XG5cblx0I2ZpcmVFcnJvcihlcnJvcjogdW5rbm93bik6IHZvaWQge1xuXHRcdHRyeSB7XG5cdFx0XHQvLyBDcmVhdGUgYW4gRXZlbnQtbGlrZSBvYmplY3QgZm9yIGVycm9yXG5cdFx0XHRjb25zdCBldmVudCA9IHtcblx0XHRcdFx0dHlwZTogXCJlcnJvclwiLFxuXHRcdFx0XHR0YXJnZXQ6IHRoaXMsXG5cdFx0XHRcdGN1cnJlbnRUYXJnZXQ6IHRoaXMsXG5cdFx0XHRcdGVycm9yLFxuXHRcdFx0XHRtZXNzYWdlOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG5cdFx0XHR9IGFzIHVua25vd24gYXMgUml2ZXRFdmVudDtcblxuXHRcdFx0dGhpcy4jZGlzcGF0Y2hFdmVudChcImVycm9yXCIsIGV2ZW50KTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZXJyb3IgaW4gZXJyb3IgZXZlbnRcIiwgeyBlcnJvcjogZXJyIH0pO1xuXHRcdH1cblxuXHRcdC8vIExvZyB0aGUgZXJyb3Jcblx0XHRsb2dnZXIoKS5lcnJvcihcIndlYnNvY2tldCBlcnJvclwiLCB7IGVycm9yIH0pO1xuXHR9XG5cblx0Ly8gRXZlbnQgaGFuZGxlciBwcm9wZXJ0aWVzIHdpdGggZ2V0dGVycy9zZXR0ZXJzXG5cdCNvbm9wZW46ICgoZXZlbnQ6IFJpdmV0RXZlbnQpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cdCNvbmNsb3NlOiAoKGV2ZW50OiBSaXZldENsb3NlRXZlbnQpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cdCNvbmVycm9yOiAoKGV2ZW50OiBSaXZldEV2ZW50KSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuXHQjb25tZXNzYWdlOiAoKGV2ZW50OiBSaXZldE1lc3NhZ2VFdmVudCkgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcblxuXHRnZXQgb25vcGVuKCk6ICgoZXZlbnQ6IFJpdmV0RXZlbnQpID0+IHZvaWQpIHwgbnVsbCB7XG5cdFx0cmV0dXJuIHRoaXMuI29ub3Blbjtcblx0fVxuXHRzZXQgb25vcGVuKGhhbmRsZXI6ICgoZXZlbnQ6IFJpdmV0RXZlbnQpID0+IHZvaWQpIHwgbnVsbCkge1xuXHRcdHRoaXMuI29ub3BlbiA9IGhhbmRsZXI7XG5cdH1cblxuXHRnZXQgb25jbG9zZSgpOiAoKGV2ZW50OiBSaXZldENsb3NlRXZlbnQpID0+IHZvaWQpIHwgbnVsbCB7XG5cdFx0cmV0dXJuIHRoaXMuI29uY2xvc2U7XG5cdH1cblx0c2V0IG9uY2xvc2UoaGFuZGxlcjogKChldmVudDogUml2ZXRDbG9zZUV2ZW50KSA9PiB2b2lkKSB8IG51bGwpIHtcblx0XHR0aGlzLiNvbmNsb3NlID0gaGFuZGxlcjtcblx0fVxuXG5cdGdldCBvbmVycm9yKCk6ICgoZXZlbnQ6IFJpdmV0RXZlbnQpID0+IHZvaWQpIHwgbnVsbCB7XG5cdFx0cmV0dXJuIHRoaXMuI29uZXJyb3I7XG5cdH1cblx0c2V0IG9uZXJyb3IoaGFuZGxlcjogKChldmVudDogUml2ZXRFdmVudCkgPT4gdm9pZCkgfCBudWxsKSB7XG5cdFx0dGhpcy4jb25lcnJvciA9IGhhbmRsZXI7XG5cdH1cblxuXHRnZXQgb25tZXNzYWdlKCk6ICgoZXZlbnQ6IFJpdmV0TWVzc2FnZUV2ZW50KSA9PiB2b2lkKSB8IG51bGwge1xuXHRcdHJldHVybiB0aGlzLiNvbm1lc3NhZ2U7XG5cdH1cblx0c2V0IG9ubWVzc2FnZShoYW5kbGVyOiAoKGV2ZW50OiBSaXZldE1lc3NhZ2VFdmVudCkgPT4gdm9pZCkgfCBudWxsKSB7XG5cdFx0dGhpcy4jb25tZXNzYWdlID0gaGFuZGxlcjtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvYWN0b3ItZHJpdmVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL2FjdG9yLWRyaXZlci50c1wiO2ltcG9ydCB0eXBlIHtcblx0QWN0b3JDb25maWcgYXMgUnVubmVyQWN0b3JDb25maWcsXG5cdFJ1bm5lckNvbmZpZyxcbn0gZnJvbSBcIkByaXZldGtpdC9lbmdpbmUtcnVubmVyXCI7XG5pbXBvcnQgeyBSdW5uZXIgfSBmcm9tIFwiQHJpdmV0a2l0L2VuZ2luZS1ydW5uZXJcIjtcbmltcG9ydCAqIGFzIGNib3IgZnJvbSBcImNib3IteFwiO1xuaW1wb3J0IHsgV1NDb250ZXh0IH0gZnJvbSBcImhvbm8vd3NcIjtcbmltcG9ydCBpbnZhcmlhbnQgZnJvbSBcImludmFyaWFudFwiO1xuaW1wb3J0IHsgRW5jb2RpbmdTY2hlbWEgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHR5cGUgeyBDbGllbnQgfSBmcm9tIFwiQC9jbGllbnQvY2xpZW50XCI7XG5pbXBvcnQge1xuXHR0eXBlIEFjdG9yRHJpdmVyLFxuXHR0eXBlIEFueUFjdG9ySW5zdGFuY2UsXG5cdEhFQURFUl9BVVRIX0RBVEEsXG5cdEhFQURFUl9DT05OX1BBUkFNUyxcblx0SEVBREVSX0VOQ09ESU5HLFxuXHR0eXBlIE1hbmFnZXJEcml2ZXIsXG5cdHNlcmlhbGl6ZUVtcHR5UGVyc2lzdERhdGEsXG59IGZyb20gXCJAL2RyaXZlci1oZWxwZXJzL21vZFwiO1xuaW1wb3J0IHR5cGUge1xuXHRBY3RvclJvdXRlcixcblx0UmVnaXN0cnlDb25maWcsXG5cdFJ1bkNvbmZpZyxcblx0VW5pdmVyc2FsV2ViU29ja2V0LFxuXHRVcGdyYWRlV2ViU29ja2V0QXJncyxcbn0gZnJvbSBcIkAvbW9kXCI7XG5pbXBvcnQge1xuXHRjcmVhdGVBY3RvclJvdXRlcixcblx0Y3JlYXRlR2VuZXJpY0Nvbm5Ecml2ZXJzLFxuXHRHZW5lcmljQ29ubkdsb2JhbFN0YXRlLFxuXHRoYW5kbGVSYXdXZWJTb2NrZXRIYW5kbGVyLFxuXHRoYW5kbGVXZWJTb2NrZXRDb25uZWN0LFxuXHRsb29rdXBJblJlZ2lzdHJ5LFxuXHRQQVRIX0NPTk5FQ1RfV0VCU09DS0VULFxuXHRQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYLFxufSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB0eXBlIHsgQ29uZmlnIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgeyBkZXNlcmlhbGl6ZUFjdG9yS2V5IH0gZnJvbSBcIi4va2V5c1wiO1xuaW1wb3J0IHsgS0VZUyB9IGZyb20gXCIuL2t2XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuaW50ZXJmYWNlIEFjdG9ySGFuZGxlciB7XG5cdGFjdG9yPzogQW55QWN0b3JJbnN0YW5jZTtcblx0YWN0b3JTdGFydFByb21pc2U/OiBQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPjtcblx0Z2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTogR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTtcblx0cGVyc2lzdGVkRGF0YT86IFVpbnQ4QXJyYXk7XG59XG5cbmV4cG9ydCB0eXBlIERyaXZlckNvbnRleHQgPSB7fTtcblxuZXhwb3J0IGNsYXNzIEVuZ2luZUFjdG9yRHJpdmVyIGltcGxlbWVudHMgQWN0b3JEcml2ZXIge1xuXHQjcmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnO1xuXHQjcnVuQ29uZmlnOiBSdW5Db25maWc7XG5cdCNtYW5hZ2VyRHJpdmVyOiBNYW5hZ2VyRHJpdmVyO1xuXHQjaW5saW5lQ2xpZW50OiBDbGllbnQ8YW55Pjtcblx0I2NvbmZpZzogQ29uZmlnO1xuXHQjcnVubmVyOiBSdW5uZXI7XG5cdCNhY3RvcnM6IE1hcDxzdHJpbmcsIEFjdG9ySGFuZGxlcj4gPSBuZXcgTWFwKCk7XG5cdCNhY3RvclJvdXRlcjogQWN0b3JSb3V0ZXI7XG5cdCN2ZXJzaW9uOiBudW1iZXIgPSAxOyAvLyBWZXJzaW9uIGZvciB0aGUgcnVubmVyIHByb3RvY29sXG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnLFxuXHRcdHJ1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRcdG1hbmFnZXJEcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG5cdFx0aW5saW5lQ2xpZW50OiBDbGllbnQ8YW55Pixcblx0XHRjb25maWc6IENvbmZpZyxcblx0KSB7XG5cdFx0dGhpcy4jcmVnaXN0cnlDb25maWcgPSByZWdpc3RyeUNvbmZpZztcblx0XHR0aGlzLiNydW5Db25maWcgPSBydW5Db25maWc7XG5cdFx0dGhpcy4jbWFuYWdlckRyaXZlciA9IG1hbmFnZXJEcml2ZXI7XG5cdFx0dGhpcy4jaW5saW5lQ2xpZW50ID0gaW5saW5lQ2xpZW50O1xuXHRcdHRoaXMuI2NvbmZpZyA9IGNvbmZpZztcblx0XHR0aGlzLiNhY3RvclJvdXRlciA9IGNyZWF0ZUFjdG9yUm91dGVyKHJ1bkNvbmZpZywgdGhpcyk7XG5cblx0XHQvLyBDcmVhdGUgcnVubmVyIGNvbmZpZ3VyYXRpb25cblx0XHRsZXQgaGFzRGlzY29ubmVjdGVkID0gZmFsc2U7XG5cdFx0Y29uc3QgcnVubmVyQ29uZmlnOiBSdW5uZXJDb25maWcgPSB7XG5cdFx0XHR2ZXJzaW9uOiB0aGlzLiN2ZXJzaW9uLFxuXHRcdFx0ZW5kcG9pbnQ6IGNvbmZpZy5lbmRwb2ludCxcblx0XHRcdHBlZ2JvYXJkRW5kcG9pbnQ6IGNvbmZpZy5wZWdib2FyZEVuZHBvaW50LFxuXHRcdFx0bmFtZXNwYWNlOiBjb25maWcubmFtZXNwYWNlLFxuXHRcdFx0dG90YWxTbG90czogY29uZmlnLnRvdGFsU2xvdHMsXG5cdFx0XHRydW5uZXJOYW1lOiBjb25maWcucnVubmVyTmFtZSxcblx0XHRcdHJ1bm5lcktleTogY29uZmlnLnJ1bm5lcktleSxcblx0XHRcdG1ldGFkYXRhOiB7XG5cdFx0XHRcdGluc3BlY3RvclRva2VuOiB0aGlzLiNydW5Db25maWcuaW5zcGVjdG9yLnRva2VuKCksXG5cdFx0XHR9LFxuXHRcdFx0cHJlcG9wdWxhdGVBY3Rvck5hbWVzOiBPYmplY3QuZnJvbUVudHJpZXMoXG5cdFx0XHRcdE9iamVjdC5rZXlzKHRoaXMuI3JlZ2lzdHJ5Q29uZmlnLnVzZSkubWFwKChuYW1lKSA9PiBbXG5cdFx0XHRcdFx0bmFtZSxcblx0XHRcdFx0XHR7IG1ldGFkYXRhOiB7fSB9LFxuXHRcdFx0XHRdKSxcblx0XHRcdCksXG5cdFx0XHRvbkNvbm5lY3RlZDogKCkgPT4ge1xuXHRcdFx0XHRpZiAoaGFzRGlzY29ubmVjdGVkKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuaW5mbyhcInJ1bm5lciByZWNvbm5lY3RlZFwiLCB7XG5cdFx0XHRcdFx0XHRuYW1lc3BhY2U6IHRoaXMuI2NvbmZpZy5uYW1lc3BhY2UsXG5cdFx0XHRcdFx0XHRydW5uZXJOYW1lOiB0aGlzLiNjb25maWcucnVubmVyTmFtZSxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJ1bm5lciBjb25uZWN0ZWRcIiwge1xuXHRcdFx0XHRcdFx0bmFtZXNwYWNlOiB0aGlzLiNjb25maWcubmFtZXNwYWNlLFxuXHRcdFx0XHRcdFx0cnVubmVyTmFtZTogdGhpcy4jY29uZmlnLnJ1bm5lck5hbWUsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRvbkRpc2Nvbm5lY3RlZDogKCkgPT4ge1xuXHRcdFx0XHRsb2dnZXIoKS53YXJuKFwicnVubmVyIGRpc2Nvbm5lY3RlZFwiLCB7XG5cdFx0XHRcdFx0bmFtZXNwYWNlOiB0aGlzLiNjb25maWcubmFtZXNwYWNlLFxuXHRcdFx0XHRcdHJ1bm5lck5hbWU6IHRoaXMuI2NvbmZpZy5ydW5uZXJOYW1lLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0aGFzRGlzY29ubmVjdGVkID0gdHJ1ZTtcblx0XHRcdH0sXG5cdFx0XHRmZXRjaDogdGhpcy4jcnVubmVyRmV0Y2guYmluZCh0aGlzKSxcblx0XHRcdHdlYnNvY2tldDogdGhpcy4jcnVubmVyV2ViU29ja2V0LmJpbmQodGhpcyksXG5cdFx0XHRvbkFjdG9yU3RhcnQ6IHRoaXMuI3J1bm5lck9uQWN0b3JTdGFydC5iaW5kKHRoaXMpLFxuXHRcdFx0b25BY3RvclN0b3A6IHRoaXMuI3J1bm5lck9uQWN0b3JTdG9wLmJpbmQodGhpcyksXG5cdFx0fTtcblxuXHRcdC8vIENyZWF0ZSBhbmQgc3RhcnQgcnVubmVyXG5cdFx0dGhpcy4jcnVubmVyID0gbmV3IFJ1bm5lcihydW5uZXJDb25maWcpO1xuXHRcdHRoaXMuI3J1bm5lci5zdGFydCgpO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZW5naW5lIHJ1bm5lciBzdGFydGVkXCIsIHtcblx0XHRcdGVuZHBvaW50OiBjb25maWcuZW5kcG9pbnQsXG5cdFx0XHRuYW1lc3BhY2U6IGNvbmZpZy5uYW1lc3BhY2UsXG5cdFx0XHRydW5uZXJOYW1lOiBjb25maWcucnVubmVyTmFtZSxcblx0XHR9KTtcblx0fVxuXG5cdGFzeW5jICNsb2FkQWN0b3JIYW5kbGVyKGFjdG9ySWQ6IHN0cmluZyk6IFByb21pc2U8QWN0b3JIYW5kbGVyPiB7XG5cdFx0Ly8gQ2hlY2sgaWYgYWN0b3IgaXMgYWxyZWFkeSBsb2FkZWRcblx0XHRjb25zdCBoYW5kbGVyID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpZiAoIWhhbmRsZXIpIHRocm93IG5ldyBFcnJvcihgQWN0b3IgaGFuZGxlciBkb2VzIG5vdCBleGlzdCAke2FjdG9ySWR9YCk7XG5cdFx0aWYgKGhhbmRsZXIuYWN0b3JTdGFydFByb21pc2UpIGF3YWl0IGhhbmRsZXIuYWN0b3JTdGFydFByb21pc2UucHJvbWlzZTtcblx0XHRpZiAoIWhhbmRsZXIuYWN0b3IpIHRocm93IG5ldyBFcnJvcihcIkFjdG9yIHNob3VsZCBiZSBsb2FkZWRcIik7XG5cdFx0cmV0dXJuIGhhbmRsZXI7XG5cdH1cblxuXHRhc3luYyBsb2FkQWN0b3IoYWN0b3JJZDogc3RyaW5nKTogUHJvbWlzZTxBbnlBY3Rvckluc3RhbmNlPiB7XG5cdFx0Y29uc3QgaGFuZGxlciA9IGF3YWl0IHRoaXMuI2xvYWRBY3RvckhhbmRsZXIoYWN0b3JJZCk7XG5cdFx0aWYgKCFoYW5kbGVyLmFjdG9yKSB0aHJvdyBuZXcgRXJyb3IoYEFjdG9yICR7YWN0b3JJZH0gZmFpbGVkIHRvIGxvYWRgKTtcblx0XHRyZXR1cm4gaGFuZGxlci5hY3Rvcjtcblx0fVxuXG5cdGdldEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoYWN0b3JJZDogc3RyaW5nKTogR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSB7XG5cdFx0Y29uc3QgaGFuZGxlciA9IHRoaXMuI2FjdG9ycy5nZXQoYWN0b3JJZCk7XG5cdFx0aWYgKCFoYW5kbGVyKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEFjdG9yICR7YWN0b3JJZH0gbm90IGxvYWRlZGApO1xuXHRcdH1cblx0XHRyZXR1cm4gaGFuZGxlci5nZW5lcmljQ29ubkdsb2JhbFN0YXRlO1xuXHR9XG5cblx0Z2V0Q29udGV4dChhY3RvcklkOiBzdHJpbmcpOiBEcml2ZXJDb250ZXh0IHtcblx0XHRyZXR1cm4ge307XG5cdH1cblxuXHRhc3luYyByZWFkUGVyc2lzdGVkRGF0YShhY3RvcklkOiBzdHJpbmcpOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQ+IHtcblx0XHRjb25zdCBoYW5kbGVyID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpZiAoIWhhbmRsZXIpIHRocm93IG5ldyBFcnJvcihgQWN0b3IgJHthY3RvcklkfSBub3QgbG9hZGVkYCk7XG5cdFx0aWYgKGhhbmRsZXIucGVyc2lzdGVkRGF0YSkgcmV0dXJuIGhhbmRsZXIucGVyc2lzdGVkRGF0YTtcblxuXHRcdGNvbnN0IFt2YWx1ZV0gPSBhd2FpdCB0aGlzLiNydW5uZXIua3ZHZXQoYWN0b3JJZCwgW0tFWVMuUEVSU0lTVF9EQVRBXSk7XG5cblx0XHRpZiAodmFsdWUgIT09IG51bGwpIHtcblx0XHRcdGhhbmRsZXIucGVyc2lzdGVkRGF0YSA9IHZhbHVlO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIHdyaXRlUGVyc2lzdGVkRGF0YShhY3RvcklkOiBzdHJpbmcsIGRhdGE6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCBoYW5kbGVyID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpZiAoIWhhbmRsZXIpIHRocm93IG5ldyBFcnJvcihgQWN0b3IgJHthY3RvcklkfSBub3QgbG9hZGVkYCk7XG5cblx0XHRoYW5kbGVyLnBlcnNpc3RlZERhdGEgPSBkYXRhO1xuXG5cdFx0YXdhaXQgdGhpcy4jcnVubmVyLmt2UHV0KGFjdG9ySWQsIFtbS0VZUy5QRVJTSVNUX0RBVEEsIGRhdGFdXSk7XG5cdH1cblxuXHRhc3luYyBzZXRBbGFybShhY3RvcjogQW55QWN0b3JJbnN0YW5jZSwgdGltZXN0YW1wOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHQvLyBUT0RPOiBTZXQgdGltZW91dFxuXHRcdC8vIFRPRE86IFVzZSBhbGFybSBvbiBzbGVlcFxuXHRcdC8vIFRPRE86IFNlbmQgYWxhcm0gdG8gcnVubmVyXG5cdH1cblxuXHRhc3luYyBnZXREYXRhYmFzZShfYWN0b3JJZDogc3RyaW5nKTogUHJvbWlzZTx1bmtub3duIHwgdW5kZWZpbmVkPiB7XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdC8vIFJ1bm5lciBsaWZlY3ljbGUgY2FsbGJhY2tzXG5cdGFzeW5jICNydW5uZXJPbkFjdG9yU3RhcnQoXG5cdFx0YWN0b3JJZDogc3RyaW5nLFxuXHRcdGdlbmVyYXRpb246IG51bWJlcixcblx0XHRjb25maWc6IFJ1bm5lckFjdG9yQ29uZmlnLFxuXHQpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJ1bm5lciBhY3RvciBzdGFydGluZ1wiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bmFtZTogY29uZmlnLm5hbWUsXG5cdFx0XHRrZXk6IGNvbmZpZy5rZXksXG5cdFx0XHRnZW5lcmF0aW9uLFxuXHRcdH0pO1xuXG5cdFx0Ly8gRGVzZXJpYWxpemUgaW5wdXRcblx0XHRsZXQgaW5wdXQ6IGFueTtcblx0XHRpZiAoY29uZmlnLmlucHV0KSB7XG5cdFx0XHRpbnB1dCA9IGNib3IuZGVjb2RlKGNvbmZpZy5pbnB1dCk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0IG9yIGNyZWF0ZSBoYW5kbGVyXG5cdFx0bGV0IGhhbmRsZXIgPSB0aGlzLiNhY3RvcnMuZ2V0KGFjdG9ySWQpO1xuXHRcdGlmICghaGFuZGxlcikge1xuXHRcdFx0aGFuZGxlciA9IHtcblx0XHRcdFx0Z2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTogbmV3IEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoKSxcblx0XHRcdFx0YWN0b3JTdGFydFByb21pc2U6IFByb21pc2Uud2l0aFJlc29sdmVycygpLFxuXHRcdFx0XHRwZXJzaXN0ZWREYXRhOiBzZXJpYWxpemVFbXB0eVBlcnNpc3REYXRhKGlucHV0KSxcblx0XHRcdH07XG5cdFx0XHR0aGlzLiNhY3RvcnMuc2V0KGFjdG9ySWQsIGhhbmRsZXIpO1xuXHRcdH1cblxuXHRcdGNvbnN0IG5hbWUgPSBjb25maWcubmFtZSBhcyBzdHJpbmc7XG5cdFx0aW52YXJpYW50KGNvbmZpZy5rZXksIFwiYWN0b3Igc2hvdWxkIGhhdmUgYSBrZXlcIik7XG5cdFx0Y29uc3Qga2V5ID0gZGVzZXJpYWxpemVBY3RvcktleShjb25maWcua2V5KTtcblxuXHRcdC8vIENyZWF0ZSBhY3RvciBpbnN0YW5jZVxuXHRcdGNvbnN0IGRlZmluaXRpb24gPSBsb29rdXBJblJlZ2lzdHJ5KFxuXHRcdFx0dGhpcy4jcmVnaXN0cnlDb25maWcsXG5cdFx0XHRjb25maWcubmFtZSBhcyBzdHJpbmcsIC8vIFRPRE86IFJlbW92ZSBjYXN0XG5cdFx0KTtcblx0XHRoYW5kbGVyLmFjdG9yID0gZGVmaW5pdGlvbi5pbnN0YW50aWF0ZSgpO1xuXG5cdFx0Ly8gU3RhcnQgYWN0b3Jcblx0XHRjb25zdCBjb25uRHJpdmVycyA9IGNyZWF0ZUdlbmVyaWNDb25uRHJpdmVycyhcblx0XHRcdGhhbmRsZXIuZ2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSxcblx0XHQpO1xuXHRcdGF3YWl0IGhhbmRsZXIuYWN0b3Iuc3RhcnQoXG5cdFx0XHRjb25uRHJpdmVycyxcblx0XHRcdHRoaXMsXG5cdFx0XHR0aGlzLiNpbmxpbmVDbGllbnQsXG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bmFtZSxcblx0XHRcdGtleSxcblx0XHRcdFwidW5rbm93blwiLCAvLyBUT0RPOiBBZGQgcmVnaW9uc1xuXHRcdCk7XG5cblx0XHQvLyBSZXNvbHZlIHByb21pc2UgaWYgd2FpdGluZ1xuXHRcdGhhbmRsZXIuYWN0b3JTdGFydFByb21pc2U/LnJlc29sdmUoKTtcblx0XHRoYW5kbGVyLmFjdG9yU3RhcnRQcm9taXNlID0gdW5kZWZpbmVkO1xuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJydW5uZXIgYWN0b3Igc3RhcnRlZFwiLCB7IGFjdG9ySWQsIG5hbWUsIGtleSB9KTtcblx0fVxuXG5cdGFzeW5jICNydW5uZXJPbkFjdG9yU3RvcChhY3RvcklkOiBzdHJpbmcsIGdlbmVyYXRpb246IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwicnVubmVyIGFjdG9yIHN0b3BwaW5nXCIsIHsgYWN0b3JJZCwgZ2VuZXJhdGlvbiB9KTtcblxuXHRcdGNvbnN0IGhhbmRsZXIgPSB0aGlzLiNhY3RvcnMuZ2V0KGFjdG9ySWQpO1xuXHRcdGlmIChoYW5kbGVyPy5hY3Rvcikge1xuXHRcdFx0YXdhaXQgaGFuZGxlci5hY3Rvci5fc3RvcCgpO1xuXHRcdFx0dGhpcy4jYWN0b3JzLmRlbGV0ZShhY3RvcklkKTtcblx0XHR9XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJ1bm5lciBhY3RvciBzdG9wcGVkXCIsIHsgYWN0b3JJZCB9KTtcblx0fVxuXG5cdGFzeW5jICNydW5uZXJGZXRjaChhY3RvcklkOiBzdHJpbmcsIHJlcXVlc3Q6IFJlcXVlc3QpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJydW5uZXIgZmV0Y2hcIiwge1xuXHRcdFx0YWN0b3JJZCxcblx0XHRcdHVybDogcmVxdWVzdC51cmwsXG5cdFx0XHRtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuXHRcdH0pO1xuXHRcdHJldHVybiBhd2FpdCB0aGlzLiNhY3RvclJvdXRlci5mZXRjaChyZXF1ZXN0LCB7IGFjdG9ySWQgfSk7XG5cdH1cblxuXHRhc3luYyAjcnVubmVyV2ViU29ja2V0KFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHR3ZWJzb2NrZXRSYXc6IGFueSxcblx0XHRyZXF1ZXN0OiBSZXF1ZXN0LFxuXHQpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCB3ZWJzb2NrZXQgPSB3ZWJzb2NrZXRSYXcgYXMgVW5pdmVyc2FsV2ViU29ja2V0O1xuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJydW5uZXIgd2Vic29ja2V0XCIsIHsgYWN0b3JJZCwgdXJsOiByZXF1ZXN0LnVybCB9KTtcblxuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuXG5cdFx0Ly8gUGFyc2UgaGVhZGVyc1xuXHRcdGNvbnN0IGVuY29kaW5nUmF3ID0gcmVxdWVzdC5oZWFkZXJzLmdldChIRUFERVJfRU5DT0RJTkcpO1xuXHRcdGNvbnN0IGNvbm5QYXJhbXNSYXcgPSByZXF1ZXN0LmhlYWRlcnMuZ2V0KEhFQURFUl9DT05OX1BBUkFNUyk7XG5cdFx0Y29uc3QgYXV0aERhdGFSYXcgPSByZXF1ZXN0LmhlYWRlcnMuZ2V0KEhFQURFUl9BVVRIX0RBVEEpO1xuXG5cdFx0Y29uc3QgZW5jb2RpbmcgPSBFbmNvZGluZ1NjaGVtYS5wYXJzZShlbmNvZGluZ1Jhdyk7XG5cdFx0Y29uc3QgY29ublBhcmFtcyA9IGNvbm5QYXJhbXNSYXcgPyBKU09OLnBhcnNlKGNvbm5QYXJhbXNSYXcpIDogdW5kZWZpbmVkO1xuXHRcdGNvbnN0IGF1dGhEYXRhID0gYXV0aERhdGFSYXcgPyBKU09OLnBhcnNlKGF1dGhEYXRhUmF3KSA6IHVuZGVmaW5lZDtcblxuXHRcdC8vIEZldGNoIFdTIGhhbmRsZXJcblx0XHQvL1xuXHRcdC8vIFdlIHN0b3JlIHRoZSBwcm9taXNlIHNpbmNlIHdlIG5lZWQgdG8gYWRkIFdlYlNvY2tldCBldmVudCBsaXN0ZW5lcnMgaW1tZWRpYXRlbHkgdGhhdCB3aWxsIHdhaXQgZm9yIHRoZSBwcm9taXNlIHRvIHJlc29sdmVcblx0XHRsZXQgd3NIYW5kbGVyUHJvbWlzZTogUHJvbWlzZTxVcGdyYWRlV2ViU29ja2V0QXJncz47XG5cdFx0aWYgKHVybC5wYXRobmFtZSA9PT0gUEFUSF9DT05ORUNUX1dFQlNPQ0tFVCkge1xuXHRcdFx0d3NIYW5kbGVyUHJvbWlzZSA9IGhhbmRsZVdlYlNvY2tldENvbm5lY3QoXG5cdFx0XHRcdHJlcXVlc3QsXG5cdFx0XHRcdHRoaXMuI3J1bkNvbmZpZyxcblx0XHRcdFx0dGhpcyxcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0ZW5jb2RpbmcsXG5cdFx0XHRcdGNvbm5QYXJhbXMsXG5cdFx0XHRcdGF1dGhEYXRhLFxuXHRcdFx0KTtcblx0XHR9IGVsc2UgaWYgKHVybC5wYXRobmFtZS5zdGFydHNXaXRoKFBBVEhfUkFXX1dFQlNPQ0tFVF9QUkVGSVgpKSB7XG5cdFx0XHR3c0hhbmRsZXJQcm9taXNlID0gaGFuZGxlUmF3V2ViU29ja2V0SGFuZGxlcihcblx0XHRcdFx0cmVxdWVzdCxcblx0XHRcdFx0dXJsLnBhdGhuYW1lICsgdXJsLnNlYXJjaCxcblx0XHRcdFx0dGhpcyxcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0YXV0aERhdGEsXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYFVucmVhY2hhYmxlIHBhdGg6ICR7dXJsLnBhdGhuYW1lfWApO1xuXHRcdH1cblxuXHRcdC8vIFRPRE86IEFkZCBjbG9zZVxuXG5cdFx0Ly8gQ29ubmVjdCB0aGUgSG9ubyBXUyBob29rIHRvIHRoZSBhZGFwdGVyXG5cdFx0Y29uc3Qgd3NDb250ZXh0ID0gbmV3IFdTQ29udGV4dCh3ZWJzb2NrZXQpO1xuXG5cdFx0d3NIYW5kbGVyUHJvbWlzZS5jYXRjaCgoZXJyKSA9PiB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImJ1aWxkaW5nIHdlYnNvY2tldCBoYW5kbGVycyBlcnJvcmVkXCIsIHsgZXJyIH0pO1xuXHRcdFx0d3NDb250ZXh0LmNsb3NlKDEwMTEsIGAke2Vycn1gKTtcblx0XHR9KTtcblxuXHRcdGlmICh3ZWJzb2NrZXQucmVhZHlTdGF0ZSA9PT0gMSkge1xuXHRcdFx0d3NIYW5kbGVyUHJvbWlzZS50aGVuKCh4KSA9PiB4Lm9uT3Blbj8uKG5ldyBFdmVudChcIm9wZW5cIiksIHdzQ29udGV4dCkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcIm9wZW5cIiwgKGV2ZW50KSA9PiB7XG5cdFx0XHRcdHdzSGFuZGxlclByb21pc2UudGhlbigoeCkgPT4geC5vbk9wZW4/LihldmVudCwgd3NDb250ZXh0KSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGV2ZW50KSA9PiB7XG5cdFx0XHR3c0hhbmRsZXJQcm9taXNlLnRoZW4oKHgpID0+IHgub25NZXNzYWdlPy4oZXZlbnQsIHdzQ29udGV4dCkpO1xuXHRcdH0pO1xuXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCAoZXZlbnQpID0+IHtcblx0XHRcdHdzSGFuZGxlclByb21pc2UudGhlbigoeCkgPT4geC5vbkNsb3NlPy4oZXZlbnQsIHdzQ29udGV4dCkpO1xuXHRcdH0pO1xuXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCAoZXZlbnQpID0+IHtcblx0XHRcdHdzSGFuZGxlclByb21pc2UudGhlbigoeCkgPT4geC5vbkVycm9yPy4oZXZlbnQsIHdzQ29udGV4dCkpO1xuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgc2xlZXAoYWN0b3JJZDogc3RyaW5nKSB7XG5cdFx0dGhpcy4jcnVubmVyLnNsZWVwQWN0b3IoYWN0b3JJZCk7XG5cdH1cblxuXHRhc3luYyBzaHV0ZG93bihpbW1lZGlhdGU6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRsb2dnZXIoKS5pbmZvKFwic3RvcHBpbmcgZW5naW5lIGFjdG9yIGRyaXZlclwiKTtcblx0XHRhd2FpdCB0aGlzLiNydW5uZXIuc2h1dGRvd24oaW1tZWRpYXRlKTtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnkvcnVuLWNvbmZpZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeS9ydW4tY29uZmlnLnRzXCI7aW1wb3J0IHR5cGUgeyBjb3JzIH0gZnJvbSBcImhvbm8vY29yc1wiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JEcml2ZXJCdWlsZGVyIH0gZnJvbSBcIkAvYWN0b3IvZHJpdmVyXCI7XG5pbXBvcnQgeyBJbnNwZWN0b3JDb25maWdTY2hlbWEgfSBmcm9tIFwiQC9pbnNwZWN0b3IvY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IE1hbmFnZXJEcml2ZXJCdWlsZGVyIH0gZnJvbSBcIkAvbWFuYWdlci9kcml2ZXJcIjtcbmltcG9ydCB0eXBlIHsgVXBncmFkZVdlYlNvY2tldCB9IGZyb20gXCJAL3V0aWxzXCI7XG5cbnR5cGUgQ29yc09wdGlvbnMgPSBOb25OdWxsYWJsZTxQYXJhbWV0ZXJzPHR5cGVvZiBjb3JzPlswXT47XG5cbmV4cG9ydCB0eXBlIEdldFVwZ3JhZGVXZWJTb2NrZXQgPSAoKSA9PiBVcGdyYWRlV2ViU29ja2V0O1xuXG5leHBvcnQgY29uc3QgRHJpdmVyQ29uZmlnU2NoZW1hID0gei5vYmplY3Qoe1xuXHQvKiogTWFjaGluZS1yZWFkYWJsZSBuYW1lIHRvIGlkZW50aWZ5IHRoaXMgZHJpdmVyIGJ5LiAqL1xuXHRuYW1lOiB6LnN0cmluZygpLFxuXHRtYW5hZ2VyOiB6LmN1c3RvbTxNYW5hZ2VyRHJpdmVyQnVpbGRlcj4oKSxcblx0YWN0b3I6IHouY3VzdG9tPEFjdG9yRHJpdmVyQnVpbGRlcj4oKSxcbn0pO1xuXG5leHBvcnQgdHlwZSBEcml2ZXJDb25maWcgPSB6LmluZmVyPHR5cGVvZiBEcml2ZXJDb25maWdTY2hlbWE+O1xuXG4vKiogQmFzZSBjb25maWcgdXNlZCBmb3IgdGhlIGFjdG9yIGNvbmZpZyBhY3Jvc3MgYWxsIHBsYXRmb3Jtcy4gKi9cbmV4cG9ydCBjb25zdCBSdW5Db25maWdTY2hlbWEgPSB6XG5cdC5vYmplY3Qoe1xuXHRcdGRyaXZlcjogRHJpdmVyQ29uZmlnU2NoZW1hLm9wdGlvbmFsKCksXG5cblx0XHQvKiogRW5kcG9pbnQgdG8gY29ubmVjdCB0byB0aGUgUml2ZXQgZW5naW5lLiBDYW4gYmUgY29uZmlndXJlZCB2aWEgUklWRVRfRU5HSU5FIGVudiB2YXIuICovXG5cdFx0ZW5naW5lOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG5cblx0XHQvLyBUaGlzIGlzIGEgZnVuY3Rpb24gdG8gYWxsb3cgZm9yIGxhenkgY29uZmlndXJhdGlvbiBvZiB1cGdyYWRlV2ViU29ja2V0IG9uIHRoZVxuXHRcdC8vIGZseS4gVGhpcyBpcyByZXF1aXJlZCBzaW5jZSB0aGUgZGVwZW5kZW5jaWVzIHRoYXQgcHJvZmllIHVwZ3JhZGVXZWJTb2NrZXRcblx0XHQvLyAoc3BlY2lmaWNhbGx5IE5vZGUuanMpIGNhbiBzb21ldGltZXMgb25seSBiZSBzcGVjaWZpZWQgYWZ0ZXIgdGhlIHJvdXRlciBpc1xuXHRcdC8vIGNyZWF0ZWQgb3IgbXVzdCBiZSBpbXBvcnRlZCBhc3luYyB1c2luZyBgYXdhaXQgaW1wb3J0KC4uLilgXG5cdFx0Z2V0VXBncmFkZVdlYlNvY2tldDogei5jdXN0b208R2V0VXBncmFkZVdlYlNvY2tldD4oKS5vcHRpb25hbCgpLFxuXG5cdFx0cm9sZTogei5lbnVtKFtcImFsbFwiLCBcInNlcnZlclwiLCBcInJ1bm5lclwiXSkub3B0aW9uYWwoKS5kZWZhdWx0KFwiYWxsXCIpLFxuXG5cdFx0LyoqIENPUlMgY29uZmlndXJhdGlvbiBmb3IgdGhlIHJvdXRlci4gVXNlcyBIb25vJ3MgQ09SUyBtaWRkbGV3YXJlIG9wdGlvbnMuICovXG5cdFx0Y29yczogei5jdXN0b208Q29yc09wdGlvbnM+KCkub3B0aW9uYWwoKSxcblxuXHRcdG1heEluY29taW5nTWVzc2FnZVNpemU6IHoubnVtYmVyKCkub3B0aW9uYWwoKS5kZWZhdWx0KDY1XzUzNiksXG5cblx0XHRpbnNwZWN0b3I6IEluc3BlY3RvckNvbmZpZ1NjaGVtYSxcblxuXHRcdC8qKlxuXHRcdCAqIEJhc2UgcGF0aCBmb3IgdGhlIHJvdXRlci4gVGhpcyBpcyB1c2VkIHRvIHByZWZpeCBhbGwgcm91dGVzLlxuXHRcdCAqIEZvciBleGFtcGxlLCBpZiB0aGUgYmFzZSBwYXRoIGlzIGAvYXBpYCwgdGhlbiB0aGUgcm91dGUgYC9hY3RvcnNgIHdpbGwgYmVcblx0XHQgKiBhdmFpbGFibGUgYXQgYC9hcGkvYWN0b3JzYC5cblx0XHQgKi9cblx0XHRiYXNlUGF0aDogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlZmF1bHQoXCIvXCIpLFxuXHR9KVxuXHQuZGVmYXVsdCh7fSk7XG5cbmV4cG9ydCB0eXBlIFJ1bkNvbmZpZyA9IHouaW5mZXI8dHlwZW9mIFJ1bkNvbmZpZ1NjaGVtYT47XG5leHBvcnQgdHlwZSBSdW5Db25maWdJbnB1dCA9IHouaW5wdXQ8dHlwZW9mIFJ1bkNvbmZpZ1NjaGVtYT47XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvY29uZmlnLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2luc3BlY3RvclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvY29uZmlnLnRzXCI7aW1wb3J0IHR5cGUgeyBjb3JzIH0gZnJvbSBcImhvbm8vY29yc1wiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IEhFQURFUl9BQ1RPUl9RVUVSWSB9IGZyb20gXCJAL2RyaXZlci1oZWxwZXJzL21vZFwiO1xuaW1wb3J0IHsgZ2V0RW52VW5pdmVyc2FsIH0gZnJvbSBcIkAvdXRpbHNcIjtcblxudHlwZSBDb3JzT3B0aW9ucyA9IE5vbk51bGxhYmxlPFBhcmFtZXRlcnM8dHlwZW9mIGNvcnM+WzBdPjtcblxuY29uc3QgZGVmYXVsdFRva2VuRm4gPSAoKSA9PiB7XG5cdGNvbnN0IGVudlRva2VuID0gZ2V0RW52VW5pdmVyc2FsKFwiUklWRVRLSVRfSU5TUEVDVE9SX1RPS0VOXCIpO1xuXG5cdGlmIChlbnZUb2tlbikge1xuXHRcdHJldHVybiBlbnZUb2tlbjtcblx0fVxuXG5cdHJldHVybiBcIlwiO1xufTtcblxuY29uc3QgZGVmYXVsdEVuYWJsZWQgPSAoKSA9PiB7XG5cdHJldHVybiAoXG5cdFx0Z2V0RW52VW5pdmVyc2FsKFwiTk9ERV9FTlZcIikgIT09IFwicHJvZHVjdGlvblwiIHx8XG5cdFx0IWdldEVudlVuaXZlcnNhbChcIlJJVkVUS0lUX0lOU1BFQ1RPUl9ESVNBQkxFXCIpXG5cdCk7XG59O1xuXG5jb25zdCBkZWZhdWx0SW5zcGVjdG9yT3JpZ2lucyA9IFtcblx0XCJodHRwOi8vbG9jYWxob3N0OjQzNzA4XCIsXG5cdFwiaHR0cHM6Ly9zdHVkaW8ucml2ZXQuZ2dcIixcbl07XG5cbmNvbnN0IGRlZmF1bHRDb3JzOiBDb3JzT3B0aW9ucyA9IHtcblx0b3JpZ2luOiAob3JpZ2luKSA9PiB7XG5cdFx0aWYgKFxuXHRcdFx0ZGVmYXVsdEluc3BlY3Rvck9yaWdpbnMuaW5jbHVkZXMob3JpZ2luKSB8fFxuXHRcdFx0KG9yaWdpbi5zdGFydHNXaXRoKFwiaHR0cHM6Ly9cIikgJiYgb3JpZ2luLmVuZHNXaXRoKFwicml2ZXQtZ2cudmVyY2VsLmFwcFwiKSlcblx0XHQpIHtcblx0XHRcdHJldHVybiBvcmlnaW47XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0fSxcblx0YWxsb3dNZXRob2RzOiBbXCJHRVRcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiUEFUQ0hcIiwgXCJERUxFVEVcIiwgXCJPUFRJT05TXCJdLFxuXHRhbGxvd0hlYWRlcnM6IFtcblx0XHRcIkNvbnRlbnQtVHlwZVwiLFxuXHRcdFwiQXV0aG9yaXphdGlvblwiLFxuXHRcdEhFQURFUl9BQ1RPUl9RVUVSWSxcblx0XHRcImxhc3QtZXZlbnQtaWRcIixcblx0XSxcblx0bWF4QWdlOiAzNjAwLFxuXHRjcmVkZW50aWFsczogdHJ1ZSxcbn07XG5cbmV4cG9ydCBjb25zdCBJbnNwZWN0b3JDb25maWdTY2hlbWEgPSB6XG5cdC5vYmplY3Qoe1xuXHRcdGVuYWJsZWQ6IHouYm9vbGVhbigpLm9wdGlvbmFsKCkuZGVmYXVsdChkZWZhdWx0RW5hYmxlZCksXG5cdFx0LyoqIENPUlMgY29uZmlndXJhdGlvbiBmb3IgdGhlIHJvdXRlci4gVXNlcyBIb25vJ3MgQ09SUyBtaWRkbGV3YXJlIG9wdGlvbnMuICovXG5cdFx0Y29yczogelxuXHRcdFx0LmN1c3RvbTxDb3JzT3B0aW9ucz4oKVxuXHRcdFx0Lm9wdGlvbmFsKClcblx0XHRcdC5kZWZhdWx0KCgpID0+IGRlZmF1bHRDb3JzKSxcblxuXHRcdC8qKlxuXHRcdCAqIFRva2VuIHVzZWQgdG8gYWNjZXNzIHRoZSBJbnNwZWN0b3IuXG5cdFx0ICovXG5cdFx0dG9rZW46IHpcblx0XHRcdC5mdW5jdGlvbigpXG5cdFx0XHQucmV0dXJucyh6LnN0cmluZygpKVxuXHRcdFx0Lm9wdGlvbmFsKClcblx0XHRcdC5kZWZhdWx0KCgpID0+IGRlZmF1bHRUb2tlbkZuKSxcblxuXHRcdC8qKlxuXHRcdCAqIERlZmF1bHQgUml2ZXRLaXQgc2VydmVyIGVuZHBvaW50IGZvciBSaXZldCBJbnNwZWN0b3IgdG8gY29ubmVjdCB0by4gVGhpcyBzaG91bGQgYmUgdGhlIHNhbWUgZW5kcG9pbnQgYXMgd2hhdCB5b3UgdXNlIGZvciB5b3VyIFJpdmV0IGNsaWVudCB0byBjb25uZWN0IHRvIFJpdmV0S2l0LlxuXHRcdCAqXG5cdFx0ICogVGhpcyBpcyBhIGNvbnZlbmllbmNlIHByb3BlcnR5IGp1c3QgZm9yIHByaW50aW5nIG91dCB0aGUgaW5zcGVjdG9yIFVSTC5cblx0XHQgKi9cblx0XHRkZWZhdWx0RW5kcG9pbnQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcblx0fSlcblx0Lm9wdGlvbmFsKClcblx0LmRlZmF1bHQoKCkgPT4gKHtcblx0XHRlbmFibGVkOiBkZWZhdWx0RW5hYmxlZCgpLFxuXHRcdHRva2VuOiBkZWZhdWx0VG9rZW5Gbixcblx0XHRjb3JzOiBkZWZhdWx0Q29ycyxcblx0fSkpO1xuZXhwb3J0IHR5cGUgSW5zcGVjdG9yQ29uZmlnID0gei5pbmZlcjx0eXBlb2YgSW5zcGVjdG9yQ29uZmlnU2NoZW1hPjtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlci1oZWxwZXJzL3V0aWxzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlci1oZWxwZXJzXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlci1oZWxwZXJzL3V0aWxzLnRzXCI7aW1wb3J0ICogYXMgY2JvciBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgdHlwZSAqIGFzIHNjaGVtYSBmcm9tIFwiQC9zY2hlbWFzL2FjdG9yLXBlcnNpc3QvbW9kXCI7XG5pbXBvcnQgeyBQRVJTSVNURURfQUNUT1JfVkVSU0lPTkVEIH0gZnJvbSBcIkAvc2NoZW1hcy9hY3Rvci1wZXJzaXN0L3ZlcnNpb25lZFwiO1xuaW1wb3J0IHsgYnVmZmVyVG9BcnJheUJ1ZmZlciB9IGZyb20gXCJAL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemVFbXB0eVBlcnNpc3REYXRhKFxuXHRpbnB1dDogdW5rbm93biB8IHVuZGVmaW5lZCxcbik6IFVpbnQ4QXJyYXkge1xuXHRjb25zdCBwZXJzaXN0RGF0YTogc2NoZW1hLlBlcnNpc3RlZEFjdG9yID0ge1xuXHRcdGlucHV0OiBpbnB1dCAhPT0gdW5kZWZpbmVkID8gYnVmZmVyVG9BcnJheUJ1ZmZlcihjYm9yLmVuY29kZShpbnB1dCkpIDogbnVsbCxcblx0XHRoYXNJbml0aWFsaXplZDogZmFsc2UsXG5cdFx0c3RhdGU6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUodW5kZWZpbmVkKSksXG5cdFx0Y29ubmVjdGlvbnM6IFtdLFxuXHRcdHNjaGVkdWxlZEV2ZW50czogW10sXG5cdH07XG5cdHJldHVybiBQRVJTSVNURURfQUNUT1JfVkVSU0lPTkVELnNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24ocGVyc2lzdERhdGEpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUva2V5cy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZS9rZXlzLnRzXCI7aW1wb3J0IHR5cGUgeyBBY3RvcktleSB9IGZyb20gXCJAL21vZFwiO1xuXG5leHBvcnQgY29uc3QgRU1QVFlfS0VZID0gXCIvXCI7XG5leHBvcnQgY29uc3QgS0VZX1NFUEFSQVRPUiA9IFwiL1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplQWN0b3JLZXkoa2V5OiBBY3RvcktleSk6IHN0cmluZyB7XG5cdC8vIFVzZSBhIHNwZWNpYWwgbWFya2VyIGZvciBlbXB0eSBrZXkgYXJyYXlzXG5cdGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG5cdFx0cmV0dXJuIEVNUFRZX0tFWTtcblx0fVxuXG5cdC8vIEVzY2FwZSBlYWNoIGtleSBwYXJ0IHRvIGhhbmRsZSB0aGUgc2VwYXJhdG9yIGFuZCB0aGUgZW1wdHkga2V5IG1hcmtlclxuXHRjb25zdCBlc2NhcGVkUGFydHMgPSBrZXkubWFwKChwYXJ0KSA9PiB7XG5cdFx0Ly8gSGFuZGxlIGVtcHR5IHN0cmluZ3MgYnkgdXNpbmcgYSBzcGVjaWFsIG1hcmtlclxuXHRcdGlmIChwYXJ0ID09PSBcIlwiKSB7XG5cdFx0XHRyZXR1cm4gXCJcXFxcMFwiOyAvLyBVc2UgXFwwIGFzIGEgbWFya2VyIGZvciBlbXB0eSBzdHJpbmdzXG5cdFx0fVxuXG5cdFx0Ly8gRXNjYXBlIGJhY2tzbGFzaGVzIGZpcnN0IHRvIGF2b2lkIGNvbmZsaWN0cyB3aXRoIG91ciBtYXJrZXJzXG5cdFx0bGV0IGVzY2FwZWQgPSBwYXJ0LnJlcGxhY2UoL1xcXFwvZywgXCJcXFxcXFxcXFwiKTtcblxuXHRcdC8vIFRoZW4gZXNjYXBlIHNlcGFyYXRvcnNcblx0XHRlc2NhcGVkID0gZXNjYXBlZC5yZXBsYWNlKC9cXC8vZywgYFxcXFwke0tFWV9TRVBBUkFUT1J9YCk7XG5cblx0XHRyZXR1cm4gZXNjYXBlZDtcblx0fSk7XG5cblx0cmV0dXJuIGVzY2FwZWRQYXJ0cy5qb2luKEtFWV9TRVBBUkFUT1IpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemVBY3RvcktleShrZXlTdHJpbmc6IHN0cmluZyB8IHVuZGVmaW5lZCk6IEFjdG9yS2V5IHtcblx0Ly8gQ2hlY2sgZm9yIHNwZWNpYWwgZW1wdHkga2V5IG1hcmtlclxuXHRpZiAoXG5cdFx0a2V5U3RyaW5nID09PSB1bmRlZmluZWQgfHxcblx0XHRrZXlTdHJpbmcgPT09IG51bGwgfHxcblx0XHRrZXlTdHJpbmcgPT09IEVNUFRZX0tFWVxuXHQpIHtcblx0XHRyZXR1cm4gW107XG5cdH1cblxuXHQvLyBTcGxpdCBieSB1bmVzY2FwZWQgc2VwYXJhdG9ycyBhbmQgdW5lc2NhcGUgdGhlIGVzY2FwZWQgY2hhcmFjdGVyc1xuXHRjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcblx0bGV0IGN1cnJlbnRQYXJ0ID0gXCJcIjtcblx0bGV0IGVzY2FwaW5nID0gZmFsc2U7XG5cdGxldCBpc0VtcHR5U3RyaW5nTWFya2VyID0gZmFsc2U7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlTdHJpbmcubGVuZ3RoOyBpKyspIHtcblx0XHRjb25zdCBjaGFyID0ga2V5U3RyaW5nW2ldO1xuXG5cdFx0aWYgKGVzY2FwaW5nKSB7XG5cdFx0XHQvLyBIYW5kbGUgc3BlY2lhbCBlc2NhcGUgc2VxdWVuY2VzXG5cdFx0XHRpZiAoY2hhciA9PT0gXCIwXCIpIHtcblx0XHRcdFx0Ly8gXFwwIHJlcHJlc2VudHMgYW4gZW1wdHkgc3RyaW5nIG1hcmtlclxuXHRcdFx0XHRpc0VtcHR5U3RyaW5nTWFya2VyID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIFRoaXMgaXMgYW4gZXNjYXBlZCBjaGFyYWN0ZXIsIGFkZCBpdCBkaXJlY3RseVxuXHRcdFx0XHRjdXJyZW50UGFydCArPSBjaGFyO1xuXHRcdFx0fVxuXHRcdFx0ZXNjYXBpbmcgPSBmYWxzZTtcblx0XHR9IGVsc2UgaWYgKGNoYXIgPT09IFwiXFxcXFwiKSB7XG5cdFx0XHQvLyBTdGFydCBvZiBhbiBlc2NhcGUgc2VxdWVuY2Vcblx0XHRcdGVzY2FwaW5nID0gdHJ1ZTtcblx0XHR9IGVsc2UgaWYgKGNoYXIgPT09IEtFWV9TRVBBUkFUT1IpIHtcblx0XHRcdC8vIFRoaXMgaXMgYSBzZXBhcmF0b3Jcblx0XHRcdGlmIChpc0VtcHR5U3RyaW5nTWFya2VyKSB7XG5cdFx0XHRcdHBhcnRzLnB1c2goXCJcIik7XG5cdFx0XHRcdGlzRW1wdHlTdHJpbmdNYXJrZXIgPSBmYWxzZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHBhcnRzLnB1c2goY3VycmVudFBhcnQpO1xuXHRcdFx0fVxuXHRcdFx0Y3VycmVudFBhcnQgPSBcIlwiO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBSZWd1bGFyIGNoYXJhY3RlclxuXHRcdFx0Y3VycmVudFBhcnQgKz0gY2hhcjtcblx0XHR9XG5cdH1cblxuXHQvLyBBZGQgdGhlIGxhc3QgcGFydFxuXHRpZiAoZXNjYXBpbmcpIHtcblx0XHQvLyBJbmNvbXBsZXRlIGVzY2FwZSBhdCB0aGUgZW5kIC0gdHJlYXQgYXMgbGl0ZXJhbCBiYWNrc2xhc2hcblx0XHRwYXJ0cy5wdXNoKGN1cnJlbnRQYXJ0ICsgXCJcXFxcXCIpO1xuXHR9IGVsc2UgaWYgKGlzRW1wdHlTdHJpbmdNYXJrZXIpIHtcblx0XHRwYXJ0cy5wdXNoKFwiXCIpO1xuXHR9IGVsc2UgaWYgKGN1cnJlbnRQYXJ0ICE9PSBcIlwiIHx8IHBhcnRzLmxlbmd0aCA+IDApIHtcblx0XHRwYXJ0cy5wdXNoKGN1cnJlbnRQYXJ0KTtcblx0fVxuXG5cdHJldHVybiBwYXJ0cztcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL2t2LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL2t2LnRzXCI7ZXhwb3J0IGNvbnN0IEtFWVMgPSB7XG5cdFBFUlNJU1RfREFUQTogVWludDhBcnJheS5mcm9tKFsxLCAxXSksXG59O1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvbG9nLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL2xvZy50c1wiO2ltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAL2NvbW1vbi9sb2dcIjtcblxuZXhwb3J0IGNvbnN0IExPR0dFUl9OQU1FID0gXCJkcml2ZXItZW5naW5lXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dnZXIoKSB7XG5cdHJldHVybiBnZXRMb2dnZXIoTE9HR0VSX05BTUUpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvY29uZmlnLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL2NvbmZpZy50c1wiO2ltcG9ydCB0eXBlIHsgSG9ubyB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgZ2V0RW52VW5pdmVyc2FsIH0gZnJvbSBcIkAvdXRpbHNcIjtcblxuZXhwb3J0IGNvbnN0IENvbmZpZ1NjaGVtYSA9IHpcblx0Lm9iamVjdCh7XG5cdFx0YXBwOiB6LmN1c3RvbTxIb25vPigpLm9wdGlvbmFsKCksXG5cdFx0ZW5kcG9pbnQ6IHpcblx0XHRcdC5zdHJpbmcoKVxuXHRcdFx0LmRlZmF1bHQoXG5cdFx0XHRcdCgpID0+IGdldEVudlVuaXZlcnNhbChcIlJJVkVUX0VOR0lORVwiKSA/PyBcImh0dHA6Ly9sb2NhbGhvc3Q6NzA4MFwiLFxuXHRcdFx0KSxcblx0XHRwZWdib2FyZEVuZHBvaW50OiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG5cdFx0bmFtZXNwYWNlOiB6XG5cdFx0XHQuc3RyaW5nKClcblx0XHRcdC5kZWZhdWx0KCgpID0+IGdldEVudlVuaXZlcnNhbChcIlJJVkVUX05BTUVTUEFDRVwiKSA/PyBcImRlZmF1bHRcIiksXG5cdFx0cnVubmVyTmFtZTogelxuXHRcdFx0LnN0cmluZygpXG5cdFx0XHQuZGVmYXVsdCgoKSA9PiBnZXRFbnZVbml2ZXJzYWwoXCJSSVZFVF9SVU5ORVJcIikgPz8gXCJyaXZldGtpdFwiKSxcblx0XHQvLyBUT0RPOiBBdXRvbWF0aWNhbGx5IGF0dGVtcHQgb3QgZGV0ZXJtaW5lIGtleSBieSBjb21tb24gZW52IHZhcnMgKGUuZy4gazhzIHBvZCBuYW1lKVxuXHRcdHJ1bm5lcktleTogelxuXHRcdFx0LnN0cmluZygpXG5cdFx0XHQuZGVmYXVsdChcblx0XHRcdFx0KCkgPT4gZ2V0RW52VW5pdmVyc2FsKFwiUklWRVRfUlVOTkVSX0tFWVwiKSA/PyBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuXHRcdFx0KSxcblx0XHR0b3RhbFNsb3RzOiB6Lm51bWJlcigpLmRlZmF1bHQoMTAwXzAwMCksXG5cdFx0YWRkcmVzc2VzOiB6XG5cdFx0XHQucmVjb3JkKFxuXHRcdFx0XHR6Lm9iamVjdCh7XG5cdFx0XHRcdFx0aG9zdDogei5zdHJpbmcoKSxcblx0XHRcdFx0XHRwb3J0OiB6Lm51bWJlcigpLFxuXHRcdFx0XHR9KSxcblx0XHRcdClcblx0XHRcdC5kZWZhdWx0KHsgbWFpbjogeyBob3N0OiBcIjEyNy4wLjAuMVwiLCBwb3J0OiA1MDUxIH0gfSksXG5cdH0pXG5cdC5kZWZhdWx0KHt9KTtcblxuZXhwb3J0IHR5cGUgSW5wdXRDb25maWcgPSB6LmlucHV0PHR5cGVvZiBDb25maWdTY2hlbWE+O1xuZXhwb3J0IHR5cGUgQ29uZmlnID0gei5pbmZlcjx0eXBlb2YgQ29uZmlnU2NoZW1hPjtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL21hbmFnZXItZHJpdmVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL21hbmFnZXItZHJpdmVyLnRzXCI7aW1wb3J0ICogYXMgY2JvciBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSG9ub0NvbnRleHQgfSBmcm9tIFwiaG9ub1wiO1xuaW1wb3J0IGludmFyaWFudCBmcm9tIFwiaW52YXJpYW50XCI7XG5pbXBvcnQgeyBBY3RvckFscmVhZHlFeGlzdHMgfSBmcm9tIFwiQC9hY3Rvci9lcnJvcnNcIjtcbmltcG9ydCB7XG5cdEhFQURFUl9BVVRIX0RBVEEsXG5cdEhFQURFUl9DT05OX1BBUkFNUyxcblx0SEVBREVSX0VOQ09ESU5HLFxuXHRIRUFERVJfRVhQT1NFX0lOVEVSTkFMX0VSUk9SLFxufSBmcm9tIFwiQC9hY3Rvci9yb3V0ZXItZW5kcG9pbnRzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZVJhbmRvbVN0cmluZyB9IGZyb20gXCJAL2FjdG9yL3V0aWxzXCI7XG5pbXBvcnQgeyBpbXBvcnRXZWJTb2NrZXQgfSBmcm9tIFwiQC9jb21tb24vd2Vic29ja2V0XCI7XG5pbXBvcnQgdHlwZSB7XG5cdEFjdG9yT3V0cHV0LFxuXHRDcmVhdGVJbnB1dCxcblx0R2V0Rm9ySWRJbnB1dCxcblx0R2V0T3JDcmVhdGVXaXRoS2V5SW5wdXQsXG5cdEdldFdpdGhLZXlJbnB1dCxcblx0TWFuYWdlckRyaXZlcixcbn0gZnJvbSBcIkAvZHJpdmVyLWhlbHBlcnMvbW9kXCI7XG5pbXBvcnQgeyB0eXBlIEVuY29kaW5nLCBub29wTmV4dCwgdHlwZSBSdW5Db25maWcgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB7XG5cdGNyZWF0ZUFjdG9yLFxuXHRkZXN0cm95QWN0b3IsXG5cdGdldEFjdG9yLFxuXHRnZXRBY3RvckJ5SWQsXG5cdGdldE9yQ3JlYXRlQWN0b3JCeUlkLFxufSBmcm9tIFwiLi9hcGktZW5kcG9pbnRzXCI7XG5pbXBvcnQgeyBFbmdpbmVBcGlFcnJvciB9IGZyb20gXCIuL2FwaS11dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBDb25maWcgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB7IGRlc2VyaWFsaXplQWN0b3JLZXksIHNlcmlhbGl6ZUFjdG9yS2V5IH0gZnJvbSBcIi4va2V5c1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgeyBjcmVhdGVXZWJTb2NrZXRQcm94eSB9IGZyb20gXCIuL3dzLXByb3h5XCI7XG5cbmV4cG9ydCBjbGFzcyBFbmdpbmVNYW5hZ2VyRHJpdmVyIGltcGxlbWVudHMgTWFuYWdlckRyaXZlciB7XG5cdCNjb25maWc6IENvbmZpZztcblx0I3J1bkNvbmZpZzogUnVuQ29uZmlnO1xuXHQjaW1wb3J0V2ViU29ja2V0UHJvbWlzZTogUHJvbWlzZTx0eXBlb2YgV2ViU29ja2V0PjtcblxuXHRjb25zdHJ1Y3Rvcihjb25maWc6IENvbmZpZywgcnVuQ29uZmlnOiBSdW5Db25maWcpIHtcblx0XHR0aGlzLiNjb25maWcgPSBjb25maWc7XG5cdFx0dGhpcy4jcnVuQ29uZmlnID0gcnVuQ29uZmlnO1xuXHRcdGlmICghdGhpcy4jcnVuQ29uZmlnLmluc3BlY3Rvci50b2tlbigpKSB7XG5cdFx0XHRjb25zdCB0b2tlbiA9IGdlbmVyYXRlUmFuZG9tU3RyaW5nKCk7XG5cdFx0XHR0aGlzLiNydW5Db25maWcuaW5zcGVjdG9yLnRva2VuID0gKCkgPT4gdG9rZW47XG5cdFx0fVxuXHRcdHRoaXMuI2ltcG9ydFdlYlNvY2tldFByb21pc2UgPSBpbXBvcnRXZWJTb2NrZXQoKTtcblx0fVxuXG5cdGFzeW5jIHNlbmRSZXF1ZXN0KGFjdG9ySWQ6IHN0cmluZywgYWN0b3JSZXF1ZXN0OiBSZXF1ZXN0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwic2VuZGluZyByZXF1ZXN0IHRvIGFjdG9yIHZpYSBndWFyZFwiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bWV0aG9kOiBhY3RvclJlcXVlc3QubWV0aG9kLFxuXHRcdFx0dXJsOiBhY3RvclJlcXVlc3QudXJsLFxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHRoaXMuI2ZvcndhcmRIdHRwUmVxdWVzdChhY3RvclJlcXVlc3QsIGFjdG9ySWQpO1xuXHR9XG5cblx0YXN5bmMgb3BlbldlYlNvY2tldChcblx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0YWN0b3JJZDogc3RyaW5nLFxuXHRcdGVuY29kaW5nOiBFbmNvZGluZyxcblx0XHRwYXJhbXM6IHVua25vd24sXG5cdCk6IFByb21pc2U8V2ViU29ja2V0PiB7XG5cdFx0Y29uc3QgV2ViU29ja2V0ID0gYXdhaXQgdGhpcy4jaW1wb3J0V2ViU29ja2V0UHJvbWlzZTtcblxuXHRcdC8vIFdlYlNvY2tldCBjb25uZWN0aW9ucyBnbyB0aHJvdWdoIGd1YXJkXG5cdFx0Y29uc3QgZ3VhcmRVcmwgPSBgJHt0aGlzLiNjb25maWcuZW5kcG9pbnR9JHtwYXRofWA7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcIm9wZW5pbmcgd2Vic29ja2V0IHRvIGFjdG9yIHZpYSBndWFyZFwiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0cGF0aCxcblx0XHRcdGd1YXJkVXJsLFxuXHRcdH0pO1xuXG5cdFx0Ly8gQ3JlYXRlIFdlYlNvY2tldCBjb25uZWN0aW9uXG5cdFx0Y29uc3Qgd3MgPSBuZXcgV2ViU29ja2V0KGd1YXJkVXJsLCB7XG5cdFx0XHRoZWFkZXJzOiBidWlsZEd1YXJkSGVhZGVyc0ZvcldlYlNvY2tldChhY3RvcklkLCBlbmNvZGluZywgcGFyYW1zKSxcblx0XHR9KTtcblxuXHRcdGxvZ2dlcigpLmRlYnVnKFwid2Vic29ja2V0IGNvbm5lY3Rpb24gb3BlbmVkXCIsIHsgYWN0b3JJZCB9KTtcblxuXHRcdHJldHVybiB3cztcblx0fVxuXG5cdGFzeW5jIHByb3h5UmVxdWVzdChcblx0XHRfYzogSG9ub0NvbnRleHQsXG5cdFx0YWN0b3JSZXF1ZXN0OiBSZXF1ZXN0LFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZm9yd2FyZGluZyByZXF1ZXN0IHRvIGFjdG9yIHZpYSBndWFyZFwiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bWV0aG9kOiBhY3RvclJlcXVlc3QubWV0aG9kLFxuXHRcdFx0dXJsOiBhY3RvclJlcXVlc3QudXJsLFxuXHRcdFx0aGFzQm9keTogISFhY3RvclJlcXVlc3QuYm9keSxcblx0XHR9KTtcblxuXHRcdHJldHVybiB0aGlzLiNmb3J3YXJkSHR0cFJlcXVlc3QoYWN0b3JSZXF1ZXN0LCBhY3RvcklkKTtcblx0fVxuXG5cdGFzeW5jIHByb3h5V2ViU29ja2V0KFxuXHRcdGM6IEhvbm9Db250ZXh0LFxuXHRcdHBhdGg6IHN0cmluZyxcblx0XHRhY3RvcklkOiBzdHJpbmcsXG5cdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0XHRhdXRoRGF0YTogdW5rbm93bixcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdGNvbnN0IHVwZ3JhZGVXZWJTb2NrZXQgPSB0aGlzLiNydW5Db25maWcuZ2V0VXBncmFkZVdlYlNvY2tldD8uKCk7XG5cdFx0aW52YXJpYW50KHVwZ3JhZGVXZWJTb2NrZXQsIFwibWlzc2luZyBnZXRVcGdyYWRlV2ViU29ja2V0XCIpO1xuXG5cdFx0Y29uc3QgZ3VhcmRVcmwgPSBgJHt0aGlzLiNjb25maWcuZW5kcG9pbnR9JHtwYXRofWA7XG5cdFx0Y29uc3Qgd3NHdWFyZFVybCA9IGd1YXJkVXJsLnJlcGxhY2UoXCJodHRwOi8vXCIsIFwid3M6Ly9cIik7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvcndhcmRpbmcgd2Vic29ja2V0IHRvIGFjdG9yIHZpYSBndWFyZFwiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0cGF0aCxcblx0XHRcdGd1YXJkVXJsLFxuXHRcdH0pO1xuXG5cdFx0Ly8gQnVpbGQgaGVhZGVyc1xuXHRcdGNvbnN0IGhlYWRlcnMgPSBidWlsZEd1YXJkSGVhZGVyc0ZvcldlYlNvY2tldChcblx0XHRcdGFjdG9ySWQsXG5cdFx0XHRlbmNvZGluZyxcblx0XHRcdHBhcmFtcyxcblx0XHRcdGF1dGhEYXRhLFxuXHRcdCk7XG5cdFx0Y29uc3QgYXJncyA9IGF3YWl0IGNyZWF0ZVdlYlNvY2tldFByb3h5KGMsIHdzR3VhcmRVcmwsIGhlYWRlcnMpO1xuXG5cdFx0cmV0dXJuIGF3YWl0IHVwZ3JhZGVXZWJTb2NrZXQoKCkgPT4gYXJncykoYywgbm9vcE5leHQoKSk7XG5cdH1cblxuXHRleHRyYVN0YXJ0dXBMb2coKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGVuZ2luZTogdGhpcy4jY29uZmlnLmVuZHBvaW50LFxuXHRcdFx0bmFtZXNwYWNlOiB0aGlzLiNjb25maWcubmFtZXNwYWNlLFxuXHRcdFx0cnVubmVyOiB0aGlzLiNjb25maWcucnVubmVyTmFtZSxcblx0XHRcdGFkZHJlc3M6IE9iamVjdC52YWx1ZXModGhpcy4jY29uZmlnLmFkZHJlc3Nlcylcblx0XHRcdFx0Lm1hcCgodikgPT4gYCR7di5ob3N0fToke3YucG9ydH1gKVxuXHRcdFx0XHQuam9pbihcIiwgXCIpLFxuXHRcdH07XG5cdH1cblxuXHRhc3luYyBnZXRGb3JJZCh7XG5cdFx0Yyxcblx0XHRuYW1lLFxuXHRcdGFjdG9ySWQsXG5cdH06IEdldEZvcklkSW5wdXQpOiBQcm9taXNlPEFjdG9yT3V0cHV0IHwgdW5kZWZpbmVkPiB7XG5cdFx0Ly8gRmV0Y2ggZnJvbSBBUEkgaWYgbm90IGluIGNhY2hlXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZ2V0QWN0b3IodGhpcy4jY29uZmlnLCBhY3RvcklkKTtcblxuXHRcdFx0Ly8gVmFsaWRhdGUgbmFtZSBtYXRjaGVzXG5cdFx0XHRpZiAocmVzcG9uc2UuYWN0b3IubmFtZSAhPT0gbmFtZSkge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImFjdG9yIG5hbWUgbWlzbWF0Y2ggZnJvbSBhcGlcIiwge1xuXHRcdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdFx0YXBpTmFtZTogcmVzcG9uc2UuYWN0b3IubmFtZSxcblx0XHRcdFx0XHRyZXF1ZXN0ZWROYW1lOiBuYW1lLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3Qga2V5UmF3ID0gcmVzcG9uc2UuYWN0b3Iua2V5O1xuXHRcdFx0aW52YXJpYW50KGtleVJhdywgYGFjdG9yICR7YWN0b3JJZH0gc2hvdWxkIGhhdmUga2V5YCk7XG5cdFx0XHRjb25zdCBrZXkgPSBkZXNlcmlhbGl6ZUFjdG9yS2V5KGtleVJhdyk7XG5cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGtleSxcblx0XHRcdH07XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGlmIChcblx0XHRcdFx0ZXJyb3IgaW5zdGFuY2VvZiBFbmdpbmVBcGlFcnJvciAmJlxuXHRcdFx0XHQoZXJyb3IgYXMgRW5naW5lQXBpRXJyb3IpLmdyb3VwID09PSBcImFjdG9yXCIgJiZcblx0XHRcdFx0KGVycm9yIGFzIEVuZ2luZUFwaUVycm9yKS5jb2RlID09PSBcIm5vdF9mb3VuZFwiXG5cdFx0XHQpIHtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGdldFdpdGhLZXkoe1xuXHRcdGMsXG5cdFx0bmFtZSxcblx0XHRrZXksXG5cdH06IEdldFdpdGhLZXlJbnB1dCk6IFByb21pc2U8QWN0b3JPdXRwdXQgfCB1bmRlZmluZWQ+IHtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImdldFdpdGhLZXk6IHNlYXJjaGluZyBmb3IgYWN0b3JcIiwgeyBuYW1lLCBrZXkgfSk7XG5cblx0XHQvLyBJZiBub3QgaW4gbG9jYWwgY2FjaGUsIGZldGNoIGJ5IGtleSBmcm9tIEFQSVxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEFjdG9yQnlJZCh0aGlzLiNjb25maWcsIG5hbWUsIGtleSk7XG5cblx0XHRcdGlmICghcmVzcG9uc2UuYWN0b3JfaWQpIHtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgYWN0b3JJZCA9IHJlc3BvbnNlLmFjdG9yX2lkO1xuXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImdldFdpdGhLZXk6IGZvdW5kIGFjdG9yIHZpYSBhcGlcIiwge1xuXHRcdFx0XHRhY3RvcklkLFxuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRrZXksXG5cdFx0XHR9KTtcblxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0bmFtZSxcblx0XHRcdFx0a2V5LFxuXHRcdFx0fTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0aWYgKFxuXHRcdFx0XHRlcnJvciBpbnN0YW5jZW9mIEVuZ2luZUFwaUVycm9yICYmXG5cdFx0XHRcdChlcnJvciBhcyBFbmdpbmVBcGlFcnJvcikuZ3JvdXAgPT09IFwiYWN0b3JcIiAmJlxuXHRcdFx0XHQoZXJyb3IgYXMgRW5naW5lQXBpRXJyb3IpLmNvZGUgPT09IFwibm90X2ZvdW5kXCJcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgZ2V0T3JDcmVhdGVXaXRoS2V5KFxuXHRcdGlucHV0OiBHZXRPckNyZWF0ZVdpdGhLZXlJbnB1dCxcblx0KTogUHJvbWlzZTxBY3Rvck91dHB1dD4ge1xuXHRcdGNvbnN0IHsgYywgbmFtZSwga2V5LCBpbnB1dDogYWN0b3JJbnB1dCwgcmVnaW9uIH0gPSBpbnB1dDtcblxuXHRcdGxvZ2dlcigpLmluZm8oXG5cdFx0XHRcImdldE9yQ3JlYXRlV2l0aEtleTogZ2V0dGluZyBvciBjcmVhdGluZyBhY3RvciB2aWEgZW5naW5lIGFwaVwiLFxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRrZXksXG5cdFx0XHR9LFxuXHRcdCk7XG5cblx0XHRjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldE9yQ3JlYXRlQWN0b3JCeUlkKHRoaXMuI2NvbmZpZywge1xuXHRcdFx0bmFtZSxcblx0XHRcdGtleTogc2VyaWFsaXplQWN0b3JLZXkoa2V5KSxcblx0XHRcdHJ1bm5lcl9uYW1lX3NlbGVjdG9yOiB0aGlzLiNjb25maWcucnVubmVyTmFtZSxcblx0XHRcdGlucHV0OiBpbnB1dCA/IGNib3IuZW5jb2RlKGFjdG9ySW5wdXQpLnRvU3RyaW5nKFwiYmFzZTY0XCIpIDogdW5kZWZpbmVkLFxuXHRcdFx0Y3Jhc2hfcG9saWN5OiBcInNsZWVwXCIsXG5cdFx0fSk7XG5cblx0XHRjb25zdCBhY3RvcklkID0gcmVzcG9uc2UuYWN0b3JfaWQ7XG5cblx0XHRsb2dnZXIoKS5pbmZvKFwiZ2V0T3JDcmVhdGVXaXRoS2V5OiBhY3RvciByZWFkeVwiLCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bmFtZSxcblx0XHRcdGtleSxcblx0XHRcdGNyZWF0ZWQ6IHJlc3BvbnNlLmNyZWF0ZWQsXG5cdFx0fSk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0YWN0b3JJZCxcblx0XHRcdG5hbWUsXG5cdFx0XHRrZXksXG5cdFx0fTtcblx0fVxuXG5cdGFzeW5jIGNyZWF0ZUFjdG9yKHtcblx0XHRjLFxuXHRcdG5hbWUsXG5cdFx0a2V5LFxuXHRcdGlucHV0LFxuXHR9OiBDcmVhdGVJbnB1dCk6IFByb21pc2U8QWN0b3JPdXRwdXQ+IHtcblx0XHQvLyBDaGVjayBpZiBhY3RvciB3aXRoIHRoZSBzYW1lIG5hbWUgYW5kIGtleSBhbHJlYWR5IGV4aXN0c1xuXHRcdGNvbnN0IGV4aXN0aW5nQWN0b3IgPSBhd2FpdCB0aGlzLmdldFdpdGhLZXkoeyBjLCBuYW1lLCBrZXkgfSk7XG5cdFx0aWYgKGV4aXN0aW5nQWN0b3IpIHtcblx0XHRcdHRocm93IG5ldyBBY3RvckFscmVhZHlFeGlzdHMobmFtZSwga2V5KTtcblx0XHR9XG5cblx0XHRsb2dnZXIoKS5pbmZvKFwiY3JlYXRpbmcgYWN0b3IgdmlhIGVuZ2luZSBhcGlcIiwgeyBuYW1lLCBrZXkgfSk7XG5cblx0XHQvLyBDcmVhdGUgYWN0b3IgdmlhIGVuZ2luZSBBUElcblx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVBY3Rvcih0aGlzLiNjb25maWcsIHtcblx0XHRcdG5hbWUsXG5cdFx0XHRydW5uZXJfbmFtZV9zZWxlY3RvcjogdGhpcy4jY29uZmlnLnJ1bm5lck5hbWUsXG5cdFx0XHRrZXk6IHNlcmlhbGl6ZUFjdG9yS2V5KGtleSksXG5cdFx0XHRpbnB1dDogaW5wdXQgPyBjYm9yLmVuY29kZShpbnB1dCkudG9TdHJpbmcoXCJiYXNlNjRcIikgOiBudWxsLFxuXHRcdFx0Y3Jhc2hfcG9saWN5OiBcInNsZWVwXCIsXG5cdFx0fSk7XG5cdFx0Y29uc3QgYWN0b3JJZCA9IHJlc3VsdC5hY3Rvci5hY3Rvcl9pZDtcblxuXHRcdGxvZ2dlcigpLmluZm8oXCJhY3RvciBjcmVhdGVkXCIsIHsgYWN0b3JJZCwgbmFtZSwga2V5IH0pO1xuXG5cdFx0cmV0dXJuIHtcblx0XHRcdGFjdG9ySWQsXG5cdFx0XHRuYW1lLFxuXHRcdFx0a2V5LFxuXHRcdH07XG5cdH1cblxuXHRhc3luYyBkZXN0cm95QWN0b3IoYWN0b3JJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0bG9nZ2VyKCkuaW5mbyhcImRlc3Ryb3lpbmcgYWN0b3IgdmlhIGVuZ2luZSBhcGlcIiwgeyBhY3RvcklkIH0pO1xuXG5cdFx0YXdhaXQgZGVzdHJveUFjdG9yKHRoaXMuI2NvbmZpZywgYWN0b3JJZCk7XG5cblx0XHRsb2dnZXIoKS5pbmZvKFwiYWN0b3IgZGVzdHJveWVkXCIsIHsgYWN0b3JJZCB9KTtcblx0fVxuXG5cdGFzeW5jICNmb3J3YXJkSHR0cFJlcXVlc3QoXG5cdFx0YWN0b3JSZXF1ZXN0OiBSZXF1ZXN0LFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdC8vIFJvdXRlIHRocm91Z2ggZ3VhcmQgcG9ydFxuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwoYWN0b3JSZXF1ZXN0LnVybCk7XG5cdFx0Y29uc3QgZ3VhcmRVcmwgPSBgJHt0aGlzLiNjb25maWcuZW5kcG9pbnR9JHt1cmwucGF0aG5hbWV9JHt1cmwuc2VhcmNofWA7XG5cblx0XHQvLyBIYW5kbGUgYm9keSBwcm9wZXJseSBiYXNlZCBvbiBtZXRob2QgYW5kIHByZXNlbmNlXG5cdFx0bGV0IGJvZHlUb1NlbmQ6IEFycmF5QnVmZmVyIHwgbnVsbCA9IG51bGw7XG5cdFx0Y29uc3QgZ3VhcmRIZWFkZXJzID0gYnVpbGRHdWFyZEhlYWRlcnNGb3JIdHRwKGFjdG9yUmVxdWVzdCwgYWN0b3JJZCk7XG5cblx0XHRpZiAoXG5cdFx0XHRhY3RvclJlcXVlc3QuYm9keSAmJlxuXHRcdFx0YWN0b3JSZXF1ZXN0Lm1ldGhvZCAhPT0gXCJHRVRcIiAmJlxuXHRcdFx0YWN0b3JSZXF1ZXN0Lm1ldGhvZCAhPT0gXCJIRUFEXCJcblx0XHQpIHtcblx0XHRcdGlmIChhY3RvclJlcXVlc3QuYm9keVVzZWQpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiUmVxdWVzdCBib2R5IGhhcyBhbHJlYWR5IGJlZW4gY29uc3VtZWRcIik7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRPRE86IFRoaXMgYnVmZmVycyB0aGUgZW50aXJlIHJlcXVlc3QgaW4gbWVtb3J5IGV2ZXJ5IHRpbWUuIFdlXG5cdFx0XHQvLyBuZWVkIHRvIHByb3Blcmx5IGltcGxlbWVudCBzdHJlYW1pbmcgYm9kaWVzLlxuXHRcdFx0Ly8gQ2xvbmUgYW5kIHJlYWQgdGhlIGJvZHkgdG8gZW5zdXJlIGl0IGNhbiBiZSBzZW50XG5cdFx0XHRjb25zdCBjbG9uZWRSZXF1ZXN0ID0gYWN0b3JSZXF1ZXN0LmNsb25lKCk7XG5cdFx0XHRib2R5VG9TZW5kID0gYXdhaXQgY2xvbmVkUmVxdWVzdC5hcnJheUJ1ZmZlcigpO1xuXG5cdFx0XHQvLyBJZiB0aGlzIGlzIGEgc3RyZWFtaW5nIHJlcXVlc3QsIHdlIG5lZWQgdG8gY29udmVydCB0aGUgaGVhZGVyc1xuXHRcdFx0Ly8gZm9yIHRoZSBiYXNpYyBhcnJheSBidWZmZXJcblx0XHRcdGd1YXJkSGVhZGVycy5kZWxldGUoXCJ0cmFuc2Zlci1lbmNvZGluZ1wiKTtcblx0XHRcdGd1YXJkSGVhZGVycy5zZXQoXG5cdFx0XHRcdFwiY29udGVudC1sZW5ndGhcIixcblx0XHRcdFx0U3RyaW5nKChib2R5VG9TZW5kIGFzIEFycmF5QnVmZmVyKS5ieXRlTGVuZ3RoKSxcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZ3VhcmRSZXF1ZXN0ID0gbmV3IFJlcXVlc3QoZ3VhcmRVcmwsIHtcblx0XHRcdG1ldGhvZDogYWN0b3JSZXF1ZXN0Lm1ldGhvZCxcblx0XHRcdGhlYWRlcnM6IGd1YXJkSGVhZGVycyxcblx0XHRcdGJvZHk6IGJvZHlUb1NlbmQsXG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gbXV0YWJsZVJlc3BvbnNlKGF3YWl0IGZldGNoKGd1YXJkUmVxdWVzdCkpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIG11dGFibGVSZXNwb25zZShmZXRjaFJlczogUmVzcG9uc2UpOiBSZXNwb25zZSB7XG5cdC8vIFdlIGNhbm5vdCByZXR1cm4gdGhlIHJhdyByZXNwb25zZSBmcm9tIGBmZXRjaGAgc2luY2UgdGhlIHJlc3BvbnNlIHR5cGUgaXMgbm90IG11dGFibGUuXG5cdC8vXG5cdC8vIEluIG9yZGVyIGZvciBtaWRkbGV3YXJlIHRvIGJlIGFibGUgdG8gbXV0YXRlIHRoZSByZXNwb25zZSwgd2UgbmVlZCB0byBidWlsZCBhIG5ldyBSZXNwb25zZSBvYmplY3QgdGhhdCBpcyBtdXRhYmxlLlxuXHRyZXR1cm4gbmV3IFJlc3BvbnNlKGZldGNoUmVzLmJvZHksIGZldGNoUmVzKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRHdWFyZEhlYWRlcnNGb3JIdHRwKFxuXHRhY3RvclJlcXVlc3Q6IFJlcXVlc3QsXG5cdGFjdG9ySWQ6IHN0cmluZyxcbik6IEhlYWRlcnMge1xuXHRjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcblx0Ly8gQ29weSBhbGwgaGVhZGVycyBmcm9tIHRoZSBvcmlnaW5hbCByZXF1ZXN0XG5cdGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGFjdG9yUmVxdWVzdC5oZWFkZXJzLmVudHJpZXMoKSkge1xuXHRcdGhlYWRlcnMuc2V0KGtleSwgdmFsdWUpO1xuXHR9XG5cdC8vIEFkZCBndWFyZC1zcGVjaWZpYyBoZWFkZXJzXG5cdGhlYWRlcnMuc2V0KFwieC1yaXZldC10YXJnZXRcIiwgXCJhY3RvclwiKTtcblx0aGVhZGVycy5zZXQoXCJ4LXJpdmV0LWFjdG9yXCIsIGFjdG9ySWQpO1xuXHRoZWFkZXJzLnNldChcIngtcml2ZXQtcG9ydFwiLCBcIm1haW5cIik7XG5cdHJldHVybiBoZWFkZXJzO1xufVxuXG5mdW5jdGlvbiBidWlsZEd1YXJkSGVhZGVyc0ZvcldlYlNvY2tldChcblx0YWN0b3JJZDogc3RyaW5nLFxuXHRlbmNvZGluZzogRW5jb2RpbmcsXG5cdHBhcmFtcz86IHVua25vd24sXG5cdGF1dGhEYXRhPzogdW5rbm93bixcbik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuXHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdGhlYWRlcnNbXCJ4LXJpdmV0LXRhcmdldFwiXSA9IFwiYWN0b3JcIjtcblx0aGVhZGVyc1tcIngtcml2ZXQtYWN0b3JcIl0gPSBhY3RvcklkO1xuXHRoZWFkZXJzW1wieC1yaXZldC1wb3J0XCJdID0gXCJtYWluXCI7XG5cdGhlYWRlcnNbSEVBREVSX0VYUE9TRV9JTlRFUk5BTF9FUlJPUl0gPSBcInRydWVcIjtcblx0aGVhZGVyc1tIRUFERVJfRU5DT0RJTkddID0gZW5jb2Rpbmc7XG5cdGlmIChwYXJhbXMpIHtcblx0XHRoZWFkZXJzW0hFQURFUl9DT05OX1BBUkFNU10gPSBKU09OLnN0cmluZ2lmeShwYXJhbXMpO1xuXHR9XG5cdGlmIChhdXRoRGF0YSkge1xuXHRcdGhlYWRlcnNbSEVBREVSX0FVVEhfREFUQV0gPSBKU09OLnN0cmluZ2lmeShhdXRoRGF0YSk7XG5cdH1cblx0cmV0dXJuIGhlYWRlcnM7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb24vd2Vic29ja2V0LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vblwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb24vd2Vic29ja2V0LnRzXCI7aW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIkAvY2xpZW50L2xvZ1wiO1xuXG4vLyBHbG9iYWwgc2luZ2xldG9uIHByb21pc2UgdGhhdCB3aWxsIGJlIHJldXNlZCBmb3Igc3Vic2VxdWVudCBjYWxsc1xubGV0IHdlYlNvY2tldFByb21pc2U6IFByb21pc2U8dHlwZW9mIFdlYlNvY2tldD4gfCBudWxsID0gbnVsbDtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGltcG9ydFdlYlNvY2tldCgpOiBQcm9taXNlPHR5cGVvZiBXZWJTb2NrZXQ+IHtcblx0Ly8gUmV0dXJuIGV4aXN0aW5nIHByb21pc2UgaWYgd2UgYWxyZWFkeSBzdGFydGVkIGxvYWRpbmdcblx0aWYgKHdlYlNvY2tldFByb21pc2UgIT09IG51bGwpIHtcblx0XHRyZXR1cm4gd2ViU29ja2V0UHJvbWlzZTtcblx0fVxuXG5cdC8vIENyZWF0ZSBhbmQgc3RvcmUgdGhlIHByb21pc2Vcblx0d2ViU29ja2V0UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG5cdFx0bGV0IF9XZWJTb2NrZXQ6IHR5cGVvZiBXZWJTb2NrZXQ7XG5cblx0XHRpZiAodHlwZW9mIFdlYlNvY2tldCAhPT0gXCJ1bmRlZmluZWRcIikge1xuXHRcdFx0Ly8gQnJvd3NlciBlbnZpcm9ubWVudFxuXHRcdFx0X1dlYlNvY2tldCA9IFdlYlNvY2tldCBhcyB1bmtub3duIGFzIHR5cGVvZiBXZWJTb2NrZXQ7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInVzaW5nIG5hdGl2ZSB3ZWJzb2NrZXRcIik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIE5vZGUuanMgZW52aXJvbm1lbnRcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGNvbnN0IHdzID0gYXdhaXQgaW1wb3J0KFwid3NcIik7XG5cdFx0XHRcdF9XZWJTb2NrZXQgPSB3cy5kZWZhdWx0IGFzIHVua25vd24gYXMgdHlwZW9mIFdlYlNvY2tldDtcblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ1c2luZyB3ZWJzb2NrZXQgZnJvbSBucG1cIik7XG5cdFx0XHR9IGNhdGNoIHtcblx0XHRcdFx0Ly8gV1Mgbm90IGF2YWlsYWJsZVxuXHRcdFx0XHRfV2ViU29ja2V0ID0gY2xhc3MgTW9ja1dlYlNvY2tldCB7XG5cdFx0XHRcdFx0Y29uc3RydWN0b3IoKSB7XG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdFx0XHRcdCdXZWJTb2NrZXQgc3VwcG9ydCByZXF1aXJlcyBpbnN0YWxsaW5nIHRoZSBcIndzXCIgcGVlciBkZXBlbmRlbmN5LicsXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBhcyB1bmtub3duIGFzIHR5cGVvZiBXZWJTb2NrZXQ7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwidXNpbmcgbW9jayB3ZWJzb2NrZXRcIik7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIF9XZWJTb2NrZXQ7XG5cdH0pKCk7XG5cblx0cmV0dXJuIHdlYlNvY2tldFByb21pc2U7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZS9hcGktdXRpbHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvYXBpLXV0aWxzLnRzXCI7aW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5cbi8vIEVycm9yIGNsYXNzIGZvciBFbmdpbmUgQVBJIGVycm9yc1xuZXhwb3J0IGNsYXNzIEVuZ2luZUFwaUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRwdWJsaWMgcmVhZG9ubHkgZ3JvdXA6IHN0cmluZyxcblx0XHRwdWJsaWMgcmVhZG9ubHkgY29kZTogc3RyaW5nLFxuXHRcdG1lc3NhZ2U/OiBzdHJpbmcsXG5cdCkge1xuXHRcdHN1cGVyKG1lc3NhZ2UgfHwgYEVuZ2luZSBBUEkgZXJyb3I6ICR7Z3JvdXB9LyR7Y29kZX1gKTtcblx0XHR0aGlzLm5hbWUgPSBcIkVuZ2luZUFwaUVycm9yXCI7XG5cdH1cbn1cblxuLy8gSGVscGVyIGZ1bmN0aW9uIGZvciBtYWtpbmcgQVBJIGNhbGxzXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBpQ2FsbDxUSW5wdXQgPSB1bmtub3duLCBUT3V0cHV0ID0gdW5rbm93bj4oXG5cdGVuZHBvaW50OiBzdHJpbmcsXG5cdG5hbWVzcGFjZTogc3RyaW5nLFxuXHRtZXRob2Q6IFwiR0VUXCIgfCBcIlBPU1RcIiB8IFwiUFVUXCIgfCBcIkRFTEVURVwiLFxuXHRwYXRoOiBzdHJpbmcsXG5cdGJvZHk/OiBUSW5wdXQsXG4pOiBQcm9taXNlPFRPdXRwdXQ+IHtcblx0Y29uc3QgdXJsID0gYCR7ZW5kcG9pbnR9JHtwYXRofSR7cGF0aC5pbmNsdWRlcyhcIj9cIikgPyBcIiZcIiA6IFwiP1wifW5hbWVzcGFjZT0ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lc3BhY2UpfWA7XG5cblx0Y29uc3Qgb3B0aW9uczogUmVxdWVzdEluaXQgPSB7XG5cdFx0bWV0aG9kLFxuXHRcdGhlYWRlcnM6IHtcblx0XHRcdFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuXHRcdH0sXG5cdH07XG5cblx0aWYgKGJvZHkgIT09IHVuZGVmaW5lZCAmJiBtZXRob2QgIT09IFwiR0VUXCIpIHtcblx0XHRvcHRpb25zLmJvZHkgPSBKU09OLnN0cmluZ2lmeShib2R5KTtcblx0fVxuXG5cdGxvZ2dlcigpLmRlYnVnKFwibWFraW5nIGFwaSBjYWxsXCIsIHsgbWV0aG9kLCB1cmwgfSk7XG5cblx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwsIG9wdGlvbnMpO1xuXG5cdGlmICghcmVzcG9uc2Uub2spIHtcblx0XHRjb25zdCBlcnJvclRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG5cdFx0bG9nZ2VyKCkuZXJyb3IoXCJhcGkgY2FsbCBmYWlsZWRcIiwge1xuXHRcdFx0c3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG5cdFx0XHRzdGF0dXNUZXh0OiByZXNwb25zZS5zdGF0dXNUZXh0LFxuXHRcdFx0ZXJyb3I6IGVycm9yVGV4dCxcblx0XHRcdG1ldGhvZCxcblx0XHRcdHBhdGgsXG5cdFx0fSk7XG5cblx0XHQvLyBUcnkgdG8gcGFyc2UgZXJyb3IgcmVzcG9uc2Vcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgZXJyb3JEYXRhID0gSlNPTi5wYXJzZShlcnJvclRleHQpO1xuXHRcdFx0aWYgKGVycm9yRGF0YS5raW5kID09PSBcImVycm9yXCIgJiYgZXJyb3JEYXRhLmdyb3VwICYmIGVycm9yRGF0YS5jb2RlKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFbmdpbmVBcGlFcnJvcihcblx0XHRcdFx0XHRlcnJvckRhdGEuZ3JvdXAsXG5cdFx0XHRcdFx0ZXJyb3JEYXRhLmNvZGUsXG5cdFx0XHRcdFx0ZXJyb3JEYXRhLm1lc3NhZ2UsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAocGFyc2VFcnJvcikge1xuXHRcdFx0Ly8gSWYgcGFyc2luZyBmYWlscyBvciBpdCdzIG5vdCBvdXIgZXhwZWN0ZWQgZXJyb3IgZm9ybWF0LCBjb250aW51ZVxuXHRcdH1cblxuXHRcdHRocm93IG5ldyBFcnJvcihcblx0XHRcdGBBUEkgY2FsbCBmYWlsZWQ6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCxcblx0XHQpO1xuXHR9XG5cblx0cmV0dXJuIHJlc3BvbnNlLmpzb24oKSBhcyBQcm9taXNlPFRPdXRwdXQ+O1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvYXBpLWVuZHBvaW50cy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZS9hcGktZW5kcG9pbnRzLnRzXCI7aW1wb3J0IHsgYXBpQ2FsbCB9IGZyb20gXCIuL2FwaS11dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBDb25maWcgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB7IHNlcmlhbGl6ZUFjdG9yS2V5IH0gZnJvbSBcIi4va2V5c1wiO1xuXG4vLyBNQVJLOiBDb21tb24gdHlwZXNcbmV4cG9ydCB0eXBlIFJpdmV0SWQgPSBzdHJpbmc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3Ige1xuXHRhY3Rvcl9pZDogUml2ZXRJZDtcblx0bmFtZTogc3RyaW5nO1xuXHRrZXk6IHN0cmluZztcblx0bmFtZXNwYWNlX2lkOiBSaXZldElkO1xuXHRydW5uZXJfbmFtZV9zZWxlY3Rvcjogc3RyaW5nO1xuXHRjcmVhdGVfdHM6IG51bWJlcjtcblx0Y29ubmVjdGFibGVfdHM/OiBudW1iZXIgfCBudWxsO1xuXHRkZXN0cm95X3RzPzogbnVtYmVyIHwgbnVsbDtcblx0c2xlZXBfdHM/OiBudW1iZXIgfCBudWxsO1xuXHRzdGFydF90cz86IG51bWJlciB8IG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3JzR2V0UmVzcG9uc2Uge1xuXHRhY3RvcjogQWN0b3I7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3JzR2V0QnlJZFJlc3BvbnNlIHtcblx0YWN0b3JfaWQ/OiBSaXZldElkIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBY3RvcnNHZXRPckNyZWF0ZVJlc3BvbnNlIHtcblx0YWN0b3I6IEFjdG9yO1xuXHRjcmVhdGVkOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFjdG9yc0dldE9yQ3JlYXRlQnlJZFJlc3BvbnNlIHtcblx0YWN0b3JfaWQ6IFJpdmV0SWQ7XG5cdGNyZWF0ZWQ6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3JzQ3JlYXRlUmVxdWVzdCB7XG5cdG5hbWU6IHN0cmluZztcblx0cnVubmVyX25hbWVfc2VsZWN0b3I6IHN0cmluZztcblx0Y3Jhc2hfcG9saWN5OiBzdHJpbmc7XG5cdGtleT86IHN0cmluZyB8IG51bGw7XG5cdGlucHV0Pzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBY3RvcnNDcmVhdGVSZXNwb25zZSB7XG5cdGFjdG9yOiBBY3Rvcjtcbn1cblxuLy8gTUFSSzogR2V0IGFjdG9yXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWN0b3IoXG5cdGNvbmZpZzogQ29uZmlnLFxuXHRhY3RvcklkOiBSaXZldElkLFxuKTogUHJvbWlzZTxBY3RvcnNHZXRSZXNwb25zZT4ge1xuXHRyZXR1cm4gYXBpQ2FsbDxuZXZlciwgQWN0b3JzR2V0UmVzcG9uc2U+KFxuXHRcdGNvbmZpZy5lbmRwb2ludCxcblx0XHRjb25maWcubmFtZXNwYWNlLFxuXHRcdFwiR0VUXCIsXG5cdFx0YC9hY3RvcnMvJHtlbmNvZGVVUklDb21wb25lbnQoYWN0b3JJZCl9YCxcblx0KTtcbn1cblxuLy8gTUFSSzogR2V0IGFjdG9yIGJ5IGlkXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWN0b3JCeUlkKFxuXHRjb25maWc6IENvbmZpZyxcblx0bmFtZTogc3RyaW5nLFxuXHRrZXk6IHN0cmluZ1tdLFxuKTogUHJvbWlzZTxBY3RvcnNHZXRCeUlkUmVzcG9uc2U+IHtcblx0Y29uc3Qgc2VyaWFsaXplZEtleSA9IHNlcmlhbGl6ZUFjdG9yS2V5KGtleSk7XG5cdHJldHVybiBhcGlDYWxsPG5ldmVyLCBBY3RvcnNHZXRCeUlkUmVzcG9uc2U+KFxuXHRcdGNvbmZpZy5lbmRwb2ludCxcblx0XHRjb25maWcubmFtZXNwYWNlLFxuXHRcdFwiR0VUXCIsXG5cdFx0YC9hY3RvcnMvYnktaWQ/bmFtZT0ke2VuY29kZVVSSUNvbXBvbmVudChuYW1lKX0ma2V5PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHNlcmlhbGl6ZWRLZXkpfWAsXG5cdCk7XG59XG5cbi8vIE1BUks6IEdldCBvciBjcmVhdGUgYWN0b3IgYnkgaWRcbmV4cG9ydCBpbnRlcmZhY2UgQWN0b3JzR2V0T3JDcmVhdGVCeUlkUmVxdWVzdCB7XG5cdG5hbWU6IHN0cmluZztcblx0a2V5OiBzdHJpbmc7XG5cdHJ1bm5lcl9uYW1lX3NlbGVjdG9yOiBzdHJpbmc7XG5cdGNyYXNoX3BvbGljeTogc3RyaW5nO1xuXHRpbnB1dD86IHN0cmluZyB8IG51bGw7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRPckNyZWF0ZUFjdG9yQnlJZChcblx0Y29uZmlnOiBDb25maWcsXG5cdHJlcXVlc3Q6IEFjdG9yc0dldE9yQ3JlYXRlQnlJZFJlcXVlc3QsXG4pOiBQcm9taXNlPEFjdG9yc0dldE9yQ3JlYXRlQnlJZFJlc3BvbnNlPiB7XG5cdHJldHVybiBhcGlDYWxsPEFjdG9yc0dldE9yQ3JlYXRlQnlJZFJlcXVlc3QsIEFjdG9yc0dldE9yQ3JlYXRlQnlJZFJlc3BvbnNlPihcblx0XHRjb25maWcuZW5kcG9pbnQsXG5cdFx0Y29uZmlnLm5hbWVzcGFjZSxcblx0XHRcIlBVVFwiLFxuXHRcdGAvYWN0b3JzL2J5LWlkYCxcblx0XHRyZXF1ZXN0LFxuXHQpO1xufVxuXG4vLyBNQVJLOiBDcmVhdGUgYWN0b3JcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVBY3Rvcihcblx0Y29uZmlnOiBDb25maWcsXG5cdHJlcXVlc3Q6IEFjdG9yc0NyZWF0ZVJlcXVlc3QsXG4pOiBQcm9taXNlPEFjdG9yc0NyZWF0ZVJlc3BvbnNlPiB7XG5cdHJldHVybiBhcGlDYWxsPEFjdG9yc0NyZWF0ZVJlcXVlc3QsIEFjdG9yc0NyZWF0ZVJlc3BvbnNlPihcblx0XHRjb25maWcuZW5kcG9pbnQsXG5cdFx0Y29uZmlnLm5hbWVzcGFjZSxcblx0XHRcIlBPU1RcIixcblx0XHRgL2FjdG9yc2AsXG5cdFx0cmVxdWVzdCxcblx0KTtcbn1cblxuLy8gTUFSSzogRGVzdHJveSBhY3RvclxuZXhwb3J0IHR5cGUgQWN0b3JzRGVsZXRlUmVzcG9uc2UgPSB7fTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlc3Ryb3lBY3Rvcihcblx0Y29uZmlnOiBDb25maWcsXG5cdGFjdG9ySWQ6IFJpdmV0SWQsXG4pOiBQcm9taXNlPEFjdG9yc0RlbGV0ZVJlc3BvbnNlPiB7XG5cdHJldHVybiBhcGlDYWxsPG5ldmVyLCBBY3RvcnNEZWxldGVSZXNwb25zZT4oXG5cdFx0Y29uZmlnLmVuZHBvaW50LFxuXHRcdGNvbmZpZy5uYW1lc3BhY2UsXG5cdFx0XCJERUxFVEVcIixcblx0XHRgL2FjdG9ycy8ke2VuY29kZVVSSUNvbXBvbmVudChhY3RvcklkKX1gLFxuXHQpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvd3MtcHJveHkudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9lbmdpbmUvd3MtcHJveHkudHNcIjtpbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSG9ub0NvbnRleHQgfSBmcm9tIFwiaG9ub1wiO1xuaW1wb3J0IHR5cGUgeyBXU0NvbnRleHQgfSBmcm9tIFwiaG9uby93c1wiO1xuaW1wb3J0IGludmFyaWFudCBmcm9tIFwiaW52YXJpYW50XCI7XG5pbXBvcnQgdHlwZSB7IENsb3NlRXZlbnQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCB7IGltcG9ydFdlYlNvY2tldCB9IGZyb20gXCJAL2NvbW1vbi93ZWJzb2NrZXRcIjtcbmltcG9ydCB0eXBlIHsgVXBncmFkZVdlYlNvY2tldEFyZ3MgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCIuL2xvZ1wiO1xuXG4vKipcbiAqIFJldHVybnMgSG9ubyBgdXBncmFkZVdlYlNvY2tldGAgYXJncyB0aGF0IHdpbGwgcHJveHkgcmVxdWVzdHMgZnJvbSB0aGUgY2xpZW50IHRvIGEgZGVzdGluYXRpb24gYWRkcmVzcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdlYlNvY2tldFByb3h5KFxuXHRjOiBIb25vQ29udGV4dCxcblx0dGFyZ2V0VXJsOiBzdHJpbmcsXG5cdGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4pOiBQcm9taXNlPFVwZ3JhZGVXZWJTb2NrZXRBcmdzPiB7XG5cdGNvbnN0IFdlYlNvY2tldCA9IGF3YWl0IGltcG9ydFdlYlNvY2tldCgpO1xuXG5cdC8vIEhBQ0s6IFNhbml0aXplIFdlYlNvY2tldC1zcGVjaWZpYyBoZWFkZXJzLiBJZiB3ZSBkb24ndCBkbyB0aGlzLCBzb21lIFdlYlNvY2tldCBpbXBsZW1lbnRhdGlvbnMgKGkuZS4gbmF0aXZlIFdlYlNvY2tldCBpbiBOb2RlLmpzKSB3aWxsIGZhaWwgdG8gY29ubmVjdC5cblx0Zm9yIChjb25zdCBbaywgdl0gb2YgYy5yZXEucmF3LmhlYWRlcnMuZW50cmllcygpKSB7XG5cdFx0aWYgKCFrLnN0YXJ0c1dpdGgoXCJzZWMtXCIpICYmIGsgIT09IFwiY29ubmVjdGlvblwiICYmIGsgIT09IFwidXBncmFkZVwiKSB7XG5cdFx0XHRoZWFkZXJzW2tdID0gdjtcblx0XHR9XG5cdH1cblxuXHQvLyBXZWJTb2NrZXQgc3RhdGVcblx0aW50ZXJmYWNlIFdzU3RhdGUge1xuXHRcdHRhcmdldFdzPzogV2ViU29ja2V0O1xuXHRcdGNvbm5lY3RQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcblx0fVxuXHRjb25zdCBzdGF0ZTogV3NTdGF0ZSA9IHt9O1xuXG5cdHJldHVybiB7XG5cdFx0b25PcGVuOiBhc3luYyAoZXZlbnQ6IGFueSwgY2xpZW50V3M6IFdTQ29udGV4dCkgPT4ge1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjbGllbnQgd2Vic29ja2V0IGNvbm5lY3RlZFwiLCB7IHRhcmdldFVybCB9KTtcblxuXHRcdFx0aWYgKGNsaWVudFdzLnJlYWR5U3RhdGUgIT09IDEpIHtcblx0XHRcdFx0bG9nZ2VyKCkud2FybihcImNsaWVudCB3ZWJzb2NrZXQgbm90IG9wZW4gb24gY29ubmVjdGlvblwiLCB7XG5cdFx0XHRcdFx0dGFyZ2V0VXJsLFxuXHRcdFx0XHRcdHJlYWR5U3RhdGU6IGNsaWVudFdzLnJlYWR5U3RhdGUsXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIENyZWF0ZSBXZWJTb2NrZXRcblx0XHRcdGNvbnN0IHRhcmdldFdzID0gbmV3IFdlYlNvY2tldCh0YXJnZXRVcmwsIHsgaGVhZGVycyB9KTtcblx0XHRcdHN0YXRlLnRhcmdldFdzID0gdGFyZ2V0V3M7XG5cblx0XHRcdC8vIFNldHVwIGNvbm5lY3Rpb24gcHJvbWlzZVxuXHRcdFx0c3RhdGUuY29ubmVjdFByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHRcdHRhcmdldFdzLmFkZEV2ZW50TGlzdGVuZXIoXCJvcGVuXCIsICgpID0+IHtcblx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInRhcmdldCB3ZWJzb2NrZXQgY29ubmVjdGVkXCIsIHsgdGFyZ2V0VXJsIH0pO1xuXG5cdFx0XHRcdFx0aWYgKGNsaWVudFdzLnJlYWR5U3RhdGUgIT09IDEpIHtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLndhcm4oXCJjbGllbnQgd2Vic29ja2V0IGNsb3NlZCBiZWZvcmUgdGFyZ2V0IGNvbm5lY3RlZFwiLCB7XG5cdFx0XHRcdFx0XHRcdHRhcmdldFVybCxcblx0XHRcdFx0XHRcdFx0Y2xpZW50UmVhZHlTdGF0ZTogY2xpZW50V3MucmVhZHlTdGF0ZSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0dGFyZ2V0V3MuY2xvc2UoMTAwMSwgXCJDbGllbnQgZGlzY29ubmVjdGVkXCIpO1xuXHRcdFx0XHRcdFx0cmVqZWN0KG5ldyBFcnJvcihcIkNsaWVudCBkaXNjb25uZWN0ZWRcIikpO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXNvbHZlKCk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdHRhcmdldFdzLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcblx0XHRcdFx0XHRsb2dnZXIoKS53YXJuKFwidGFyZ2V0IHdlYnNvY2tldCBlcnJvciBkdXJpbmcgY29ubmVjdGlvblwiLCB7XG5cdFx0XHRcdFx0XHR0YXJnZXRVcmwsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0cmVqZWN0KGVycm9yKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gU2V0dXAgYmlkaXJlY3Rpb25hbCBmb3J3YXJkaW5nXG5cdFx0XHRzdGF0ZS50YXJnZXRXcy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCAoZXZlbnQpID0+IHtcblx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdHR5cGVvZiBldmVudC5kYXRhID09PSBcInN0cmluZ1wiIHx8XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdGNsaWVudFdzLnNlbmQoZXZlbnQuZGF0YSk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoZXZlbnQuZGF0YSBpbnN0YW5jZW9mIEJsb2IpIHtcblx0XHRcdFx0XHRldmVudC5kYXRhLmFycmF5QnVmZmVyKCkudGhlbigoYnVmZmVyKSA9PiB7XG5cdFx0XHRcdFx0XHRjbGllbnRXcy5zZW5kKGJ1ZmZlcik7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0XHRzdGF0ZS50YXJnZXRXcy5hZGRFdmVudExpc3RlbmVyKFwiY2xvc2VcIiwgKGV2ZW50KSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwidGFyZ2V0IHdlYnNvY2tldCBjbG9zZWRcIiwge1xuXHRcdFx0XHRcdHRhcmdldFVybCxcblx0XHRcdFx0XHRjb2RlOiBldmVudC5jb2RlLFxuXHRcdFx0XHRcdHJlYXNvbjogZXZlbnQucmVhc29uLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0Y2xvc2VXZWJTb2NrZXRJZk9wZW4oY2xpZW50V3MsIGV2ZW50LmNvZGUsIGV2ZW50LnJlYXNvbik7XG5cdFx0XHR9KTtcblxuXHRcdFx0c3RhdGUudGFyZ2V0V3MuYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIChlcnJvcikgPT4ge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcInRhcmdldCB3ZWJzb2NrZXQgZXJyb3JcIiwgeyB0YXJnZXRVcmwsIGVycm9yIH0pO1xuXHRcdFx0XHRjbG9zZVdlYlNvY2tldElmT3BlbihjbGllbnRXcywgMTAxMSwgXCJUYXJnZXQgV2ViU29ja2V0IGVycm9yXCIpO1xuXHRcdFx0fSk7XG5cdFx0fSxcblxuXHRcdG9uTWVzc2FnZTogYXN5bmMgKGV2ZW50OiBhbnksIGNsaWVudFdzOiBXU0NvbnRleHQpID0+IHtcblx0XHRcdGlmICghc3RhdGUudGFyZ2V0V3MgfHwgIXN0YXRlLmNvbm5lY3RQcm9taXNlKSB7XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwid2Vic29ja2V0IHN0YXRlIG5vdCBpbml0aWFsaXplZFwiLCB7IHRhcmdldFVybCB9KTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRhd2FpdCBzdGF0ZS5jb25uZWN0UHJvbWlzZTtcblx0XHRcdFx0aWYgKHN0YXRlLnRhcmdldFdzLnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5PUEVOKSB7XG5cdFx0XHRcdFx0c3RhdGUudGFyZ2V0V3Muc2VuZChldmVudC5kYXRhKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsb2dnZXIoKS53YXJuKFwidGFyZ2V0IHdlYnNvY2tldCBub3Qgb3BlblwiLCB7XG5cdFx0XHRcdFx0XHR0YXJnZXRVcmwsXG5cdFx0XHRcdFx0XHRyZWFkeVN0YXRlOiBzdGF0ZS50YXJnZXRXcy5yZWFkeVN0YXRlLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBjb25uZWN0IHRvIHRhcmdldCB3ZWJzb2NrZXRcIiwge1xuXHRcdFx0XHRcdHRhcmdldFVybCxcblx0XHRcdFx0XHRlcnJvcixcblx0XHRcdFx0fSk7XG5cdFx0XHRcdGNsb3NlV2ViU29ja2V0SWZPcGVuKGNsaWVudFdzLCAxMDExLCBcIkZhaWxlZCB0byBjb25uZWN0IHRvIHRhcmdldFwiKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0b25DbG9zZTogKGV2ZW50OiBhbnksIGNsaWVudFdzOiBXU0NvbnRleHQpID0+IHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiY2xpZW50IHdlYnNvY2tldCBjbG9zZWRcIiwge1xuXHRcdFx0XHR0YXJnZXRVcmwsXG5cdFx0XHRcdGNvZGU6IGV2ZW50LmNvZGUsXG5cdFx0XHRcdHJlYXNvbjogZXZlbnQucmVhc29uLFxuXHRcdFx0XHR3YXNDbGVhbjogZXZlbnQud2FzQ2xlYW4sXG5cdFx0XHR9KTtcblxuXHRcdFx0aWYgKHN0YXRlLnRhcmdldFdzKSB7XG5cdFx0XHRcdGlmIChcblx0XHRcdFx0XHRzdGF0ZS50YXJnZXRXcy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTiB8fFxuXHRcdFx0XHRcdHN0YXRlLnRhcmdldFdzLnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5DT05ORUNUSU5HXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHN0YXRlLnRhcmdldFdzLmNsb3NlKDEwMDAsIGV2ZW50LnJlYXNvbiB8fCBcIkNsaWVudCBkaXNjb25uZWN0ZWRcIik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0b25FcnJvcjogKGV2ZW50OiBhbnksIGNsaWVudFdzOiBXU0NvbnRleHQpID0+IHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiY2xpZW50IHdlYnNvY2tldCBlcnJvclwiLCB7IHRhcmdldFVybCwgZXZlbnQgfSk7XG5cblx0XHRcdGlmIChzdGF0ZS50YXJnZXRXcykge1xuXHRcdFx0XHRpZiAoc3RhdGUudGFyZ2V0V3MucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcblx0XHRcdFx0XHRzdGF0ZS50YXJnZXRXcy5jbG9zZSgxMDExLCBcIkNsaWVudCBXZWJTb2NrZXQgZXJyb3JcIik7XG5cdFx0XHRcdH0gZWxzZSBpZiAoc3RhdGUudGFyZ2V0V3MucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0LkNPTk5FQ1RJTkcpIHtcblx0XHRcdFx0XHRzdGF0ZS50YXJnZXRXcy5jbG9zZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0fTtcbn1cblxuZnVuY3Rpb24gY2xvc2VXZWJTb2NrZXRJZk9wZW4oXG5cdHdzOiBXZWJTb2NrZXQgfCBXU0NvbnRleHQsXG5cdGNvZGU6IG51bWJlcixcblx0cmVhc29uOiBzdHJpbmcsXG4pOiB2b2lkIHtcblx0aWYgKHdzLnJlYWR5U3RhdGUgPT09IDEpIHtcblx0XHR3cy5jbG9zZShjb2RlLCByZWFzb24pO1xuXHR9IGVsc2UgaWYgKFwiY2xvc2VcIiBpbiB3cyAmJiAod3MgYXMgV2ViU29ja2V0KS5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuXHRcdHdzLmNsb3NlKGNvZGUsIHJlYXNvbik7XG5cdH1cbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZW5naW5lL21vZC50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2VuZ2luZS9tb2QudHNcIjtpbXBvcnQgdHlwZSB7IENsaWVudCB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTWFuYWdlckRyaXZlciB9IGZyb20gXCJAL21hbmFnZXIvZHJpdmVyXCI7XG5pbXBvcnQgdHlwZSB7IFJlZ2lzdHJ5Q29uZmlnIH0gZnJvbSBcIkAvcmVnaXN0cnkvY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IERyaXZlckNvbmZpZywgUnVuQ29uZmlnIH0gZnJvbSBcIkAvcmVnaXN0cnkvcnVuLWNvbmZpZ1wiO1xuaW1wb3J0IHsgRW5naW5lQWN0b3JEcml2ZXIgfSBmcm9tIFwiLi9hY3Rvci1kcml2ZXJcIjtcbmltcG9ydCB7IENvbmZpZ1NjaGVtYSwgdHlwZSBJbnB1dENvbmZpZyB9IGZyb20gXCIuL2NvbmZpZ1wiO1xuaW1wb3J0IHsgRW5naW5lTWFuYWdlckRyaXZlciB9IGZyb20gXCIuL21hbmFnZXItZHJpdmVyXCI7XG5cbmV4cG9ydCB7IEVuZ2luZUFjdG9yRHJpdmVyIH0gZnJvbSBcIi4vYWN0b3ItZHJpdmVyXCI7XG5leHBvcnQgeyB0eXBlIENvbmZpZywgQ29uZmlnU2NoZW1hLCB0eXBlIElucHV0Q29uZmlnIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5leHBvcnQgeyBFbmdpbmVNYW5hZ2VyRHJpdmVyIH0gZnJvbSBcIi4vbWFuYWdlci1kcml2ZXJcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVuZ2luZURyaXZlcihpbnB1dENvbmZpZz86IElucHV0Q29uZmlnKTogRHJpdmVyQ29uZmlnIHtcblx0Y29uc3QgY29uZmlnID0gQ29uZmlnU2NoZW1hLnBhcnNlKGlucHV0Q29uZmlnKTtcblxuXHRyZXR1cm4ge1xuXHRcdG5hbWU6IFwiZW5naW5lXCIsXG5cdFx0bWFuYWdlcjogKF9yZWdpc3RyeUNvbmZpZywgcnVuQ29uZmlnKSA9PiB7XG5cdFx0XHRyZXR1cm4gbmV3IEVuZ2luZU1hbmFnZXJEcml2ZXIoY29uZmlnLCBydW5Db25maWcpO1xuXHRcdH0sXG5cdFx0YWN0b3I6IChcblx0XHRcdHJlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZyxcblx0XHRcdHJ1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRcdFx0bWFuYWdlckRyaXZlcjogTWFuYWdlckRyaXZlcixcblx0XHRcdGlubGluZUNsaWVudDogQ2xpZW50PGFueT4sXG5cdFx0KSA9PiB7XG5cdFx0XHRyZXR1cm4gbmV3IEVuZ2luZUFjdG9yRHJpdmVyKFxuXHRcdFx0XHRyZWdpc3RyeUNvbmZpZyxcblx0XHRcdFx0cnVuQ29uZmlnLFxuXHRcdFx0XHRtYW5hZ2VyRHJpdmVyLFxuXHRcdFx0XHRpbmxpbmVDbGllbnQsXG5cdFx0XHRcdGNvbmZpZyxcblx0XHRcdCk7XG5cdFx0fSxcblx0fTtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW0vYWN0b3IudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL2FjdG9yLnRzXCI7aW1wb3J0IHR5cGUgeyBHZW5lcmljQ29ubkdsb2JhbFN0YXRlIH0gZnJvbSBcIkAvYWN0b3IvZ2VuZXJpYy1jb25uLWRyaXZlclwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIkAvYWN0b3IvbG9nXCI7XG5pbXBvcnQgdHlwZSB7IEFueUNsaWVudCB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHtcblx0QWN0b3JEcml2ZXIsXG5cdEFueUFjdG9ySW5zdGFuY2UsXG5cdE1hbmFnZXJEcml2ZXIsXG59IGZyb20gXCJAL2RyaXZlci1oZWxwZXJzL21vZFwiO1xuaW1wb3J0IHR5cGUgeyBSZWdpc3RyeUNvbmZpZywgUnVuQ29uZmlnIH0gZnJvbSBcIkAvbW9kXCI7XG5pbXBvcnQgeyBidWZmZXJUb0FycmF5QnVmZmVyIH0gZnJvbSBcIkAvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgRmlsZVN5c3RlbUdsb2JhbFN0YXRlIH0gZnJvbSBcIi4vZ2xvYmFsLXN0YXRlXCI7XG5cbmV4cG9ydCB0eXBlIEFjdG9yRHJpdmVyQ29udGV4dCA9IFJlY29yZDxuZXZlciwgbmV2ZXI+O1xuXG4vKipcbiAqIEZpbGUgU3lzdGVtIGltcGxlbWVudGF0aW9uIG9mIHRoZSBBY3RvciBEcml2ZXJcbiAqL1xuZXhwb3J0IGNsYXNzIEZpbGVTeXN0ZW1BY3RvckRyaXZlciBpbXBsZW1lbnRzIEFjdG9yRHJpdmVyIHtcblx0I3JlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZztcblx0I3J1bkNvbmZpZzogUnVuQ29uZmlnO1xuXHQjbWFuYWdlckRyaXZlcjogTWFuYWdlckRyaXZlcjtcblx0I2lubGluZUNsaWVudDogQW55Q2xpZW50O1xuXHQjc3RhdGU6IEZpbGVTeXN0ZW1HbG9iYWxTdGF0ZTtcblxuXHRjb25zdHJ1Y3Rvcihcblx0XHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdFx0cnVuQ29uZmlnOiBSdW5Db25maWcsXG5cdFx0bWFuYWdlckRyaXZlcjogTWFuYWdlckRyaXZlcixcblx0XHRpbmxpbmVDbGllbnQ6IEFueUNsaWVudCxcblx0XHRzdGF0ZTogRmlsZVN5c3RlbUdsb2JhbFN0YXRlLFxuXHQpIHtcblx0XHR0aGlzLiNyZWdpc3RyeUNvbmZpZyA9IHJlZ2lzdHJ5Q29uZmlnO1xuXHRcdHRoaXMuI3J1bkNvbmZpZyA9IHJ1bkNvbmZpZztcblx0XHR0aGlzLiNtYW5hZ2VyRHJpdmVyID0gbWFuYWdlckRyaXZlcjtcblx0XHR0aGlzLiNpbmxpbmVDbGllbnQgPSBpbmxpbmVDbGllbnQ7XG5cdFx0dGhpcy4jc3RhdGUgPSBzdGF0ZTtcblx0fVxuXG5cdGFzeW5jIGxvYWRBY3RvcihhY3RvcklkOiBzdHJpbmcpOiBQcm9taXNlPEFueUFjdG9ySW5zdGFuY2U+IHtcblx0XHRyZXR1cm4gdGhpcy4jc3RhdGUuc3RhcnRBY3Rvcihcblx0XHRcdHRoaXMuI3JlZ2lzdHJ5Q29uZmlnLFxuXHRcdFx0dGhpcy4jcnVuQ29uZmlnLFxuXHRcdFx0dGhpcy4jaW5saW5lQ2xpZW50LFxuXHRcdFx0dGhpcyxcblx0XHRcdGFjdG9ySWQsXG5cdFx0KTtcblx0fVxuXG5cdGdldEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoYWN0b3JJZDogc3RyaW5nKTogR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSB7XG5cdFx0cmV0dXJuIHRoaXMuI3N0YXRlLmdldEFjdG9yT3JFcnJvcihhY3RvcklkKS5nZW5lcmljQ29ubkdsb2JhbFN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgY3VycmVudCBzdG9yYWdlIGRpcmVjdG9yeSBwYXRoXG5cdCAqL1xuXHRnZXQgc3RvcmFnZVBhdGgoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy4jc3RhdGUuc3RvcmFnZVBhdGg7XG5cdH1cblxuXHRnZXRDb250ZXh0KF9hY3RvcklkOiBzdHJpbmcpOiBBY3RvckRyaXZlckNvbnRleHQge1xuXHRcdHJldHVybiB7fTtcblx0fVxuXG5cdGFzeW5jIHJlYWRQZXJzaXN0ZWREYXRhKGFjdG9ySWQ6IHN0cmluZyk6IFByb21pc2U8VWludDhBcnJheSB8IHVuZGVmaW5lZD4ge1xuXHRcdHJldHVybiBuZXcgVWludDhBcnJheShcblx0XHRcdChhd2FpdCB0aGlzLiNzdGF0ZS5sb2FkQWN0b3JTdGF0ZU9yRXJyb3IoYWN0b3JJZCkpLnBlcnNpc3RlZERhdGEsXG5cdFx0KTtcblx0fVxuXG5cdGFzeW5jIHdyaXRlUGVyc2lzdGVkRGF0YShhY3RvcklkOiBzdHJpbmcsIGRhdGE6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCBzdGF0ZSA9IGF3YWl0IHRoaXMuI3N0YXRlLmxvYWRBY3RvclN0YXRlT3JFcnJvcihhY3RvcklkKTtcblxuXHRcdC8vIFNhdmUgc3RhdGUgdG8gZGlza1xuXHRcdGF3YWl0IHRoaXMuI3N0YXRlLndyaXRlQWN0b3IoYWN0b3JJZCwge1xuXHRcdFx0Li4uc3RhdGUsXG5cdFx0XHRwZXJzaXN0ZWREYXRhOiBidWZmZXJUb0FycmF5QnVmZmVyKGRhdGEpLFxuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgc2V0QWxhcm0oYWN0b3I6IEFueUFjdG9ySW5zdGFuY2UsIHRpbWVzdGFtcDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0YXdhaXQgdGhpcy4jc3RhdGUuc2V0QWN0b3JBbGFybShhY3Rvci5pZCwgdGltZXN0YW1wKTtcblx0fVxuXG5cdGdldERhdGFiYXNlKGFjdG9ySWQ6IHN0cmluZyk6IFByb21pc2U8dW5rbm93biB8IHVuZGVmaW5lZD4ge1xuXHRcdHJldHVybiB0aGlzLiNzdGF0ZS5jcmVhdGVEYXRhYmFzZShhY3RvcklkKTtcblx0fVxuXG5cdHNsZWVwKGFjdG9ySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdHJldHVybiB0aGlzLiNzdGF0ZS5zbGVlcEFjdG9yKGFjdG9ySWQpO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL2dsb2JhbC1zdGF0ZS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW0vZ2xvYmFsLXN0YXRlLnRzXCI7aW1wb3J0ICogYXMgY3J5cHRvIGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0ICogYXMgZnNTeW5jIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgaW52YXJpYW50IGZyb20gXCJpbnZhcmlhbnRcIjtcbmltcG9ydCB7IGxvb2t1cEluUmVnaXN0cnkgfSBmcm9tIFwiQC9hY3Rvci9kZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBBY3RvckFscmVhZHlFeGlzdHMgfSBmcm9tIFwiQC9hY3Rvci9lcnJvcnNcIjtcbmltcG9ydCB7XG5cdGNyZWF0ZUdlbmVyaWNDb25uRHJpdmVycyxcblx0R2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZSxcbn0gZnJvbSBcIkAvYWN0b3IvZ2VuZXJpYy1jb25uLWRyaXZlclwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBY3Rvckluc3RhbmNlIH0gZnJvbSBcIkAvYWN0b3IvaW5zdGFuY2VcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JLZXkgfSBmcm9tIFwiQC9hY3Rvci9tb2RcIjtcbmltcG9ydCB7IGdlbmVyYXRlUmFuZG9tU3RyaW5nIH0gZnJvbSBcIkAvYWN0b3IvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgQW55Q2xpZW50IH0gZnJvbSBcIkAvY2xpZW50L2NsaWVudFwiO1xuaW1wb3J0IHtcblx0dHlwZSBBY3RvckRyaXZlcixcblx0c2VyaWFsaXplRW1wdHlQZXJzaXN0RGF0YSxcbn0gZnJvbSBcIkAvZHJpdmVyLWhlbHBlcnMvbW9kXCI7XG5pbXBvcnQgdHlwZSB7IFJlZ2lzdHJ5Q29uZmlnIH0gZnJvbSBcIkAvcmVnaXN0cnkvY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IFJ1bkNvbmZpZyB9IGZyb20gXCJAL3JlZ2lzdHJ5L3J1bi1jb25maWdcIjtcbmltcG9ydCB0eXBlICogYXMgc2NoZW1hIGZyb20gXCJAL3NjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyL21vZFwiO1xuaW1wb3J0IHtcblx0QUNUT1JfQUxBUk1fVkVSU0lPTkVELFxuXHRBQ1RPUl9TVEFURV9WRVJTSU9ORUQsXG59IGZyb20gXCJAL3NjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyL3ZlcnNpb25lZFwiO1xuaW1wb3J0IHtcblx0YnVmZmVyVG9BcnJheUJ1ZmZlcixcblx0dHlwZSBMb25nVGltZW91dEhhbmRsZSxcblx0U2luZ2xlUHJvbWlzZVF1ZXVlLFxuXHRzZXRMb25nVGltZW91dCxcblx0c3RyaW5naWZ5RXJyb3IsXG59IGZyb20gXCJAL3V0aWxzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB7XG5cdGVuc3VyZURpcmVjdG9yeUV4aXN0cyxcblx0ZW5zdXJlRGlyZWN0b3J5RXhpc3RzU3luYyxcblx0Z2V0U3RvcmFnZVBhdGgsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbi8vIEFjdG9yIGhhbmRsZXIgdG8gdHJhY2sgcnVubmluZyBpbnN0YW5jZXNcblxuaW50ZXJmYWNlIEFjdG9yRW50cnkge1xuXHRpZDogc3RyaW5nO1xuXG5cdHN0YXRlPzogc2NoZW1hLkFjdG9yU3RhdGU7XG5cdC8qKiBQcm9taXNlIGZvciBsb2FkaW5nIHRoZSBhY3RvciBzdGF0ZS4gKi9cblx0bG9hZFByb21pc2U/OiBQcm9taXNlPEFjdG9yRW50cnk+O1xuXG5cdGFjdG9yPzogQW55QWN0b3JJbnN0YW5jZTtcblx0LyoqIFByb21pc2UgZm9yIHN0YXJ0aW5nIHRoZSBhY3Rvci4gKi9cblx0c3RhcnRQcm9taXNlPzogUHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD47XG5cblx0Z2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTogR2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTtcblxuXHRhbGFybVRpbWVvdXQ/OiBMb25nVGltZW91dEhhbmRsZTtcblx0LyoqIFRoZSB0aW1lc3RhbXAgY3VycmVudGx5IHNjaGVkdWxlZCBmb3IgdGhpcyBhY3RvcidzIGFsYXJtIChtcyBzaW5jZSBlcG9jaCkuICovXG5cdGFsYXJtVGltZXN0YW1wPzogbnVtYmVyO1xuXG5cdC8qKiBSZXNvbHZlciBmb3IgcGVuZGluZyB3cml0ZSBvcGVyYXRpb25zIHRoYXQgbmVlZCB0byBiZSBub3RpZmllZCB3aGVuIGFueSB3cml0ZSBjb21wbGV0ZXMgKi9cblx0cGVuZGluZ1dyaXRlUmVzb2x2ZXI/OiBQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPjtcblxuXHQvKiogSWYgdGhlIGFjdG9yIGhhcyBiZWVuIHJlbW92ZWQgYnkgZGVzdHJveSBvciBzbGVlcC4gKi9cblx0cmVtb3ZlZDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBHbG9iYWwgc3RhdGUgZm9yIHRoZSBmaWxlIHN5c3RlbSBkcml2ZXJcbiAqL1xuZXhwb3J0IGNsYXNzIEZpbGVTeXN0ZW1HbG9iYWxTdGF0ZSB7XG5cdCNzdG9yYWdlUGF0aDogc3RyaW5nO1xuXHQjc3RhdGVEaXI6IHN0cmluZztcblx0I2Ric0Rpcjogc3RyaW5nO1xuXHQjYWxhcm1zRGlyOiBzdHJpbmc7XG5cblx0I3BlcnNpc3Q6IGJvb2xlYW47XG5cdCNhY3RvcnMgPSBuZXcgTWFwPHN0cmluZywgQWN0b3JFbnRyeT4oKTtcblx0I2FjdG9yQ291bnRPblN0YXJ0dXA6IG51bWJlciA9IDA7XG5cblx0I3J1bm5lclBhcmFtcz86IHtcblx0XHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWc7XG5cdFx0cnVuQ29uZmlnOiBSdW5Db25maWc7XG5cdFx0aW5saW5lQ2xpZW50OiBBbnlDbGllbnQ7XG5cdFx0YWN0b3JEcml2ZXI6IEFjdG9yRHJpdmVyO1xuXHR9O1xuXG5cdGdldCBzdG9yYWdlUGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy4jc3RvcmFnZVBhdGg7XG5cdH1cblxuXHRnZXQgYWN0b3JDb3VudE9uU3RhcnR1cCgpIHtcblx0XHRyZXR1cm4gdGhpcy4jYWN0b3JDb3VudE9uU3RhcnR1cDtcblx0fVxuXG5cdGNvbnN0cnVjdG9yKHBlcnNpc3Q6IGJvb2xlYW4gPSB0cnVlLCBjdXN0b21QYXRoPzogc3RyaW5nKSB7XG5cdFx0dGhpcy4jcGVyc2lzdCA9IHBlcnNpc3Q7XG5cdFx0dGhpcy4jc3RvcmFnZVBhdGggPSBwZXJzaXN0ID8gZ2V0U3RvcmFnZVBhdGgoY3VzdG9tUGF0aCkgOiBcIi90bXBcIjtcblx0XHR0aGlzLiNzdGF0ZURpciA9IHBhdGguam9pbih0aGlzLiNzdG9yYWdlUGF0aCwgXCJzdGF0ZVwiKTtcblx0XHR0aGlzLiNkYnNEaXIgPSBwYXRoLmpvaW4odGhpcy4jc3RvcmFnZVBhdGgsIFwiZGF0YWJhc2VzXCIpO1xuXHRcdHRoaXMuI2FsYXJtc0RpciA9IHBhdGguam9pbih0aGlzLiNzdG9yYWdlUGF0aCwgXCJhbGFybXNcIik7XG5cblx0XHRpZiAodGhpcy4jcGVyc2lzdCkge1xuXHRcdFx0Ly8gRW5zdXJlIHN0b3JhZ2UgZGlyZWN0b3JpZXMgZXhpc3Qgc3luY2hyb25vdXNseSBkdXJpbmcgaW5pdGlhbGl6YXRpb25cblx0XHRcdGVuc3VyZURpcmVjdG9yeUV4aXN0c1N5bmModGhpcy4jc3RhdGVEaXIpO1xuXHRcdFx0ZW5zdXJlRGlyZWN0b3J5RXhpc3RzU3luYyh0aGlzLiNkYnNEaXIpO1xuXHRcdFx0ZW5zdXJlRGlyZWN0b3J5RXhpc3RzU3luYyh0aGlzLiNhbGFybXNEaXIpO1xuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCBhY3RvcklkcyA9IGZzU3luYy5yZWFkZGlyU3luYyh0aGlzLiNzdGF0ZURpcik7XG5cdFx0XHRcdHRoaXMuI2FjdG9yQ291bnRPblN0YXJ0dXAgPSBhY3Rvcklkcy5sZW5ndGg7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBjb3VudCBhY3RvcnNcIiwgeyBlcnJvciB9KTtcblx0XHRcdH1cblxuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmaWxlIHN5c3RlbSBkcml2ZXIgcmVhZHlcIiwge1xuXHRcdFx0XHRkaXI6IHRoaXMuI3N0b3JhZ2VQYXRoLFxuXHRcdFx0XHRhY3RvckNvdW50OiB0aGlzLiNhY3RvckNvdW50T25TdGFydHVwLFxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIENsZWFudXAgc3RhbGUgdGVtcCBmaWxlcyBvbiBzdGFydHVwXG5cdFx0XHR0cnkge1xuXHRcdFx0XHR0aGlzLiNjbGVhbnVwVGVtcEZpbGVzU3luYygpO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIGNsZWFudXAgdGVtcCBmaWxlc1wiLCB7IGVycm9yOiBlcnIgfSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwibWVtb3J5IGRyaXZlciByZWFkeVwiKTtcblx0XHR9XG5cdH1cblxuXHRnZXRBY3RvclN0YXRlUGF0aChhY3RvcklkOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRcdHJldHVybiBwYXRoLmpvaW4odGhpcy4jc3RhdGVEaXIsIGFjdG9ySWQpO1xuXHR9XG5cblx0Z2V0QWN0b3JEYlBhdGgoYWN0b3JJZDogc3RyaW5nKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gcGF0aC5qb2luKHRoaXMuI2Ric0RpciwgYCR7YWN0b3JJZH0uZGJgKTtcblx0fVxuXG5cdGdldEFjdG9yQWxhcm1QYXRoKGFjdG9ySWQ6IHN0cmluZyk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHBhdGguam9pbih0aGlzLiNhbGFybXNEaXIsIGFjdG9ySWQpO1xuXHR9XG5cblx0YXN5bmMgKmdldEFjdG9yc0l0ZXJhdG9yKHBhcmFtczoge1xuXHRcdGN1cnNvcj86IHN0cmluZztcblx0fSk6IEFzeW5jR2VuZXJhdG9yPHNjaGVtYS5BY3RvclN0YXRlPiB7XG5cdFx0bGV0IGFjdG9ySWRzID0gQXJyYXkuZnJvbSh0aGlzLiNhY3RvcnMua2V5cygpKS5zb3J0KCk7XG5cblx0XHQvLyBDaGVjayBpZiBzdGF0ZSBkaXJlY3RvcnkgZXhpc3RzIGZpcnN0XG5cdFx0aWYgKGZzU3luYy5leGlzdHNTeW5jKHRoaXMuI3N0YXRlRGlyKSkge1xuXHRcdFx0YWN0b3JJZHMgPSBmc1N5bmNcblx0XHRcdFx0LnJlYWRkaXJTeW5jKHRoaXMuI3N0YXRlRGlyKVxuXHRcdFx0XHQuZmlsdGVyKChpZCkgPT4gIWlkLmluY2x1ZGVzKFwiLnRtcFwiKSlcblx0XHRcdFx0LnNvcnQoKTtcblx0XHR9XG5cblx0XHRjb25zdCBzdGFydEluZGV4ID0gcGFyYW1zLmN1cnNvciA/IGFjdG9ySWRzLmluZGV4T2YocGFyYW1zLmN1cnNvcikgKyAxIDogMDtcblxuXHRcdGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgYWN0b3JJZHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGFjdG9ySWQgPSBhY3Rvcklkc1tpXTtcblx0XHRcdGlmICghYWN0b3JJZCkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3Qgc3RhdGUgPSBhd2FpdCB0aGlzLmxvYWRBY3RvclN0YXRlT3JFcnJvcihhY3RvcklkKTtcblx0XHRcdFx0eWllbGQgc3RhdGU7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBsb2FkIGFjdG9yIHN0YXRlXCIsIHsgYWN0b3JJZCwgZXJyb3IgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEVuc3VyZXMgYW4gZW50cnkgZXhpc3RzIGZvciB0aGlzIGFjdG9yLlxuXHQgKlxuXHQgKiBVc2VkIGZvciAjY3JlYXRlQWN0b3IgYW5kICNsb2FkQWN0b3IuXG5cdCAqL1xuXHQjdXBzZXJ0RW50cnkoYWN0b3JJZDogc3RyaW5nKTogQWN0b3JFbnRyeSB7XG5cdFx0bGV0IGVudHJ5ID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpZiAoZW50cnkpIHtcblx0XHRcdHJldHVybiBlbnRyeTtcblx0XHR9XG5cblx0XHRlbnRyeSA9IHtcblx0XHRcdGlkOiBhY3RvcklkLFxuXHRcdFx0Z2VuZXJpY0Nvbm5HbG9iYWxTdGF0ZTogbmV3IEdlbmVyaWNDb25uR2xvYmFsU3RhdGUoKSxcblx0XHRcdHJlbW92ZWQ6IGZhbHNlLFxuXHRcdH07XG5cdFx0dGhpcy4jYWN0b3JzLnNldChhY3RvcklkLCBlbnRyeSk7XG5cdFx0cmV0dXJuIGVudHJ5O1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgYWN0b3IgYW5kIHdyaXRlcyB0byBmaWxlIHN5c3RlbS5cblx0ICovXG5cdGFzeW5jIGNyZWF0ZUFjdG9yKFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHRuYW1lOiBzdHJpbmcsXG5cdFx0a2V5OiBBY3RvcktleSxcblx0XHRpbnB1dDogdW5rbm93biB8IHVuZGVmaW5lZCxcblx0KTogUHJvbWlzZTxBY3RvckVudHJ5PiB7XG5cdFx0Ly8gVE9ETzogRG9lcyBub3QgY2hlY2sgaWYgYWN0b3IgYWxyZWFkeSBleGlzdHMgb24gZnNcblxuXHRcdGlmICh0aGlzLiNhY3RvcnMuaGFzKGFjdG9ySWQpKSB7XG5cdFx0XHR0aHJvdyBuZXcgQWN0b3JBbHJlYWR5RXhpc3RzKG5hbWUsIGtleSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZW50cnkgPSB0aGlzLiN1cHNlcnRFbnRyeShhY3RvcklkKTtcblx0XHRlbnRyeS5zdGF0ZSA9IHtcblx0XHRcdGFjdG9ySWQsXG5cdFx0XHRuYW1lLFxuXHRcdFx0a2V5LFxuXHRcdFx0Y3JlYXRlZEF0OiBCaWdJbnQoRGF0ZS5ub3coKSksXG5cdFx0XHRwZXJzaXN0ZWREYXRhOiBidWZmZXJUb0FycmF5QnVmZmVyKHNlcmlhbGl6ZUVtcHR5UGVyc2lzdERhdGEoaW5wdXQpKSxcblx0XHR9O1xuXHRcdGF3YWl0IHRoaXMud3JpdGVBY3RvcihhY3RvcklkLCBlbnRyeS5zdGF0ZSk7XG5cdFx0cmV0dXJuIGVudHJ5O1xuXHR9XG5cblx0LyoqXG5cdCAqIExvYWRzIHRoZSBhY3RvciBmcm9tIGRpc2sgb3IgcmV0dXJucyB0aGUgZXhpc3RpbmcgYWN0b3IgZW50cnkuIFRoaXMgd2lsbCByZXR1cm4gYW4gZW50cnkgZXZlbiBpZiB0aGUgYWN0b3IgZG9lcyBub3QgYWN0dWFsbHkgZXhpc3QuXG5cdCAqL1xuXHRhc3luYyBsb2FkQWN0b3IoYWN0b3JJZDogc3RyaW5nKTogUHJvbWlzZTxBY3RvckVudHJ5PiB7XG5cdFx0Y29uc3QgZW50cnkgPSB0aGlzLiN1cHNlcnRFbnRyeShhY3RvcklkKTtcblxuXHRcdC8vIENoZWNrIGlmIGFscmVhZHkgbG9hZGVkXG5cdFx0aWYgKGVudHJ5LnN0YXRlKSB7XG5cdFx0XHRyZXR1cm4gZW50cnk7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgbm90IHBlcnNpc3RlZCwgdGhlbiBkb24ndCBsb2FkIGZyb20gRlNcblx0XHRpZiAoIXRoaXMuI3BlcnNpc3QpIHtcblx0XHRcdHJldHVybiBlbnRyeTtcblx0XHR9XG5cblx0XHQvLyBJZiBzdGF0ZSBpcyBjdXJyZW50bHkgYmVpbmcgbG9hZGVkLCB3YWl0IGZvciBpdFxuXHRcdGlmIChlbnRyeS5sb2FkUHJvbWlzZSkge1xuXHRcdFx0YXdhaXQgZW50cnkubG9hZFByb21pc2U7XG5cdFx0XHRyZXR1cm4gZW50cnk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RhcnQgbG9hZGluZyBzdGF0ZVxuXHRcdGVudHJ5LmxvYWRQcm9taXNlID0gdGhpcy5sb2FkQWN0b3JTdGF0ZShlbnRyeSk7XG5cdFx0cmV0dXJuIGVudHJ5LmxvYWRQcm9taXNlO1xuXHR9XG5cblx0cHJpdmF0ZSBhc3luYyBsb2FkQWN0b3JTdGF0ZShlbnRyeTogQWN0b3JFbnRyeSkge1xuXHRcdGNvbnN0IHN0YXRlRmlsZVBhdGggPSB0aGlzLmdldEFjdG9yU3RhdGVQYXRoKGVudHJ5LmlkKTtcblxuXHRcdC8vIFJlYWQgJiBwYXJzZSBmaWxlXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHN0YXRlRGF0YSA9IGF3YWl0IGZzLnJlYWRGaWxlKHN0YXRlRmlsZVBhdGgpO1xuXG5cdFx0XHQvLyBDYWNoZSB0aGUgbG9hZGVkIHN0YXRlIGluIGhhbmRsZXJcblx0XHRcdGVudHJ5LnN0YXRlID0gQUNUT1JfU1RBVEVfVkVSU0lPTkVELmRlc2VyaWFsaXplV2l0aEVtYmVkZGVkVmVyc2lvbihcblx0XHRcdFx0bmV3IFVpbnQ4QXJyYXkoc3RhdGVEYXRhKSxcblx0XHRcdCk7XG5cblx0XHRcdHJldHVybiBlbnRyeTtcblx0XHR9IGNhdGNoIChpbm5lckVycm9yOiBhbnkpIHtcblx0XHRcdC8vIEZpbGUgZG9lcyBub3QgZXhpc3QsIG1lYW5pbmcgdGhlIGFjdG9yIGRvZXMgbm90IGV4aXN0XG5cdFx0XHRpZiAoaW5uZXJFcnJvci5jb2RlID09PSBcIkVOT0VOVFwiKSB7XG5cdFx0XHRcdGVudHJ5LmxvYWRQcm9taXNlID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRyZXR1cm4gZW50cnk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZvciBvdGhlciBlcnJvcnMsIHRocm93XG5cdFx0XHRjb25zdCBlcnJvciA9IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgYWN0b3Igc3RhdGU6ICR7aW5uZXJFcnJvcn1gKTtcblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGxvYWRPckNyZWF0ZUFjdG9yKFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHRuYW1lOiBzdHJpbmcsXG5cdFx0a2V5OiBBY3RvcktleSxcblx0XHRpbnB1dDogdW5rbm93biB8IHVuZGVmaW5lZCxcblx0KTogUHJvbWlzZTxBY3RvckVudHJ5PiB7XG5cdFx0Ly8gQXR0ZW1wdCB0byBsb2FkIGFjdG9yXG5cdFx0Y29uc3QgZW50cnkgPSBhd2FpdCB0aGlzLmxvYWRBY3RvcihhY3RvcklkKTtcblxuXHRcdC8vIElmIG5vIHN0YXRlIGZvciB0aGlzIGFjdG9yLCB0aGVuIGNyZWF0ZSAmIHdyaXRlIHN0YXRlXG5cdFx0aWYgKCFlbnRyeS5zdGF0ZSkge1xuXHRcdFx0ZW50cnkuc3RhdGUgPSB7XG5cdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGtleToga2V5IGFzIHJlYWRvbmx5IHN0cmluZ1tdLFxuXHRcdFx0XHRjcmVhdGVkQXQ6IEJpZ0ludChEYXRlLm5vdygpKSxcblx0XHRcdFx0cGVyc2lzdGVkRGF0YTogYnVmZmVyVG9BcnJheUJ1ZmZlcihzZXJpYWxpemVFbXB0eVBlcnNpc3REYXRhKGlucHV0KSksXG5cdFx0XHR9O1xuXHRcdFx0YXdhaXQgdGhpcy53cml0ZUFjdG9yKGFjdG9ySWQsIGVudHJ5LnN0YXRlKTtcblx0XHR9XG5cdFx0cmV0dXJuIGVudHJ5O1xuXHR9XG5cblx0YXN5bmMgc2xlZXBBY3RvcihhY3RvcklkOiBzdHJpbmcpIHtcblx0XHRpbnZhcmlhbnQoXG5cdFx0XHR0aGlzLiNwZXJzaXN0LFxuXHRcdFx0XCJjYW5ub3Qgc2xlZXAgYWN0b3Igd2l0aCBtZW1vcnkgZHJpdmVyLCBtdXN0IHVzZSBmaWxlIHN5c3RlbSBkcml2ZXJcIixcblx0XHQpO1xuXG5cdFx0Y29uc3QgYWN0b3IgPSB0aGlzLiNhY3RvcnMuZ2V0KGFjdG9ySWQpO1xuXHRcdGludmFyaWFudChhY3RvciwgYHRyaWVkIHRvIHNsZWVwICR7YWN0b3JJZH0sIGRvZXMgbm90IGV4aXN0YCk7XG5cblx0XHQvLyBXYWl0IGZvciBhY3RvciB0byBmdWxseSBzdGFydCBiZWZvcmUgc3RvcHBpbmcgaXQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zXG5cdFx0aWYgKGFjdG9yLmxvYWRQcm9taXNlKSBhd2FpdCBhY3Rvci5sb2FkUHJvbWlzZS5jYXRjaCgpO1xuXHRcdGlmIChhY3Rvci5zdGFydFByb21pc2U/LnByb21pc2UpIGF3YWl0IGFjdG9yLnN0YXJ0UHJvbWlzZS5wcm9taXNlLmNhdGNoKCk7XG5cblx0XHQvLyBNYXJrIGFzIHJlbW92ZWRcblx0XHRhY3Rvci5yZW1vdmVkID0gdHJ1ZTtcblxuXHRcdC8vIFN0b3AgYWN0b3Jcblx0XHRpbnZhcmlhbnQoYWN0b3IuYWN0b3IsIFwiYWN0b3Igc2hvdWxkIGJlIGxvYWRlZFwiKTtcblx0XHRhd2FpdCBhY3Rvci5hY3Rvci5fc3RvcCgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGZyb20gbWFwIGFmdGVyIHN0b3AgaXMgY29tcGxldGVcblx0XHR0aGlzLiNhY3RvcnMuZGVsZXRlKGFjdG9ySWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNhdmUgYWN0b3Igc3RhdGUgdG8gZGlzay5cblx0ICovXG5cdGFzeW5jIHdyaXRlQWN0b3IoYWN0b3JJZDogc3RyaW5nLCBzdGF0ZTogc2NoZW1hLkFjdG9yU3RhdGUpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuI3BlcnNpc3QpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBlbnRyeSA9IHRoaXMuI2FjdG9ycy5nZXQoYWN0b3JJZCk7XG5cdFx0aW52YXJpYW50KGVudHJ5LCBcImFjdG9yIGVudHJ5IGRvZXMgbm90IGV4aXN0XCIpO1xuXG5cdFx0YXdhaXQgdGhpcy4jcGVyZm9ybVdyaXRlKGFjdG9ySWQsIHN0YXRlKTtcblx0fVxuXG5cdGFzeW5jIHNldEFjdG9yQWxhcm0oYWN0b3JJZDogc3RyaW5nLCB0aW1lc3RhbXA6IG51bWJlcikge1xuXHRcdGNvbnN0IGVudHJ5ID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpbnZhcmlhbnQoZW50cnksIFwiYWN0b3IgZW50cnkgZG9lcyBub3QgZXhpc3RcIik7XG5cblx0XHQvLyBQZXJzaXN0IGFsYXJtIHRvIGRpc2tcblx0XHRpZiAodGhpcy4jcGVyc2lzdCkge1xuXHRcdFx0Y29uc3QgYWxhcm1QYXRoID0gdGhpcy5nZXRBY3RvckFsYXJtUGF0aChhY3RvcklkKTtcblx0XHRcdGNvbnN0IHRlbXBQYXRoID0gYCR7YWxhcm1QYXRofS50bXAuJHtjcnlwdG8ucmFuZG9tVVVJRCgpfWA7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRhd2FpdCBlbnN1cmVEaXJlY3RvcnlFeGlzdHMocGF0aC5kaXJuYW1lKGFsYXJtUGF0aCkpO1xuXHRcdFx0XHRjb25zdCBhbGFybURhdGE6IHNjaGVtYS5BY3RvckFsYXJtID0ge1xuXHRcdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdFx0dGltZXN0YW1wOiBCaWdJbnQodGltZXN0YW1wKSxcblx0XHRcdFx0fTtcblx0XHRcdFx0Y29uc3QgZGF0YSA9XG5cdFx0XHRcdFx0QUNUT1JfQUxBUk1fVkVSU0lPTkVELnNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oYWxhcm1EYXRhKTtcblx0XHRcdFx0YXdhaXQgZnMud3JpdGVGaWxlKHRlbXBQYXRoLCBkYXRhKTtcblx0XHRcdFx0YXdhaXQgZnMucmVuYW1lKHRlbXBQYXRoLCBhbGFybVBhdGgpO1xuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRhd2FpdCBmcy51bmxpbmsodGVtcFBhdGgpO1xuXHRcdFx0XHR9IGNhdGNoIHt9XG5cdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIHdyaXRlIGFsYXJtXCIsIHsgYWN0b3JJZCwgZXJyb3IgfSk7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHdyaXRlIGFsYXJtOiAke2Vycm9yfWApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNjaGVkdWxlIHRpbWVvdXRcblx0XHR0aGlzLiNzY2hlZHVsZUFsYXJtVGltZW91dChhY3RvcklkLCB0aW1lc3RhbXApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBlcmZvcm0gdGhlIGFjdHVhbCB3cml0ZSBvcGVyYXRpb24gd2l0aCBhdG9taWMgd3JpdGVzXG5cdCAqL1xuXHRhc3luYyAjcGVyZm9ybVdyaXRlKFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHRzdGF0ZTogc2NoZW1hLkFjdG9yU3RhdGUsXG5cdCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IGRhdGFQYXRoID0gdGhpcy5nZXRBY3RvclN0YXRlUGF0aChhY3RvcklkKTtcblx0XHQvLyBHZW5lcmF0ZSB1bmlxdWUgdGVtcCBmaWxlbmFtZSB0byBwcmV2ZW50IGFueSByYWNlIGNvbmRpdGlvbnNcblx0XHRjb25zdCB0ZW1wUGF0aCA9IGAke2RhdGFQYXRofS50bXAuJHtjcnlwdG8ucmFuZG9tVVVJRCgpfWA7XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gQ3JlYXRlIGRpcmVjdG9yeSBpZiBuZWVkZWRcblx0XHRcdGF3YWl0IGVuc3VyZURpcmVjdG9yeUV4aXN0cyhwYXRoLmRpcm5hbWUoZGF0YVBhdGgpKTtcblxuXHRcdFx0Ly8gQ29udmVydCB0byBCQVJFIHR5cGVzIGZvciBzZXJpYWxpemF0aW9uXG5cdFx0XHRjb25zdCBiYXJlU3RhdGU6IHNjaGVtYS5BY3RvclN0YXRlID0ge1xuXHRcdFx0XHRhY3RvcklkOiBzdGF0ZS5hY3RvcklkLFxuXHRcdFx0XHRuYW1lOiBzdGF0ZS5uYW1lLFxuXHRcdFx0XHRrZXk6IHN0YXRlLmtleSxcblx0XHRcdFx0Y3JlYXRlZEF0OiBzdGF0ZS5jcmVhdGVkQXQsXG5cdFx0XHRcdHBlcnNpc3RlZERhdGE6IHN0YXRlLnBlcnNpc3RlZERhdGEsXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBQZXJmb3JtIGF0b21pYyB3cml0ZVxuXHRcdFx0Y29uc3Qgc2VyaWFsaXplZFN0YXRlID1cblx0XHRcdFx0QUNUT1JfU1RBVEVfVkVSU0lPTkVELnNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oYmFyZVN0YXRlKTtcblx0XHRcdGF3YWl0IGZzLndyaXRlRmlsZSh0ZW1wUGF0aCwgc2VyaWFsaXplZFN0YXRlKTtcblx0XHRcdGF3YWl0IGZzLnJlbmFtZSh0ZW1wUGF0aCwgZGF0YVBhdGgpO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHQvLyBDbGVhbnVwIHRlbXAgZmlsZSBvbiBlcnJvclxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0YXdhaXQgZnMudW5saW5rKHRlbXBQYXRoKTtcblx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHQvLyBJZ25vcmUgY2xlYW51cCBlcnJvcnNcblx0XHRcdH1cblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIHNhdmUgYWN0b3Igc3RhdGVcIiwgeyBhY3RvcklkLCBlcnJvciB9KTtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHNhdmUgYWN0b3Igc3RhdGU6ICR7ZXJyb3J9YCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENhbGwgdGhpcyBtZXRob2QgYWZ0ZXIgdGhlIGFjdG9yIGRyaXZlciBoYXMgYmVlbiBpbml0aWF0ZWQuXG5cdCAqXG5cdCAqIFRoaXMgd2lsbCB0cmlnZ2VyIGFsbCBpbml0aWFsIGFsYXJtcyBmcm9tIHRoZSBmaWxlIHN5c3RlbS5cblx0ICpcblx0ICogVGhpcyBuZWVkcyB0byBiZSBzeW5jIHNpbmNlIERyaXZlckNvbmZpZy5hY3RvciBpcyBzeW5jXG5cdCAqL1xuXHRvblJ1bm5lclN0YXJ0KFxuXHRcdHJlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZyxcblx0XHRydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0XHRpbmxpbmVDbGllbnQ6IEFueUNsaWVudCxcblx0XHRhY3RvckRyaXZlcjogQWN0b3JEcml2ZXIsXG5cdCkge1xuXHRcdGlmICh0aGlzLiNydW5uZXJQYXJhbXMpIHtcblx0XHRcdGxvZ2dlcigpLndhcm4oXCJhbHJlYWR5IGNhbGxlZCBvblJ1bm5lclN0YXJ0XCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFNhdmUgcnVubmVyIHBhcmFtcyBmb3IgZnV0dXJlIHVzZVxuXHRcdHRoaXMuI3J1bm5lclBhcmFtcyA9IHtcblx0XHRcdHJlZ2lzdHJ5Q29uZmlnLFxuXHRcdFx0cnVuQ29uZmlnLFxuXHRcdFx0aW5saW5lQ2xpZW50LFxuXHRcdFx0YWN0b3JEcml2ZXIsXG5cdFx0fTtcblxuXHRcdC8vIExvYWQgYWxhcm1zIGZyb20gZGlzayBhbmQgc2NoZWR1bGUgdGltZW91dHNcblx0XHR0cnkge1xuXHRcdFx0dGhpcy4jbG9hZEFsYXJtc1N5bmMoKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIGxvYWQgYWxhcm1zIG9uIHN0YXJ0dXBcIiwgeyBlcnJvcjogZXJyIH0pO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIHN0YXJ0QWN0b3IoXG5cdFx0cmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnLFxuXHRcdHJ1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRcdGlubGluZUNsaWVudDogQW55Q2xpZW50LFxuXHRcdGFjdG9yRHJpdmVyOiBBY3RvckRyaXZlcixcblx0XHRhY3RvcklkOiBzdHJpbmcsXG5cdCk6IFByb21pc2U8QW55QWN0b3JJbnN0YW5jZT4ge1xuXHRcdC8vIEdldCB0aGUgYWN0b3IgbWV0YWRhdGFcblx0XHRjb25zdCBlbnRyeSA9IGF3YWl0IHRoaXMubG9hZEFjdG9yKGFjdG9ySWQpO1xuXHRcdGlmICghZW50cnkuc3RhdGUpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgQWN0b3IgZG9lcyBleGlzdCBhbmQgY2Fubm90IGJlIHN0YXJ0ZWQ6ICR7YWN0b3JJZH1gKTtcblx0XHR9XG5cblx0XHQvLyBBY3RvciBhbHJlYWR5IHN0YXJ0aW5nXG5cdFx0aWYgKGVudHJ5LnN0YXJ0UHJvbWlzZSkge1xuXHRcdFx0YXdhaXQgZW50cnkuc3RhcnRQcm9taXNlLnByb21pc2U7XG5cdFx0XHRpbnZhcmlhbnQoZW50cnkuYWN0b3IsIFwiYWN0b3Igc2hvdWxkIGhhdmUgbG9hZGVkXCIpO1xuXHRcdFx0cmV0dXJuIGVudHJ5LmFjdG9yO1xuXHRcdH1cblxuXHRcdC8vIEFjdG9yIGFscmVhZHkgbG9hZGVkXG5cdFx0aWYgKGVudHJ5LmFjdG9yKSB7XG5cdFx0XHRyZXR1cm4gZW50cnkuYWN0b3I7XG5cdFx0fVxuXG5cdFx0Ly8gQ3JlYXRlIHN0YXJ0IHByb21pc2Vcblx0XHRlbnRyeS5zdGFydFByb21pc2UgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTtcblxuXHRcdHRyeSB7XG5cdFx0XHQvLyBDcmVhdGUgYWN0b3Jcblx0XHRcdGNvbnN0IGRlZmluaXRpb24gPSBsb29rdXBJblJlZ2lzdHJ5KHJlZ2lzdHJ5Q29uZmlnLCBlbnRyeS5zdGF0ZS5uYW1lKTtcblx0XHRcdGVudHJ5LmFjdG9yID0gZGVmaW5pdGlvbi5pbnN0YW50aWF0ZSgpO1xuXG5cdFx0XHQvLyBTdGFydCBhY3RvclxuXHRcdFx0Y29uc3QgY29ubkRyaXZlcnMgPSBjcmVhdGVHZW5lcmljQ29ubkRyaXZlcnMoXG5cdFx0XHRcdGVudHJ5LmdlbmVyaWNDb25uR2xvYmFsU3RhdGUsXG5cdFx0XHQpO1xuXHRcdFx0YXdhaXQgZW50cnkuYWN0b3Iuc3RhcnQoXG5cdFx0XHRcdGNvbm5Ecml2ZXJzLFxuXHRcdFx0XHRhY3RvckRyaXZlcixcblx0XHRcdFx0aW5saW5lQ2xpZW50LFxuXHRcdFx0XHRhY3RvcklkLFxuXHRcdFx0XHRlbnRyeS5zdGF0ZS5uYW1lLFxuXHRcdFx0XHRlbnRyeS5zdGF0ZS5rZXkgYXMgc3RyaW5nW10sXG5cdFx0XHRcdFwidW5rbm93blwiLFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gRmluaXNoXG5cdFx0XHRlbnRyeS5zdGFydFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdFx0ZW50cnkuc3RhcnRQcm9taXNlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRyZXR1cm4gZW50cnkuYWN0b3I7XG5cdFx0fSBjYXRjaCAoaW5uZXJFcnJvcikge1xuXHRcdFx0Y29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoXG5cdFx0XHRcdGBGYWlsZWQgdG8gc3RhcnQgYWN0b3IgJHthY3RvcklkfTogJHtpbm5lckVycm9yfWAsXG5cdFx0XHRcdHsgY2F1c2U6IGlubmVyRXJyb3IgfSxcblx0XHRcdCk7XG5cdFx0XHRlbnRyeS5zdGFydFByb21pc2U/LnJlamVjdChlcnJvcik7XG5cdFx0XHRlbnRyeS5zdGFydFByb21pc2UgPSB1bmRlZmluZWQ7XG5cdFx0XHR0aHJvdyBlcnJvcjtcblx0XHR9XG5cdH1cblxuXHRhc3luYyBsb2FkQWN0b3JTdGF0ZU9yRXJyb3IoYWN0b3JJZDogc3RyaW5nKTogUHJvbWlzZTxzY2hlbWEuQWN0b3JTdGF0ZT4ge1xuXHRcdGNvbnN0IHN0YXRlID0gKGF3YWl0IHRoaXMubG9hZEFjdG9yKGFjdG9ySWQpKS5zdGF0ZTtcblx0XHRpZiAoIXN0YXRlKSB0aHJvdyBuZXcgRXJyb3IoYEFjdG9yIGRvZXMgbm90IGV4aXN0OiAke2FjdG9ySWR9YCk7XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cblx0Z2V0QWN0b3JPckVycm9yKGFjdG9ySWQ6IHN0cmluZyk6IEFjdG9yRW50cnkge1xuXHRcdGNvbnN0IGVudHJ5ID0gdGhpcy4jYWN0b3JzLmdldChhY3RvcklkKTtcblx0XHRpZiAoIWVudHJ5KSB0aHJvdyBuZXcgRXJyb3IoYE5vIGVudHJ5IGZvciBhY3RvcjogJHthY3RvcklkfWApO1xuXHRcdHJldHVybiBlbnRyeTtcblx0fVxuXG5cdGFzeW5jIGNyZWF0ZURhdGFiYXNlKGFjdG9ySWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0QWN0b3JEYlBhdGgoYWN0b3JJZCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCBhbGwgcGVyc2lzdGVkIGFsYXJtcyBmcm9tIGRpc2sgYW5kIHNjaGVkdWxlIHRoZWlyIHRpbWVycy5cblx0ICovXG5cdCNsb2FkQWxhcm1zU3luYygpOiB2b2lkIHtcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgZmlsZXMgPSBmc1N5bmMuZXhpc3RzU3luYyh0aGlzLiNhbGFybXNEaXIpXG5cdFx0XHRcdD8gZnNTeW5jLnJlYWRkaXJTeW5jKHRoaXMuI2FsYXJtc0Rpcilcblx0XHRcdFx0OiBbXTtcblx0XHRcdGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuXHRcdFx0XHQvLyBTa2lwIHRlbXAgZmlsZXNcblx0XHRcdFx0aWYgKGZpbGUuaW5jbHVkZXMoXCIudG1wLlwiKSkgY29udGludWU7XG5cdFx0XHRcdGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHRoaXMuI2FsYXJtc0RpciwgZmlsZSk7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29uc3QgYnVmID0gZnNTeW5jLnJlYWRGaWxlU3luYyhmdWxsUGF0aCk7XG5cdFx0XHRcdFx0Y29uc3QgYWxhcm1EYXRhID1cblx0XHRcdFx0XHRcdEFDVE9SX0FMQVJNX1ZFUlNJT05FRC5kZXNlcmlhbGl6ZVdpdGhFbWJlZGRlZFZlcnNpb24oXG5cdFx0XHRcdFx0XHRcdG5ldyBVaW50OEFycmF5KGJ1ZiksXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdGNvbnN0IHRpbWVzdGFtcCA9IE51bWJlcihhbGFybURhdGEudGltZXN0YW1wKTtcblx0XHRcdFx0XHRpZiAoTnVtYmVyLmlzRmluaXRlKHRpbWVzdGFtcCkpIHtcblx0XHRcdFx0XHRcdHRoaXMuI3NjaGVkdWxlQWxhcm1UaW1lb3V0KGFsYXJtRGF0YS5hY3RvcklkLCB0aW1lc3RhbXApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImludmFsaWQgYWxhcm0gZmlsZSBjb250ZW50c1wiLCB7IGZpbGUgfSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byByZWFkIGFsYXJtIGZpbGVcIiwge1xuXHRcdFx0XHRcdFx0ZmlsZSxcblx0XHRcdFx0XHRcdGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnIpLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBsaXN0IGFsYXJtcyBkaXJlY3RvcnlcIiwgeyBlcnJvcjogZXJyIH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTY2hlZHVsZSBhbiBhbGFybSB0aW1lciBmb3IgYW4gYWN0b3Igd2l0aG91dCB3cml0aW5nIHRvIGRpc2suXG5cdCAqL1xuXHQjc2NoZWR1bGVBbGFybVRpbWVvdXQoYWN0b3JJZDogc3RyaW5nLCB0aW1lc3RhbXA6IG51bWJlcikge1xuXHRcdGNvbnN0IGVudHJ5ID0gdGhpcy4jdXBzZXJ0RW50cnkoYWN0b3JJZCk7XG5cblx0XHQvLyBJZiB0aGVyZSdzIGFscmVhZHkgYW4gZWFybGllciBhbGFybSBzY2hlZHVsZWQsIGRvIG5vdCBvdmVycmlkZSBpdC5cblx0XHRpZiAoXG5cdFx0XHRlbnRyeS5hbGFybVRpbWVzdGFtcCAhPT0gdW5kZWZpbmVkICYmXG5cdFx0XHR0aW1lc3RhbXAgPj0gZW50cnkuYWxhcm1UaW1lc3RhbXBcblx0XHQpIHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic2tpcHBpbmcgYWxhcm0gc2NoZWR1bGUgKGxhdGVyIHRoYW4gZXhpc3RpbmcpXCIsIHtcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0dGltZXN0YW1wLFxuXHRcdFx0XHRjdXJyZW50OiBlbnRyeS5hbGFybVRpbWVzdGFtcCxcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGxvZ2dlcigpLmRlYnVnKFwic2NoZWR1bGluZyBhbGFybVwiLCB7IGFjdG9ySWQsIHRpbWVzdGFtcCB9KTtcblxuXHRcdC8vIENhbmNlbCBleGlzdGluZyB0aW1lb3V0IGFuZCB1cGRhdGUgdGhlIGN1cnJlbnQgc2NoZWR1bGVkIHRpbWVzdGFtcFxuXHRcdGVudHJ5LmFsYXJtVGltZW91dD8uYWJvcnQoKTtcblx0XHRlbnRyeS5hbGFybVRpbWVzdGFtcCA9IHRpbWVzdGFtcDtcblxuXHRcdGNvbnN0IGRlbGF5ID0gTWF0aC5tYXgoMCwgdGltZXN0YW1wIC0gRGF0ZS5ub3coKSk7XG5cdFx0ZW50cnkuYWxhcm1UaW1lb3V0ID0gc2V0TG9uZ1RpbWVvdXQoYXN5bmMgKCkgPT4ge1xuXHRcdFx0Ly8gQ2xlYXIgY3VycmVudGx5IHNjaGVkdWxlZCB0aW1lc3RhbXAgYXMgdGhpcyBhbGFybSBpcyBmaXJpbmcgbm93XG5cdFx0XHRlbnRyeS5hbGFybVRpbWVzdGFtcCA9IHVuZGVmaW5lZDtcblx0XHRcdC8vIE9uIHRyaWdnZXI6IHJlbW92ZSBwZXJzaXN0ZWQgYWxhcm0gZmlsZVxuXHRcdFx0aWYgKHRoaXMuI3BlcnNpc3QpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRhd2FpdCBmcy51bmxpbmsodGhpcy5nZXRBY3RvckFsYXJtUGF0aChhY3RvcklkKSk7XG5cdFx0XHRcdH0gY2F0Y2ggKGVycjogYW55KSB7XG5cdFx0XHRcdFx0aWYgKGVycj8uY29kZSAhPT0gXCJFTk9FTlRcIikge1xuXHRcdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmYWlsZWQgdG8gcmVtb3ZlIGFsYXJtIGZpbGVcIiwge1xuXHRcdFx0XHRcdFx0XHRhY3RvcklkLFxuXHRcdFx0XHRcdFx0XHRlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyKSxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInRyaWdnZXJpbmcgYWxhcm1cIiwgeyBhY3RvcklkLCB0aW1lc3RhbXAgfSk7XG5cblx0XHRcdFx0Ly8gRW5zdXJlIGFjdG9yIHN0YXRlIGV4aXN0cyBhbmQgc3RhcnQgYWN0b3IgaWYgbmVlZGVkXG5cdFx0XHRcdGNvbnN0IGxvYWRlZCA9IGF3YWl0IHRoaXMubG9hZEFjdG9yKGFjdG9ySWQpO1xuXHRcdFx0XHRpZiAoIWxvYWRlZC5zdGF0ZSkgdGhyb3cgbmV3IEVycm9yKGBBY3RvciBkb2VzIG5vdCBleGlzdDogJHthY3RvcklkfWApO1xuXG5cdFx0XHRcdC8vIFN0YXJ0IGFjdG9yIGlmIG5vdCBhbHJlYWR5IHJ1bm5pbmdcblx0XHRcdFx0Y29uc3QgcnVubmVyUGFyYW1zID0gdGhpcy4jcnVubmVyUGFyYW1zO1xuXHRcdFx0XHRpbnZhcmlhbnQocnVubmVyUGFyYW1zLCBcIm1pc3NpbmcgcnVubmVyIHBhcmFtc1wiKTtcblx0XHRcdFx0aWYgKCFsb2FkZWQuYWN0b3IpIHtcblx0XHRcdFx0XHRhd2FpdCB0aGlzLnN0YXJ0QWN0b3IoXG5cdFx0XHRcdFx0XHRydW5uZXJQYXJhbXMucmVnaXN0cnlDb25maWcsXG5cdFx0XHRcdFx0XHRydW5uZXJQYXJhbXMucnVuQ29uZmlnLFxuXHRcdFx0XHRcdFx0cnVubmVyUGFyYW1zLmlubGluZUNsaWVudCxcblx0XHRcdFx0XHRcdHJ1bm5lclBhcmFtcy5hY3RvckRyaXZlcixcblx0XHRcdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGludmFyaWFudChsb2FkZWQuYWN0b3IsIFwiYWN0b3Igc2hvdWxkIGJlIGxvYWRlZCBhZnRlciB3YWtlXCIpO1xuXHRcdFx0XHRhd2FpdCBsb2FkZWQuYWN0b3IuX29uQWxhcm0oKTtcblx0XHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBoYW5kbGUgYWxhcm1cIiwge1xuXHRcdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVyciksXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0sIGRlbGF5KTtcblx0fVxuXG5cdGdldE9yQ3JlYXRlSW5zcGVjdG9yQWNjZXNzVG9rZW4oKTogc3RyaW5nIHtcblx0XHRjb25zdCB0b2tlblBhdGggPSBwYXRoLmpvaW4odGhpcy4jc3RvcmFnZVBhdGgsIFwiaW5zcGVjdG9yLXRva2VuXCIpO1xuXHRcdGlmIChmc1N5bmMuZXhpc3RzU3luYyh0b2tlblBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gZnNTeW5jLnJlYWRGaWxlU3luYyh0b2tlblBhdGgsIFwidXRmLThcIik7XG5cdFx0fVxuXG5cdFx0Y29uc3QgbmV3VG9rZW4gPSBnZW5lcmF0ZVJhbmRvbVN0cmluZygpO1xuXHRcdGZzU3luYy53cml0ZUZpbGVTeW5jKHRva2VuUGF0aCwgbmV3VG9rZW4pO1xuXHRcdHJldHVybiBuZXdUb2tlbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhbnVwIHN0YWxlIHRlbXAgZmlsZXMgb24gc3RhcnR1cCAoc3luY2hyb25vdXMpXG5cdCAqL1xuXHQjY2xlYW51cFRlbXBGaWxlc1N5bmMoKTogdm9pZCB7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IGZpbGVzID0gZnNTeW5jLnJlYWRkaXJTeW5jKHRoaXMuI3N0YXRlRGlyKTtcblx0XHRcdGNvbnN0IHRlbXBGaWxlcyA9IGZpbGVzLmZpbHRlcigoZikgPT4gZi5pbmNsdWRlcyhcIi50bXAuXCIpKTtcblxuXHRcdFx0Y29uc3Qgb25lSG91ckFnbyA9IERhdGUubm93KCkgLSAzNjAwMDAwOyAvLyAxIGhvdXIgaW4gbXNcblxuXHRcdFx0Zm9yIChjb25zdCB0ZW1wRmlsZSBvZiB0ZW1wRmlsZXMpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbih0aGlzLiNzdGF0ZURpciwgdGVtcEZpbGUpO1xuXHRcdFx0XHRcdGNvbnN0IHN0YXQgPSBmc1N5bmMuc3RhdFN5bmMoZnVsbFBhdGgpO1xuXG5cdFx0XHRcdFx0Ly8gUmVtb3ZlIGlmIG9sZGVyIHRoYW4gMSBob3VyXG5cdFx0XHRcdFx0aWYgKHN0YXQubXRpbWVNcyA8IG9uZUhvdXJBZ28pIHtcblx0XHRcdFx0XHRcdGZzU3luYy51bmxpbmtTeW5jKGZ1bGxQYXRoKTtcblx0XHRcdFx0XHRcdGxvZ2dlcigpLmluZm8oXCJjbGVhbmVkIHVwIHN0YWxlIHRlbXAgZmlsZVwiLCB7IGZpbGU6IHRlbXBGaWxlIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmYWlsZWQgdG8gY2xlYW51cCB0ZW1wIGZpbGVcIiwge1xuXHRcdFx0XHRcdFx0ZmlsZTogdGVtcEZpbGUsXG5cdFx0XHRcdFx0XHRlcnJvcjogZXJyLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byByZWFkIGFjdG9ycyBkaXJlY3RvcnkgZm9yIGNsZWFudXBcIiwge1xuXHRcdFx0XHRlcnJvcjogZXJyLFxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2Rpc3Qvc2NoZW1hcy9maWxlLXN5c3RlbS1kcml2ZXIvdjEudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9kaXN0L3NjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZGlzdC9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci92MS50c1wiO2ltcG9ydCAqIGFzIGJhcmUgZnJvbSBcIkBiYXJlLXRzL2xpYlwiXG5cbmNvbnN0IGNvbmZpZyA9IC8qIEBfX1BVUkVfXyAqLyBiYXJlLkNvbmZpZyh7fSlcblxuZXhwb3J0IHR5cGUgdTY0ID0gYmlnaW50XG5leHBvcnQgdHlwZSB1aW50ID0gYmlnaW50XG5cbmZ1bmN0aW9uIHJlYWQwKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgY29uc3QgbGVuID0gYmFyZS5yZWFkVWludFNhZmUoYmMpXG4gICAgaWYgKGxlbiA9PT0gMCkgeyByZXR1cm4gW10gfVxuICAgIGNvbnN0IHJlc3VsdCA9IFtiYXJlLnJlYWRTdHJpbmcoYmMpXVxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgcmVzdWx0W2ldID0gYmFyZS5yZWFkU3RyaW5nKGJjKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHdyaXRlMChiYzogYmFyZS5CeXRlQ3Vyc29yLCB4OiByZWFkb25seSBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVVaW50U2FmZShiYywgeC5sZW5ndGgpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHhbaV0pXG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBBY3RvclN0YXRlID0ge1xuICAgIHJlYWRvbmx5IGFjdG9ySWQ6IHN0cmluZyxcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkga2V5OiByZWFkb25seSBzdHJpbmdbXSxcbiAgICByZWFkb25seSBwZXJzaXN0ZWREYXRhOiBBcnJheUJ1ZmZlcixcbiAgICByZWFkb25seSBjcmVhdGVkQXQ6IHU2NCxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRBY3RvclN0YXRlKGJjOiBiYXJlLkJ5dGVDdXJzb3IpOiBBY3RvclN0YXRlIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBhY3RvcklkOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBuYW1lOiBiYXJlLnJlYWRTdHJpbmcoYmMpLFxuICAgICAgICBrZXk6IHJlYWQwKGJjKSxcbiAgICAgICAgcGVyc2lzdGVkRGF0YTogYmFyZS5yZWFkRGF0YShiYyksXG4gICAgICAgIGNyZWF0ZWRBdDogYmFyZS5yZWFkVTY0KGJjKSxcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUFjdG9yU3RhdGUoYmM6IGJhcmUuQnl0ZUN1cnNvciwgeDogQWN0b3JTdGF0ZSk6IHZvaWQge1xuICAgIGJhcmUud3JpdGVTdHJpbmcoYmMsIHguYWN0b3JJZClcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4Lm5hbWUpXG4gICAgd3JpdGUwKGJjLCB4LmtleSlcbiAgICBiYXJlLndyaXRlRGF0YShiYywgeC5wZXJzaXN0ZWREYXRhKVxuICAgIGJhcmUud3JpdGVVNjQoYmMsIHguY3JlYXRlZEF0KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlQWN0b3JTdGF0ZSh4OiBBY3RvclN0YXRlKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZUFjdG9yU3RhdGUoYmMsIHgpXG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJjLnZpZXcuYnVmZmVyLCBiYy52aWV3LmJ5dGVPZmZzZXQsIGJjLm9mZnNldClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUFjdG9yU3RhdGUoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBBY3RvclN0YXRlIHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkQWN0b3JTdGF0ZShiYylcbiAgICBpZiAoYmMub2Zmc2V0IDwgYmMudmlldy5ieXRlTGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBiYXJlLkJhcmVFcnJvcihiYy5vZmZzZXQsIFwicmVtYWluaW5nIGJ5dGVzXCIpXG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbn1cblxuZXhwb3J0IHR5cGUgQWN0b3JBbGFybSA9IHtcbiAgICByZWFkb25seSBhY3RvcklkOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgdGltZXN0YW1wOiB1aW50LFxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFjdG9yQWxhcm0oYmM6IGJhcmUuQnl0ZUN1cnNvcik6IEFjdG9yQWxhcm0ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGFjdG9ySWQ6IGJhcmUucmVhZFN0cmluZyhiYyksXG4gICAgICAgIHRpbWVzdGFtcDogYmFyZS5yZWFkVWludChiYyksXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVBY3RvckFsYXJtKGJjOiBiYXJlLkJ5dGVDdXJzb3IsIHg6IEFjdG9yQWxhcm0pOiB2b2lkIHtcbiAgICBiYXJlLndyaXRlU3RyaW5nKGJjLCB4LmFjdG9ySWQpXG4gICAgYmFyZS53cml0ZVVpbnQoYmMsIHgudGltZXN0YW1wKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlQWN0b3JBbGFybSh4OiBBY3RvckFsYXJtKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYmMgPSBuZXcgYmFyZS5CeXRlQ3Vyc29yKFxuICAgICAgICBuZXcgVWludDhBcnJheShjb25maWcuaW5pdGlhbEJ1ZmZlckxlbmd0aCksXG4gICAgICAgIGNvbmZpZ1xuICAgIClcbiAgICB3cml0ZUFjdG9yQWxhcm0oYmMsIHgpXG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJjLnZpZXcuYnVmZmVyLCBiYy52aWV3LmJ5dGVPZmZzZXQsIGJjLm9mZnNldClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUFjdG9yQWxhcm0oYnl0ZXM6IFVpbnQ4QXJyYXkpOiBBY3RvckFsYXJtIHtcbiAgICBjb25zdCBiYyA9IG5ldyBiYXJlLkJ5dGVDdXJzb3IoYnl0ZXMsIGNvbmZpZylcbiAgICBjb25zdCByZXN1bHQgPSByZWFkQWN0b3JBbGFybShiYylcbiAgICBpZiAoYmMub2Zmc2V0IDwgYmMudmlldy5ieXRlTGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBiYXJlLkJhcmVFcnJvcihiYy5vZmZzZXQsIFwicmVtYWluaW5nIGJ5dGVzXCIpXG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3NjaGVtYXMvZmlsZS1zeXN0ZW0tZHJpdmVyL3ZlcnNpb25lZC50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci92ZXJzaW9uZWQudHNcIjtpbXBvcnQge1xuXHRjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcixcblx0dHlwZSBNaWdyYXRpb25Gbixcbn0gZnJvbSBcIkAvY29tbW9uL3ZlcnNpb25lZC1kYXRhXCI7XG5pbXBvcnQgKiBhcyB2MSBmcm9tIFwiLi4vLi4vLi4vZGlzdC9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci92MVwiO1xuXG5leHBvcnQgY29uc3QgQ1VSUkVOVF9WRVJTSU9OID0gMTtcblxuZXhwb3J0IHR5cGUgQ3VycmVudEFjdG9yU3RhdGUgPSB2MS5BY3RvclN0YXRlO1xuZXhwb3J0IHR5cGUgQ3VycmVudEFjdG9yQWxhcm0gPSB2MS5BY3RvckFsYXJtO1xuXG5jb25zdCBtaWdyYXRpb25zID0gbmV3IE1hcDxudW1iZXIsIE1pZ3JhdGlvbkZuPGFueSwgYW55Pj4oKTtcblxuZXhwb3J0IGNvbnN0IEFDVE9SX1NUQVRFX1ZFUlNJT05FRCA9XG5cdGNyZWF0ZVZlcnNpb25lZERhdGFIYW5kbGVyPEN1cnJlbnRBY3RvclN0YXRlPih7XG5cdFx0Y3VycmVudFZlcnNpb246IENVUlJFTlRfVkVSU0lPTixcblx0XHRtaWdyYXRpb25zLFxuXHRcdHNlcmlhbGl6ZVZlcnNpb246IChkYXRhKSA9PiB2MS5lbmNvZGVBY3RvclN0YXRlKGRhdGEpLFxuXHRcdGRlc2VyaWFsaXplVmVyc2lvbjogKGJ5dGVzKSA9PiB2MS5kZWNvZGVBY3RvclN0YXRlKGJ5dGVzKSxcblx0fSk7XG5cbmV4cG9ydCBjb25zdCBBQ1RPUl9BTEFSTV9WRVJTSU9ORUQgPVxuXHRjcmVhdGVWZXJzaW9uZWREYXRhSGFuZGxlcjxDdXJyZW50QWN0b3JBbGFybT4oe1xuXHRcdGN1cnJlbnRWZXJzaW9uOiBDVVJSRU5UX1ZFUlNJT04sXG5cdFx0bWlncmF0aW9ucyxcblx0XHRzZXJpYWxpemVWZXJzaW9uOiAoZGF0YSkgPT4gdjEuZW5jb2RlQWN0b3JBbGFybShkYXRhKSxcblx0XHRkZXNlcmlhbGl6ZVZlcnNpb246IChieXRlcykgPT4gdjEuZGVjb2RlQWN0b3JBbGFybShieXRlcyksXG5cdH0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbS9sb2cudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL2xvZy50c1wiO2ltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAL2NvbW1vbi9sb2dcIjtcblxuZXhwb3J0IGNvbnN0IExPR0dFUl9OQU1FID0gXCJkcml2ZXItZnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2dlcigpIHtcblx0cmV0dXJuIGdldExvZ2dlcihMT0dHRVJfTkFNRSk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL3V0aWxzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW1cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbS91dGlscy50c1wiO2ltcG9ydCAqIGFzIGNyeXB0byBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCAqIGFzIGZzU3luYyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCAqIGFzIG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JLZXkgfSBmcm9tIFwiQC9hY3Rvci9tb2RcIjtcblxuLyoqXG4gKiBHZW5lcmF0ZSBhIGRldGVybWluaXN0aWMgYWN0b3IgSUQgZnJvbSBuYW1lIGFuZCBrZXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQWN0b3JJZChuYW1lOiBzdHJpbmcsIGtleTogQWN0b3JLZXkpOiBzdHJpbmcge1xuXHQvLyBHZW5lcmF0ZSBkZXRlcm1pbmlzdGljIGtleSBzdHJpbmdcblx0Y29uc3QganNvblN0cmluZyA9IEpTT04uc3RyaW5naWZ5KFtuYW1lLCBrZXldKTtcblxuXHQvLyBIYXNoIHRvIGVuc3VyZSBzYWZlIGZpbGUgc3lzdGVtIG5hbWVzXG5cdGNvbnN0IGhhc2ggPSBjcnlwdG9cblx0XHQuY3JlYXRlSGFzaChcInNoYTI1NlwiKVxuXHRcdC51cGRhdGUoanNvblN0cmluZylcblx0XHQuZGlnZXN0KFwiaGV4XCIpXG5cdFx0LnN1YnN0cmluZygwLCAxNik7XG5cblx0cmV0dXJuIGhhc2g7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgaGFzaCBmb3IgYSBwYXRoLCBub3JtYWxpemluZyBpdCBmaXJzdFxuICovXG5mdW5jdGlvbiBjcmVhdGVIYXNoRm9yUGF0aChkaXJQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuXHQvLyBOb3JtYWxpemUgdGhlIHBhdGggZmlyc3Rcblx0Y29uc3Qgbm9ybWFsaXplZFBhdGggPSBwYXRoLm5vcm1hbGl6ZShkaXJQYXRoKTtcblxuXHQvLyBFeHRyYWN0IHRoZSBsYXN0IHBhdGggY29tcG9uZW50IGZvciByZWFkYWJpbGl0eVxuXHRjb25zdCBsYXN0Q29tcG9uZW50ID0gcGF0aC5iYXNlbmFtZShub3JtYWxpemVkUGF0aCk7XG5cblx0Ly8gQ3JlYXRlIFNIQS0yNTYgaGFzaFxuXHRjb25zdCBoYXNoID0gY3J5cHRvXG5cdFx0LmNyZWF0ZUhhc2goXCJzaGEyNTZcIilcblx0XHQudXBkYXRlKG5vcm1hbGl6ZWRQYXRoKVxuXHRcdC5kaWdlc3QoXCJoZXhcIilcblx0XHQuc3Vic3RyaW5nKDAsIDgpOyAvLyBUYWtlIGZpcnN0IDggY2hhcmFjdGVycyBmb3IgYnJldml0eVxuXG5cdHJldHVybiBgJHtsYXN0Q29tcG9uZW50fS0ke2hhc2h9YDtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHN0b3JhZ2UgcGF0aCBmb3IgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3Rvcnkgb3IgYSBzcGVjaWZpZWQgcGF0aFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RvcmFnZVBhdGgoY3VzdG9tUGF0aD86IHN0cmluZyk6IHN0cmluZyB7XG5cdGNvbnN0IGRhdGFQYXRoID0gZ2V0RGF0YVBhdGgoXCJyaXZldGtpdFwiKTtcblx0Y29uc3QgcGF0aFRvSGFzaCA9IGN1c3RvbVBhdGggfHwgcHJvY2Vzcy5jd2QoKTtcblx0Y29uc3QgZGlySGFzaCA9IGNyZWF0ZUhhc2hGb3JQYXRoKHBhdGhUb0hhc2gpO1xuXHRyZXR1cm4gcGF0aC5qb2luKGRhdGFQYXRoLCBkaXJIYXNoKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhIHBhdGggZXhpc3RzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYXRoRXhpc3RzKHBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGZzLmFjY2VzcyhwYXRoKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSBjYXRjaCB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59XG5cbi8qKlxuICogRW5zdXJlIGEgZGlyZWN0b3J5IGV4aXN0cywgY3JlYXRpbmcgaXQgaWYgbmVjZXNzYXJ5XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVEaXJlY3RvcnlFeGlzdHMoXG5cdGRpcmVjdG9yeVBhdGg6IHN0cmluZyxcbik6IFByb21pc2U8dm9pZD4ge1xuXHRpZiAoIShhd2FpdCBwYXRoRXhpc3RzKGRpcmVjdG9yeVBhdGgpKSkge1xuXHRcdGF3YWl0IGZzLm1rZGlyKGRpcmVjdG9yeVBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXHR9XG59XG5cbi8qKlxuICogRW5zdXJlIGEgZGlyZWN0b3J5IGV4aXN0cyBzeW5jaHJvbm91c2x5IC0gb25seSB1c2VkIGR1cmluZyBpbml0aWFsaXphdGlvblxuICogQWxsIG90aGVyIG9wZXJhdGlvbnMgdXNlIHRoZSBhc3luYyB2ZXJzaW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVEaXJlY3RvcnlFeGlzdHNTeW5jKGRpcmVjdG9yeVBhdGg6IHN0cmluZyk6IHZvaWQge1xuXHRpZiAoIWZzU3luYy5leGlzdHNTeW5jKGRpcmVjdG9yeVBhdGgpKSB7XG5cdFx0ZnNTeW5jLm1rZGlyU3luYyhkaXJlY3RvcnlQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblx0fVxufVxuXG4vKipcbiAqIFJldHVybnMgcGxhdGZvcm0tc3BlY2lmaWMgZGF0YSBkaXJlY3RvcnlcbiAqL1xuZnVuY3Rpb24gZ2V0RGF0YVBhdGgoYXBwTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3QgcGxhdGZvcm0gPSBwcm9jZXNzLnBsYXRmb3JtO1xuXHRjb25zdCBob21lRGlyID0gb3MuaG9tZWRpcigpO1xuXG5cdHN3aXRjaCAocGxhdGZvcm0pIHtcblx0XHRjYXNlIFwid2luMzJcIjpcblx0XHRcdHJldHVybiBwYXRoLmpvaW4oXG5cdFx0XHRcdHByb2Nlc3MuZW52LkFQUERBVEEgfHwgcGF0aC5qb2luKGhvbWVEaXIsIFwiQXBwRGF0YVwiLCBcIlJvYW1pbmdcIiksXG5cdFx0XHRcdGFwcE5hbWUsXG5cdFx0XHQpO1xuXHRcdGNhc2UgXCJkYXJ3aW5cIjpcblx0XHRcdHJldHVybiBwYXRoLmpvaW4oaG9tZURpciwgXCJMaWJyYXJ5XCIsIFwiQXBwbGljYXRpb24gU3VwcG9ydFwiLCBhcHBOYW1lKTtcblx0XHRkZWZhdWx0OiAvLyBsaW51eCBhbmQgb3RoZXJzXG5cdFx0XHRyZXR1cm4gcGF0aC5qb2luKFxuXHRcdFx0XHRwcm9jZXNzLmVudi5YREdfREFUQV9IT01FIHx8IHBhdGguam9pbihob21lRGlyLCBcIi5sb2NhbFwiLCBcInNoYXJlXCIpLFxuXHRcdFx0XHRhcHBOYW1lLFxuXHRcdFx0KTtcblx0fVxufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbS9tYW5hZ2VyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW1cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9maWxlLXN5c3RlbS9tYW5hZ2VyLnRzXCI7aW1wb3J0IHR5cGUgeyBDb250ZXh0IGFzIEhvbm9Db250ZXh0IH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCBpbnZhcmlhbnQgZnJvbSBcImludmFyaWFudFwiO1xuaW1wb3J0IHsgdHlwZSBBY3RvclJvdXRlciwgY3JlYXRlQWN0b3JSb3V0ZXIgfSBmcm9tIFwiQC9hY3Rvci9yb3V0ZXJcIjtcbmltcG9ydCB7XG5cdGhhbmRsZVJhd1dlYlNvY2tldEhhbmRsZXIsXG5cdGhhbmRsZVdlYlNvY2tldENvbm5lY3QsXG59IGZyb20gXCJAL2FjdG9yL3JvdXRlci1lbmRwb2ludHNcIjtcbmltcG9ydCB7IGNyZWF0ZUNsaWVudFdpdGhEcml2ZXIgfSBmcm9tIFwiQC9jbGllbnQvY2xpZW50XCI7XG5pbXBvcnQgeyBJbmxpbmVXZWJTb2NrZXRBZGFwdGVyMiB9IGZyb20gXCJAL2NvbW1vbi9pbmxpbmUtd2Vic29ja2V0LWFkYXB0ZXIyXCI7XG5pbXBvcnQgeyBub29wTmV4dCB9IGZyb20gXCJAL2NvbW1vbi91dGlsc1wiO1xuaW1wb3J0IHR5cGUge1xuXHRBY3RvckRyaXZlcixcblx0QWN0b3JPdXRwdXQsXG5cdENyZWF0ZUlucHV0LFxuXHRHZXRGb3JJZElucHV0LFxuXHRHZXRPckNyZWF0ZVdpdGhLZXlJbnB1dCxcblx0R2V0V2l0aEtleUlucHV0LFxuXHRNYW5hZ2VyRHJpdmVyLFxufSBmcm9tIFwiQC9kcml2ZXItaGVscGVycy9tb2RcIjtcbmltcG9ydCB7IGNyZWF0ZUlubGluZUNsaWVudERyaXZlciB9IGZyb20gXCJAL2lubGluZS1jbGllbnQtZHJpdmVyL21vZFwiO1xuaW1wb3J0IHsgTWFuYWdlckluc3BlY3RvciB9IGZyb20gXCJAL2luc3BlY3Rvci9tYW5hZ2VyXCI7XG5pbXBvcnQgeyB0eXBlIEFjdG9yLCBBY3RvckZlYXR1cmUsIHR5cGUgQWN0b3JJZCB9IGZyb20gXCJAL2luc3BlY3Rvci9tb2RcIjtcbmltcG9ydCB7XG5cdHR5cGUgRHJpdmVyQ29uZmlnLFxuXHR0eXBlIEVuY29kaW5nLFxuXHRQQVRIX0NPTk5FQ1RfV0VCU09DS0VULFxuXHRQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYLFxuXHR0eXBlIFJlZ2lzdHJ5Q29uZmlnLFxuXHR0eXBlIFJ1bkNvbmZpZyxcbn0gZnJvbSBcIkAvbW9kXCI7XG5pbXBvcnQgdHlwZSAqIGFzIHNjaGVtYSBmcm9tIFwiQC9zY2hlbWFzL2ZpbGUtc3lzdGVtLWRyaXZlci9tb2RcIjtcbmltcG9ydCB0eXBlIHsgRmlsZVN5c3RlbUdsb2JhbFN0YXRlIH0gZnJvbSBcIi4vZ2xvYmFsLXN0YXRlXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB7IGdlbmVyYXRlQWN0b3JJZCB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBjbGFzcyBGaWxlU3lzdGVtTWFuYWdlckRyaXZlciBpbXBsZW1lbnRzIE1hbmFnZXJEcml2ZXIge1xuXHQjcmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnO1xuXHQjcnVuQ29uZmlnOiBSdW5Db25maWc7XG5cdCNzdGF0ZTogRmlsZVN5c3RlbUdsb2JhbFN0YXRlO1xuXHQjZHJpdmVyQ29uZmlnOiBEcml2ZXJDb25maWc7XG5cblx0I2FjdG9yRHJpdmVyOiBBY3RvckRyaXZlcjtcblx0I2FjdG9yUm91dGVyOiBBY3RvclJvdXRlcjtcblxuXHRpbnNwZWN0b3I/OiBNYW5hZ2VySW5zcGVjdG9yO1xuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHJlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZyxcblx0XHRydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0XHRzdGF0ZTogRmlsZVN5c3RlbUdsb2JhbFN0YXRlLFxuXHRcdGRyaXZlckNvbmZpZzogRHJpdmVyQ29uZmlnLFxuXHQpIHtcblx0XHR0aGlzLiNyZWdpc3RyeUNvbmZpZyA9IHJlZ2lzdHJ5Q29uZmlnO1xuXHRcdHRoaXMuI3J1bkNvbmZpZyA9IHJ1bkNvbmZpZztcblx0XHR0aGlzLiNzdGF0ZSA9IHN0YXRlO1xuXHRcdHRoaXMuI2RyaXZlckNvbmZpZyA9IGRyaXZlckNvbmZpZztcblxuXHRcdGlmIChydW5Db25maWcuaW5zcGVjdG9yLmVuYWJsZWQpIHtcblx0XHRcdGlmICghdGhpcy4jcnVuQ29uZmlnLmluc3BlY3Rvci50b2tlbigpKSB7XG5cdFx0XHRcdHRoaXMuI3J1bkNvbmZpZy5pbnNwZWN0b3IudG9rZW4gPSAoKSA9PlxuXHRcdFx0XHRcdHRoaXMuI3N0YXRlLmdldE9yQ3JlYXRlSW5zcGVjdG9yQWNjZXNzVG9rZW4oKTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHN0YXJ0ZWRBdCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcblx0XHRcdGZ1bmN0aW9uIHRyYW5zZm9ybUFjdG9yKGFjdG9yU3RhdGU6IHNjaGVtYS5BY3RvclN0YXRlKTogQWN0b3Ige1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdGlkOiBhY3RvclN0YXRlLmFjdG9ySWQgYXMgQWN0b3JJZCxcblx0XHRcdFx0XHRuYW1lOiBhY3RvclN0YXRlLm5hbWUsXG5cdFx0XHRcdFx0a2V5OiBhY3RvclN0YXRlLmtleSBhcyBzdHJpbmdbXSxcblx0XHRcdFx0XHRzdGFydGVkQXQ6IHN0YXJ0ZWRBdCxcblx0XHRcdFx0XHRjcmVhdGVkQXQ6IG5ldyBEYXRlKE51bWJlcihhY3RvclN0YXRlLmNyZWF0ZWRBdCkpLnRvSVNPU3RyaW5nKCksXG5cdFx0XHRcdFx0ZmVhdHVyZXM6IFtcblx0XHRcdFx0XHRcdEFjdG9yRmVhdHVyZS5TdGF0ZSxcblx0XHRcdFx0XHRcdEFjdG9yRmVhdHVyZS5Db25uZWN0aW9ucyxcblx0XHRcdFx0XHRcdEFjdG9yRmVhdHVyZS5Db25zb2xlLFxuXHRcdFx0XHRcdFx0QWN0b3JGZWF0dXJlLkV2ZW50c01vbml0b3JpbmcsXG5cdFx0XHRcdFx0XHRBY3RvckZlYXR1cmUuRGF0YWJhc2UsXG5cdFx0XHRcdFx0XSxcblx0XHRcdFx0fTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5pbnNwZWN0b3IgPSBuZXcgTWFuYWdlckluc3BlY3RvcigoKSA9PiB7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0Z2V0QWxsQWN0b3JzOiBhc3luYyAoeyBjdXJzb3IsIGxpbWl0IH0pID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IGl0ciA9IHRoaXMuI3N0YXRlLmdldEFjdG9yc0l0ZXJhdG9yKHsgY3Vyc29yIH0pO1xuXHRcdFx0XHRcdFx0Y29uc3QgYWN0b3JzOiBBY3RvcltdID0gW107XG5cblx0XHRcdFx0XHRcdGZvciBhd2FpdCAoY29uc3QgYWN0b3Igb2YgaXRyKSB7XG5cdFx0XHRcdFx0XHRcdGFjdG9ycy5wdXNoKHRyYW5zZm9ybUFjdG9yKGFjdG9yKSk7XG5cdFx0XHRcdFx0XHRcdGlmIChsaW1pdCAmJiBhY3RvcnMubGVuZ3RoID49IGxpbWl0KSB7XG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJldHVybiBhY3RvcnM7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRnZXRBY3RvckJ5SWQ6IGFzeW5jIChpZCkgPT4ge1xuXHRcdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy4jc3RhdGUubG9hZEFjdG9yU3RhdGVPckVycm9yKGlkKTtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRyYW5zZm9ybUFjdG9yKHJlc3VsdCk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRnZXRCdWlsZHM6IGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLiNyZWdpc3RyeUNvbmZpZy51c2UpLm1hcCgobmFtZSkgPT4gKHtcblx0XHRcdFx0XHRcdFx0bmFtZSxcblx0XHRcdFx0XHRcdH0pKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNyZWF0ZUFjdG9yOiBhc3luYyAoaW5wdXQpID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgdGhpcy5jcmVhdGVBY3RvcihpbnB1dCk7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLiNzdGF0ZS5sb2FkQWN0b3JTdGF0ZU9yRXJyb3IoYWN0b3JJZCk7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cmFuc2Zvcm1BY3RvcihyZXN1bHQpO1xuXHRcdFx0XHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH07XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHQvLyBBY3RvcnMgcnVuIG9uIHRoZSBzYW1lIG5vZGUgYXMgdGhlIG1hbmFnZXIsIHNvIHdlIGNyZWF0ZSBhIGR1bW15IGFjdG9yIHJvdXRlciB0aGF0IHdlIHJvdXRlIHJlcXVlc3RzIHRvXG5cdFx0Y29uc3QgaW5saW5lQ2xpZW50ID0gY3JlYXRlQ2xpZW50V2l0aERyaXZlcihjcmVhdGVJbmxpbmVDbGllbnREcml2ZXIodGhpcykpO1xuXHRcdHRoaXMuI2FjdG9yRHJpdmVyID0gdGhpcy4jZHJpdmVyQ29uZmlnLmFjdG9yKFxuXHRcdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0XHRydW5Db25maWcsXG5cdFx0XHR0aGlzLFxuXHRcdFx0aW5saW5lQ2xpZW50LFxuXHRcdCk7XG5cdFx0dGhpcy4jYWN0b3JSb3V0ZXIgPSBjcmVhdGVBY3RvclJvdXRlcih0aGlzLiNydW5Db25maWcsIHRoaXMuI2FjdG9yRHJpdmVyKTtcblx0fVxuXG5cdGFzeW5jIHNlbmRSZXF1ZXN0KGFjdG9ySWQ6IHN0cmluZywgYWN0b3JSZXF1ZXN0OiBSZXF1ZXN0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdHJldHVybiBhd2FpdCB0aGlzLiNhY3RvclJvdXRlci5mZXRjaChhY3RvclJlcXVlc3QsIHtcblx0XHRcdGFjdG9ySWQsXG5cdFx0fSk7XG5cdH1cblxuXHRhc3luYyBvcGVuV2ViU29ja2V0KFxuXHRcdHBhdGg6IHN0cmluZyxcblx0XHRhY3RvcklkOiBzdHJpbmcsXG5cdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdHBhcmFtczogdW5rbm93bixcblx0KTogUHJvbWlzZTxXZWJTb2NrZXQ+IHtcblx0XHQvLyBUT0RPOlxuXG5cdFx0Ly8gSGFuZGxlIHJhdyBXZWJTb2NrZXQgcGF0aHNcblx0XHRpZiAocGF0aCA9PT0gUEFUSF9DT05ORUNUX1dFQlNPQ0tFVCkge1xuXHRcdFx0Ly8gSGFuZGxlIHN0YW5kYXJkIGNvbm5lY3Rcblx0XHRcdGNvbnN0IHdzSGFuZGxlciA9IGF3YWl0IGhhbmRsZVdlYlNvY2tldENvbm5lY3QoXG5cdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0dGhpcy4jcnVuQ29uZmlnLFxuXHRcdFx0XHR0aGlzLiNhY3RvckRyaXZlcixcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0ZW5jb2RpbmcsXG5cdFx0XHRcdHBhcmFtcyxcblx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0KTtcblx0XHRcdHJldHVybiBuZXcgSW5saW5lV2ViU29ja2V0QWRhcHRlcjIod3NIYW5kbGVyKTtcblx0XHR9IGVsc2UgaWYgKHBhdGguc3RhcnRzV2l0aChQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYKSkge1xuXHRcdFx0Ly8gSGFuZGxlIHdlYnNvY2tldCBwcm94eVxuXHRcdFx0Y29uc3Qgd3NIYW5kbGVyID0gYXdhaXQgaGFuZGxlUmF3V2ViU29ja2V0SGFuZGxlcihcblx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHRwYXRoLFxuXHRcdFx0XHR0aGlzLiNhY3RvckRyaXZlcixcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0KTtcblx0XHRcdHJldHVybiBuZXcgSW5saW5lV2ViU29ja2V0QWRhcHRlcjIod3NIYW5kbGVyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBVbnJlYWNoYWJsZSBwYXRoOiAke3BhdGh9YCk7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgcHJveHlSZXF1ZXN0KFxuXHRcdGM6IEhvbm9Db250ZXh0LFxuXHRcdGFjdG9yUmVxdWVzdDogUmVxdWVzdCxcblx0XHRhY3RvcklkOiBzdHJpbmcsXG5cdCk6IFByb21pc2U8UmVzcG9uc2U+IHtcblx0XHRyZXR1cm4gYXdhaXQgdGhpcy4jYWN0b3JSb3V0ZXIuZmV0Y2goYWN0b3JSZXF1ZXN0LCB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgcHJveHlXZWJTb2NrZXQoXG5cdFx0YzogSG9ub0NvbnRleHQsXG5cdFx0cGF0aDogc3RyaW5nLFxuXHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHRlbmNvZGluZzogRW5jb2RpbmcsXG5cdFx0Y29ublBhcmFtczogdW5rbm93bixcblx0XHRhdXRoRGF0YTogdW5rbm93bixcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdGNvbnN0IHVwZ3JhZGVXZWJTb2NrZXQgPSB0aGlzLiNydW5Db25maWcuZ2V0VXBncmFkZVdlYlNvY2tldD8uKCk7XG5cdFx0aW52YXJpYW50KHVwZ3JhZGVXZWJTb2NrZXQsIFwibWlzc2luZyBnZXRVcGdyYWRlV2ViU29ja2V0XCIpO1xuXG5cdFx0Ly8gSGFuZGxlIHJhdyBXZWJTb2NrZXQgcGF0aHNcblx0XHRpZiAocGF0aCA9PT0gUEFUSF9DT05ORUNUX1dFQlNPQ0tFVCkge1xuXHRcdFx0Ly8gSGFuZGxlIHN0YW5kYXJkIGNvbm5lY3Rcblx0XHRcdGNvbnN0IHdzSGFuZGxlciA9IGF3YWl0IGhhbmRsZVdlYlNvY2tldENvbm5lY3QoXG5cdFx0XHRcdGMucmVxLnJhdyxcblx0XHRcdFx0dGhpcy4jcnVuQ29uZmlnLFxuXHRcdFx0XHR0aGlzLiNhY3RvckRyaXZlcixcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0ZW5jb2RpbmcsXG5cdFx0XHRcdGNvbm5QYXJhbXMsXG5cdFx0XHRcdGF1dGhEYXRhLFxuXHRcdFx0KTtcblxuXHRcdFx0cmV0dXJuIHVwZ3JhZGVXZWJTb2NrZXQoKCkgPT4gd3NIYW5kbGVyKShjLCBub29wTmV4dCgpKTtcblx0XHR9IGVsc2UgaWYgKHBhdGguc3RhcnRzV2l0aChQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYKSkge1xuXHRcdFx0Ly8gSGFuZGxlIHdlYnNvY2tldCBwcm94eVxuXHRcdFx0Y29uc3Qgd3NIYW5kbGVyID0gYXdhaXQgaGFuZGxlUmF3V2ViU29ja2V0SGFuZGxlcihcblx0XHRcdFx0Yy5yZXEucmF3LFxuXHRcdFx0XHRwYXRoLFxuXHRcdFx0XHR0aGlzLiNhY3RvckRyaXZlcixcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0YXV0aERhdGEsXG5cdFx0XHQpO1xuXG5cdFx0XHRyZXR1cm4gdXBncmFkZVdlYlNvY2tldCgoKSA9PiB3c0hhbmRsZXIpKGMsIG5vb3BOZXh0KCkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYFVucmVhY2hhYmxlIHBhdGg6ICR7cGF0aH1gKTtcblx0XHR9XG5cdH1cblxuXHRhc3luYyBnZXRGb3JJZCh7IGFjdG9ySWQgfTogR2V0Rm9ySWRJbnB1dCk6IFByb21pc2U8QWN0b3JPdXRwdXQgfCB1bmRlZmluZWQ+IHtcblx0XHQvLyBWYWxpZGF0ZSB0aGUgYWN0b3IgZXhpc3RzXG5cdFx0Y29uc3QgYWN0b3IgPSBhd2FpdCB0aGlzLiNzdGF0ZS5sb2FkQWN0b3IoYWN0b3JJZCk7XG5cdFx0aWYgKCFhY3Rvci5zdGF0ZSkge1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gTG9hZCBhY3RvciBzdGF0ZVxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0bmFtZTogYWN0b3Iuc3RhdGUubmFtZSxcblx0XHRcdFx0a2V5OiBhY3Rvci5zdGF0ZS5rZXkgYXMgc3RyaW5nW10sXG5cdFx0XHR9O1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byByZWFkIGFjdG9yIHN0YXRlXCIsIHsgYWN0b3JJZCwgZXJyb3IgfSk7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGdldFdpdGhLZXkoe1xuXHRcdG5hbWUsXG5cdFx0a2V5LFxuXHR9OiBHZXRXaXRoS2V5SW5wdXQpOiBQcm9taXNlPEFjdG9yT3V0cHV0IHwgdW5kZWZpbmVkPiB7XG5cdFx0Ly8gR2VuZXJhdGUgdGhlIGRldGVybWluaXN0aWMgYWN0b3IgSURcblx0XHRjb25zdCBhY3RvcklkID0gZ2VuZXJhdGVBY3RvcklkKG5hbWUsIGtleSk7XG5cblx0XHQvLyBDaGVjayBpZiBhY3RvciBleGlzdHNcblx0XHRjb25zdCBhY3RvciA9IGF3YWl0IHRoaXMuI3N0YXRlLmxvYWRBY3RvcihhY3RvcklkKTtcblx0XHRpZiAoYWN0b3Iuc3RhdGUpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGtleSxcblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdGFzeW5jIGdldE9yQ3JlYXRlV2l0aEtleShcblx0XHRpbnB1dDogR2V0T3JDcmVhdGVXaXRoS2V5SW5wdXQsXG5cdCk6IFByb21pc2U8QWN0b3JPdXRwdXQ+IHtcblx0XHQvLyBHZW5lcmF0ZSB0aGUgZGV0ZXJtaW5pc3RpYyBhY3RvciBJRFxuXHRcdGNvbnN0IGFjdG9ySWQgPSBnZW5lcmF0ZUFjdG9ySWQoaW5wdXQubmFtZSwgaW5wdXQua2V5KTtcblxuXHRcdC8vIFVzZSB0aGUgYXRvbWljIGdldE9yQ3JlYXRlQWN0b3IgbWV0aG9kXG5cdFx0Y29uc3QgYWN0b3JFbnRyeSA9IGF3YWl0IHRoaXMuI3N0YXRlLmxvYWRPckNyZWF0ZUFjdG9yKFxuXHRcdFx0YWN0b3JJZCxcblx0XHRcdGlucHV0Lm5hbWUsXG5cdFx0XHRpbnB1dC5rZXksXG5cdFx0XHRpbnB1dC5pbnB1dCxcblx0XHQpO1xuXHRcdGludmFyaWFudChhY3RvckVudHJ5LnN0YXRlLCBcIm11c3QgaGF2ZSBzdGF0ZVwiKTtcblxuXHRcdHJldHVybiB7XG5cdFx0XHRhY3RvcklkOiBhY3RvckVudHJ5LnN0YXRlLmFjdG9ySWQsXG5cdFx0XHRuYW1lOiBhY3RvckVudHJ5LnN0YXRlLm5hbWUsXG5cdFx0XHRrZXk6IGFjdG9yRW50cnkuc3RhdGUua2V5IGFzIHN0cmluZ1tdLFxuXHRcdH07XG5cdH1cblxuXHRhc3luYyBjcmVhdGVBY3Rvcih7IG5hbWUsIGtleSwgaW5wdXQgfTogQ3JlYXRlSW5wdXQpOiBQcm9taXNlPEFjdG9yT3V0cHV0PiB7XG5cdFx0Ly8gR2VuZXJhdGUgdGhlIGRldGVybWluaXN0aWMgYWN0b3IgSURcblx0XHRjb25zdCBhY3RvcklkID0gZ2VuZXJhdGVBY3RvcklkKG5hbWUsIGtleSk7XG5cblx0XHRhd2FpdCB0aGlzLiNzdGF0ZS5jcmVhdGVBY3RvcihhY3RvcklkLCBuYW1lLCBrZXksIGlucHV0KTtcblxuXHRcdHJldHVybiB7XG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0bmFtZSxcblx0XHRcdGtleSxcblx0XHR9O1xuXHR9XG5cblx0ZXh0cmFTdGFydHVwTG9nKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRpbnN0YW5jZXM6IHRoaXMuI3N0YXRlLmFjdG9yQ291bnRPblN0YXJ0dXAsXG5cdFx0XHRkYXRhOiB0aGlzLiNzdGF0ZS5zdG9yYWdlUGF0aCxcblx0XHR9O1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbmxpbmUtY2xpZW50LWRyaXZlci9tb2QudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5saW5lLWNsaWVudC1kcml2ZXJcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5saW5lLWNsaWVudC1kcml2ZXIvbW9kLnRzXCI7aW1wb3J0ICogYXMgY2JvciBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSG9ub0NvbnRleHQgfSBmcm9tIFwiaG9ub1wiO1xuaW1wb3J0IGludmFyaWFudCBmcm9tIFwiaW52YXJpYW50XCI7XG5pbXBvcnQgb25DaGFuZ2UgZnJvbSBcIm9uLWNoYW5nZVwiO1xuaW1wb3J0IHR5cGUgeyBXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tIFwiQC9hY3Rvci9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgRW5jb2RpbmcgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHtcblx0UEFUSF9DT05ORUNUX1dFQlNPQ0tFVCxcblx0UEFUSF9SQVdfV0VCU09DS0VUX1BSRUZJWCxcbn0gZnJvbSBcIkAvYWN0b3Ivcm91dGVyXCI7XG5pbXBvcnQge1xuXHRIRUFERVJfQ09OTl9JRCxcblx0SEVBREVSX0NPTk5fUEFSQU1TLFxuXHRIRUFERVJfQ09OTl9UT0tFTixcblx0SEVBREVSX0VOQ09ESU5HLFxuXHRIRUFERVJfRVhQT1NFX0lOVEVSTkFMX0VSUk9SLFxufSBmcm9tIFwiQC9hY3Rvci9yb3V0ZXItZW5kcG9pbnRzXCI7XG5pbXBvcnQgeyBhc3NlcnRVbnJlYWNoYWJsZSB9IGZyb20gXCJAL2FjdG9yL3V0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudERyaXZlciB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB7IEFjdG9yRXJyb3IgYXMgQ2xpZW50QWN0b3JFcnJvciB9IGZyb20gXCJAL2NsaWVudC9lcnJvcnNcIjtcbmltcG9ydCB7IHNlbmRIdHRwUmVxdWVzdCB9IGZyb20gXCJAL2NsaWVudC91dGlsc1wiO1xuaW1wb3J0IHsgaW1wb3J0RXZlbnRTb3VyY2UgfSBmcm9tIFwiQC9jb21tb24vZXZlbnRzb3VyY2VcIjtcbmltcG9ydCB0eXBlIHsgVW5pdmVyc2FsRXZlbnRTb3VyY2UgfSBmcm9tIFwiQC9jb21tb24vZXZlbnRzb3VyY2UtaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBkZWNvbnN0cnVjdEVycm9yIH0gZnJvbSBcIkAvY29tbW9uL3V0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IE1hbmFnZXJEcml2ZXIgfSBmcm9tIFwiQC9tYW5hZ2VyL2RyaXZlclwiO1xuaW1wb3J0IHR5cGUgeyBBY3RvclF1ZXJ5IH0gZnJvbSBcIkAvbWFuYWdlci9wcm90b2NvbC9xdWVyeVwiO1xuaW1wb3J0IHR5cGUgeyBSdW5Db25maWcgfSBmcm9tIFwiQC9tb2RcIjtcbmltcG9ydCB0eXBlICogYXMgcHJvdG9jb2wgZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvbW9kXCI7XG5pbXBvcnQge1xuXHRIVFRQX0FDVElPTl9SRVFVRVNUX1ZFUlNJT05FRCxcblx0SFRUUF9BQ1RJT05fUkVTUE9OU0VfVkVSU0lPTkVELFxuXHRUT19DTElFTlRfVkVSU0lPTkVELFxuXHRUT19TRVJWRVJfVkVSU0lPTkVELFxufSBmcm9tIFwiQC9zY2hlbWFzL2NsaWVudC1wcm90b2NvbC92ZXJzaW9uZWRcIjtcbmltcG9ydCB7IGJ1ZmZlclRvQXJyYXlCdWZmZXIsIGh0dHBVc2VyQWdlbnQgfSBmcm9tIFwiQC91dGlsc1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5cbi8qKlxuICogQ2xpZW50IGRyaXZlciB0aGF0IGNhbGxzIHRoZSBtYW5hZ2VyIGRyaXZlciBpbmxpbmUuXG4gKlxuICogVGhpcyBpcyBvbmx5IGFwcGxpY2FibGUgdG8gc3RhbmRhbG9uZSAmIGNvb3JkaW5hdGVkIHRvcG9sb2dpZXMuXG4gKlxuICogVGhpcyBkcml2ZXIgY2FuIGFjY2VzcyBwcml2YXRlIHJlc291cmNlcy5cbiAqXG4gKiBUaGlzIGRyaXZlciBzZXJ2ZXMgYSBkb3VibGUgcHVycG9zZSBhczpcbiAqIC0gUHJvdmlkaW5nIHRoZSBjbGllbnQgZm9yIHRoZSBpbnRlcm5hbCByZXF1ZXN0c1xuICogLSBQcm92aWRlIHRoZSBkcml2ZXIgZm9yIHRoZSBtYW5hZ2VyIEhUVFAgcm91dGVyIChzZWUgbWFuYWdlci9yb3V0ZXIudHMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVJbmxpbmVDbGllbnREcml2ZXIoXG5cdG1hbmFnZXJEcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG4pOiBDbGllbnREcml2ZXIge1xuXHRjb25zdCBkcml2ZXI6IENsaWVudERyaXZlciA9IHtcblx0XHRhY3Rpb246IGFzeW5jIDxBcmdzIGV4dGVuZHMgQXJyYXk8dW5rbm93bj4gPSB1bmtub3duW10sIFJlc3BvbnNlID0gdW5rbm93bj4oXG5cdFx0XHRjOiBIb25vQ29udGV4dCB8IHVuZGVmaW5lZCxcblx0XHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0XHRlbmNvZGluZzogRW5jb2RpbmcsXG5cdFx0XHRwYXJhbXM6IHVua25vd24sXG5cdFx0XHRhY3Rpb25OYW1lOiBzdHJpbmcsXG5cdFx0XHRhcmdzOiBBcmdzLFxuXHRcdFx0b3B0czogeyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9LFxuXHRcdCk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdC8vIEdldCB0aGUgYWN0b3IgSURcblx0XHRcdFx0Y29uc3QgeyBhY3RvcklkIH0gPSBhd2FpdCBxdWVyeUFjdG9yKGMsIGFjdG9yUXVlcnksIG1hbmFnZXJEcml2ZXIpO1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvdW5kIGFjdG9yIGZvciBhY3Rpb25cIiwgeyBhY3RvcklkIH0pO1xuXHRcdFx0XHRpbnZhcmlhbnQoYWN0b3JJZCwgXCJNaXNzaW5nIGFjdG9yIElEXCIpO1xuXG5cdFx0XHRcdC8vIEludm9rZSB0aGUgYWN0aW9uXG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiaGFuZGxpbmcgYWN0aW9uXCIsIHsgYWN0aW9uTmFtZSwgZW5jb2RpbmcgfSk7XG5cdFx0XHRcdGNvbnN0IHJlc3BvbnNlRGF0YSA9IGF3YWl0IHNlbmRIdHRwUmVxdWVzdDxcblx0XHRcdFx0XHRwcm90b2NvbC5IdHRwQWN0aW9uUmVxdWVzdCxcblx0XHRcdFx0XHRwcm90b2NvbC5IdHRwQWN0aW9uUmVzcG9uc2Vcblx0XHRcdFx0Pih7XG5cdFx0XHRcdFx0dXJsOiBgaHR0cDovL2FjdG9yL2FjdGlvbi8ke2VuY29kZVVSSUNvbXBvbmVudChhY3Rpb25OYW1lKX1gLFxuXHRcdFx0XHRcdG1ldGhvZDogXCJQT1NUXCIsXG5cdFx0XHRcdFx0aGVhZGVyczoge1xuXHRcdFx0XHRcdFx0W0hFQURFUl9FTkNPRElOR106IGVuY29kaW5nLFxuXHRcdFx0XHRcdFx0Li4uKHBhcmFtcyAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdFx0XHRcdD8geyBbSEVBREVSX0NPTk5fUEFSQU1TXTogSlNPTi5zdHJpbmdpZnkocGFyYW1zKSB9XG5cdFx0XHRcdFx0XHRcdDoge30pLFxuXHRcdFx0XHRcdFx0W0hFQURFUl9FWFBPU0VfSU5URVJOQUxfRVJST1JdOiBcInRydWVcIixcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGJvZHk6IHtcblx0XHRcdFx0XHRcdGFyZ3M6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUoYXJncykpLFxuXHRcdFx0XHRcdH0gc2F0aXNmaWVzIHByb3RvY29sLkh0dHBBY3Rpb25SZXF1ZXN0LFxuXHRcdFx0XHRcdGVuY29kaW5nOiBlbmNvZGluZyxcblx0XHRcdFx0XHRjdXN0b21GZXRjaDogbWFuYWdlckRyaXZlci5zZW5kUmVxdWVzdC5iaW5kKG1hbmFnZXJEcml2ZXIsIGFjdG9ySWQpLFxuXHRcdFx0XHRcdHNpZ25hbDogb3B0cz8uc2lnbmFsLFxuXHRcdFx0XHRcdHJlcXVlc3RWZXJzaW9uZWREYXRhSGFuZGxlcjogSFRUUF9BQ1RJT05fUkVRVUVTVF9WRVJTSU9ORUQsXG5cdFx0XHRcdFx0cmVzcG9uc2VWZXJzaW9uZWREYXRhSGFuZGxlcjogSFRUUF9BQ1RJT05fUkVTUE9OU0VfVkVSU0lPTkVELFxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRyZXR1cm4gY2Jvci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkocmVzcG9uc2VEYXRhLm91dHB1dCkpO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdC8vIFN0YW5kYXJkaXplIHRvIENsaWVudEFjdG9yRXJyb3IgaW5zdGVhZCBvZiB0aGUgbmF0aXZlIGJhY2tlbmQgZXJyb3Jcblx0XHRcdFx0Y29uc3QgeyBjb2RlLCBtZXNzYWdlLCBtZXRhZGF0YSB9ID0gZGVjb25zdHJ1Y3RFcnJvcihcblx0XHRcdFx0XHRlcnIsXG5cdFx0XHRcdFx0bG9nZ2VyKCksXG5cdFx0XHRcdFx0e30sXG5cdFx0XHRcdFx0dHJ1ZSxcblx0XHRcdFx0KTtcblx0XHRcdFx0Y29uc3QgeCA9IG5ldyBDbGllbnRBY3RvckVycm9yKGNvZGUsIG1lc3NhZ2UsIG1ldGFkYXRhKTtcblx0XHRcdFx0dGhyb3cgbmV3IENsaWVudEFjdG9yRXJyb3IoY29kZSwgbWVzc2FnZSwgbWV0YWRhdGEpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRyZXNvbHZlQWN0b3JJZDogYXN5bmMgKFxuXHRcdFx0YzogSG9ub0NvbnRleHQgfCB1bmRlZmluZWQsXG5cdFx0XHRhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRcdFx0X2VuY29kaW5nS2luZDogRW5jb2RpbmcsXG5cdFx0KTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcblx0XHRcdC8vIEdldCB0aGUgYWN0b3IgSURcblx0XHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgcXVlcnlBY3RvcihjLCBhY3RvclF1ZXJ5LCBtYW5hZ2VyRHJpdmVyKTtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicmVzb2x2ZWQgYWN0b3JcIiwgeyBhY3RvcklkIH0pO1xuXHRcdFx0aW52YXJpYW50KGFjdG9ySWQsIFwibWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdFx0cmV0dXJuIGFjdG9ySWQ7XG5cdFx0fSxcblxuXHRcdGNvbm5lY3RXZWJTb2NrZXQ6IGFzeW5jIChcblx0XHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdFx0YWN0b3JRdWVyeTogQWN0b3JRdWVyeSxcblx0XHRcdGVuY29kaW5nS2luZDogRW5jb2RpbmcsXG5cdFx0XHRwYXJhbXM/OiB1bmtub3duLFxuXHRcdCk6IFByb21pc2U8V2ViU29ja2V0PiA9PiB7XG5cdFx0XHQvLyBHZXQgdGhlIGFjdG9yIElEXG5cdFx0XHRjb25zdCB7IGFjdG9ySWQgfSA9IGF3YWl0IHF1ZXJ5QWN0b3IoYywgYWN0b3JRdWVyeSwgbWFuYWdlckRyaXZlcik7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvdW5kIGFjdG9yIGZvciBhY3Rpb25cIiwgeyBhY3RvcklkIH0pO1xuXHRcdFx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdFx0Ly8gSW52b2tlIHRoZSBhY3Rpb25cblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwib3BlbmluZyB3ZWJzb2NrZXRcIiwgeyBhY3RvcklkLCBlbmNvZGluZzogZW5jb2RpbmdLaW5kIH0pO1xuXG5cdFx0XHQvLyBPcGVuIFdlYlNvY2tldFxuXHRcdFx0Y29uc3Qgd3MgPSBhd2FpdCBtYW5hZ2VyRHJpdmVyLm9wZW5XZWJTb2NrZXQoXG5cdFx0XHRcdFBBVEhfQ09OTkVDVF9XRUJTT0NLRVQsXG5cdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdGVuY29kaW5nS2luZCxcblx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gTm9kZSAmIGJyb3dzZXIgV2ViU29ja2V0IHR5cGVzIGFyZSBpbmNvbXBhdGlibGVcblx0XHRcdHJldHVybiB3cyBhcyBhbnk7XG5cdFx0fSxcblxuXHRcdGNvbm5lY3RTc2U6IGFzeW5jIChcblx0XHRcdGM6IEhvbm9Db250ZXh0IHwgdW5kZWZpbmVkLFxuXHRcdFx0YWN0b3JRdWVyeTogQWN0b3JRdWVyeSxcblx0XHRcdGVuY29kaW5nS2luZDogRW5jb2RpbmcsXG5cdFx0XHRwYXJhbXM6IHVua25vd24sXG5cdFx0KTogUHJvbWlzZTxVbml2ZXJzYWxFdmVudFNvdXJjZT4gPT4ge1xuXHRcdFx0Ly8gR2V0IHRoZSBhY3RvciBJRFxuXHRcdFx0Y29uc3QgeyBhY3RvcklkIH0gPSBhd2FpdCBxdWVyeUFjdG9yKGMsIGFjdG9yUXVlcnksIG1hbmFnZXJEcml2ZXIpO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJmb3VuZCBhY3RvciBmb3Igc3NlIGNvbm5lY3Rpb25cIiwgeyBhY3RvcklkIH0pO1xuXHRcdFx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJvcGVuaW5nIHNzZSBjb25uZWN0aW9uXCIsIHtcblx0XHRcdFx0YWN0b3JJZCxcblx0XHRcdFx0ZW5jb2Rpbmc6IGVuY29kaW5nS2luZCxcblx0XHRcdH0pO1xuXG5cdFx0XHRjb25zdCBFdmVudFNvdXJjZUNsYXNzID0gYXdhaXQgaW1wb3J0RXZlbnRTb3VyY2UoKTtcblxuXHRcdFx0Y29uc3QgZXZlbnRTb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2VDbGFzcyhcImh0dHA6Ly9hY3Rvci9jb25uZWN0L3NzZVwiLCB7XG5cdFx0XHRcdGZldGNoOiAoaW5wdXQsIGluaXQpID0+IHtcblx0XHRcdFx0XHRyZXR1cm4gZmV0Y2goaW5wdXQsIHtcblx0XHRcdFx0XHRcdC4uLmluaXQsXG5cdFx0XHRcdFx0XHRoZWFkZXJzOiB7XG5cdFx0XHRcdFx0XHRcdC4uLmluaXQ/LmhlYWRlcnMsXG5cdFx0XHRcdFx0XHRcdFwiVXNlci1BZ2VudFwiOiBodHRwVXNlckFnZW50KCksXG5cdFx0XHRcdFx0XHRcdFtIRUFERVJfRU5DT0RJTkddOiBlbmNvZGluZ0tpbmQsXG5cdFx0XHRcdFx0XHRcdC4uLihwYXJhbXMgIT09IHVuZGVmaW5lZFxuXHRcdFx0XHRcdFx0XHRcdD8geyBbSEVBREVSX0NPTk5fUEFSQU1TXTogSlNPTi5zdHJpbmdpZnkocGFyYW1zKSB9XG5cdFx0XHRcdFx0XHRcdFx0OiB7fSksXG5cdFx0XHRcdFx0XHRcdFtIRUFERVJfRVhQT1NFX0lOVEVSTkFMX0VSUk9SXTogXCJ0cnVlXCIsXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9LFxuXHRcdFx0fSkgYXMgVW5pdmVyc2FsRXZlbnRTb3VyY2U7XG5cblx0XHRcdHJldHVybiBldmVudFNvdXJjZTtcblx0XHR9LFxuXG5cdFx0c2VuZEh0dHBNZXNzYWdlOiBhc3luYyAoXG5cdFx0XHRjOiBIb25vQ29udGV4dCB8IHVuZGVmaW5lZCxcblx0XHRcdGFjdG9ySWQ6IHN0cmluZyxcblx0XHRcdGVuY29kaW5nOiBFbmNvZGluZyxcblx0XHRcdGNvbm5lY3Rpb25JZDogc3RyaW5nLFxuXHRcdFx0Y29ubmVjdGlvblRva2VuOiBzdHJpbmcsXG5cdFx0XHRtZXNzYWdlOiBwcm90b2NvbC5Ub1NlcnZlcixcblx0XHQpOiBQcm9taXNlPHZvaWQ+ID0+IHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwic2VuZGluZyBodHRwIG1lc3NhZ2VcIiwgeyBhY3RvcklkLCBjb25uZWN0aW9uSWQgfSk7XG5cblx0XHRcdC8vIFNlbmQgYW4gSFRUUCByZXF1ZXN0IHRvIHRoZSBjb25uZWN0aW9ucyBlbmRwb2ludFxuXHRcdFx0YXdhaXQgc2VuZEh0dHBSZXF1ZXN0KHtcblx0XHRcdFx0dXJsOiBcImh0dHA6Ly9hY3Rvci9jb25uZWN0aW9ucy9tZXNzYWdlXCIsXG5cdFx0XHRcdG1ldGhvZDogXCJQT1NUXCIsXG5cdFx0XHRcdGhlYWRlcnM6IHtcblx0XHRcdFx0XHRbSEVBREVSX0VOQ09ESU5HXTogZW5jb2RpbmcsXG5cdFx0XHRcdFx0W0hFQURFUl9DT05OX0lEXTogY29ubmVjdGlvbklkLFxuXHRcdFx0XHRcdFtIRUFERVJfQ09OTl9UT0tFTl06IGNvbm5lY3Rpb25Ub2tlbixcblx0XHRcdFx0XHRbSEVBREVSX0VYUE9TRV9JTlRFUk5BTF9FUlJPUl06IFwidHJ1ZVwiLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRib2R5OiBtZXNzYWdlLFxuXHRcdFx0XHRlbmNvZGluZyxcblx0XHRcdFx0c2tpcFBhcnNlUmVzcG9uc2U6IHRydWUsXG5cdFx0XHRcdGN1c3RvbUZldGNoOiBtYW5hZ2VyRHJpdmVyLnNlbmRSZXF1ZXN0LmJpbmQobWFuYWdlckRyaXZlciwgYWN0b3JJZCksXG5cdFx0XHRcdHJlcXVlc3RWZXJzaW9uZWREYXRhSGFuZGxlcjogVE9fU0VSVkVSX1ZFUlNJT05FRCxcblx0XHRcdFx0cmVzcG9uc2VWZXJzaW9uZWREYXRhSGFuZGxlcjogVE9fQ0xJRU5UX1ZFUlNJT05FRCxcblx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRyYXdIdHRwUmVxdWVzdDogYXN5bmMgKFxuXHRcdFx0YzogSG9ub0NvbnRleHQgfCB1bmRlZmluZWQsXG5cdFx0XHRhY3RvclF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRcdFx0ZW5jb2Rpbmc6IEVuY29kaW5nLFxuXHRcdFx0cGFyYW1zOiB1bmtub3duLFxuXHRcdFx0cGF0aDogc3RyaW5nLFxuXHRcdFx0aW5pdDogUmVxdWVzdEluaXQsXG5cdFx0KTogUHJvbWlzZTxSZXNwb25zZT4gPT4ge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Ly8gR2V0IHRoZSBhY3RvciBJRFxuXHRcdFx0XHRjb25zdCB7IGFjdG9ySWQgfSA9IGF3YWl0IHF1ZXJ5QWN0b3IoYywgYWN0b3JRdWVyeSwgbWFuYWdlckRyaXZlcik7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiZm91bmQgYWN0b3IgZm9yIHJhdyBodHRwXCIsIHsgYWN0b3JJZCB9KTtcblx0XHRcdFx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdFx0XHQvLyBCdWlsZCB0aGUgVVJMIHdpdGggbm9ybWFsaXplZCBwYXRoXG5cdFx0XHRcdGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gcGF0aC5zdGFydHNXaXRoKFwiL1wiKSA/IHBhdGguc2xpY2UoMSkgOiBwYXRoO1xuXHRcdFx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKGBodHRwOi8vYWN0b3IvcmF3L2h0dHAvJHtub3JtYWxpemVkUGF0aH1gKTtcblxuXHRcdFx0XHQvLyBGb3J3YXJkIGNvbm4gcGFyYW1zIGlmIHByb3ZpZGVkXG5cdFx0XHRcdGNvbnN0IHByb3h5UmVxdWVzdEhlYWRlcnMgPSBuZXcgSGVhZGVycyhpbml0LmhlYWRlcnMpO1xuXHRcdFx0XHRpZiAocGFyYW1zKSB7XG5cdFx0XHRcdFx0cHJveHlSZXF1ZXN0SGVhZGVycy5zZXQoSEVBREVSX0NPTk5fUEFSQU1TLCBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcndhcmQgdGhlIHJlcXVlc3QgdG8gdGhlIGFjdG9yXG5cdFx0XHRcdGNvbnN0IHByb3h5UmVxdWVzdCA9IG5ldyBSZXF1ZXN0KHVybCwge1xuXHRcdFx0XHRcdC4uLmluaXQsXG5cdFx0XHRcdFx0aGVhZGVyczogcHJveHlSZXF1ZXN0SGVhZGVycyxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmV0dXJuIGF3YWl0IG1hbmFnZXJEcml2ZXIuc2VuZFJlcXVlc3QoYWN0b3JJZCwgcHJveHlSZXF1ZXN0KTtcblx0XHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0XHQvLyBTdGFuZGFyZGl6ZSB0byBDbGllbnRBY3RvckVycm9yIGluc3RlYWQgb2YgdGhlIG5hdGl2ZSBiYWNrZW5kIGVycm9yXG5cdFx0XHRcdGNvbnN0IHsgY29kZSwgbWVzc2FnZSwgbWV0YWRhdGEgfSA9IGRlY29uc3RydWN0RXJyb3IoXG5cdFx0XHRcdFx0ZXJyLFxuXHRcdFx0XHRcdGxvZ2dlcigpLFxuXHRcdFx0XHRcdHt9LFxuXHRcdFx0XHRcdHRydWUsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdHRocm93IG5ldyBDbGllbnRBY3RvckVycm9yKGNvZGUsIG1lc3NhZ2UsIG1ldGFkYXRhKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0cmF3V2ViU29ja2V0OiBhc3luYyAoXG5cdFx0XHRjOiBIb25vQ29udGV4dCB8IHVuZGVmaW5lZCxcblx0XHRcdGFjdG9yUXVlcnk6IEFjdG9yUXVlcnksXG5cdFx0XHRlbmNvZGluZzogRW5jb2RpbmcsXG5cdFx0XHRwYXJhbXM6IHVua25vd24sXG5cdFx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0XHRwcm90b2NvbHM6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkLFxuXHRcdCk6IFByb21pc2U8V2ViU29ja2V0PiA9PiB7XG5cdFx0XHQvLyBHZXQgdGhlIGFjdG9yIElEXG5cdFx0XHRjb25zdCB7IGFjdG9ySWQgfSA9IGF3YWl0IHF1ZXJ5QWN0b3IoYywgYWN0b3JRdWVyeSwgbWFuYWdlckRyaXZlcik7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvdW5kIGFjdG9yIGZvciBhY3Rpb25cIiwgeyBhY3RvcklkIH0pO1xuXHRcdFx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdFx0Ly8gTm9ybWFsaXplIHBhdGggdG8gbWF0Y2ggcmF3IEhUVFAgYmVoYXZpb3Jcblx0XHRcdGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gcGF0aC5zdGFydHNXaXRoKFwiL1wiKSA/IHBhdGguc2xpY2UoMSkgOiBwYXRoO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJvcGVuaW5nIHdlYnNvY2tldFwiLCB7XG5cdFx0XHRcdGFjdG9ySWQsXG5cdFx0XHRcdGVuY29kaW5nLFxuXHRcdFx0XHRwYXRoOiBub3JtYWxpemVkUGF0aCxcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBPcGVuIFdlYlNvY2tldFxuXHRcdFx0Y29uc3Qgd3MgPSBhd2FpdCBtYW5hZ2VyRHJpdmVyLm9wZW5XZWJTb2NrZXQoXG5cdFx0XHRcdGAke1BBVEhfUkFXX1dFQlNPQ0tFVF9QUkVGSVh9JHtub3JtYWxpemVkUGF0aH1gLFxuXHRcdFx0XHRhY3RvcklkLFxuXHRcdFx0XHRlbmNvZGluZyxcblx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gTm9kZSAmIGJyb3dzZXIgV2ViU29ja2V0IHR5cGVzIGFyZSBpbmNvbXBhdGlibGVcblx0XHRcdHJldHVybiB3cyBhcyBhbnk7XG5cdFx0fSxcblx0fTtcblxuXHRyZXR1cm4gZHJpdmVyO1xufVxuXG4vKipcbiAqIFF1ZXJ5IHRoZSBtYW5hZ2VyIGRyaXZlciB0byBnZXQgb3IgY3JlYXRlIGEgYWN0b3IgYmFzZWQgb24gdGhlIHByb3ZpZGVkIHF1ZXJ5XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBxdWVyeUFjdG9yKFxuXHRjOiBIb25vQ29udGV4dCB8IHVuZGVmaW5lZCxcblx0cXVlcnk6IEFjdG9yUXVlcnksXG5cdGRyaXZlcjogTWFuYWdlckRyaXZlcixcbik6IFByb21pc2U8eyBhY3RvcklkOiBzdHJpbmcgfT4ge1xuXHRsb2dnZXIoKS5kZWJ1ZyhcInF1ZXJ5aW5nIGFjdG9yXCIsIHsgcXVlcnkgfSk7XG5cdGxldCBhY3Rvck91dHB1dDogeyBhY3RvcklkOiBzdHJpbmcgfTtcblx0aWYgKFwiZ2V0Rm9ySWRcIiBpbiBxdWVyeSkge1xuXHRcdGNvbnN0IG91dHB1dCA9IGF3YWl0IGRyaXZlci5nZXRGb3JJZCh7XG5cdFx0XHRjLFxuXHRcdFx0bmFtZTogcXVlcnkuZ2V0Rm9ySWQubmFtZSxcblx0XHRcdGFjdG9ySWQ6IHF1ZXJ5LmdldEZvcklkLmFjdG9ySWQsXG5cdFx0fSk7XG5cdFx0aWYgKCFvdXRwdXQpIHRocm93IG5ldyBlcnJvcnMuQWN0b3JOb3RGb3VuZChxdWVyeS5nZXRGb3JJZC5hY3RvcklkKTtcblx0XHRhY3Rvck91dHB1dCA9IG91dHB1dDtcblx0fSBlbHNlIGlmIChcImdldEZvcktleVwiIGluIHF1ZXJ5KSB7XG5cdFx0Y29uc3QgZXhpc3RpbmdBY3RvciA9IGF3YWl0IGRyaXZlci5nZXRXaXRoS2V5KHtcblx0XHRcdGMsXG5cdFx0XHRuYW1lOiBxdWVyeS5nZXRGb3JLZXkubmFtZSxcblx0XHRcdGtleTogcXVlcnkuZ2V0Rm9yS2V5LmtleSxcblx0XHR9KTtcblx0XHRpZiAoIWV4aXN0aW5nQWN0b3IpIHtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuQWN0b3JOb3RGb3VuZChcblx0XHRcdFx0YCR7cXVlcnkuZ2V0Rm9yS2V5Lm5hbWV9OiR7SlNPTi5zdHJpbmdpZnkocXVlcnkuZ2V0Rm9yS2V5LmtleSl9YCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGFjdG9yT3V0cHV0ID0gZXhpc3RpbmdBY3Rvcjtcblx0fSBlbHNlIGlmIChcImdldE9yQ3JlYXRlRm9yS2V5XCIgaW4gcXVlcnkpIHtcblx0XHRjb25zdCBnZXRPckNyZWF0ZU91dHB1dCA9IGF3YWl0IGRyaXZlci5nZXRPckNyZWF0ZVdpdGhLZXkoe1xuXHRcdFx0Yyxcblx0XHRcdG5hbWU6IHF1ZXJ5LmdldE9yQ3JlYXRlRm9yS2V5Lm5hbWUsXG5cdFx0XHRrZXk6IHF1ZXJ5LmdldE9yQ3JlYXRlRm9yS2V5LmtleSxcblx0XHRcdGlucHV0OiBxdWVyeS5nZXRPckNyZWF0ZUZvcktleS5pbnB1dCxcblx0XHRcdHJlZ2lvbjogcXVlcnkuZ2V0T3JDcmVhdGVGb3JLZXkucmVnaW9uLFxuXHRcdH0pO1xuXHRcdGFjdG9yT3V0cHV0ID0ge1xuXHRcdFx0YWN0b3JJZDogZ2V0T3JDcmVhdGVPdXRwdXQuYWN0b3JJZCxcblx0XHR9O1xuXHR9IGVsc2UgaWYgKFwiY3JlYXRlXCIgaW4gcXVlcnkpIHtcblx0XHRjb25zdCBjcmVhdGVPdXRwdXQgPSBhd2FpdCBkcml2ZXIuY3JlYXRlQWN0b3Ioe1xuXHRcdFx0Yyxcblx0XHRcdG5hbWU6IHF1ZXJ5LmNyZWF0ZS5uYW1lLFxuXHRcdFx0a2V5OiBxdWVyeS5jcmVhdGUua2V5LFxuXHRcdFx0aW5wdXQ6IHF1ZXJ5LmNyZWF0ZS5pbnB1dCxcblx0XHRcdHJlZ2lvbjogcXVlcnkuY3JlYXRlLnJlZ2lvbixcblx0XHR9KTtcblx0XHRhY3Rvck91dHB1dCA9IHtcblx0XHRcdGFjdG9ySWQ6IGNyZWF0ZU91dHB1dC5hY3RvcklkLFxuXHRcdH07XG5cdH0gZWxzZSB7XG5cdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUmVxdWVzdChcIkludmFsaWQgcXVlcnkgZm9ybWF0XCIpO1xuXHR9XG5cblx0bG9nZ2VyKCkuZGVidWcoXCJhY3RvciBxdWVyeSByZXN1bHRcIiwge1xuXHRcdGFjdG9ySWQ6IGFjdG9yT3V0cHV0LmFjdG9ySWQsXG5cdH0pO1xuXHRyZXR1cm4geyBhY3RvcklkOiBhY3Rvck91dHB1dC5hY3RvcklkIH07XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgb24tY2hhbmdlIGxpYnJhcnkncyBwcm94eSByZWN1cnNpdmVseSBmcm9tIGEgdmFsdWUgc28gd2UgY2FuIGNsb25lIGl0IHdpdGggYHN0cnVjdHVyZWRDbG9uZWAuXG4gKi9cbmZ1bmN0aW9uIHVucHJveHlSZWN1cnNpdmU8VD4ob2JqUHJveGllZDogVCk6IFQge1xuXHRjb25zdCBvYmogPSBvbkNoYW5nZS50YXJnZXQ8YW55PihvYmpQcm94aWVkKTtcblxuXHQvLyBTaG9ydCBjaXJjdWl0IGlmIHRoaXMgb2JqZWN0IHdhcyBwcm94aWVkXG5cdC8vXG5cdC8vIElmIHRoZSByZWZlcmVuY2UgaXMgZGlmZmVyZW50LCB0aGVuIHRoaXMgdmFsdWUgd2FzIHByb3hpZWQgYW5kIG5vXG5cdC8vIG5lc3RlZCB2YWx1ZXMgYXJlIHByb3hpZWRcblx0aWYgKG9iaiAhPT0gb2JqUHJveGllZCkgcmV0dXJuIG9iajtcblxuXHQvLyBIYW5kbGUgbnVsbC91bmRlZmluZWRcblx0aWYgKCFvYmogfHwgdHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIikge1xuXHRcdHJldHVybiBvYmo7XG5cdH1cblxuXHQvLyBIYW5kbGUgYXJyYXlzXG5cdGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcblx0XHRyZXR1cm4gb2JqLm1hcCgoeCkgPT4gdW5wcm94eVJlY3Vyc2l2ZTxhbnk+KHgpKSBhcyBUO1xuXHR9XG5cblx0Ly8gSGFuZGxlIG9iamVjdHNcblx0Y29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcblx0Zm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG5cdFx0cmVzdWx0W2tleV0gPSB1bnByb3h5UmVjdXJzaXZlPGFueT4ob2JqW2tleV0pO1xuXHR9XG5cblx0cmV0dXJuIHJlc3VsdDtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2NvbW1vbi9ldmVudHNvdXJjZS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9jb21tb25cIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvY29tbW9uL2V2ZW50c291cmNlLnRzXCI7aW1wb3J0IHR5cGUgeyBFdmVudFNvdXJjZSB9IGZyb20gXCJldmVudHNvdXJjZVwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIkAvY2xpZW50L2xvZ1wiO1xuXG4vLyBHbG9iYWwgc2luZ2xldG9uIHByb21pc2UgdGhhdCB3aWxsIGJlIHJldXNlZCBmb3Igc3Vic2VxdWVudCBjYWxsc1xubGV0IGV2ZW50U291cmNlUHJvbWlzZTogUHJvbWlzZTx0eXBlb2YgRXZlbnRTb3VyY2U+IHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICogSW1wb3J0IGBldmVudHNvdXJjZWAgZnJvbSB0aGUgY3VzdG9tIGBldmVudHNvdXJjZWAgbGlicmFyeS4gV2UgbmVlZCBhIGN1c3RvbSBpbXBsZW1uZXRhdGlvbiBzaW5jZSB3ZSBuZWVkIHRvIGF0dGFjaCBvdXIgb3duIGN1c3RvbSBoZWFkZXJzIHRvIHRoZSByZXF1ZXN0LlxuICoqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGltcG9ydEV2ZW50U291cmNlKCk6IFByb21pc2U8dHlwZW9mIEV2ZW50U291cmNlPiB7XG5cdC8vIFJldHVybiBleGlzdGluZyBwcm9taXNlIGlmIHdlIGFscmVhZHkgc3RhcnRlZCBsb2FkaW5nXG5cdGlmIChldmVudFNvdXJjZVByb21pc2UgIT09IG51bGwpIHtcblx0XHRyZXR1cm4gZXZlbnRTb3VyY2VQcm9taXNlO1xuXHR9XG5cblx0Ly8gQ3JlYXRlIGFuZCBzdG9yZSB0aGUgcHJvbWlzZVxuXHRldmVudFNvdXJjZVByb21pc2UgPSAoYXN5bmMgKCkgPT4ge1xuXHRcdGxldCBfRXZlbnRTb3VyY2U6IHR5cGVvZiBFdmVudFNvdXJjZTtcblxuXHRcdC8vIE5vZGUuanMgZW52aXJvbm1lbnRcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgZXMgPSBhd2FpdCBpbXBvcnQoXCJldmVudHNvdXJjZVwiKTtcblx0XHRcdF9FdmVudFNvdXJjZSA9IGVzLkV2ZW50U291cmNlO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ1c2luZyBldmVudHNvdXJjZSBmcm9tIG5wbVwiKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdC8vIEV2ZW50U291cmNlIG5vdCBhdmFpbGFibGVcblx0XHRcdF9FdmVudFNvdXJjZSA9IGNsYXNzIE1vY2tFdmVudFNvdXJjZSB7XG5cdFx0XHRcdGNvbnN0cnVjdG9yKCkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihcblx0XHRcdFx0XHRcdCdFdmVudFNvdXJjZSBzdXBwb3J0IHJlcXVpcmVzIGluc3RhbGxpbmcgdGhlIFwiZXZlbnRzb3VyY2VcIiBwZWVyIGRlcGVuZGVuY3kuJyxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGFzIHVua25vd24gYXMgdHlwZW9mIEV2ZW50U291cmNlO1xuXHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ1c2luZyBtb2NrIGV2ZW50c291cmNlXCIpO1xuXHRcdH1cblxuXHRcdHJldHVybiBfRXZlbnRTb3VyY2U7XG5cdH0pKCk7XG5cblx0cmV0dXJuIGV2ZW50U291cmNlUHJvbWlzZTtcbn1cblxuLy9leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW1wb3J0RXZlbnRTb3VyY2UoKTogUHJvbWlzZTx0eXBlb2YgRXZlbnRTb3VyY2U+IHtcbi8vXHQvLyBSZXR1cm4gZXhpc3RpbmcgcHJvbWlzZSBpZiB3ZSBhbHJlYWR5IHN0YXJ0ZWQgbG9hZGluZ1xuLy9cdGlmIChldmVudFNvdXJjZVByb21pc2UgIT09IG51bGwpIHtcbi8vXHRcdHJldHVybiBldmVudFNvdXJjZVByb21pc2U7XG4vL1x0fVxuLy9cbi8vXHQvLyBDcmVhdGUgYW5kIHN0b3JlIHRoZSBwcm9taXNlXG4vL1x0ZXZlbnRTb3VyY2VQcm9taXNlID0gKGFzeW5jICgpID0+IHtcbi8vXHRcdGxldCBfRXZlbnRTb3VyY2U6IHR5cGVvZiBFdmVudFNvdXJjZTtcbi8vXG4vL1x0XHRpZiAodHlwZW9mIEV2ZW50U291cmNlICE9PSBcInVuZGVmaW5lZFwiKSB7XG4vL1x0XHRcdC8vIEJyb3dzZXIgZW52aXJvbm1lbnRcbi8vXHRcdFx0X0V2ZW50U291cmNlID0gRXZlbnRTb3VyY2U7XG4vL1x0XHRcdGxvZ2dlcigpLmRlYnVnKFwidXNpbmcgbmF0aXZlIGV2ZW50c291cmNlXCIpO1xuLy9cdFx0fSBlbHNlIHtcbi8vXHRcdFx0Ly8gTm9kZS5qcyBlbnZpcm9ubWVudFxuLy9cdFx0XHR0cnkge1xuLy9cdFx0XHRcdGNvbnN0IGVzID0gYXdhaXQgaW1wb3J0KFwiZXZlbnRzb3VyY2VcIik7XG4vL1x0XHRcdFx0X0V2ZW50U291cmNlID0gZXMuRXZlbnRTb3VyY2U7XG4vL1x0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJ1c2luZyBldmVudHNvdXJjZSBmcm9tIG5wbVwiKTtcbi8vXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG4vL1x0XHRcdFx0Ly8gRXZlbnRTb3VyY2Ugbm90IGF2YWlsYWJsZVxuLy9cdFx0XHRcdF9FdmVudFNvdXJjZSA9IGNsYXNzIE1vY2tFdmVudFNvdXJjZSB7XG4vL1x0XHRcdFx0XHRjb25zdHJ1Y3RvcigpIHtcbi8vXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuLy9cdFx0XHRcdFx0XHRcdCdFdmVudFNvdXJjZSBzdXBwb3J0IHJlcXVpcmVzIGluc3RhbGxpbmcgdGhlIFwiZXZlbnRzb3VyY2VcIiBwZWVyIGRlcGVuZGVuY3kuJyxcbi8vXHRcdFx0XHRcdFx0KTtcbi8vXHRcdFx0XHRcdH1cbi8vXHRcdFx0XHR9IGFzIHVua25vd24gYXMgdHlwZW9mIEV2ZW50U291cmNlO1xuLy9cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwidXNpbmcgbW9jayBldmVudHNvdXJjZVwiKTtcbi8vXHRcdFx0fVxuLy9cdFx0fVxuLy9cbi8vXHRcdHJldHVybiBfRXZlbnRTb3VyY2U7XG4vL1x0fSkoKTtcbi8vXG4vL1x0cmV0dXJuIGV2ZW50U291cmNlUHJvbWlzZTtcbi8vfVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5saW5lLWNsaWVudC1kcml2ZXIvbG9nLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2lubGluZS1jbGllbnQtZHJpdmVyXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2lubGluZS1jbGllbnQtZHJpdmVyL2xvZy50c1wiO2ltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAL2NvbW1vbi8vbG9nXCI7XG5cbmV4cG9ydCBjb25zdCBMT0dHRVJfTkFNRSA9IFwiaW5saW5lLWNsaWVudC1kcml2ZXJcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2dlcigpIHtcblx0cmV0dXJuIGdldExvZ2dlcihMT0dHRVJfTkFNRSk7XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3IvbWFuYWdlci50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9pbnNwZWN0b3JcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvaW5zcGVjdG9yL21hbmFnZXIudHNcIjtpbXBvcnQgeyBzVmFsaWRhdG9yIH0gZnJvbSBcIkBob25vL3N0YW5kYXJkLXZhbGlkYXRvclwiO1xuaW1wb3J0IHsgSG9ubyB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgaW52YXJpYW50IGZyb20gXCJpbnZhcmlhbnRcIjtcbmltcG9ydCB0eXBlIHsgQ3JlYXRlSW5wdXQgfSBmcm9tIFwiQC9tYW5hZ2VyL2RyaXZlclwiO1xuaW1wb3J0IHsgaW5zcGVjdG9yTG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgeyB0eXBlIEFjdG9yLCB0eXBlIEJ1aWxkcywgQ3JlYXRlQWN0b3JTY2hlbWEgfSBmcm9tIFwiLi9wcm90b2NvbC9jb21tb25cIjtcblxuZXhwb3J0IHR5cGUgTWFuYWdlckluc3BlY3RvclJvdXRlckVudiA9IHtcblx0VmFyaWFibGVzOiB7XG5cdFx0aW5zcGVjdG9yOiBNYW5hZ2VySW5zcGVjdG9yO1xuXHR9O1xufTtcblxuLyoqXG4gKiBDcmVhdGUgYSByb3V0ZXIgZm9yIHRoZSBNYW5hZ2VyIEluc3BlY3Rvci5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWFuYWdlckluc3BlY3RvclJvdXRlcigpIHtcblx0cmV0dXJuIG5ldyBIb25vPE1hbmFnZXJJbnNwZWN0b3JSb3V0ZXJFbnY+KClcblx0XHQuZ2V0KFwiL3BpbmdcIiwgKGMpID0+IHtcblx0XHRcdHJldHVybiBjLmpzb24oeyBtZXNzYWdlOiBcInBvbmdcIiB9LCAyMDApO1xuXHRcdH0pXG5cdFx0LmdldChcIi9hY3RvcnNcIiwgYXN5bmMgKGMpID0+IHtcblx0XHRcdGNvbnN0IGxpbWl0ID0gTnVtYmVyLnBhcnNlSW50KGMucmVxLnF1ZXJ5KFwibGltaXRcIikgPz8gXCJcIikgfHwgdW5kZWZpbmVkO1xuXHRcdFx0Y29uc3QgY3Vyc29yID0gYy5yZXEucXVlcnkoXCJjdXJzb3JcIikgfHwgdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIWxpbWl0IHx8IChsaW1pdCAmJiBsaW1pdCA8PSAwKSkge1xuXHRcdFx0XHRyZXR1cm4gYy5qc29uKFwiSW52YWxpZCBsaW1pdFwiLCA0MDApO1xuXHRcdFx0fVxuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCBhY3RvcnMgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldEFsbEFjdG9ycyh7XG5cdFx0XHRcdFx0bGltaXQsXG5cdFx0XHRcdFx0Y3Vyc29yLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuIGMuanNvbihhY3RvcnMsIDIwMCk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRpbnNwZWN0b3JMb2dnZXIoKS5lcnJvcihcIkZhaWxlZCB0byBmZXRjaCBhY3RvcnNcIiwgZXJyb3IpO1xuXHRcdFx0XHRyZXR1cm4gYy5qc29uKFwiRmFpbGVkIHRvIGZldGNoIGFjdG9yc1wiLCA1MDApO1xuXHRcdFx0fVxuXHRcdH0pXG5cblx0XHQucG9zdChcIi9hY3RvcnNcIiwgc1ZhbGlkYXRvcihcImpzb25cIiwgQ3JlYXRlQWN0b3JTY2hlbWEpLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0Y29uc3QgYWN0b3IgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmNyZWF0ZUFjdG9yKFxuXHRcdFx0XHRjLnJlcS52YWxpZChcImpzb25cIiksXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuIGMuanNvbihhY3RvciwgMjAxKTtcblx0XHR9KVxuXHRcdC5nZXQoXCIvYnVpbGRzXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjb25zdCBidWlsZHMgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldEJ1aWxkcygpO1xuXHRcdFx0cmV0dXJuIGMuanNvbihidWlsZHMsIDIwMCk7XG5cdFx0fSlcblx0XHQuZ2V0KFwiL2FjdG9yLzppZFwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0Y29uc3QgaWQgPSBjLnJlcS5wYXJhbShcImlkXCIpO1xuXHRcdFx0Y29uc3QgYWN0b3IgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldEFjdG9yQnlJZChpZCk7XG5cdFx0XHRpZiAoIWFjdG9yKSB7XG5cdFx0XHRcdHJldHVybiBjLmpzb24oeyBlcnJvcjogXCJBY3RvciBub3QgZm91bmRcIiB9LCA0MDQpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGMuanNvbihhY3RvciwgMjAwKTtcblx0XHR9KVxuXHRcdC5nZXQoXCIvYm9vdHN0cmFwXCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjb25zdCBhY3RvcnMgPSBhd2FpdCBjLnZhci5pbnNwZWN0b3IuYWNjZXNzb3JzLmdldEFsbEFjdG9ycyh7XG5cdFx0XHRcdGxpbWl0OiAxMCxcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IGFjdG9ycyB9LCAyMDApO1xuXHRcdH0pO1xufVxuXG5pbnRlcmZhY2UgTWFuYWdlckluc3BlY3RvckFjY2Vzc29ycyB7XG5cdGdldEFsbEFjdG9yczogKHBhcmFtOiB7IGN1cnNvcj86IHN0cmluZzsgbGltaXQ6IG51bWJlciB9KSA9PiBQcm9taXNlPEFjdG9yW10+O1xuXHRnZXRBY3RvckJ5SWQ6IChpZDogc3RyaW5nKSA9PiBQcm9taXNlPEFjdG9yIHwgbnVsbD47XG5cdGdldEJ1aWxkczogKCkgPT4gUHJvbWlzZTxCdWlsZHM+O1xuXHRjcmVhdGVBY3RvcjogKGlucHV0OiBDcmVhdGVJbnB1dCkgPT4gUHJvbWlzZTxBY3RvciB8IG51bGw+O1xufVxuXG4vKipcbiAqIFByb3ZpZGVzIGEgdW5pZmllZCBpbnRlcmZhY2UgZm9yIGluc3BlY3RpbmcgYWN0b3IgZXh0ZXJuYWwgYW5kIGludGVybmFsIHN0YXRlLlxuICovXG5leHBvcnQgY2xhc3MgTWFuYWdlckluc3BlY3RvciB7XG5cdHB1YmxpYyByZWFkb25seSBhY2Nlc3NvcnM6IE1hbmFnZXJJbnNwZWN0b3JBY2Nlc3NvcnM7XG5cblx0Y29uc3RydWN0b3IoYWNjZXNzb3JzOiAoKSA9PiBNYW5hZ2VySW5zcGVjdG9yQWNjZXNzb3JzKSB7XG5cdFx0dGhpcy5hY2Nlc3NvcnMgPSBhY2Nlc3NvcnMoKTtcblx0XHRpbnNwZWN0b3JMb2dnZXIoKS5kZWJ1ZyhcIk1hbmFnZXIgSW5zcGVjdG9yIGVuYWJsZWQgYW5kIHJlYWR5XCIpO1xuXHR9XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtL21vZC50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9kcml2ZXJzL2ZpbGUtc3lzdGVtXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnMvZmlsZS1zeXN0ZW0vbW9kLnRzXCI7aW1wb3J0IHR5cGUgeyBEcml2ZXJDb25maWcgfSBmcm9tIFwiQC9yZWdpc3RyeS9ydW4tY29uZmlnXCI7XG5pbXBvcnQgeyBGaWxlU3lzdGVtQWN0b3JEcml2ZXIgfSBmcm9tIFwiLi9hY3RvclwiO1xuaW1wb3J0IHsgRmlsZVN5c3RlbUdsb2JhbFN0YXRlIH0gZnJvbSBcIi4vZ2xvYmFsLXN0YXRlXCI7XG5pbXBvcnQgeyBGaWxlU3lzdGVtTWFuYWdlckRyaXZlciB9IGZyb20gXCIuL21hbmFnZXJcIjtcblxuZXhwb3J0IHsgRmlsZVN5c3RlbUFjdG9yRHJpdmVyIH0gZnJvbSBcIi4vYWN0b3JcIjtcbmV4cG9ydCB7IEZpbGVTeXN0ZW1HbG9iYWxTdGF0ZSB9IGZyb20gXCIuL2dsb2JhbC1zdGF0ZVwiO1xuZXhwb3J0IHsgRmlsZVN5c3RlbU1hbmFnZXJEcml2ZXIgfSBmcm9tIFwiLi9tYW5hZ2VyXCI7XG5leHBvcnQgeyBnZXRTdG9yYWdlUGF0aCB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGaWxlU3lzdGVtT3JNZW1vcnlEcml2ZXIoXG5cdHBlcnNpc3Q6IGJvb2xlYW4gPSB0cnVlLFxuXHRjdXN0b21QYXRoPzogc3RyaW5nLFxuKTogRHJpdmVyQ29uZmlnIHtcblx0Y29uc3Qgc3RhdGUgPSBuZXcgRmlsZVN5c3RlbUdsb2JhbFN0YXRlKHBlcnNpc3QsIGN1c3RvbVBhdGgpO1xuXHRjb25zdCBkcml2ZXJDb25maWc6IERyaXZlckNvbmZpZyA9IHtcblx0XHRuYW1lOiBwZXJzaXN0ID8gXCJmaWxlLXN5c3RlbVwiIDogXCJtZW1vcnlcIixcblx0XHRtYW5hZ2VyOiAocmVnaXN0cnlDb25maWcsIHJ1bkNvbmZpZykgPT5cblx0XHRcdG5ldyBGaWxlU3lzdGVtTWFuYWdlckRyaXZlcihcblx0XHRcdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0XHRcdHJ1bkNvbmZpZyxcblx0XHRcdFx0c3RhdGUsXG5cdFx0XHRcdGRyaXZlckNvbmZpZyxcblx0XHRcdCksXG5cdFx0YWN0b3I6IChyZWdpc3RyeUNvbmZpZywgcnVuQ29uZmlnLCBtYW5hZ2VyRHJpdmVyLCBpbmxpbmVDbGllbnQpID0+IHtcblx0XHRcdGNvbnN0IGFjdG9yRHJpdmVyID0gbmV3IEZpbGVTeXN0ZW1BY3RvckRyaXZlcihcblx0XHRcdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0XHRcdHJ1bkNvbmZpZyxcblx0XHRcdFx0bWFuYWdlckRyaXZlcixcblx0XHRcdFx0aW5saW5lQ2xpZW50LFxuXHRcdFx0XHRzdGF0ZSxcblx0XHRcdCk7XG5cblx0XHRcdHN0YXRlLm9uUnVubmVyU3RhcnQocmVnaXN0cnlDb25maWcsIHJ1bkNvbmZpZywgaW5saW5lQ2xpZW50LCBhY3RvckRyaXZlcik7XG5cblx0XHRcdHJldHVybiBhY3RvckRyaXZlcjtcblx0XHR9LFxuXHR9O1xuXHRyZXR1cm4gZHJpdmVyQ29uZmlnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRmlsZVN5c3RlbURyaXZlcihvcHRzPzogeyBwYXRoPzogc3RyaW5nIH0pOiBEcml2ZXJDb25maWcge1xuXHRyZXR1cm4gY3JlYXRlRmlsZVN5c3RlbU9yTWVtb3J5RHJpdmVyKHRydWUsIG9wdHM/LnBhdGgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWVtb3J5RHJpdmVyKCk6IERyaXZlckNvbmZpZyB7XG5cdHJldHVybiBjcmVhdGVGaWxlU3lzdGVtT3JNZW1vcnlEcml2ZXIoZmFsc2UpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9kZWZhdWx0LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL2RyaXZlcnNcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvZHJpdmVycy9kZWZhdWx0LnRzXCI7aW1wb3J0IHsgVXNlckVycm9yIH0gZnJvbSBcIkAvYWN0b3IvZXJyb3JzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiQC9hY3Rvci9sb2dcIjtcbmltcG9ydCB7IGNyZWF0ZUVuZ2luZURyaXZlciB9IGZyb20gXCJAL2RyaXZlcnMvZW5naW5lL21vZFwiO1xuaW1wb3J0IHsgY3JlYXRlRmlsZVN5c3RlbU9yTWVtb3J5RHJpdmVyIH0gZnJvbSBcIkAvZHJpdmVycy9maWxlLXN5c3RlbS9tb2RcIjtcbmltcG9ydCB0eXBlIHsgRHJpdmVyQ29uZmlnLCBSdW5Db25maWcgfSBmcm9tIFwiQC9yZWdpc3RyeS9ydW4tY29uZmlnXCI7XG5pbXBvcnQgeyBnZXRFbnZVbml2ZXJzYWwgfSBmcm9tIFwiQC91dGlsc1wiO1xuXG4vKipcbiAqIENob29zZXMgdGhlIGFwcHJvcHJpYXRlIGRyaXZlciBiYXNlZCBvbiB0aGUgcnVuIGNvbmZpZ3VyYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaG9vc2VEZWZhdWx0RHJpdmVyKHJ1bkNvbmZpZzogUnVuQ29uZmlnKTogRHJpdmVyQ29uZmlnIHtcblx0Y29uc3QgZW5naW5lRW5kcG9pbnQgPSBydW5Db25maWcuZW5naW5lIHx8IGdldEVudlVuaXZlcnNhbChcIlJJVkVUX0VOR0lORVwiKTtcblxuXHRpZiAoZW5naW5lRW5kcG9pbnQgJiYgcnVuQ29uZmlnLmRyaXZlcikge1xuXHRcdHRocm93IG5ldyBVc2VyRXJyb3IoXG5cdFx0XHRcIkNhbm5vdCBzcGVjaWZ5IGJvdGggJ2VuZ2luZScgYW5kICdkcml2ZXInIGluIGNvbmZpZ3VyYXRpb25cIixcblx0XHQpO1xuXHR9XG5cblx0aWYgKHJ1bkNvbmZpZy5kcml2ZXIpIHtcblx0XHRyZXR1cm4gcnVuQ29uZmlnLmRyaXZlcjtcblx0fVxuXG5cdGlmIChlbmdpbmVFbmRwb2ludCkge1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwidXNpbmcgcml2ZXQgZW5naW5lIGRyaXZlclwiLCB7IGVuZHBvaW50OiBlbmdpbmVFbmRwb2ludCB9KTtcblx0XHRyZXR1cm4gY3JlYXRlRW5naW5lRHJpdmVyKHsgZW5kcG9pbnQ6IGVuZ2luZUVuZHBvaW50IH0pO1xuXHR9XG5cblx0bG9nZ2VyKCkuZGVidWcoXCJ1c2luZyBkZWZhdWx0IGZpbGUgc3lzdGVtIGRyaXZlclwiKTtcblx0cmV0dXJuIGNyZWF0ZUZpbGVTeXN0ZW1Pck1lbW9yeURyaXZlcih0cnVlKTtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL21hbmFnZXIvcm91dGVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL21hbmFnZXJcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvbWFuYWdlci9yb3V0ZXIudHNcIjtpbXBvcnQgeyBjcmVhdGVSb3V0ZSwgT3BlbkFQSUhvbm8gfSBmcm9tIFwiQGhvbm8vem9kLW9wZW5hcGlcIjtcbmltcG9ydCAqIGFzIGNib3IgZnJvbSBcImNib3IteFwiO1xuaW1wb3J0IHtcblx0SG9ubyxcblx0dHlwZSBDb250ZXh0IGFzIEhvbm9Db250ZXh0LFxuXHR0eXBlIE1pZGRsZXdhcmVIYW5kbGVyLFxufSBmcm9tIFwiaG9ub1wiO1xuaW1wb3J0IHsgY29ycyB9IGZyb20gXCJob25vL2NvcnNcIjtcbmltcG9ydCB7IHN0cmVhbVNTRSB9IGZyb20gXCJob25vL3N0cmVhbWluZ1wiO1xuaW1wb3J0IHR5cGUgeyBXU0NvbnRleHQgfSBmcm9tIFwiaG9uby93c1wiO1xuaW1wb3J0IGludmFyaWFudCBmcm9tIFwiaW52YXJpYW50XCI7XG5pbXBvcnQgdHlwZSB7IENsb3NlRXZlbnQsIE1lc3NhZ2VFdmVudCwgV2ViU29ja2V0IH0gZnJvbSBcIndzXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0ICogYXMgZXJyb3JzIGZyb20gXCJAL2FjdG9yL2Vycm9yc1wiO1xuaW1wb3J0IHR5cGUgeyBUcmFuc3BvcnQgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9vbGRcIjtcbmltcG9ydCB0eXBlIHsgRW5jb2RpbmcgfSBmcm9tIFwiQC9hY3Rvci9wcm90b2NvbC9zZXJkZVwiO1xuaW1wb3J0IHtcblx0UEFUSF9DT05ORUNUX1dFQlNPQ0tFVCxcblx0UEFUSF9SQVdfV0VCU09DS0VUX1BSRUZJWCxcbn0gZnJvbSBcIkAvYWN0b3Ivcm91dGVyXCI7XG5pbXBvcnQge1xuXHRBTExPV0VEX1BVQkxJQ19IRUFERVJTLFxuXHRnZXRSZXF1ZXN0RW5jb2RpbmcsXG5cdGdldFJlcXVlc3RRdWVyeSxcblx0SEVBREVSX0FDVE9SX0lELFxuXHRIRUFERVJfQUNUT1JfUVVFUlksXG5cdEhFQURFUl9BVVRIX0RBVEEsXG5cdEhFQURFUl9DT05OX0lELFxuXHRIRUFERVJfQ09OTl9QQVJBTVMsXG5cdEhFQURFUl9DT05OX1RPS0VOLFxuXHRIRUFERVJfRU5DT0RJTkcsXG59IGZyb20gXCJAL2FjdG9yL3JvdXRlci1lbmRwb2ludHNcIjtcbmltcG9ydCB0eXBlIHsgQ2xpZW50RHJpdmVyIH0gZnJvbSBcIkAvY2xpZW50L2NsaWVudFwiO1xuaW1wb3J0IHtcblx0aGFuZGxlUm91dGVFcnJvcixcblx0aGFuZGxlUm91dGVOb3RGb3VuZCxcblx0bG9nZ2VyTWlkZGxld2FyZSxcbn0gZnJvbSBcIkAvY29tbW9uL3JvdXRlclwiO1xuaW1wb3J0IHtcblx0dHlwZSBEZWNvbnN0cnVjdGVkRXJyb3IsXG5cdGRlY29uc3RydWN0RXJyb3IsXG5cdG5vb3BOZXh0LFxuXHRzdHJpbmdpZnlFcnJvcixcbn0gZnJvbSBcIkAvY29tbW9uL3V0aWxzXCI7XG5pbXBvcnQgeyBjcmVhdGVNYW5hZ2VySW5zcGVjdG9yUm91dGVyIH0gZnJvbSBcIkAvaW5zcGVjdG9yL21hbmFnZXJcIjtcbmltcG9ydCB7IHNlY3VyZUluc3BlY3RvciB9IGZyb20gXCJAL2luc3BlY3Rvci91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBVcGdyYWRlV2ViU29ja2V0QXJncyB9IGZyb20gXCJAL21vZFwiO1xuaW1wb3J0IHR5cGUgeyBSZWdpc3RyeUNvbmZpZyB9IGZyb20gXCJAL3JlZ2lzdHJ5L2NvbmZpZ1wiO1xuaW1wb3J0IHR5cGUgeyBSdW5Db25maWcgfSBmcm9tIFwiQC9yZWdpc3RyeS9ydW4tY29uZmlnXCI7XG5pbXBvcnQgdHlwZSAqIGFzIHByb3RvY29sIGZyb20gXCJAL3NjaGVtYXMvY2xpZW50LXByb3RvY29sL21vZFwiO1xuaW1wb3J0IHtcblx0SFRUUF9SRVNPTFZFX1JFU1BPTlNFX1ZFUlNJT05FRCxcblx0VE9fQ0xJRU5UX1ZFUlNJT05FRCxcbn0gZnJvbSBcIkAvc2NoZW1hcy9jbGllbnQtcHJvdG9jb2wvdmVyc2lvbmVkXCI7XG5pbXBvcnQgeyBzZXJpYWxpemVXaXRoRW5jb2RpbmcgfSBmcm9tIFwiQC9zZXJkZVwiO1xuaW1wb3J0IHsgYnVmZmVyVG9BcnJheUJ1ZmZlciB9IGZyb20gXCJAL3V0aWxzXCI7XG5pbXBvcnQgeyBhdXRoZW50aWNhdGVFbmRwb2ludCB9IGZyb20gXCIuL2F1dGhcIjtcbmltcG9ydCB0eXBlIHsgTWFuYWdlckRyaXZlciB9IGZyb20gXCIuL2RyaXZlclwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yUXVlcnkgfSBmcm9tIFwiLi9wcm90b2NvbC9xdWVyeVwiO1xuaW1wb3J0IHtcblx0QWN0b3JRdWVyeVNjaGVtYSxcblx0Q29ubmVjdFJlcXVlc3RTY2hlbWEsXG5cdENvbm5lY3RXZWJTb2NrZXRSZXF1ZXN0U2NoZW1hLFxuXHRDb25uTWVzc2FnZVJlcXVlc3RTY2hlbWEsXG5cdFJlc29sdmVSZXF1ZXN0U2NoZW1hLFxufSBmcm9tIFwiLi9wcm90b2NvbC9xdWVyeVwiO1xuXG4vKipcbiAqIFBhcnNlIFdlYlNvY2tldCBwcm90b2NvbCBoZWFkZXJzIGZvciBxdWVyeSBhbmQgY29ubmVjdGlvbiBwYXJhbWV0ZXJzXG4gKi9cbmZ1bmN0aW9uIHBhcnNlV2ViU29ja2V0UHJvdG9jb2xzKHByb3RvY29sczogc3RyaW5nIHwgdW5kZWZpbmVkKToge1xuXHRxdWVyeVJhdzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXHRlbmNvZGluZ1Jhdzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXHRjb25uUGFyYW1zUmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59IHtcblx0bGV0IHF1ZXJ5UmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cdGxldCBlbmNvZGluZ1Jhdzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXHRsZXQgY29ublBhcmFtc1Jhdzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG5cdGlmIChwcm90b2NvbHMpIHtcblx0XHRjb25zdCBwcm90b2NvbExpc3QgPSBwcm90b2NvbHMuc3BsaXQoXCIsXCIpLm1hcCgocCkgPT4gcC50cmltKCkpO1xuXHRcdGZvciAoY29uc3QgcHJvdG9jb2wgb2YgcHJvdG9jb2xMaXN0KSB7XG5cdFx0XHRpZiAocHJvdG9jb2wuc3RhcnRzV2l0aChcInF1ZXJ5LlwiKSkge1xuXHRcdFx0XHRxdWVyeVJhdyA9IGRlY29kZVVSSUNvbXBvbmVudChwcm90b2NvbC5zdWJzdHJpbmcoXCJxdWVyeS5cIi5sZW5ndGgpKTtcblx0XHRcdH0gZWxzZSBpZiAocHJvdG9jb2wuc3RhcnRzV2l0aChcImVuY29kaW5nLlwiKSkge1xuXHRcdFx0XHRlbmNvZGluZ1JhdyA9IHByb3RvY29sLnN1YnN0cmluZyhcImVuY29kaW5nLlwiLmxlbmd0aCk7XG5cdFx0XHR9IGVsc2UgaWYgKHByb3RvY29sLnN0YXJ0c1dpdGgoXCJjb25uX3BhcmFtcy5cIikpIHtcblx0XHRcdFx0Y29ublBhcmFtc1JhdyA9IGRlY29kZVVSSUNvbXBvbmVudChcblx0XHRcdFx0XHRwcm90b2NvbC5zdWJzdHJpbmcoXCJjb25uX3BhcmFtcy5cIi5sZW5ndGgpLFxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7IHF1ZXJ5UmF3LCBlbmNvZGluZ1JhdywgY29ublBhcmFtc1JhdyB9O1xufVxuXG5jb25zdCBPUEVOQVBJX0VOQ09ESU5HID0gei5zdHJpbmcoKS5vcGVuYXBpKHtcblx0ZGVzY3JpcHRpb246IFwiVGhlIGVuY29kaW5nIGZvcm1hdCB0byB1c2UgZm9yIHRoZSByZXNwb25zZSAoanNvbiwgY2JvcilcIixcblx0ZXhhbXBsZTogXCJqc29uXCIsXG59KTtcblxuY29uc3QgT1BFTkFQSV9BQ1RPUl9RVUVSWSA9IHouc3RyaW5nKCkub3BlbmFwaSh7XG5cdGRlc2NyaXB0aW9uOiBcIkFjdG9yIHF1ZXJ5IGluZm9ybWF0aW9uXCIsXG59KTtcblxuY29uc3QgT1BFTkFQSV9DT05OX1BBUkFNUyA9IHouc3RyaW5nKCkub3BlbmFwaSh7XG5cdGRlc2NyaXB0aW9uOiBcIkNvbm5lY3Rpb24gcGFyYW1ldGVyc1wiLFxufSk7XG5cbmNvbnN0IE9QRU5BUElfQUNUT1JfSUQgPSB6LnN0cmluZygpLm9wZW5hcGkoe1xuXHRkZXNjcmlwdGlvbjogXCJBY3RvciBJRCAodXNlZCBpbiBzb21lIGVuZHBvaW50cylcIixcblx0ZXhhbXBsZTogXCJhY3Rvci0xMjM0NTZcIixcbn0pO1xuXG5jb25zdCBPUEVOQVBJX0NPTk5fSUQgPSB6LnN0cmluZygpLm9wZW5hcGkoe1xuXHRkZXNjcmlwdGlvbjogXCJDb25uZWN0aW9uIElEXCIsXG5cdGV4YW1wbGU6IFwiY29ubi0xMjM0NTZcIixcbn0pO1xuXG5jb25zdCBPUEVOQVBJX0NPTk5fVE9LRU4gPSB6LnN0cmluZygpLm9wZW5hcGkoe1xuXHRkZXNjcmlwdGlvbjogXCJDb25uZWN0aW9uIHRva2VuXCIsXG59KTtcblxuZnVuY3Rpb24gYnVpbGRPcGVuQXBpUmVzcG9uc2VzPFQ+KHNjaGVtYTogVCwgdmFsaWRhdGVCb2R5OiBib29sZWFuKSB7XG5cdHJldHVybiB7XG5cdFx0MjAwOiB7XG5cdFx0XHRkZXNjcmlwdGlvbjogXCJTdWNjZXNzXCIsXG5cdFx0XHRjb250ZW50OiB2YWxpZGF0ZUJvZHlcblx0XHRcdFx0PyB7XG5cdFx0XHRcdFx0XHRcImFwcGxpY2F0aW9uL2pzb25cIjoge1xuXHRcdFx0XHRcdFx0XHRzY2hlbWEsXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0OiB7fSxcblx0XHR9LFxuXHRcdDQwMDoge1xuXHRcdFx0ZGVzY3JpcHRpb246IFwiVXNlciBlcnJvclwiLFxuXHRcdH0sXG5cdFx0NTAwOiB7XG5cdFx0XHRkZXNjcmlwdGlvbjogXCJJbnRlcm5hbCBlcnJvclwiLFxuXHRcdH0sXG5cdH07XG59XG5cbi8qKlxuICogT25seSB1c2UgYHZhbGlkYXRlQm9keWAgdG8gYHRydWVgIGlmIHlvdSBuZWVkIHRvIGV4cG9ydCBPcGVuQVBJIEpTT04uXG4gKlxuICogSWYgbGVmdCBlbmFibGVkIGZvciBwcm9kdWN0aW9uLCB0aGlzIHdpbGwgY2F1c2UgZXJyb3JzLiBXZSBkaXNhYmxlIEpTT04gdmFsaWRhdGlvbiBzaW5jZTpcbiAqIC0gSXQgcHJldmVudHMgdXMgZnJvbSBwcm94eWluZyByZXF1ZXN0cywgc2luY2UgdmFsaWRhdGluZyB0aGUgYm9keSByZXF1aXJlcyBjb25zdW1pbmcgdGhlIGJvZHkgc28gd2UgY2FuJ3QgZm9yd2FyZCB0aGUgYm9keVxuICogLSBXZSB2YWxpZGF0ZSBhbGwgdHlwZXMgYXQgdGhlIGFjdG9yIHJvdXRlciBsYXllciBzaW5jZSBtb3N0IHJlcXVlc3RzIGFyZSBwcm94aWVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNYW5hZ2VyUm91dGVyKFxuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdHJ1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRpbmxpbmVDbGllbnREcml2ZXI6IENsaWVudERyaXZlcixcblx0bWFuYWdlckRyaXZlcjogTWFuYWdlckRyaXZlcixcblx0dmFsaWRhdGVCb2R5OiBib29sZWFuLFxuKTogeyByb3V0ZXI6IEhvbm87IG9wZW5hcGk6IE9wZW5BUElIb25vIH0ge1xuXHRjb25zdCByb3V0ZXIgPSBuZXcgT3BlbkFQSUhvbm8oeyBzdHJpY3Q6IGZhbHNlIH0pLmJhc2VQYXRoKFxuXHRcdHJ1bkNvbmZpZy5iYXNlUGF0aCxcblx0KTtcblxuXHRyb3V0ZXIudXNlKFwiKlwiLCBsb2dnZXJNaWRkbGV3YXJlKGxvZ2dlcigpKSk7XG5cblx0aWYgKHJ1bkNvbmZpZy5jb3JzIHx8IHJ1bkNvbmZpZy5pbnNwZWN0b3I/LmNvcnMpIHtcblx0XHRyb3V0ZXIudXNlKFwiKlwiLCBhc3luYyAoYywgbmV4dCkgPT4ge1xuXHRcdFx0Ly8gRG9uJ3QgYXBwbHkgdG8gV2ViU29ja2V0IHJvdXRlc1xuXHRcdFx0Ly8gSEFDSzogVGhpcyBjb3VsZCBiZSBpbnNlY3VyZSBpZiB3ZSBoYWQgYSB2YXJhcmdzIHBhdGguIFdlIGhhdmUgdG8gY2hlY2sgdGhlIHBhdGggc3VmZml4IGZvciBXUyBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSBwYXRoIHRoYXQgdGhpcyByb3V0ZXIgd2FzIG1vdW50ZWQuXG5cdFx0XHQvLyBIQUNLOiBDaGVja2luZyBcIi93ZWJzb2NrZXQvXCIgaXMgbm90IHNhZmUsIGJ1dCB0aGVyZSBpcyBubyBvdGhlciB3YXkgdG8gaGFuZGxlIHRoaXMgaWYgd2UgZG9uJ3Qga25vdyB0aGUgYmFzZSBwYXRoIHRoaXMgaXNcblx0XHRcdC8vIG1vdW50ZWQgb25cblx0XHRcdGNvbnN0IHBhdGggPSBjLnJlcS5wYXRoO1xuXHRcdFx0aWYgKFxuXHRcdFx0XHRwYXRoLmVuZHNXaXRoKFwiL2FjdG9ycy9jb25uZWN0L3dlYnNvY2tldFwiKSB8fFxuXHRcdFx0XHRwYXRoLmluY2x1ZGVzKFwiL2FjdG9ycy9yYXcvd2Vic29ja2V0L1wiKSB8fFxuXHRcdFx0XHQvLyBpbnNwZWN0b3JzIGltcGxlbWVudCB0aGVpciBvd24gQ09SUyBoYW5kbGluZ1xuXHRcdFx0XHRwYXRoLmVuZHNXaXRoKFwiL2luc3BlY3RcIikgfHxcblx0XHRcdFx0cGF0aC5lbmRzV2l0aChcIi9hY3RvcnMvaW5zcGVjdFwiKVxuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiBuZXh0KCk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBjb3JzKHtcblx0XHRcdFx0Li4uKHJ1bkNvbmZpZy5jb3JzID8/IHt9KSxcblx0XHRcdFx0Li4uKHJ1bkNvbmZpZy5pbnNwZWN0b3I/LmNvcnMgPz8ge30pLFxuXHRcdFx0XHRvcmlnaW46IChvcmlnaW4sIGMpID0+IHtcblx0XHRcdFx0XHRjb25zdCBpbnNwZWN0b3JPcmlnaW4gPSBydW5Db25maWcuaW5zcGVjdG9yPy5jb3JzPy5vcmlnaW47XG5cblx0XHRcdFx0XHRpZiAoaW5zcGVjdG9yT3JpZ2luICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdGlmICh0eXBlb2YgaW5zcGVjdG9yT3JpZ2luID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgYWxsb3dlZCA9IGluc3BlY3Rvck9yaWdpbihvcmlnaW4sIGMpO1xuXHRcdFx0XHRcdFx0XHRpZiAoYWxsb3dlZCkgcmV0dXJuIGFsbG93ZWQ7XG5cdFx0XHRcdFx0XHRcdC8vIFByb2NlZWQgdG8gbmV4dCBDT1JTIGNvbmZpZyBpZiBub25lIHByb3ZpZGVkXG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW5zcGVjdG9yT3JpZ2luKSkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaW5zcGVjdG9yT3JpZ2luLmluY2x1ZGVzKG9yaWdpbikgPyBvcmlnaW4gOiB1bmRlZmluZWQ7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaW5zcGVjdG9yT3JpZ2luO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChydW5Db25maWcuY29ycz8ub3JpZ2luICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdGlmICh0eXBlb2YgcnVuQ29uZmlnLmNvcnMub3JpZ2luID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgYWxsb3dlZCA9IHJ1bkNvbmZpZy5jb3JzLm9yaWdpbihvcmlnaW4sIGMpO1xuXHRcdFx0XHRcdFx0XHRpZiAoYWxsb3dlZCkgcmV0dXJuIGFsbG93ZWQ7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcnVuQ29uZmlnLmNvcnMub3JpZ2luIGFzIHN0cmluZztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdFx0fSxcblx0XHRcdFx0YWxsb3dNZXRob2RzOiAob3JpZ2luLCBjKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgaW5zcGVjdG9yTWV0aG9kcyA9IHJ1bkNvbmZpZy5pbnNwZWN0b3I/LmNvcnM/LmFsbG93TWV0aG9kcztcblx0XHRcdFx0XHRpZiAoaW5zcGVjdG9yTWV0aG9kcykge1xuXHRcdFx0XHRcdFx0aWYgKHR5cGVvZiBpbnNwZWN0b3JNZXRob2RzID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGluc3BlY3Rvck1ldGhvZHMob3JpZ2luLCBjKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJldHVybiBpbnNwZWN0b3JNZXRob2RzO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChydW5Db25maWcuY29ycz8uYWxsb3dNZXRob2RzKSB7XG5cdFx0XHRcdFx0XHRpZiAodHlwZW9mIHJ1bkNvbmZpZy5jb3JzLmFsbG93TWV0aG9kcyA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBydW5Db25maWcuY29ycy5hbGxvd01ldGhvZHMob3JpZ2luLCBjKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJldHVybiBydW5Db25maWcuY29ycy5hbGxvd01ldGhvZHM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRhbGxvd0hlYWRlcnM6IFtcblx0XHRcdFx0XHQuLi4ocnVuQ29uZmlnLmNvcnM/LmFsbG93SGVhZGVycyA/PyBbXSksXG5cdFx0XHRcdFx0Li4uKHJ1bkNvbmZpZy5pbnNwZWN0b3I/LmNvcnM/LmFsbG93SGVhZGVycyA/PyBbXSksXG5cdFx0XHRcdFx0Li4uQUxMT1dFRF9QVUJMSUNfSEVBREVSUyxcblx0XHRcdFx0XHRcIkNvbnRlbnQtVHlwZVwiLFxuXHRcdFx0XHRcdFwiVXNlci1BZ2VudFwiLFxuXHRcdFx0XHRdLFxuXHRcdFx0XHRjcmVkZW50aWFsczpcblx0XHRcdFx0XHRydW5Db25maWcuY29ycz8uY3JlZGVudGlhbHMgPz9cblx0XHRcdFx0XHRydW5Db25maWcuaW5zcGVjdG9yPy5jb3JzPy5jcmVkZW50aWFscyA/P1xuXHRcdFx0XHRcdHRydWUsXG5cdFx0XHR9KShjLCBuZXh0KTtcblx0XHR9KTtcblx0fVxuXG5cdC8vIEdFVCAvXG5cdHJvdXRlci5nZXQoXCIvXCIsIChjOiBIb25vQ29udGV4dCkgPT4ge1xuXHRcdHJldHVybiBjLnRleHQoXG5cdFx0XHRcIlRoaXMgaXMgYW4gUml2ZXRLaXQgcmVnaXN0cnkuXFxuXFxuTGVhcm4gbW9yZSBhdCBodHRwczovL3JpdmV0a2l0Lm9yZ1wiLFxuXHRcdCk7XG5cdH0pO1xuXG5cdC8vIFBPU1QgL2FjdG9ycy9yZXNvbHZlXG5cdHtcblx0XHRjb25zdCBSZXNvbHZlUXVlcnlTY2hlbWEgPSB6XG5cdFx0XHQub2JqZWN0KHtcblx0XHRcdFx0cXVlcnk6IHouYW55KCkub3BlbmFwaSh7XG5cdFx0XHRcdFx0ZXhhbXBsZTogeyBnZXRGb3JJZDogeyBhY3RvcklkOiBcImFjdG9yLTEyM1wiIH0gfSxcblx0XHRcdFx0fSksXG5cdFx0XHR9KVxuXHRcdFx0Lm9wZW5hcGkoXCJSZXNvbHZlUXVlcnlcIik7XG5cblx0XHRjb25zdCBSZXNvbHZlUmVzcG9uc2VTY2hlbWEgPSB6XG5cdFx0XHQub2JqZWN0KHtcblx0XHRcdFx0aTogei5zdHJpbmcoKS5vcGVuYXBpKHtcblx0XHRcdFx0XHRleGFtcGxlOiBcImFjdG9yLTEyM1wiLFxuXHRcdFx0XHR9KSxcblx0XHRcdH0pXG5cdFx0XHQub3BlbmFwaShcIlJlc29sdmVSZXNwb25zZVwiKTtcblxuXHRcdGNvbnN0IHJlc29sdmVSb3V0ZSA9IGNyZWF0ZVJvdXRlKHtcblx0XHRcdG1ldGhvZDogXCJwb3N0XCIsXG5cdFx0XHRwYXRoOiBcIi9hY3RvcnMvcmVzb2x2ZVwiLFxuXHRcdFx0cmVxdWVzdDoge1xuXHRcdFx0XHRib2R5OiB7XG5cdFx0XHRcdFx0Y29udGVudDogdmFsaWRhdGVCb2R5XG5cdFx0XHRcdFx0XHQ/IHtcblx0XHRcdFx0XHRcdFx0XHRcImFwcGxpY2F0aW9uL2pzb25cIjoge1xuXHRcdFx0XHRcdFx0XHRcdFx0c2NoZW1hOiBSZXNvbHZlUXVlcnlTY2hlbWEsXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0OiB7fSxcblx0XHRcdFx0fSxcblx0XHRcdFx0aGVhZGVyczogei5vYmplY3Qoe1xuXHRcdFx0XHRcdFtIRUFERVJfQUNUT1JfUVVFUlldOiBPUEVOQVBJX0FDVE9SX1FVRVJZLFxuXHRcdFx0XHR9KSxcblx0XHRcdH0sXG5cdFx0XHRyZXNwb25zZXM6IGJ1aWxkT3BlbkFwaVJlc3BvbnNlcyhSZXNvbHZlUmVzcG9uc2VTY2hlbWEsIHZhbGlkYXRlQm9keSksXG5cdFx0fSk7XG5cblx0XHRyb3V0ZXIub3BlbmFwaShyZXNvbHZlUm91dGUsIChjKSA9PlxuXHRcdFx0aGFuZGxlUmVzb2x2ZVJlcXVlc3QoYywgcmVnaXN0cnlDb25maWcsIG1hbmFnZXJEcml2ZXIpLFxuXHRcdCk7XG5cdH1cblxuXHQvLyBHRVQgL2FjdG9ycy9jb25uZWN0L3dlYnNvY2tldFxuXHR7XG5cdFx0Ly8gSEFDSzogV2ViU29ja2V0cyBkb24ndCB3b3JrIHdpdGggbW91bnRzLCBzbyB3ZSBuZWVkIHRvIGR5bmFtaWNhbGx5IG1hdGNoIHRoZSB0cmFpbGluZyBwYXRoXG5cdFx0cm91dGVyLnVzZShcIipcIiwgKGMsIG5leHQpID0+IHtcblx0XHRcdGlmIChjLnJlcS5wYXRoLmVuZHNXaXRoKFwiL2FjdG9ycy9jb25uZWN0L3dlYnNvY2tldFwiKSkge1xuXHRcdFx0XHRyZXR1cm4gaGFuZGxlV2ViU29ja2V0Q29ubmVjdFJlcXVlc3QoXG5cdFx0XHRcdFx0Yyxcblx0XHRcdFx0XHRyZWdpc3RyeUNvbmZpZyxcblx0XHRcdFx0XHRydW5Db25maWcsXG5cdFx0XHRcdFx0bWFuYWdlckRyaXZlcixcblx0XHRcdFx0KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG5leHQoKTtcblx0XHR9KTtcblxuXHRcdC8vIFRoaXMgcm91dGUgaXMgYSBub29wLCBqdXN0IHVzZWQgdG8gZ2VuZXJhdGUgZG9jc1xuXHRcdGNvbnN0IHdzUm91dGUgPSBjcmVhdGVSb3V0ZSh7XG5cdFx0XHRtZXRob2Q6IFwiZ2V0XCIsXG5cdFx0XHRwYXRoOiBcIi9hY3RvcnMvY29ubmVjdC93ZWJzb2NrZXRcIixcblx0XHRcdHJlc3BvbnNlczoge1xuXHRcdFx0XHQxMDE6IHtcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjogXCJXZWJTb2NrZXQgdXBncmFkZVwiLFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9KTtcblxuXHRcdHJvdXRlci5vcGVuYXBpKHdzUm91dGUsICgpID0+IHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNob3VsZCBiZSB1bnJlYWNoYWJsZVwiKTtcblx0XHR9KTtcblx0fVxuXG5cdC8vIEdFVCAvYWN0b3JzL2Nvbm5lY3Qvc3NlXG5cdHtcblx0XHRjb25zdCBzc2VSb3V0ZSA9IGNyZWF0ZVJvdXRlKHtcblx0XHRcdG1ldGhvZDogXCJnZXRcIixcblx0XHRcdHBhdGg6IFwiL2FjdG9ycy9jb25uZWN0L3NzZVwiLFxuXHRcdFx0cmVxdWVzdDoge1xuXHRcdFx0XHRoZWFkZXJzOiB6Lm9iamVjdCh7XG5cdFx0XHRcdFx0W0hFQURFUl9FTkNPRElOR106IE9QRU5BUElfRU5DT0RJTkcsXG5cdFx0XHRcdFx0W0hFQURFUl9BQ1RPUl9RVUVSWV06IE9QRU5BUElfQUNUT1JfUVVFUlksXG5cdFx0XHRcdFx0W0hFQURFUl9DT05OX1BBUkFNU106IE9QRU5BUElfQ09OTl9QQVJBTVMub3B0aW9uYWwoKSxcblx0XHRcdFx0fSksXG5cdFx0XHR9LFxuXHRcdFx0cmVzcG9uc2VzOiB7XG5cdFx0XHRcdDIwMDoge1xuXHRcdFx0XHRcdGRlc2NyaXB0aW9uOiBcIlNTRSBzdHJlYW1cIixcblx0XHRcdFx0XHRjb250ZW50OiB7XG5cdFx0XHRcdFx0XHRcInRleHQvZXZlbnQtc3RyZWFtXCI6IHtcblx0XHRcdFx0XHRcdFx0c2NoZW1hOiB6LnVua25vd24oKSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fSxcblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHRyb3V0ZXIub3BlbmFwaShzc2VSb3V0ZSwgKGMpID0+XG5cdFx0XHRoYW5kbGVTc2VDb25uZWN0UmVxdWVzdChjLCByZWdpc3RyeUNvbmZpZywgcnVuQ29uZmlnLCBtYW5hZ2VyRHJpdmVyKSxcblx0XHQpO1xuXHR9XG5cblx0Ly8gUE9TVCAvYWN0b3JzL2FjdGlvbi86YWN0aW9uXG5cdHtcblx0XHRjb25zdCBBY3Rpb25QYXJhbXNTY2hlbWEgPSB6XG5cdFx0XHQub2JqZWN0KHtcblx0XHRcdFx0YWN0aW9uOiB6LnN0cmluZygpLm9wZW5hcGkoe1xuXHRcdFx0XHRcdHBhcmFtOiB7XG5cdFx0XHRcdFx0XHRuYW1lOiBcImFjdGlvblwiLFxuXHRcdFx0XHRcdFx0aW46IFwicGF0aFwiLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXhhbXBsZTogXCJteUFjdGlvblwiLFxuXHRcdFx0XHR9KSxcblx0XHRcdH0pXG5cdFx0XHQub3BlbmFwaShcIkFjdGlvblBhcmFtc1wiKTtcblxuXHRcdGNvbnN0IEFjdGlvblJlcXVlc3RTY2hlbWEgPSB6XG5cdFx0XHQub2JqZWN0KHtcblx0XHRcdFx0cXVlcnk6IHouYW55KCkub3BlbmFwaSh7XG5cdFx0XHRcdFx0ZXhhbXBsZTogeyBnZXRGb3JJZDogeyBhY3RvcklkOiBcImFjdG9yLTEyM1wiIH0gfSxcblx0XHRcdFx0fSksXG5cdFx0XHRcdGJvZHk6IHpcblx0XHRcdFx0XHQuYW55KClcblx0XHRcdFx0XHQub3B0aW9uYWwoKVxuXHRcdFx0XHRcdC5vcGVuYXBpKHtcblx0XHRcdFx0XHRcdGV4YW1wbGU6IHsgcGFyYW0xOiBcInZhbHVlMVwiLCBwYXJhbTI6IDEyMyB9LFxuXHRcdFx0XHRcdH0pLFxuXHRcdFx0fSlcblx0XHRcdC5vcGVuYXBpKFwiQWN0aW9uUmVxdWVzdFwiKTtcblxuXHRcdGNvbnN0IEFjdGlvblJlc3BvbnNlU2NoZW1hID0gei5hbnkoKS5vcGVuYXBpKFwiQWN0aW9uUmVzcG9uc2VcIik7XG5cblx0XHRjb25zdCBhY3Rpb25Sb3V0ZSA9IGNyZWF0ZVJvdXRlKHtcblx0XHRcdG1ldGhvZDogXCJwb3N0XCIsXG5cdFx0XHRwYXRoOiBcIi9hY3RvcnMvYWN0aW9ucy97YWN0aW9ufVwiLFxuXHRcdFx0cmVxdWVzdDoge1xuXHRcdFx0XHRwYXJhbXM6IEFjdGlvblBhcmFtc1NjaGVtYSxcblx0XHRcdFx0Ym9keToge1xuXHRcdFx0XHRcdGNvbnRlbnQ6IHZhbGlkYXRlQm9keVxuXHRcdFx0XHRcdFx0PyB7XG5cdFx0XHRcdFx0XHRcdFx0XCJhcHBsaWNhdGlvbi9qc29uXCI6IHtcblx0XHRcdFx0XHRcdFx0XHRcdHNjaGVtYTogQWN0aW9uUmVxdWVzdFNjaGVtYSxcblx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQ6IHt9LFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRoZWFkZXJzOiB6Lm9iamVjdCh7XG5cdFx0XHRcdFx0W0hFQURFUl9FTkNPRElOR106IE9QRU5BUElfRU5DT0RJTkcsXG5cdFx0XHRcdFx0W0hFQURFUl9DT05OX1BBUkFNU106IE9QRU5BUElfQ09OTl9QQVJBTVMub3B0aW9uYWwoKSxcblx0XHRcdFx0fSksXG5cdFx0XHR9LFxuXHRcdFx0cmVzcG9uc2VzOiBidWlsZE9wZW5BcGlSZXNwb25zZXMoQWN0aW9uUmVzcG9uc2VTY2hlbWEsIHZhbGlkYXRlQm9keSksXG5cdFx0fSk7XG5cblx0XHRyb3V0ZXIub3BlbmFwaShhY3Rpb25Sb3V0ZSwgKGMpID0+XG5cdFx0XHRoYW5kbGVBY3Rpb25SZXF1ZXN0KGMsIHJlZ2lzdHJ5Q29uZmlnLCBydW5Db25maWcsIG1hbmFnZXJEcml2ZXIpLFxuXHRcdCk7XG5cdH1cblxuXHQvLyBQT1NUIC9hY3RvcnMvbWVzc2FnZVxuXHR7XG5cdFx0Y29uc3QgQ29ubmVjdGlvbk1lc3NhZ2VSZXF1ZXN0U2NoZW1hID0gelxuXHRcdFx0Lm9iamVjdCh7XG5cdFx0XHRcdG1lc3NhZ2U6IHouYW55KCkub3BlbmFwaSh7XG5cdFx0XHRcdFx0ZXhhbXBsZTogeyB0eXBlOiBcIm1lc3NhZ2VcIiwgY29udGVudDogXCJIZWxsbywgYWN0b3IhXCIgfSxcblx0XHRcdFx0fSksXG5cdFx0XHR9KVxuXHRcdFx0Lm9wZW5hcGkoXCJDb25uZWN0aW9uTWVzc2FnZVJlcXVlc3RcIik7XG5cblx0XHRjb25zdCBDb25uZWN0aW9uTWVzc2FnZVJlc3BvbnNlU2NoZW1hID0gelxuXHRcdFx0LmFueSgpXG5cdFx0XHQub3BlbmFwaShcIkNvbm5lY3Rpb25NZXNzYWdlUmVzcG9uc2VcIik7XG5cblx0XHRjb25zdCBtZXNzYWdlUm91dGUgPSBjcmVhdGVSb3V0ZSh7XG5cdFx0XHRtZXRob2Q6IFwicG9zdFwiLFxuXHRcdFx0cGF0aDogXCIvYWN0b3JzL21lc3NhZ2VcIixcblx0XHRcdHJlcXVlc3Q6IHtcblx0XHRcdFx0Ym9keToge1xuXHRcdFx0XHRcdGNvbnRlbnQ6IHZhbGlkYXRlQm9keVxuXHRcdFx0XHRcdFx0PyB7XG5cdFx0XHRcdFx0XHRcdFx0XCJhcHBsaWNhdGlvbi9qc29uXCI6IHtcblx0XHRcdFx0XHRcdFx0XHRcdHNjaGVtYTogQ29ubmVjdGlvbk1lc3NhZ2VSZXF1ZXN0U2NoZW1hLFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdDoge30sXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGhlYWRlcnM6IHoub2JqZWN0KHtcblx0XHRcdFx0XHRbSEVBREVSX0FDVE9SX0lEXTogT1BFTkFQSV9BQ1RPUl9JRCxcblx0XHRcdFx0XHRbSEVBREVSX0NPTk5fSURdOiBPUEVOQVBJX0NPTk5fSUQsXG5cdFx0XHRcdFx0W0hFQURFUl9FTkNPRElOR106IE9QRU5BUElfRU5DT0RJTkcsXG5cdFx0XHRcdFx0W0hFQURFUl9DT05OX1RPS0VOXTogT1BFTkFQSV9DT05OX1RPS0VOLFxuXHRcdFx0XHR9KSxcblx0XHRcdH0sXG5cdFx0XHRyZXNwb25zZXM6IGJ1aWxkT3BlbkFwaVJlc3BvbnNlcyhcblx0XHRcdFx0Q29ubmVjdGlvbk1lc3NhZ2VSZXNwb25zZVNjaGVtYSxcblx0XHRcdFx0dmFsaWRhdGVCb2R5LFxuXHRcdFx0KSxcblx0XHR9KTtcblxuXHRcdHJvdXRlci5vcGVuYXBpKG1lc3NhZ2VSb3V0ZSwgKGMpID0+XG5cdFx0XHRoYW5kbGVNZXNzYWdlUmVxdWVzdChjLCByZWdpc3RyeUNvbmZpZywgcnVuQ29uZmlnLCBtYW5hZ2VyRHJpdmVyKSxcblx0XHQpO1xuXHR9XG5cblx0Ly8gUmF3IEhUVFAgZW5kcG9pbnRzIC0gL2FjdG9ycy9yYXcvaHR0cC8qXG5cdHtcblx0XHRjb25zdCBSYXdIdHRwUmVxdWVzdEJvZHlTY2hlbWEgPSB6LmFueSgpLm9wdGlvbmFsKCkub3BlbmFwaSh7XG5cdFx0XHRkZXNjcmlwdGlvbjogXCJSYXcgcmVxdWVzdCBib2R5IChjYW4gYmUgYW55IGNvbnRlbnQgdHlwZSlcIixcblx0XHR9KTtcblxuXHRcdGNvbnN0IFJhd0h0dHBSZXNwb25zZVNjaGVtYSA9IHouYW55KCkub3BlbmFwaSh7XG5cdFx0XHRkZXNjcmlwdGlvbjogXCJSYXcgcmVzcG9uc2UgZnJvbSBhY3RvcidzIG9uRmV0Y2ggaGFuZGxlclwiLFxuXHRcdH0pO1xuXG5cdFx0Ly8gRGVmaW5lIGNvbW1vbiByb3V0ZSBjb25maWdcblx0XHRjb25zdCByYXdIdHRwUm91dGVDb25maWcgPSB7XG5cdFx0XHRwYXRoOiBcIi9hY3RvcnMvcmF3L2h0dHAvKlwiLFxuXHRcdFx0cmVxdWVzdDoge1xuXHRcdFx0XHRoZWFkZXJzOiB6Lm9iamVjdCh7XG5cdFx0XHRcdFx0W0hFQURFUl9BQ1RPUl9RVUVSWV06IE9QRU5BUElfQUNUT1JfUVVFUlkub3B0aW9uYWwoKSxcblx0XHRcdFx0XHRbSEVBREVSX0NPTk5fUEFSQU1TXTogT1BFTkFQSV9DT05OX1BBUkFNUy5vcHRpb25hbCgpLFxuXHRcdFx0XHR9KSxcblx0XHRcdFx0Ym9keToge1xuXHRcdFx0XHRcdGNvbnRlbnQ6IHtcblx0XHRcdFx0XHRcdFwiKi8qXCI6IHtcblx0XHRcdFx0XHRcdFx0c2NoZW1hOiBSYXdIdHRwUmVxdWVzdEJvZHlTY2hlbWEsXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdFx0cmVzcG9uc2VzOiB7XG5cdFx0XHRcdDIwMDoge1xuXHRcdFx0XHRcdGRlc2NyaXB0aW9uOiBcIlN1Y2Nlc3MgLSByZXNwb25zZSBmcm9tIGFjdG9yJ3Mgb25GZXRjaCBoYW5kbGVyXCIsXG5cdFx0XHRcdFx0Y29udGVudDoge1xuXHRcdFx0XHRcdFx0XCIqLypcIjoge1xuXHRcdFx0XHRcdFx0XHRzY2hlbWE6IFJhd0h0dHBSZXNwb25zZVNjaGVtYSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fSxcblx0XHRcdFx0NDA0OiB7XG5cdFx0XHRcdFx0ZGVzY3JpcHRpb246IFwiQWN0b3IgZG9lcyBub3QgaGF2ZSBhbiBvbkZldGNoIGhhbmRsZXJcIixcblx0XHRcdFx0fSxcblx0XHRcdFx0NTAwOiB7XG5cdFx0XHRcdFx0ZGVzY3JpcHRpb246IFwiSW50ZXJuYWwgc2VydmVyIGVycm9yIG9yIGludmFsaWQgcmVzcG9uc2UgZnJvbSBhY3RvclwiLFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9O1xuXG5cdFx0Ly8gQ3JlYXRlIHJvdXRlcyBmb3IgZWFjaCBIVFRQIG1ldGhvZFxuXHRcdGNvbnN0IGh0dHBNZXRob2RzID0gW1xuXHRcdFx0XCJnZXRcIixcblx0XHRcdFwicG9zdFwiLFxuXHRcdFx0XCJwdXRcIixcblx0XHRcdFwiZGVsZXRlXCIsXG5cdFx0XHRcInBhdGNoXCIsXG5cdFx0XHRcImhlYWRcIixcblx0XHRcdFwib3B0aW9uc1wiLFxuXHRcdF0gYXMgY29uc3Q7XG5cdFx0Zm9yIChjb25zdCBtZXRob2Qgb2YgaHR0cE1ldGhvZHMpIHtcblx0XHRcdGNvbnN0IHJvdXRlID0gY3JlYXRlUm91dGUoe1xuXHRcdFx0XHRtZXRob2QsXG5cdFx0XHRcdC4uLnJhd0h0dHBSb3V0ZUNvbmZpZyxcblx0XHRcdH0pO1xuXG5cdFx0XHRyb3V0ZXIub3BlbmFwaShyb3V0ZSwgYXN5bmMgKGMpID0+IHtcblx0XHRcdFx0cmV0dXJuIGhhbmRsZVJhd0h0dHBSZXF1ZXN0KFxuXHRcdFx0XHRcdGMsXG5cdFx0XHRcdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0XHRcdFx0cnVuQ29uZmlnLFxuXHRcdFx0XHRcdG1hbmFnZXJEcml2ZXIsXG5cdFx0XHRcdCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHQvLyBSYXcgV2ViU29ja2V0IGVuZHBvaW50IC0gL2FjdG9ycy9yYXcvd2Vic29ja2V0Lypcblx0e1xuXHRcdC8vIEhBQ0s6IFdlYlNvY2tldHMgZG9uJ3Qgd29yayB3aXRoIG1vdW50cywgc28gd2UgbmVlZCB0byBkeW5hbWljYWxseSBtYXRjaCB0aGUgdHJhaWxpbmcgcGF0aFxuXHRcdHJvdXRlci51c2UoXCIqXCIsIGFzeW5jIChjLCBuZXh0KSA9PiB7XG5cdFx0XHRpZiAoYy5yZXEucGF0aC5pbmNsdWRlcyhcIi9yYXcvd2Vic29ja2V0L1wiKSkge1xuXHRcdFx0XHRyZXR1cm4gaGFuZGxlUmF3V2ViU29ja2V0UmVxdWVzdChcblx0XHRcdFx0XHRjLFxuXHRcdFx0XHRcdHJlZ2lzdHJ5Q29uZmlnLFxuXHRcdFx0XHRcdHJ1bkNvbmZpZyxcblx0XHRcdFx0XHRtYW5hZ2VyRHJpdmVyLFxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbmV4dCgpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gVGhpcyByb3V0ZSBpcyBhIG5vb3AsIGp1c3QgdXNlZCB0byBnZW5lcmF0ZSBkb2NzXG5cdFx0Y29uc3QgcmF3V2ViU29ja2V0Um91dGUgPSBjcmVhdGVSb3V0ZSh7XG5cdFx0XHRtZXRob2Q6IFwiZ2V0XCIsXG5cdFx0XHRwYXRoOiBcIi9hY3RvcnMvcmF3L3dlYnNvY2tldC8qXCIsXG5cdFx0XHRyZXF1ZXN0OiB7fSxcblx0XHRcdHJlc3BvbnNlczoge1xuXHRcdFx0XHQxMDE6IHtcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjogXCJXZWJTb2NrZXQgdXBncmFkZSBzdWNjZXNzZnVsXCIsXG5cdFx0XHRcdH0sXG5cdFx0XHRcdDQwMDoge1xuXHRcdFx0XHRcdGRlc2NyaXB0aW9uOiBcIldlYlNvY2tldHMgbm90IGVuYWJsZWQgb3IgaW52YWxpZCByZXF1ZXN0XCIsXG5cdFx0XHRcdH0sXG5cdFx0XHRcdDQwNDoge1xuXHRcdFx0XHRcdGRlc2NyaXB0aW9uOiBcIkFjdG9yIGRvZXMgbm90IGhhdmUgYW4gb25XZWJTb2NrZXQgaGFuZGxlclwiLFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9KTtcblxuXHRcdHJvdXRlci5vcGVuYXBpKHJhd1dlYlNvY2tldFJvdXRlLCAoKSA9PiB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJTaG91bGQgYmUgdW5yZWFjaGFibGVcIik7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAocnVuQ29uZmlnLmluc3BlY3Rvcj8uZW5hYmxlZCkge1xuXHRcdHJvdXRlci5yb3V0ZShcblx0XHRcdFwiL2FjdG9ycy9pbnNwZWN0XCIsXG5cdFx0XHRuZXcgSG9ubygpXG5cdFx0XHRcdC51c2UoXG5cdFx0XHRcdFx0Y29ycyhydW5Db25maWcuaW5zcGVjdG9yLmNvcnMpLFxuXHRcdFx0XHRcdHNlY3VyZUluc3BlY3RvcihydW5Db25maWcpLFxuXHRcdFx0XHRcdHVuaXZlcnNhbEFjdG9yUHJveHkoe1xuXHRcdFx0XHRcdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0XHRcdFx0XHRydW5Db25maWcsXG5cdFx0XHRcdFx0XHRkcml2ZXI6IG1hbmFnZXJEcml2ZXIsXG5cdFx0XHRcdFx0fSksXG5cdFx0XHRcdClcblx0XHRcdFx0LmFsbChcIi9cIiwgKGMpID0+XG5cdFx0XHRcdFx0Ly8gdGhpcyBzaG91bGQgYmUgaGFuZGxlZCBieSB0aGUgYWN0b3IgcHJveHksIGJ1dCBqdXN0IGluIGNhc2Vcblx0XHRcdFx0XHRjLnRleHQoXCJVbnJlYWNoYWJsZS5cIiwgNDA0KSxcblx0XHRcdFx0KSxcblx0XHQpO1xuXHRcdHJvdXRlci5yb3V0ZShcblx0XHRcdFwiL2luc3BlY3RcIixcblx0XHRcdG5ldyBIb25vKClcblx0XHRcdFx0LnVzZShcblx0XHRcdFx0XHRjb3JzKHJ1bkNvbmZpZy5pbnNwZWN0b3IuY29ycyksXG5cdFx0XHRcdFx0c2VjdXJlSW5zcGVjdG9yKHJ1bkNvbmZpZyksXG5cdFx0XHRcdFx0YXN5bmMgKGMsIG5leHQpID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IGluc3BlY3RvciA9IG1hbmFnZXJEcml2ZXIuaW5zcGVjdG9yO1xuXHRcdFx0XHRcdFx0aW52YXJpYW50KGluc3BlY3RvciwgXCJpbnNwZWN0b3Igbm90IHN1cHBvcnRlZCBvbiB0aGlzIHBsYXRmb3JtXCIpO1xuXG5cdFx0XHRcdFx0XHRjLnNldChcImluc3BlY3RvclwiLCBpbnNwZWN0b3IpO1xuXHRcdFx0XHRcdFx0YXdhaXQgbmV4dCgpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdClcblx0XHRcdFx0LnJvdXRlKFwiL1wiLCBjcmVhdGVNYW5hZ2VySW5zcGVjdG9yUm91dGVyKCkpLFxuXHRcdCk7XG5cdH1cblxuXHRpZiAocmVnaXN0cnlDb25maWcudGVzdC5lbmFibGVkKSB7XG5cdFx0Ly8gQWRkIEhUVFAgZW5kcG9pbnQgdG8gdGVzdCB0aGUgaW5saW5lIGNsaWVudFxuXHRcdC8vXG5cdFx0Ly8gV2UgaGF2ZSB0byBkbyB0aGlzIGluIGEgcm91dGVyIHNpbmNlIHRoaXMgbmVlZHMgdG8gcnVuIGluIHRoZSBzYW1lIHNlcnZlciBhcyB0aGUgUml2ZXRLaXQgcmVnaXN0cnkuIFNvbWUgdGVzdCBjb250ZXh0cyB0byBub3QgcnVuIGluIHRoZSBzYW1lIHNlcnZlci5cblx0XHRyb3V0ZXIucG9zdChcIi50ZXN0L2lubGluZS1kcml2ZXIvY2FsbFwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0Ly8gVE9ETzogdXNlIG9wZW5hcGkgaW5zdGVhZFxuXHRcdFx0Y29uc3QgYnVmZmVyID0gYXdhaXQgYy5yZXEuYXJyYXlCdWZmZXIoKTtcblx0XHRcdGNvbnN0IHsgZW5jb2RpbmcsIHRyYW5zcG9ydCwgbWV0aG9kLCBhcmdzIH06IFRlc3RJbmxpbmVEcml2ZXJDYWxsUmVxdWVzdCA9XG5cdFx0XHRcdGNib3IuZGVjb2RlKG5ldyBVaW50OEFycmF5KGJ1ZmZlcikpO1xuXG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJlY2VpdmVkIGlubGluZSByZXF1ZXN0XCIsIHtcblx0XHRcdFx0ZW5jb2RpbmcsXG5cdFx0XHRcdHRyYW5zcG9ydCxcblx0XHRcdFx0bWV0aG9kLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIEZvcndhcmQgaW5saW5lIGRyaXZlciByZXF1ZXN0XG5cdFx0XHRsZXQgcmVzcG9uc2U6IFRlc3RJbmxpbmVEcml2ZXJDYWxsUmVzcG9uc2U8dW5rbm93bj47XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCBvdXRwdXQgPSBhd2FpdCAoKGlubGluZUNsaWVudERyaXZlciBhcyBhbnkpW21ldGhvZF0gYXMgYW55KShcblx0XHRcdFx0XHQuLi5hcmdzLFxuXHRcdFx0XHQpO1xuXHRcdFx0XHRyZXNwb25zZSA9IHsgb2s6IG91dHB1dCB9O1xuXHRcdFx0fSBjYXRjaCAocmF3RXJyKSB7XG5cdFx0XHRcdGNvbnN0IGVyciA9IGRlY29uc3RydWN0RXJyb3IocmF3RXJyLCBsb2dnZXIoKSwge30sIHRydWUpO1xuXHRcdFx0XHRyZXNwb25zZSA9IHsgZXJyIH07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBjLmJvZHkoY2Jvci5lbmNvZGUocmVzcG9uc2UpKTtcblx0XHR9KTtcblxuXHRcdHJvdXRlci5nZXQoXCIudGVzdC9pbmxpbmUtZHJpdmVyL2Nvbm5lY3Qtd2Vic29ja2V0XCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjb25zdCB1cGdyYWRlV2ViU29ja2V0ID0gcnVuQ29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQ/LigpO1xuXHRcdFx0aW52YXJpYW50KHVwZ3JhZGVXZWJTb2NrZXQsIFwid2Vic29ja2V0cyBub3Qgc3VwcG9ydGVkIG9uIHRoaXMgcGxhdGZvcm1cIik7XG5cblx0XHRcdHJldHVybiB1cGdyYWRlV2ViU29ja2V0KGFzeW5jIChjOiBhbnkpID0+IHtcblx0XHRcdFx0Y29uc3Qge1xuXHRcdFx0XHRcdGFjdG9yUXVlcnk6IGFjdG9yUXVlcnlSYXcsXG5cdFx0XHRcdFx0cGFyYW1zOiBwYXJhbXNSYXcsXG5cdFx0XHRcdFx0ZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHR9ID0gYy5yZXEucXVlcnkoKSBhcyB7XG5cdFx0XHRcdFx0YWN0b3JRdWVyeTogc3RyaW5nO1xuXHRcdFx0XHRcdHBhcmFtcz86IHN0cmluZztcblx0XHRcdFx0XHRlbmNvZGluZ0tpbmQ6IEVuY29kaW5nO1xuXHRcdFx0XHR9O1xuXHRcdFx0XHRjb25zdCBhY3RvclF1ZXJ5ID0gSlNPTi5wYXJzZShhY3RvclF1ZXJ5UmF3KTtcblx0XHRcdFx0Y29uc3QgcGFyYW1zID1cblx0XHRcdFx0XHRwYXJhbXNSYXcgIT09IHVuZGVmaW5lZCA/IEpTT04ucGFyc2UocGFyYW1zUmF3KSA6IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJlY2VpdmVkIHRlc3QgaW5saW5lIGRyaXZlciB3ZWJzb2NrZXRcIiwge1xuXHRcdFx0XHRcdGFjdG9yUXVlcnksXG5cdFx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0XHRcdGVuY29kaW5nS2luZCxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gQ29ubmVjdCB0byB0aGUgYWN0b3IgdXNpbmcgdGhlIGlubGluZSBjbGllbnQgZHJpdmVyIC0gdGhpcyByZXR1cm5zIGEgUHJvbWlzZTxXZWJTb2NrZXQ+XG5cdFx0XHRcdGNvbnN0IGNsaWVudFdzUHJvbWlzZSA9IGlubGluZUNsaWVudERyaXZlci5jb25uZWN0V2ViU29ja2V0KFxuXHRcdFx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdFx0XHRhY3RvclF1ZXJ5LFxuXHRcdFx0XHRcdGVuY29kaW5nS2luZCxcblx0XHRcdFx0XHRwYXJhbXMsXG5cdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdHJldHVybiBhd2FpdCBjcmVhdGVUZXN0V2ViU29ja2V0UHJveHkoY2xpZW50V3NQcm9taXNlLCBcInN0YW5kYXJkXCIpO1xuXHRcdFx0fSkoYywgbm9vcE5leHQoKSk7XG5cdFx0fSk7XG5cblx0XHRyb3V0ZXIuZ2V0KFwiLnRlc3QvaW5saW5lLWRyaXZlci9yYXctd2Vic29ja2V0XCIsIGFzeW5jIChjKSA9PiB7XG5cdFx0XHRjb25zdCB1cGdyYWRlV2ViU29ja2V0ID0gcnVuQ29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQ/LigpO1xuXHRcdFx0aW52YXJpYW50KHVwZ3JhZGVXZWJTb2NrZXQsIFwid2Vic29ja2V0cyBub3Qgc3VwcG9ydGVkIG9uIHRoaXMgcGxhdGZvcm1cIik7XG5cblx0XHRcdHJldHVybiB1cGdyYWRlV2ViU29ja2V0KGFzeW5jIChjOiBhbnkpID0+IHtcblx0XHRcdFx0Y29uc3Qge1xuXHRcdFx0XHRcdGFjdG9yUXVlcnk6IGFjdG9yUXVlcnlSYXcsXG5cdFx0XHRcdFx0cGFyYW1zOiBwYXJhbXNSYXcsXG5cdFx0XHRcdFx0ZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHRcdHBhdGgsXG5cdFx0XHRcdFx0cHJvdG9jb2xzOiBwcm90b2NvbHNSYXcsXG5cdFx0XHRcdH0gPSBjLnJlcS5xdWVyeSgpIGFzIHtcblx0XHRcdFx0XHRhY3RvclF1ZXJ5OiBzdHJpbmc7XG5cdFx0XHRcdFx0cGFyYW1zPzogc3RyaW5nO1xuXHRcdFx0XHRcdGVuY29kaW5nS2luZDogRW5jb2Rpbmc7XG5cdFx0XHRcdFx0cGF0aDogc3RyaW5nO1xuXHRcdFx0XHRcdHByb3RvY29scz86IHN0cmluZztcblx0XHRcdFx0fTtcblx0XHRcdFx0Y29uc3QgYWN0b3JRdWVyeSA9IEpTT04ucGFyc2UoYWN0b3JRdWVyeVJhdyk7XG5cdFx0XHRcdGNvbnN0IHBhcmFtcyA9XG5cdFx0XHRcdFx0cGFyYW1zUmF3ICE9PSB1bmRlZmluZWQgPyBKU09OLnBhcnNlKHBhcmFtc1JhdykgOiB1bmRlZmluZWQ7XG5cdFx0XHRcdGNvbnN0IHByb3RvY29scyA9XG5cdFx0XHRcdFx0cHJvdG9jb2xzUmF3ICE9PSB1bmRlZmluZWQgPyBKU09OLnBhcnNlKHByb3RvY29sc1JhdykgOiB1bmRlZmluZWQ7XG5cblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJyZWNlaXZlZCB0ZXN0IGlubGluZSBkcml2ZXIgcmF3IHdlYnNvY2tldFwiLCB7XG5cdFx0XHRcdFx0YWN0b3JRdWVyeSxcblx0XHRcdFx0XHRwYXJhbXMsXG5cdFx0XHRcdFx0ZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHRcdHBhdGgsXG5cdFx0XHRcdFx0cHJvdG9jb2xzLFxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQvLyBDb25uZWN0IHRvIHRoZSBhY3RvciB1c2luZyB0aGUgaW5saW5lIGNsaWVudCBkcml2ZXIgLSB0aGlzIHJldHVybnMgYSBQcm9taXNlPFdlYlNvY2tldD5cblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjYWxsaW5nIGlubGluZUNsaWVudERyaXZlci5yYXdXZWJTb2NrZXRcIik7XG5cdFx0XHRcdGNvbnN0IGNsaWVudFdzUHJvbWlzZSA9IGlubGluZUNsaWVudERyaXZlci5yYXdXZWJTb2NrZXQoXG5cdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHRcdGFjdG9yUXVlcnksXG5cdFx0XHRcdFx0ZW5jb2RpbmdLaW5kLFxuXHRcdFx0XHRcdHBhcmFtcyxcblx0XHRcdFx0XHRwYXRoLFxuXHRcdFx0XHRcdHByb3RvY29scyxcblx0XHRcdFx0XHR1bmRlZmluZWQsXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJjYWxsaW5nIGNyZWF0ZVRlc3RXZWJTb2NrZXRQcm94eVwiKTtcblx0XHRcdFx0cmV0dXJuIGF3YWl0IGNyZWF0ZVRlc3RXZWJTb2NrZXRQcm94eShjbGllbnRXc1Byb21pc2UsIFwicmF3XCIpO1xuXHRcdFx0fSkoYywgbm9vcE5leHQoKSk7XG5cdFx0fSk7XG5cblx0XHQvLyBSYXcgSFRUUCBlbmRwb2ludCBmb3IgdGVzdCBpbmxpbmUgZHJpdmVyXG5cdFx0cm91dGVyLmFsbChcIi50ZXN0L2lubGluZS1kcml2ZXIvcmF3LWh0dHAvKlwiLCBhc3luYyAoYykgPT4ge1xuXHRcdFx0Ly8gRXh0cmFjdCBwYXJhbWV0ZXJzIGZyb20gaGVhZGVyc1xuXHRcdFx0Y29uc3QgYWN0b3JRdWVyeUhlYWRlciA9IGMucmVxLmhlYWRlcihIRUFERVJfQUNUT1JfUVVFUlkpO1xuXHRcdFx0Y29uc3QgcGFyYW1zSGVhZGVyID0gYy5yZXEuaGVhZGVyKEhFQURFUl9DT05OX1BBUkFNUyk7XG5cdFx0XHRjb25zdCBlbmNvZGluZ0hlYWRlciA9IGMucmVxLmhlYWRlcihIRUFERVJfRU5DT0RJTkcpO1xuXG5cdFx0XHRpZiAoIWFjdG9yUXVlcnlIZWFkZXIgfHwgIWVuY29kaW5nSGVhZGVyKSB7XG5cdFx0XHRcdHJldHVybiBjLnRleHQoXCJNaXNzaW5nIHJlcXVpcmVkIGhlYWRlcnNcIiwgNDAwKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgYWN0b3JRdWVyeSA9IEpTT04ucGFyc2UoYWN0b3JRdWVyeUhlYWRlcik7XG5cdFx0XHRjb25zdCBwYXJhbXMgPSBwYXJhbXNIZWFkZXIgPyBKU09OLnBhcnNlKHBhcmFtc0hlYWRlcikgOiB1bmRlZmluZWQ7XG5cdFx0XHRjb25zdCBlbmNvZGluZyA9IGVuY29kaW5nSGVhZGVyIGFzIEVuY29kaW5nO1xuXG5cdFx0XHQvLyBFeHRyYWN0IHRoZSBwYXRoIGFmdGVyIC9yYXctaHR0cC9cblx0XHRcdGNvbnN0IGZ1bGxQYXRoID0gYy5yZXEucGF0aDtcblx0XHRcdGNvbnN0IHBhdGhPbmx5ID1cblx0XHRcdFx0ZnVsbFBhdGguc3BsaXQoXCIvLnRlc3QvaW5saW5lLWRyaXZlci9yYXctaHR0cC9cIilbMV0gfHwgXCJcIjtcblxuXHRcdFx0Ly8gSW5jbHVkZSBxdWVyeSBzdHJpbmdcblx0XHRcdGNvbnN0IHVybCA9IG5ldyBVUkwoYy5yZXEudXJsKTtcblx0XHRcdGNvbnN0IHBhdGhXaXRoUXVlcnkgPSBwYXRoT25seSArIHVybC5zZWFyY2g7XG5cblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicmVjZWl2ZWQgdGVzdCBpbmxpbmUgZHJpdmVyIHJhdyBodHRwXCIsIHtcblx0XHRcdFx0YWN0b3JRdWVyeSxcblx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0XHRlbmNvZGluZyxcblx0XHRcdFx0cGF0aDogcGF0aFdpdGhRdWVyeSxcblx0XHRcdFx0bWV0aG9kOiBjLnJlcS5tZXRob2QsXG5cdFx0XHR9KTtcblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Ly8gRm9yd2FyZCB0aGUgcmVxdWVzdCB1c2luZyB0aGUgaW5saW5lIGNsaWVudCBkcml2ZXJcblx0XHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCBpbmxpbmVDbGllbnREcml2ZXIucmF3SHR0cFJlcXVlc3QoXG5cdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHRcdGFjdG9yUXVlcnksXG5cdFx0XHRcdFx0ZW5jb2RpbmcsXG5cdFx0XHRcdFx0cGFyYW1zLFxuXHRcdFx0XHRcdHBhdGhXaXRoUXVlcnksXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0bWV0aG9kOiBjLnJlcS5tZXRob2QsXG5cdFx0XHRcdFx0XHRoZWFkZXJzOiBjLnJlcS5yYXcuaGVhZGVycyxcblx0XHRcdFx0XHRcdGJvZHk6IGMucmVxLnJhdy5ib2R5LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0dW5kZWZpbmVkLFxuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdC8vIFJldHVybiB0aGUgcmVzcG9uc2UgZGlyZWN0bHlcblx0XHRcdFx0cmV0dXJuIHJlc3BvbnNlO1xuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiB0ZXN0IGlubGluZSByYXcgaHR0cFwiLCB7XG5cdFx0XHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gUmV0dXJuIGVycm9yIHJlc3BvbnNlXG5cdFx0XHRcdGNvbnN0IGVyciA9IGRlY29uc3RydWN0RXJyb3IoZXJyb3IsIGxvZ2dlcigpLCB7fSwgdHJ1ZSk7XG5cdFx0XHRcdHJldHVybiBjLmpzb24oXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0ZXJyb3I6IHtcblx0XHRcdFx0XHRcdFx0Y29kZTogZXJyLmNvZGUsXG5cdFx0XHRcdFx0XHRcdG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuXHRcdFx0XHRcdFx0XHRtZXRhZGF0YTogZXJyLm1ldGFkYXRhLFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGVyci5zdGF0dXNDb2RlLFxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0bWFuYWdlckRyaXZlci5tb2RpZnlNYW5hZ2VyUm91dGVyPy4oXG5cdFx0cmVnaXN0cnlDb25maWcsXG5cdFx0cm91dGVyIGFzIHVua25vd24gYXMgSG9ubyxcblx0KTtcblxuXHQvLyBNb3VudCBvbiBib3RoIC8gYW5kIC9yZWdpc3RyeVxuXHQvL1xuXHQvLyBXZSBkbyB0aGlzIGJlY2F1c2UgdGhlIGRlZmF1bHQgcmVxdWVzdHMgYXJlIHRvIGAvcmVnaXN0cnkvKmAuXG5cdC8vXG5cdC8vIElmIHVzaW5nIGBhcHAuZmV0Y2hgIGRpcmVjdGx5IGluIGEgbm9uLWhvbm8gcm91dGVyLCBwYXRoc1xuXHQvLyBtaWdodCBub3QgYmUgdHJ1bmNhdGVkIHNvIHRoZXknbGwgY29tZSB0byB0aGlzIHJvdXRlciBhc1xuXHQvLyBgL3JlZ2lzdHJ5LypgLiBJZiBtb3VudGVkIGNvcnJlY3RseSBpbiBIb25vLCByZXF1ZXN0cyB3aWxsXG5cdC8vIGNvbWUgaW4gYXQgdGhlIHJvb3QgYXMgYC8qYC5cblx0Y29uc3QgbW91bnRlZFJvdXRlciA9IG5ldyBIb25vKCk7XG5cdG1vdW50ZWRSb3V0ZXIucm91dGUoXCIvXCIsIHJvdXRlcik7XG5cdG1vdW50ZWRSb3V0ZXIucm91dGUoXCIvcmVnaXN0cnlcIiwgcm91dGVyKTtcblxuXHQvLyBJTVBPUlRBTlQ6IFRoZXNlIG11c3QgYmUgb24gYG1vdW50ZWRSb3V0ZXJgIGluc3RlYWQgb2YgYHJvdXRlcmAgb3IgZWxzZSB0aGV5IHdpbGwgbm90IGJlIGNhbGxlZC5cblx0bW91bnRlZFJvdXRlci5ub3RGb3VuZChoYW5kbGVSb3V0ZU5vdEZvdW5kKTtcblx0bW91bnRlZFJvdXRlci5vbkVycm9yKGhhbmRsZVJvdXRlRXJyb3IuYmluZCh1bmRlZmluZWQsIHt9KSk7XG5cblx0cmV0dXJuIHsgcm91dGVyOiBtb3VudGVkUm91dGVyLCBvcGVuYXBpOiByb3V0ZXIgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZXN0SW5saW5lRHJpdmVyQ2FsbFJlcXVlc3Qge1xuXHRlbmNvZGluZzogRW5jb2Rpbmc7XG5cdHRyYW5zcG9ydDogVHJhbnNwb3J0O1xuXHRtZXRob2Q6IHN0cmluZztcblx0YXJnczogdW5rbm93bltdO1xufVxuXG5leHBvcnQgdHlwZSBUZXN0SW5saW5lRHJpdmVyQ2FsbFJlc3BvbnNlPFQ+ID1cblx0fCB7XG5cdFx0XHRvazogVDtcblx0ICB9XG5cdHwge1xuXHRcdFx0ZXJyOiBEZWNvbnN0cnVjdGVkRXJyb3I7XG5cdCAgfTtcblxuLyoqXG4gKiBRdWVyeSB0aGUgbWFuYWdlciBkcml2ZXIgdG8gZ2V0IG9yIGNyZWF0ZSBhIGFjdG9yIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBxdWVyeVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcXVlcnlBY3Rvcihcblx0YzogSG9ub0NvbnRleHQsXG5cdHF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRkcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG4pOiBQcm9taXNlPHsgYWN0b3JJZDogc3RyaW5nIH0+IHtcblx0bG9nZ2VyKCkuZGVidWcoXCJxdWVyeWluZyBhY3RvclwiLCB7IHF1ZXJ5IH0pO1xuXHRsZXQgYWN0b3JPdXRwdXQ6IHsgYWN0b3JJZDogc3RyaW5nIH07XG5cdGlmIChcImdldEZvcklkXCIgaW4gcXVlcnkpIHtcblx0XHRjb25zdCBvdXRwdXQgPSBhd2FpdCBkcml2ZXIuZ2V0Rm9ySWQoe1xuXHRcdFx0Yyxcblx0XHRcdG5hbWU6IHF1ZXJ5LmdldEZvcklkLm5hbWUsXG5cdFx0XHRhY3RvcklkOiBxdWVyeS5nZXRGb3JJZC5hY3RvcklkLFxuXHRcdH0pO1xuXHRcdGlmICghb3V0cHV0KSB0aHJvdyBuZXcgZXJyb3JzLkFjdG9yTm90Rm91bmQocXVlcnkuZ2V0Rm9ySWQuYWN0b3JJZCk7XG5cdFx0YWN0b3JPdXRwdXQgPSBvdXRwdXQ7XG5cdH0gZWxzZSBpZiAoXCJnZXRGb3JLZXlcIiBpbiBxdWVyeSkge1xuXHRcdGNvbnN0IGV4aXN0aW5nQWN0b3IgPSBhd2FpdCBkcml2ZXIuZ2V0V2l0aEtleSh7XG5cdFx0XHRjLFxuXHRcdFx0bmFtZTogcXVlcnkuZ2V0Rm9yS2V5Lm5hbWUsXG5cdFx0XHRrZXk6IHF1ZXJ5LmdldEZvcktleS5rZXksXG5cdFx0fSk7XG5cdFx0aWYgKCFleGlzdGluZ0FjdG9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkFjdG9yTm90Rm91bmQoXG5cdFx0XHRcdGAke3F1ZXJ5LmdldEZvcktleS5uYW1lfToke0pTT04uc3RyaW5naWZ5KHF1ZXJ5LmdldEZvcktleS5rZXkpfWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRhY3Rvck91dHB1dCA9IGV4aXN0aW5nQWN0b3I7XG5cdH0gZWxzZSBpZiAoXCJnZXRPckNyZWF0ZUZvcktleVwiIGluIHF1ZXJ5KSB7XG5cdFx0Y29uc3QgZ2V0T3JDcmVhdGVPdXRwdXQgPSBhd2FpdCBkcml2ZXIuZ2V0T3JDcmVhdGVXaXRoS2V5KHtcblx0XHRcdGMsXG5cdFx0XHRuYW1lOiBxdWVyeS5nZXRPckNyZWF0ZUZvcktleS5uYW1lLFxuXHRcdFx0a2V5OiBxdWVyeS5nZXRPckNyZWF0ZUZvcktleS5rZXksXG5cdFx0XHRpbnB1dDogcXVlcnkuZ2V0T3JDcmVhdGVGb3JLZXkuaW5wdXQsXG5cdFx0XHRyZWdpb246IHF1ZXJ5LmdldE9yQ3JlYXRlRm9yS2V5LnJlZ2lvbixcblx0XHR9KTtcblx0XHRhY3Rvck91dHB1dCA9IHtcblx0XHRcdGFjdG9ySWQ6IGdldE9yQ3JlYXRlT3V0cHV0LmFjdG9ySWQsXG5cdFx0fTtcblx0fSBlbHNlIGlmIChcImNyZWF0ZVwiIGluIHF1ZXJ5KSB7XG5cdFx0Y29uc3QgY3JlYXRlT3V0cHV0ID0gYXdhaXQgZHJpdmVyLmNyZWF0ZUFjdG9yKHtcblx0XHRcdGMsXG5cdFx0XHRuYW1lOiBxdWVyeS5jcmVhdGUubmFtZSxcblx0XHRcdGtleTogcXVlcnkuY3JlYXRlLmtleSxcblx0XHRcdGlucHV0OiBxdWVyeS5jcmVhdGUuaW5wdXQsXG5cdFx0XHRyZWdpb246IHF1ZXJ5LmNyZWF0ZS5yZWdpb24sXG5cdFx0fSk7XG5cdFx0YWN0b3JPdXRwdXQgPSB7XG5cdFx0XHRhY3RvcklkOiBjcmVhdGVPdXRwdXQuYWN0b3JJZCxcblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFJlcXVlc3QoXCJJbnZhbGlkIHF1ZXJ5IGZvcm1hdFwiKTtcblx0fVxuXG5cdGxvZ2dlcigpLmRlYnVnKFwiYWN0b3IgcXVlcnkgcmVzdWx0XCIsIHtcblx0XHRhY3RvcklkOiBhY3Rvck91dHB1dC5hY3RvcklkLFxuXHR9KTtcblx0cmV0dXJuIHsgYWN0b3JJZDogYWN0b3JPdXRwdXQuYWN0b3JJZCB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBXZWJTb2NrZXQgcHJveHkgZm9yIHRlc3QgZW5kcG9pbnRzIHRoYXQgZm9yd2FyZHMgbWVzc2FnZXMgYmV0d2VlbiBzZXJ2ZXIgYW5kIGNsaWVudCBXZWJTb2NrZXRzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVRlc3RXZWJTb2NrZXRQcm94eShcblx0Y2xpZW50V3NQcm9taXNlOiBQcm9taXNlPFdlYlNvY2tldD4sXG5cdGNvbm5lY3Rpb25UeXBlOiBzdHJpbmcsXG4pOiBQcm9taXNlPFVwZ3JhZGVXZWJTb2NrZXRBcmdzPiB7XG5cdC8vIFN0b3JlIGEgcmVmZXJlbmNlIHRvIHRoZSByZXNvbHZlZCBXZWJTb2NrZXRcblx0bGV0IGNsaWVudFdzOiBXZWJTb2NrZXQgfCBudWxsID0gbnVsbDtcblx0dHJ5IHtcblx0XHQvLyBSZXNvbHZlIHRoZSBjbGllbnQgV2ViU29ja2V0IHByb21pc2Vcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImF3YWl0aW5nIGNsaWVudCB3ZWJzb2NrZXQgcHJvbWlzZVwiKTtcblx0XHRjb25zdCB3cyA9IGF3YWl0IGNsaWVudFdzUHJvbWlzZTtcblx0XHRjbGllbnRXcyA9IHdzO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiY2xpZW50IHdlYnNvY2tldCBwcm9taXNlIHJlc29sdmVkXCIsIHtcblx0XHRcdGNvbnN0cnVjdG9yOiB3cz8uY29uc3RydWN0b3IubmFtZSxcblx0XHR9KTtcblxuXHRcdC8vIFdhaXQgZm9yIHdzIHRvIG9wZW5cblx0XHRhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHRjb25zdCBvbk9wZW4gPSAoKSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFwidGVzdCB3ZWJzb2NrZXQgY29ubmVjdGlvbiBvcGVuZWRcIik7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdH07XG5cdFx0XHRjb25zdCBvbkVycm9yID0gKGVycm9yOiBhbnkpID0+IHtcblx0XHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJ0ZXN0IHdlYnNvY2tldCBjb25uZWN0aW9uIGZhaWxlZFwiLCB7IGVycm9yIH0pO1xuXHRcdFx0XHRyZWplY3QoXG5cdFx0XHRcdFx0bmV3IEVycm9yKGBGYWlsZWQgdG8gb3BlbiBXZWJTb2NrZXQ6ICR7ZXJyb3IubWVzc2FnZSB8fCBlcnJvcn1gKSxcblx0XHRcdFx0KTtcblx0XHRcdH07XG5cdFx0XHR3cy5hZGRFdmVudExpc3RlbmVyKFwib3BlblwiLCBvbk9wZW4pO1xuXHRcdFx0d3MuYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIG9uRXJyb3IpO1xuXHRcdH0pO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGxvZ2dlcigpLmVycm9yKFxuXHRcdFx0YGZhaWxlZCB0byBlc3RhYmxpc2ggY2xpZW50ICR7Y29ubmVjdGlvblR5cGV9IHdlYnNvY2tldCBjb25uZWN0aW9uYCxcblx0XHRcdHsgZXJyb3IgfSxcblx0XHQpO1xuXHRcdHJldHVybiB7XG5cdFx0XHRvbk9wZW46IChfZXZ0LCBzZXJ2ZXJXcykgPT4ge1xuXHRcdFx0XHRzZXJ2ZXJXcy5jbG9zZSgxMDExLCBcIkZhaWxlZCB0byBlc3RhYmxpc2ggY29ubmVjdGlvblwiKTtcblx0XHRcdH0sXG5cdFx0XHRvbk1lc3NhZ2U6ICgpID0+IHt9LFxuXHRcdFx0b25FcnJvcjogKCkgPT4ge30sXG5cdFx0XHRvbkNsb3NlOiAoKSA9PiB7fSxcblx0XHR9O1xuXHR9XG5cblx0Ly8gQ3JlYXRlIFdlYlNvY2tldCBwcm94eSBoYW5kbGVycyB0byByZWxheSBtZXNzYWdlcyBiZXR3ZWVuIGNsaWVudCBhbmQgc2VydmVyXG5cdHJldHVybiB7XG5cdFx0b25PcGVuOiAoX2V2dDogYW55LCBzZXJ2ZXJXczogV1NDb250ZXh0KSA9PiB7XG5cdFx0XHRsb2dnZXIoKS5kZWJ1ZyhgdGVzdCAke2Nvbm5lY3Rpb25UeXBlfSB3ZWJzb2NrZXQgY29ubmVjdGlvbiBvcGVuZWRgKTtcblxuXHRcdFx0Ly8gQ2hlY2sgV2ViU29ja2V0IHR5cGVcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwiY2xpZW50V3MgaW5mb1wiLCB7XG5cdFx0XHRcdGNvbnN0cnVjdG9yOiBjbGllbnRXcy5jb25zdHJ1Y3Rvci5uYW1lLFxuXHRcdFx0XHRoYXNBZGRFdmVudExpc3RlbmVyOiB0eXBlb2YgY2xpZW50V3MuYWRkRXZlbnRMaXN0ZW5lciA9PT0gXCJmdW5jdGlvblwiLFxuXHRcdFx0XHRyZWFkeVN0YXRlOiBjbGllbnRXcy5yZWFkeVN0YXRlLFxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIEFkZCBtZXNzYWdlIGhhbmRsZXIgdG8gZm9yd2FyZCBtZXNzYWdlcyBmcm9tIGNsaWVudCB0byBzZXJ2ZXJcblx0XHRcdGNsaWVudFdzLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChjbGllbnRFdnQ6IE1lc3NhZ2VFdmVudCkgPT4ge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1Zyhcblx0XHRcdFx0XHRgdGVzdCAke2Nvbm5lY3Rpb25UeXBlfSB3ZWJzb2NrZXQgY29ubmVjdGlvbiBtZXNzYWdlIGZyb20gY2xpZW50YCxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRkYXRhVHlwZTogdHlwZW9mIGNsaWVudEV2dC5kYXRhLFxuXHRcdFx0XHRcdFx0aXNCbG9iOiBjbGllbnRFdnQuZGF0YSBpbnN0YW5jZW9mIEJsb2IsXG5cdFx0XHRcdFx0XHRpc0FycmF5QnVmZmVyOiBjbGllbnRFdnQuZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyLFxuXHRcdFx0XHRcdFx0ZGF0YUNvbnN0cnVjdG9yOiBjbGllbnRFdnQuZGF0YT8uY29uc3RydWN0b3I/Lm5hbWUsXG5cdFx0XHRcdFx0XHRkYXRhU3RyOlxuXHRcdFx0XHRcdFx0XHR0eXBlb2YgY2xpZW50RXZ0LmRhdGEgPT09IFwic3RyaW5nXCJcblx0XHRcdFx0XHRcdFx0XHQ/IGNsaWVudEV2dC5kYXRhLnN1YnN0cmluZygwLCAxMDApXG5cdFx0XHRcdFx0XHRcdFx0OiB1bmRlZmluZWQsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0KTtcblxuXHRcdFx0XHRpZiAoc2VydmVyV3MucmVhZHlTdGF0ZSA9PT0gMSkge1xuXHRcdFx0XHRcdC8vIE9QRU5cblx0XHRcdFx0XHQvLyBIYW5kbGUgQmxvYiBkYXRhXG5cdFx0XHRcdFx0aWYgKGNsaWVudEV2dC5kYXRhIGluc3RhbmNlb2YgQmxvYikge1xuXHRcdFx0XHRcdFx0Y2xpZW50RXZ0LmRhdGFcblx0XHRcdFx0XHRcdFx0LmFycmF5QnVmZmVyKClcblx0XHRcdFx0XHRcdFx0LnRoZW4oKGJ1ZmZlcikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdGxvZ2dlcigpLmRlYnVnKFxuXHRcdFx0XHRcdFx0XHRcdFx0XCJjb252ZXJ0ZWQgY2xpZW50IGJsb2IgdG8gYXJyYXlidWZmZXIsIHNlbmRpbmcgdG8gc2VydmVyXCIsXG5cdFx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGJ1ZmZlclNpemU6IGJ1ZmZlci5ieXRlTGVuZ3RoLFxuXHRcdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRcdHNlcnZlcldzLnNlbmQoYnVmZmVyIGFzIGFueSk7XG5cdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0XHRcdC5jYXRjaCgoZXJyb3IpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBjb252ZXJ0IGJsb2IgdG8gYXJyYXlidWZmZXJcIiwge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3IsXG5cdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcInNlbmRpbmcgY2xpZW50IGRhdGEgZGlyZWN0bHkgdG8gc2VydmVyXCIsIHtcblx0XHRcdFx0XHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBjbGllbnRFdnQuZGF0YSxcblx0XHRcdFx0XHRcdFx0ZGF0YUxlbmd0aDpcblx0XHRcdFx0XHRcdFx0XHR0eXBlb2YgY2xpZW50RXZ0LmRhdGEgPT09IFwic3RyaW5nXCJcblx0XHRcdFx0XHRcdFx0XHRcdD8gY2xpZW50RXZ0LmRhdGEubGVuZ3RoXG5cdFx0XHRcdFx0XHRcdFx0XHQ6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0c2VydmVyV3Muc2VuZChjbGllbnRFdnQuZGF0YSBhcyBhbnkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIEFkZCBjbG9zZSBoYW5kbGVyIHRvIGNsb3NlIHNlcnZlciB3aGVuIGNsaWVudCBjbG9zZXNcblx0XHRcdGNsaWVudFdzLmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCAoY2xpZW50RXZ0OiBDbG9zZUV2ZW50KSA9PiB7XG5cdFx0XHRcdGxvZ2dlcigpLmRlYnVnKGB0ZXN0ICR7Y29ubmVjdGlvblR5cGV9IHdlYnNvY2tldCBjb25uZWN0aW9uIGNsb3NlZGApO1xuXG5cdFx0XHRcdGlmIChzZXJ2ZXJXcy5yZWFkeVN0YXRlICE9PSAzKSB7XG5cdFx0XHRcdFx0Ly8gTm90IENMT1NFRFxuXHRcdFx0XHRcdHNlcnZlcldzLmNsb3NlKGNsaWVudEV2dC5jb2RlLCBjbGllbnRFdnQucmVhc29uKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIEFkZCBlcnJvciBoYW5kbGVyXG5cdFx0XHRjbGllbnRXcy5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgKCkgPT4ge1xuXHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhgdGVzdCAke2Nvbm5lY3Rpb25UeXBlfSB3ZWJzb2NrZXQgY29ubmVjdGlvbiBlcnJvcmApO1xuXG5cdFx0XHRcdGlmIChzZXJ2ZXJXcy5yZWFkeVN0YXRlICE9PSAzKSB7XG5cdFx0XHRcdFx0Ly8gTm90IENMT1NFRFxuXHRcdFx0XHRcdHNlcnZlcldzLmNsb3NlKDEwMTEsIFwiRXJyb3IgaW4gY2xpZW50IHdlYnNvY2tldFwiKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSxcblx0XHRvbk1lc3NhZ2U6IChldnQ6IHsgZGF0YTogYW55IH0pID0+IHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKFwicmVjZWl2ZWQgbWVzc2FnZSBmcm9tIHNlcnZlclwiLCB7XG5cdFx0XHRcdGRhdGFUeXBlOiB0eXBlb2YgZXZ0LmRhdGEsXG5cdFx0XHRcdGlzQmxvYjogZXZ0LmRhdGEgaW5zdGFuY2VvZiBCbG9iLFxuXHRcdFx0XHRpc0FycmF5QnVmZmVyOiBldnQuZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyLFxuXHRcdFx0XHRkYXRhQ29uc3RydWN0b3I6IGV2dC5kYXRhPy5jb25zdHJ1Y3Rvcj8ubmFtZSxcblx0XHRcdFx0ZGF0YVN0cjpcblx0XHRcdFx0XHR0eXBlb2YgZXZ0LmRhdGEgPT09IFwic3RyaW5nXCIgPyBldnQuZGF0YS5zdWJzdHJpbmcoMCwgMTAwKSA6IHVuZGVmaW5lZCxcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBGb3J3YXJkIG1lc3NhZ2VzIGZyb20gc2VydmVyIHdlYnNvY2tldCB0byBjbGllbnQgd2Vic29ja2V0XG5cdFx0XHRpZiAoY2xpZW50V3MucmVhZHlTdGF0ZSA9PT0gMSkge1xuXHRcdFx0XHQvLyBPUEVOXG5cdFx0XHRcdC8vIEhhbmRsZSBCbG9iIGRhdGFcblx0XHRcdFx0aWYgKGV2dC5kYXRhIGluc3RhbmNlb2YgQmxvYikge1xuXHRcdFx0XHRcdGV2dC5kYXRhXG5cdFx0XHRcdFx0XHQuYXJyYXlCdWZmZXIoKVxuXHRcdFx0XHRcdFx0LnRoZW4oKGJ1ZmZlcikgPT4ge1xuXHRcdFx0XHRcdFx0XHRsb2dnZXIoKS5kZWJ1ZyhcImNvbnZlcnRlZCBibG9iIHRvIGFycmF5YnVmZmVyLCBzZW5kaW5nXCIsIHtcblx0XHRcdFx0XHRcdFx0XHRidWZmZXJTaXplOiBidWZmZXIuYnl0ZUxlbmd0aCxcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdGNsaWVudFdzLnNlbmQoYnVmZmVyKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0XHQuY2F0Y2goKGVycm9yKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGxvZ2dlcigpLmVycm9yKFwiZmFpbGVkIHRvIGNvbnZlcnQgYmxvYiB0byBhcnJheWJ1ZmZlclwiLCB7XG5cdFx0XHRcdFx0XHRcdFx0ZXJyb3IsXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bG9nZ2VyKCkuZGVidWcoXCJzZW5kaW5nIGRhdGEgZGlyZWN0bHlcIiwge1xuXHRcdFx0XHRcdFx0ZGF0YVR5cGU6IHR5cGVvZiBldnQuZGF0YSxcblx0XHRcdFx0XHRcdGRhdGFMZW5ndGg6XG5cdFx0XHRcdFx0XHRcdHR5cGVvZiBldnQuZGF0YSA9PT0gXCJzdHJpbmdcIiA/IGV2dC5kYXRhLmxlbmd0aCA6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRjbGllbnRXcy5zZW5kKGV2dC5kYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0b25DbG9zZTogKFxuXHRcdFx0ZXZlbnQ6IHtcblx0XHRcdFx0d2FzQ2xlYW46IGJvb2xlYW47XG5cdFx0XHRcdGNvZGU6IG51bWJlcjtcblx0XHRcdFx0cmVhc29uOiBzdHJpbmc7XG5cdFx0XHR9LFxuXHRcdFx0c2VydmVyV3M6IFdTQ29udGV4dCxcblx0XHQpID0+IHtcblx0XHRcdGxvZ2dlcigpLmRlYnVnKGBzZXJ2ZXIgJHtjb25uZWN0aW9uVHlwZX0gd2Vic29ja2V0IGNsb3NlZGAsIHtcblx0XHRcdFx0d2FzQ2xlYW46IGV2ZW50Lndhc0NsZWFuLFxuXHRcdFx0XHRjb2RlOiBldmVudC5jb2RlLFxuXHRcdFx0XHRyZWFzb246IGV2ZW50LnJlYXNvbixcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBIQUNLOiBDbG9zZSBzb2NrZXQgaW4gb3JkZXIgdG8gZml4IGJ1ZyB3aXRoIENsb3VkZmxhcmUgbGVhdmluZyBXUyBpbiBjbG9zaW5nIHN0YXRlXG5cdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vY2xvdWRmbGFyZS93b3JrZXJkL2lzc3Vlcy8yNTY5XG5cdFx0XHRzZXJ2ZXJXcy5jbG9zZSgxMDAwLCBcImhhY2tfZm9yY2VfY2xvc2VcIik7XG5cblx0XHRcdC8vIENsb3NlIHRoZSBjbGllbnQgd2Vic29ja2V0IHdoZW4gdGhlIHNlcnZlciB3ZWJzb2NrZXQgY2xvc2VzXG5cdFx0XHRpZiAoXG5cdFx0XHRcdGNsaWVudFdzICYmXG5cdFx0XHRcdGNsaWVudFdzLnJlYWR5U3RhdGUgIT09IGNsaWVudFdzLkNMT1NFRCAmJlxuXHRcdFx0XHRjbGllbnRXcy5yZWFkeVN0YXRlICE9PSBjbGllbnRXcy5DTE9TSU5HXG5cdFx0XHQpIHtcblx0XHRcdFx0Ly8gRG9uJ3QgcGFzcyBjb2RlL21lc3NhZ2Ugc2luY2UgdGhpcyBtYXkgYWZmZWN0IGhvdyBjbG9zZSBldmVudHMgYXJlIHRyaWdnZXJlZFxuXHRcdFx0XHRjbGllbnRXcy5jbG9zZSgxMDAwLCBldmVudC5yZWFzb24pO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0b25FcnJvcjogKGVycm9yOiB1bmtub3duKSA9PiB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihgZXJyb3IgaW4gc2VydmVyICR7Y29ubmVjdGlvblR5cGV9IHdlYnNvY2tldGAsIHsgZXJyb3IgfSk7XG5cblx0XHRcdC8vIENsb3NlIHRoZSBjbGllbnQgd2Vic29ja2V0IG9uIGVycm9yXG5cdFx0XHRpZiAoXG5cdFx0XHRcdGNsaWVudFdzICYmXG5cdFx0XHRcdGNsaWVudFdzLnJlYWR5U3RhdGUgIT09IGNsaWVudFdzLkNMT1NFRCAmJlxuXHRcdFx0XHRjbGllbnRXcy5yZWFkeVN0YXRlICE9PSBjbGllbnRXcy5DTE9TSU5HXG5cdFx0XHQpIHtcblx0XHRcdFx0Y2xpZW50V3MuY2xvc2UoMTAxMSwgXCJFcnJvciBpbiBzZXJ2ZXIgd2Vic29ja2V0XCIpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdH07XG59XG5cbi8qKlxuICogSGFuZGxlIFNTRSBjb25uZWN0aW9uIHJlcXVlc3RcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3NlQ29ubmVjdFJlcXVlc3QoXG5cdGM6IEhvbm9Db250ZXh0LFxuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdF9ydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0ZHJpdmVyOiBNYW5hZ2VyRHJpdmVyLFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRsZXQgZW5jb2Rpbmc6IEVuY29kaW5nIHwgdW5kZWZpbmVkO1xuXHR0cnkge1xuXHRcdGVuY29kaW5nID0gZ2V0UmVxdWVzdEVuY29kaW5nKGMucmVxKTtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInNzZSBjb25uZWN0aW9uIHJlcXVlc3QgcmVjZWl2ZWRcIiwgeyBlbmNvZGluZyB9KTtcblxuXHRcdGNvbnN0IHBhcmFtcyA9IENvbm5lY3RSZXF1ZXN0U2NoZW1hLnNhZmVQYXJzZSh7XG5cdFx0XHRxdWVyeTogZ2V0UmVxdWVzdFF1ZXJ5KGMpLFxuXHRcdFx0ZW5jb2Rpbmc6IGMucmVxLmhlYWRlcihIRUFERVJfRU5DT0RJTkcpLFxuXHRcdFx0Y29ublBhcmFtczogYy5yZXEuaGVhZGVyKEhFQURFUl9DT05OX1BBUkFNUyksXG5cdFx0fSk7XG5cblx0XHRpZiAoIXBhcmFtcy5zdWNjZXNzKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImludmFsaWQgY29ubmVjdGlvbiBwYXJhbWV0ZXJzXCIsIHtcblx0XHRcdFx0ZXJyb3I6IHBhcmFtcy5lcnJvcixcblx0XHRcdH0pO1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUmVxdWVzdChwYXJhbXMuZXJyb3IpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHF1ZXJ5ID0gcGFyYW1zLmRhdGEucXVlcnk7XG5cblx0XHQvLyBQYXJzZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZm9yIGF1dGhlbnRpY2F0aW9uXG5cdFx0Y29uc3QgY29ublBhcmFtcyA9IHBhcmFtcy5kYXRhLmNvbm5QYXJhbXNcblx0XHRcdD8gSlNPTi5wYXJzZShwYXJhbXMuZGF0YS5jb25uUGFyYW1zKVxuXHRcdFx0OiB1bmRlZmluZWQ7XG5cblx0XHQvLyBBdXRoZW50aWNhdGUgdGhlIHJlcXVlc3Rcblx0XHRjb25zdCBhdXRoRGF0YSA9IGF3YWl0IGF1dGhlbnRpY2F0ZUVuZHBvaW50KFxuXHRcdFx0Yyxcblx0XHRcdGRyaXZlcixcblx0XHRcdHJlZ2lzdHJ5Q29uZmlnLFxuXHRcdFx0cXVlcnksXG5cdFx0XHRbXCJjb25uZWN0XCJdLFxuXHRcdFx0Y29ublBhcmFtcyxcblx0XHQpO1xuXG5cdFx0Ly8gR2V0IHRoZSBhY3RvciBJRFxuXHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgcXVlcnlBY3RvcihjLCBxdWVyeSwgZHJpdmVyKTtcblx0XHRpbnZhcmlhbnQoYWN0b3JJZCwgXCJNaXNzaW5nIGFjdG9yIElEXCIpO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwic3NlIGNvbm5lY3Rpb24gdG8gYWN0b3JcIiwgeyBhY3RvcklkIH0pO1xuXG5cdFx0Ly8gSGFuZGxlIGJhc2VkIG9uIG1vZGVcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInVzaW5nIGN1c3RvbSBwcm94eSBtb2RlIGZvciBzc2UgY29ubmVjdGlvblwiKTtcblx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKFwiaHR0cDovL2FjdG9yL2Nvbm5lY3Qvc3NlXCIpO1xuXG5cdFx0Ly8gQWx3YXlzIGJ1aWxkIGZyZXNoIHJlcXVlc3QgdG8gcHJldmVudCBmb3J3YXJkaW5nIHVud2FudGVkIGhlYWRlcnNcblx0XHRjb25zdCBwcm94eVJlcXVlc3RIZWFkZXJlcyA9IG5ldyBIZWFkZXJzKCk7XG5cdFx0cHJveHlSZXF1ZXN0SGVhZGVyZXMuc2V0KEhFQURFUl9FTkNPRElORywgcGFyYW1zLmRhdGEuZW5jb2RpbmcpO1xuXHRcdGlmIChwYXJhbXMuZGF0YS5jb25uUGFyYW1zKSB7XG5cdFx0XHRwcm94eVJlcXVlc3RIZWFkZXJlcy5zZXQoSEVBREVSX0NPTk5fUEFSQU1TLCBwYXJhbXMuZGF0YS5jb25uUGFyYW1zKTtcblx0XHR9XG5cdFx0aWYgKGF1dGhEYXRhKSB7XG5cdFx0XHRwcm94eVJlcXVlc3RIZWFkZXJlcy5zZXQoSEVBREVSX0FVVEhfREFUQSwgSlNPTi5zdHJpbmdpZnkoYXV0aERhdGEpKTtcblx0XHR9XG5cblx0XHRjb25zdCBwcm94eVJlcXVlc3QgPSBuZXcgUmVxdWVzdCh1cmwsIHsgaGVhZGVyczogcHJveHlSZXF1ZXN0SGVhZGVyZXMgfSk7XG5cblx0XHRyZXR1cm4gYXdhaXQgZHJpdmVyLnByb3h5UmVxdWVzdChjLCBwcm94eVJlcXVlc3QsIGFjdG9ySWQpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdC8vIElmIHdlIHJlY2VpdmUgYW4gZXJyb3IgZHVyaW5nIHNldHVwLCB3ZSBzZW5kIHRoZSBlcnJvciBhbmQgY2xvc2UgdGhlIHNvY2tldCBpbW1lZGlhdGVseVxuXHRcdC8vXG5cdFx0Ly8gV2UgaGF2ZSB0byByZXR1cm4gdGhlIGVycm9yIG92ZXIgU1NFIHNpbmNlIFNTRSBjbGllbnRzIGNhbm5vdCByZWFkIHZhbmlsbGEgSFRUUCByZXNwb25zZXNcblxuXHRcdGNvbnN0IHsgY29kZSwgbWVzc2FnZSwgbWV0YWRhdGEgfSA9IGRlY29uc3RydWN0RXJyb3IoZXJyb3IsIGxvZ2dlcigpLCB7XG5cdFx0XHRzc2VFdmVudDogXCJzZXR1cFwiLFxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHN0cmVhbVNTRShjLCBhc3luYyAoc3RyZWFtKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRpZiAoZW5jb2RpbmcpIHtcblx0XHRcdFx0XHQvLyBTZXJpYWxpemUgYW5kIHNlbmQgdGhlIGNvbm5lY3Rpb24gZXJyb3Jcblx0XHRcdFx0XHRjb25zdCBlcnJvck1zZzogcHJvdG9jb2wuVG9DbGllbnQgPSB7XG5cdFx0XHRcdFx0XHRib2R5OiB7XG5cdFx0XHRcdFx0XHRcdHRhZzogXCJFcnJvclwiLFxuXHRcdFx0XHRcdFx0XHR2YWw6IHtcblx0XHRcdFx0XHRcdFx0XHRjb2RlLFxuXHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2UsXG5cdFx0XHRcdFx0XHRcdFx0bWV0YWRhdGE6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUobWV0YWRhdGEpKSxcblx0XHRcdFx0XHRcdFx0XHRhY3Rpb25JZDogbnVsbCxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIFNlbmQgdGhlIGVycm9yIG1lc3NhZ2UgdG8gdGhlIGNsaWVudFxuXHRcdFx0XHRcdGNvbnN0IHNlcmlhbGl6ZWQgPSBzZXJpYWxpemVXaXRoRW5jb2RpbmcoXG5cdFx0XHRcdFx0XHRlbmNvZGluZyxcblx0XHRcdFx0XHRcdGVycm9yTXNnLFxuXHRcdFx0XHRcdFx0VE9fQ0xJRU5UX1ZFUlNJT05FRCxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdGF3YWl0IHN0cmVhbS53cml0ZVNTRSh7XG5cdFx0XHRcdFx0XHRkYXRhOlxuXHRcdFx0XHRcdFx0XHR0eXBlb2Ygc2VyaWFsaXplZCA9PT0gXCJzdHJpbmdcIlxuXHRcdFx0XHRcdFx0XHRcdD8gc2VyaWFsaXplZFxuXHRcdFx0XHRcdFx0XHRcdDogQnVmZmVyLmZyb20oc2VyaWFsaXplZCkudG9TdHJpbmcoXCJiYXNlNjRcIiksXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly8gV2UgZG9uJ3Qga25vdyB0aGUgZW5jb2RpbmcsIHNlbmQgYW4gZXJyb3IgYW5kIGNsb3NlXG5cdFx0XHRcdFx0YXdhaXQgc3RyZWFtLndyaXRlU1NFKHtcblx0XHRcdFx0XHRcdGRhdGE6IGNvZGUsXG5cdFx0XHRcdFx0XHRldmVudDogXCJlcnJvclwiLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGNhdGNoIChzZXJpYWxpemVFcnJvcikge1xuXHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBzZW5kIGVycm9yIHRvIHNzZSBjbGllbnRcIiwge1xuXHRcdFx0XHRcdGVycm9yOiBzZXJpYWxpemVFcnJvcixcblx0XHRcdFx0fSk7XG5cdFx0XHRcdGF3YWl0IHN0cmVhbS53cml0ZVNTRSh7XG5cdFx0XHRcdFx0ZGF0YTogXCJpbnRlcm5hbCBlcnJvciBkdXJpbmcgZXJyb3IgaGFuZGxpbmdcIixcblx0XHRcdFx0XHRldmVudDogXCJlcnJvclwiLFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RyZWFtIHdpbGwgZXhpdCBjb21wbGV0ZWx5IG9uY2UgZnVuY3Rpb24gZXhpdHNcblx0XHR9KTtcblx0fVxufVxuXG4vKipcbiAqIEhhbmRsZSBXZWJTb2NrZXQgY29ubmVjdGlvbiByZXF1ZXN0XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVdlYlNvY2tldENvbm5lY3RSZXF1ZXN0KFxuXHRjOiBIb25vQ29udGV4dCxcblx0cmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnLFxuXHRydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0ZHJpdmVyOiBNYW5hZ2VyRHJpdmVyLFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRjb25zdCB1cGdyYWRlV2ViU29ja2V0ID0gcnVuQ29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQ/LigpO1xuXHRpZiAoIXVwZ3JhZGVXZWJTb2NrZXQpIHtcblx0XHRyZXR1cm4gYy50ZXh0KFxuXHRcdFx0XCJXZWJTb2NrZXRzIGFyZSBub3QgZW5hYmxlZCBmb3IgdGhpcyBkcml2ZXIuIFVzZSBTU0UgaW5zdGVhZC5cIixcblx0XHRcdDQwMCxcblx0XHQpO1xuXHR9XG5cblx0bGV0IGVuY29kaW5nOiBFbmNvZGluZyB8IHVuZGVmaW5lZDtcblx0dHJ5IHtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcIndlYnNvY2tldCBjb25uZWN0aW9uIHJlcXVlc3QgcmVjZWl2ZWRcIik7XG5cblx0XHQvLyBQYXJzZSBjb25maWd1cmF0aW9uIGZyb20gU2VjLVdlYlNvY2tldC1Qcm90b2NvbCBoZWFkZXJcblx0XHQvL1xuXHRcdC8vIFdlIHVzZSB0aGlzIGluc3RlYWQgb2YgcXVlcnkgcGFyYW1ldGVycyBzaW5jZSB0aGlzIGlzIG1vcmUgc2VjdXJlIHRoYW5cblx0XHQvLyBxdWVyeSBwYXJhbWV0ZXJzLiBRdWVyeSBwYXJhbWV0ZXJzIG9mdGVuIGdldCBsb2dnZWQuXG5cdFx0Ly9cblx0XHQvLyBCcm93c2VycyBkb24ndCBzdXBwb3J0IHVzaW5nIGhlYWRlcnMsIHNvIHRoaXMgaXMgdGhlIG9ubHkgd2F5IHRvXG5cdFx0Ly8gcGFzcyBkYXRhIHNlY3VyZWx5LlxuXHRcdGNvbnN0IHByb3RvY29scyA9IGMucmVxLmhlYWRlcihcInNlYy13ZWJzb2NrZXQtcHJvdG9jb2xcIik7XG5cdFx0Y29uc3QgeyBxdWVyeVJhdywgZW5jb2RpbmdSYXcsIGNvbm5QYXJhbXNSYXcgfSA9XG5cdFx0XHRwYXJzZVdlYlNvY2tldFByb3RvY29scyhwcm90b2NvbHMpO1xuXG5cdFx0Ly8gUGFyc2UgcXVlcnlcblx0XHRsZXQgcXVlcnlVbnZhbGlkYXRlZDogdW5rbm93bjtcblx0XHR0cnkge1xuXHRcdFx0cXVlcnlVbnZhbGlkYXRlZCA9IEpTT04ucGFyc2UocXVlcnlSYXchKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0bG9nZ2VyKCkuZXJyb3IoXCJpbnZhbGlkIHF1ZXJ5IGpzb25cIiwgeyBlcnJvciB9KTtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFF1ZXJ5SlNPTihlcnJvcik7XG5cdFx0fVxuXG5cdFx0Ly8gUGFyc2UgY29ubiBwYXJhbXNcblx0XHRsZXQgY29ublBhcmFtc1VudmFsaWRhdGVkOiB1bmtub3duID0gbnVsbDtcblx0XHR0cnkge1xuXHRcdFx0aWYgKGNvbm5QYXJhbXNSYXcpIHtcblx0XHRcdFx0Y29ublBhcmFtc1VudmFsaWRhdGVkID0gSlNPTi5wYXJzZShjb25uUGFyYW1zUmF3ISk7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiaW52YWxpZCBjb25uIHBhcmFtc1wiLCB7IGVycm9yIH0pO1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUGFyYW1zKFxuXHRcdFx0XHRgSW52YWxpZCBwYXJhbXMgSlNPTjogJHtzdHJpbmdpZnlFcnJvcihlcnJvcil9YCxcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgY2FuJ3QgdXNlIHRoZSBzdGFuZGFyZCBoZWFkZXJzIHdpdGggV2ViU29ja2V0c1xuXHRcdC8vXG5cdFx0Ly8gQWxsIG90aGVyIGluZm9ybWF0aW9uIHdpbGwgYmUgc2VudCBvdmVyIHRoZSBzb2NrZXQgaXRzZWxmLCBzaW5jZSB0aGF0IGRhdGEgbmVlZHMgdG8gYmUgRTJFRVxuXHRcdGNvbnN0IHBhcmFtcyA9IENvbm5lY3RXZWJTb2NrZXRSZXF1ZXN0U2NoZW1hLnNhZmVQYXJzZSh7XG5cdFx0XHRxdWVyeTogcXVlcnlVbnZhbGlkYXRlZCxcblx0XHRcdGVuY29kaW5nOiBlbmNvZGluZ1Jhdyxcblx0XHRcdGNvbm5QYXJhbXM6IGNvbm5QYXJhbXNVbnZhbGlkYXRlZCxcblx0XHR9KTtcblx0XHRpZiAoIXBhcmFtcy5zdWNjZXNzKSB7XG5cdFx0XHRsb2dnZXIoKS5lcnJvcihcImludmFsaWQgY29ubmVjdGlvbiBwYXJhbWV0ZXJzXCIsIHtcblx0XHRcdFx0ZXJyb3I6IHBhcmFtcy5lcnJvcixcblx0XHRcdH0pO1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUmVxdWVzdChwYXJhbXMuZXJyb3IpO1xuXHRcdH1cblx0XHRlbmNvZGluZyA9IHBhcmFtcy5kYXRhLmVuY29kaW5nO1xuXG5cdFx0Ly8gQXV0aGVudGljYXRlIGVuZHBvaW50XG5cdFx0Y29uc3QgYXV0aERhdGEgPSBhd2FpdCBhdXRoZW50aWNhdGVFbmRwb2ludChcblx0XHRcdGMsXG5cdFx0XHRkcml2ZXIsXG5cdFx0XHRyZWdpc3RyeUNvbmZpZyxcblx0XHRcdHBhcmFtcy5kYXRhLnF1ZXJ5LFxuXHRcdFx0W1wiY29ubmVjdFwiXSxcblx0XHRcdGNvbm5QYXJhbXNSYXcsXG5cdFx0KTtcblxuXHRcdC8vIEdldCB0aGUgYWN0b3IgSURcblx0XHRjb25zdCB7IGFjdG9ySWQgfSA9IGF3YWl0IHF1ZXJ5QWN0b3IoYywgcGFyYW1zLmRhdGEucXVlcnksIGRyaXZlcik7XG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJmb3VuZCBhY3RvciBmb3Igd2Vic29ja2V0IGNvbm5lY3Rpb25cIiwge1xuXHRcdFx0YWN0b3JJZCxcblx0XHR9KTtcblx0XHRpbnZhcmlhbnQoYWN0b3JJZCwgXCJtaXNzaW5nIGFjdG9yIGlkXCIpO1xuXG5cdFx0Ly8gUHJveHkgdGhlIFdlYlNvY2tldCBjb25uZWN0aW9uIHRvIHRoZSBhY3RvclxuXHRcdC8vXG5cdFx0Ly8gVGhlIHByb3h5V2ViU29ja2V0IGhhbmRsZXIgd2lsbDpcblx0XHQvLyAxLiBWYWxpZGF0ZSB0aGUgV2ViU29ja2V0IHVwZ3JhZGUgcmVxdWVzdFxuXHRcdC8vIDIuIEZvcndhcmQgdGhlIHJlcXVlc3QgdG8gdGhlIGFjdG9yIHdpdGggdGhlIGFwcHJvcHJpYXRlIHBhdGhcblx0XHQvLyAzLiBIYW5kbGUgdGhlIFdlYlNvY2tldCBwYWlyIGFuZCBwcm94eSBtZXNzYWdlcyBiZXR3ZWVuIGNsaWVudCBhbmQgYWN0b3Jcblx0XHRyZXR1cm4gYXdhaXQgZHJpdmVyLnByb3h5V2ViU29ja2V0KFxuXHRcdFx0Yyxcblx0XHRcdFBBVEhfQ09OTkVDVF9XRUJTT0NLRVQsXG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0cGFyYW1zLmRhdGEuZW5jb2RpbmcsXG5cdFx0XHRwYXJhbXMuZGF0YS5jb25uUGFyYW1zLFxuXHRcdFx0YXV0aERhdGEsXG5cdFx0KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHQvLyBJZiB3ZSByZWNlaXZlIGFuIGVycm9yIGR1cmluZyBzZXR1cCwgd2Ugc2VuZCB0aGUgZXJyb3IgYW5kIGNsb3NlIHRoZSBzb2NrZXQgaW1tZWRpYXRlbHlcblx0XHQvL1xuXHRcdC8vIFdlIGhhdmUgdG8gcmV0dXJuIHRoZSBlcnJvciBvdmVyIFdTIHNpbmNlIFdlYlNvY2tldCBjbGllbnRzIGNhbm5vdCByZWFkIHZhbmlsbGEgSFRUUCByZXNwb25zZXNcblxuXHRcdGNvbnN0IHsgY29kZSwgbWVzc2FnZSwgbWV0YWRhdGEgfSA9IGRlY29uc3RydWN0RXJyb3IoZXJyb3IsIGxvZ2dlcigpLCB7XG5cdFx0XHR3c0V2ZW50OiBcInNldHVwXCIsXG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gYXdhaXQgdXBncmFkZVdlYlNvY2tldCgoKSA9PiAoe1xuXHRcdFx0b25PcGVuOiAoX2V2dDogdW5rbm93biwgd3M6IFdTQ29udGV4dCkgPT4ge1xuXHRcdFx0XHRpZiAoZW5jb2RpbmcpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0Ly8gU2VyaWFsaXplIGFuZCBzZW5kIHRoZSBjb25uZWN0aW9uIGVycm9yXG5cdFx0XHRcdFx0XHRjb25zdCBlcnJvck1zZzogcHJvdG9jb2wuVG9DbGllbnQgPSB7XG5cdFx0XHRcdFx0XHRcdGJvZHk6IHtcblx0XHRcdFx0XHRcdFx0XHR0YWc6IFwiRXJyb3JcIixcblx0XHRcdFx0XHRcdFx0XHR2YWw6IHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvZGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRtZXNzYWdlLFxuXHRcdFx0XHRcdFx0XHRcdFx0bWV0YWRhdGE6IGJ1ZmZlclRvQXJyYXlCdWZmZXIoY2Jvci5lbmNvZGUobWV0YWRhdGEpKSxcblx0XHRcdFx0XHRcdFx0XHRcdGFjdGlvbklkOiBudWxsLFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHQvLyBTZW5kIHRoZSBlcnJvciBtZXNzYWdlIHRvIHRoZSBjbGllbnRcblx0XHRcdFx0XHRcdGNvbnN0IHNlcmlhbGl6ZWQgPSBzZXJpYWxpemVXaXRoRW5jb2RpbmcoXG5cdFx0XHRcdFx0XHRcdGVuY29kaW5nLFxuXHRcdFx0XHRcdFx0XHRlcnJvck1zZyxcblx0XHRcdFx0XHRcdFx0VE9fQ0xJRU5UX1ZFUlNJT05FRCxcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHR3cy5zZW5kKHNlcmlhbGl6ZWQpO1xuXG5cdFx0XHRcdFx0XHQvLyBDbG9zZSB0aGUgY29ubmVjdGlvbiB3aXRoIGFuIGVycm9yIGNvZGVcblx0XHRcdFx0XHRcdHdzLmNsb3NlKDEwMTEsIGNvZGUpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKHNlcmlhbGl6ZUVycm9yKSB7XG5cdFx0XHRcdFx0XHRsb2dnZXIoKS5lcnJvcihcImZhaWxlZCB0byBzZW5kIGVycm9yIHRvIHdlYnNvY2tldCBjbGllbnRcIiwge1xuXHRcdFx0XHRcdFx0XHRlcnJvcjogc2VyaWFsaXplRXJyb3IsXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdHdzLmNsb3NlKDEwMTEsIFwiaW50ZXJuYWwgZXJyb3IgZHVyaW5nIGVycm9yIGhhbmRsaW5nXCIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBXZSBkb24ndCBrbm93IHRoZSBlbmNvZGluZyBzbyB3ZSBzZW5kIHdoYXQgd2UgY2FuXG5cdFx0XHRcdFx0d3MuY2xvc2UoMTAxMSwgY29kZSk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0fSkpKGMsIG5vb3BOZXh0KCkpO1xuXHR9XG59XG5cbi8qKlxuICogSGFuZGxlIGEgY29ubmVjdGlvbiBtZXNzYWdlIHJlcXVlc3QgdG8gYSBhY3RvclxuICpcbiAqIFRoZXJlIGlzIG5vIGF1dGhlbnRpY2F0aW9uIGhhbmRsZXIgb24gdGhpcyByZXF1ZXN0IHNpbmNlIHRoZSBjb25uZWN0aW9uXG4gKiB0b2tlbiBpcyB1c2VkIHRvIGF1dGhlbnRpY2F0ZSB0aGUgbWVzc2FnZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlTWVzc2FnZVJlcXVlc3QoXG5cdGM6IEhvbm9Db250ZXh0LFxuXHRfcmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnLFxuXHRfcnVuQ29uZmlnOiBSdW5Db25maWcsXG5cdGRyaXZlcjogTWFuYWdlckRyaXZlcixcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcblx0bG9nZ2VyKCkuZGVidWcoXCJjb25uZWN0aW9uIG1lc3NhZ2UgcmVxdWVzdCByZWNlaXZlZFwiKTtcblx0dHJ5IHtcblx0XHRjb25zdCBwYXJhbXMgPSBDb25uTWVzc2FnZVJlcXVlc3RTY2hlbWEuc2FmZVBhcnNlKHtcblx0XHRcdGFjdG9ySWQ6IGMucmVxLmhlYWRlcihIRUFERVJfQUNUT1JfSUQpLFxuXHRcdFx0Y29ubklkOiBjLnJlcS5oZWFkZXIoSEVBREVSX0NPTk5fSUQpLFxuXHRcdFx0ZW5jb2Rpbmc6IGMucmVxLmhlYWRlcihIRUFERVJfRU5DT0RJTkcpLFxuXHRcdFx0Y29ublRva2VuOiBjLnJlcS5oZWFkZXIoSEVBREVSX0NPTk5fVE9LRU4pLFxuXHRcdH0pO1xuXHRcdGlmICghcGFyYW1zLnN1Y2Nlc3MpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiaW52YWxpZCBjb25uZWN0aW9uIHBhcmFtZXRlcnNcIiwge1xuXHRcdFx0XHRlcnJvcjogcGFyYW1zLmVycm9yLFxuXHRcdFx0fSk7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRSZXF1ZXN0KHBhcmFtcy5lcnJvcik7XG5cdFx0fVxuXHRcdGNvbnN0IHsgYWN0b3JJZCwgY29ubklkLCBlbmNvZGluZywgY29ublRva2VuIH0gPSBwYXJhbXMuZGF0YTtcblxuXHRcdC8vIFRPRE86IFRoaXMgZW5kcG9pbnQgY2FuIGJlIHVzZWQgdG8gZXhoYXVzZSByZXNvdXJjZXMgKERvUyBhdHRhY2spIG9uIGFuIGFjdG9yIGlmIHlvdSBrbm93IHRoZSBhY3RvciBJRDpcblx0XHQvLyAxLiBHZXQgdGhlIGFjdG9yIElEICh1c3VhbGx5IHRoaXMgaXMgcmVhc29uYWJseSBzZWN1cmUsIGJ1dCB3ZSBkb24ndCBhc3N1bWUgYWN0b3IgSUQgaXMgc2Vuc2l0aXZlKVxuXHRcdC8vIDIuIFNwYW0gbWVzc2FnZXMgdG8gdGhlIGFjdG9yICh0aGUgY29ubiB0b2tlbiBjYW4gYmUgaW52YWxpZClcblx0XHQvLyAzLiBUaGUgYWN0b3Igd2lsbCBiZSBleGhhdXN0ZWQgcHJvY2Vzc2luZyBtZXNzYWdlcyBcdTIwMTQgZXZlbiBpZiB0aGUgdG9rZW4gaXMgaW52YWxpZFxuXHRcdC8vXG5cdFx0Ly8gVGhlIHNvbHV0aW9uIGlzIHdlIG5lZWQgdG8gbW92ZSB0aGUgYXV0aG9yaXphdGlvbiBvZiB0aGUgY29ubmVjdGlvbiB0b2tlbiB0byB0aGlzIHJlcXVlc3QgaGFuZGxlclxuXHRcdC8vIEFORCBpbmNsdWRlIHRoZSBhY3RvciBJRCBpbiB0aGUgY29ubmVjdGlvbiB0b2tlbiBzbyB3ZSBjYW4gdmVyaWZ5IHRoYXQgaXQgaGFzIHBlcm1pc3Npb24gdG8gc2VuZFxuXHRcdC8vIGEgbWVzc2FnZSB0byB0aGF0IGFjdG9yLiBUaGlzIHdvdWxkIHJlcXVpcmUgY2hhbmdpbmcgdGhlIHRva2VuIHRvIGEgSldUIHNvIHdlIGNhbiBpbmNsdWRlIGEgc2VjdXJlXG5cdFx0Ly8gcGF5bG9hZCwgYnV0IHRoaXMgcmVxdWlyZXMgbWFuYWdpbmcgYSBwcml2YXRlIGtleSAmIG1hbmFnaW5nIGtleSByb3RhdGlvbnMuXG5cdFx0Ly9cblx0XHQvLyBBbGwgb3RoZXIgc29sdXRpb25zIChlLmcuIGluY2x1ZGUgdGhlIGFjdG9yIG5hbWUgYXMgYSBoZWFkZXIgb3IgaW5jbHVkZSB0aGUgYWN0b3IgbmFtZSBpbiB0aGUgYWN0b3IgSUQpXG5cdFx0Ly8gaGF2ZSBleHBsb2l0cyB0aGF0IGFsbG93IHRoZSBjYWxsZXIgdG8gc2VuZCBtZXNzYWdlcyB0byBhcmJpdHJhcnkgYWN0b3JzLlxuXHRcdC8vXG5cdFx0Ly8gQ3VycmVudGx5LCB3ZSBhc3N1bWUgdGhpcyBpcyBub3QgYSBjcml0aWNhbCBwcm9ibGVtIGJlY2F1c2UgcmVxdWVzdHMgd2lsbCBsaWtlbHkgZ2V0IHJhdGVcblx0XHQvLyBsaW1pdGVkIGJlZm9yZSBlbm91Z2ggbWVzc2FnZXMgYXJlIHBhc3NlZCB0byB0aGUgYWN0b3IgdG8gZXhoYXVzdCByZXNvdXJjZXMuXG5cblx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKFwiaHR0cDovL2FjdG9yL2Nvbm5lY3Rpb25zL21lc3NhZ2VcIik7XG5cblx0XHQvLyBBbHdheXMgYnVpbGQgZnJlc2ggcmVxdWVzdCB0byBwcmV2ZW50IGZvcndhcmRpbmcgdW53YW50ZWQgaGVhZGVyc1xuXHRcdGNvbnN0IHByb3h5UmVxdWVzdEhlYWRlcnMgPSBuZXcgSGVhZGVycygpO1xuXHRcdHByb3h5UmVxdWVzdEhlYWRlcnMuc2V0KEhFQURFUl9FTkNPRElORywgZW5jb2RpbmcpO1xuXHRcdHByb3h5UmVxdWVzdEhlYWRlcnMuc2V0KEhFQURFUl9DT05OX0lELCBjb25uSWQpO1xuXHRcdHByb3h5UmVxdWVzdEhlYWRlcnMuc2V0KEhFQURFUl9DT05OX1RPS0VOLCBjb25uVG9rZW4pO1xuXG5cdFx0Y29uc3QgcHJveHlSZXF1ZXN0ID0gbmV3IFJlcXVlc3QodXJsLCB7XG5cdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0Ym9keTogYy5yZXEucmF3LmJvZHksXG5cdFx0XHRkdXBsZXg6IFwiaGFsZlwiLFxuXHRcdFx0aGVhZGVyczogcHJveHlSZXF1ZXN0SGVhZGVycyxcblx0XHR9KTtcblxuXHRcdHJldHVybiBhd2FpdCBkcml2ZXIucHJveHlSZXF1ZXN0KGMsIHByb3h5UmVxdWVzdCwgYWN0b3JJZCk7XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBwcm94eWluZyBjb25uZWN0aW9uIG1lc3NhZ2VcIiwgeyBlcnJvciB9KTtcblxuXHRcdC8vIFVzZSBQcm94eUVycm9yIGlmIGl0J3Mgbm90IGFscmVhZHkgYW4gQWN0b3JFcnJvclxuXHRcdGlmICghZXJyb3JzLkFjdG9yRXJyb3IuaXNBY3RvckVycm9yKGVycm9yKSkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5Qcm94eUVycm9yKFwiY29ubmVjdGlvbiBtZXNzYWdlXCIsIGVycm9yKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogSGFuZGxlIGFuIGFjdGlvbiByZXF1ZXN0IHRvIGEgYWN0b3JcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlQWN0aW9uUmVxdWVzdChcblx0YzogSG9ub0NvbnRleHQsXG5cdHJlZ2lzdHJ5Q29uZmlnOiBSZWdpc3RyeUNvbmZpZyxcblx0X3J1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRkcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgYWN0aW9uTmFtZSA9IGMucmVxLnBhcmFtKFwiYWN0aW9uXCIpO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiYWN0aW9uIGNhbGwgcmVjZWl2ZWRcIiwgeyBhY3Rpb25OYW1lIH0pO1xuXG5cdFx0Y29uc3QgcGFyYW1zID0gQ29ubmVjdFJlcXVlc3RTY2hlbWEuc2FmZVBhcnNlKHtcblx0XHRcdHF1ZXJ5OiBnZXRSZXF1ZXN0UXVlcnkoYyksXG5cdFx0XHRlbmNvZGluZzogYy5yZXEuaGVhZGVyKEhFQURFUl9FTkNPRElORyksXG5cdFx0XHRjb25uUGFyYW1zOiBjLnJlcS5oZWFkZXIoSEVBREVSX0NPTk5fUEFSQU1TKSxcblx0XHR9KTtcblxuXHRcdGlmICghcGFyYW1zLnN1Y2Nlc3MpIHtcblx0XHRcdGxvZ2dlcigpLmVycm9yKFwiaW52YWxpZCBjb25uZWN0aW9uIHBhcmFtZXRlcnNcIiwge1xuXHRcdFx0XHRlcnJvcjogcGFyYW1zLmVycm9yLFxuXHRcdFx0fSk7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRSZXF1ZXN0KHBhcmFtcy5lcnJvcik7XG5cdFx0fVxuXG5cdFx0Ly8gUGFyc2UgY29ubmVjdGlvbiBwYXJhbWV0ZXJzIGZvciBhdXRoZW50aWNhdGlvblxuXHRcdGNvbnN0IGNvbm5QYXJhbXMgPSBwYXJhbXMuZGF0YS5jb25uUGFyYW1zXG5cdFx0XHQ/IEpTT04ucGFyc2UocGFyYW1zLmRhdGEuY29ublBhcmFtcylcblx0XHRcdDogdW5kZWZpbmVkO1xuXG5cdFx0Ly8gQXV0aGVudGljYXRlIHRoZSByZXF1ZXN0XG5cdFx0Y29uc3QgYXV0aERhdGEgPSBhd2FpdCBhdXRoZW50aWNhdGVFbmRwb2ludChcblx0XHRcdGMsXG5cdFx0XHRkcml2ZXIsXG5cdFx0XHRyZWdpc3RyeUNvbmZpZyxcblx0XHRcdHBhcmFtcy5kYXRhLnF1ZXJ5LFxuXHRcdFx0W1wiYWN0aW9uXCJdLFxuXHRcdFx0Y29ublBhcmFtcyxcblx0XHQpO1xuXG5cdFx0Ly8gR2V0IHRoZSBhY3RvciBJRFxuXHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgcXVlcnlBY3RvcihjLCBwYXJhbXMuZGF0YS5xdWVyeSwgZHJpdmVyKTtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvdW5kIGFjdG9yIGZvciBhY3Rpb25cIiwgeyBhY3RvcklkIH0pO1xuXHRcdGludmFyaWFudChhY3RvcklkLCBcIk1pc3NpbmcgYWN0b3IgSURcIik7XG5cblx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKFxuXHRcdFx0YGh0dHA6Ly9hY3Rvci9hY3Rpb24vJHtlbmNvZGVVUklDb21wb25lbnQoYWN0aW9uTmFtZSl9YCxcblx0XHQpO1xuXG5cdFx0Ly8gQWx3YXlzIGJ1aWxkIGZyZXNoIHJlcXVlc3QgdG8gcHJldmVudCBmb3J3YXJkaW5nIHVud2FudGVkIGhlYWRlcnNcblx0XHRjb25zdCBwcm94eVJlcXVlc3RIZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcblx0XHRwcm94eVJlcXVlc3RIZWFkZXJzLnNldChIRUFERVJfRU5DT0RJTkcsIHBhcmFtcy5kYXRhLmVuY29kaW5nKTtcblx0XHRpZiAocGFyYW1zLmRhdGEuY29ublBhcmFtcykge1xuXHRcdFx0cHJveHlSZXF1ZXN0SGVhZGVycy5zZXQoSEVBREVSX0NPTk5fUEFSQU1TLCBwYXJhbXMuZGF0YS5jb25uUGFyYW1zKTtcblx0XHR9XG5cdFx0aWYgKGF1dGhEYXRhKSB7XG5cdFx0XHRwcm94eVJlcXVlc3RIZWFkZXJzLnNldChIRUFERVJfQVVUSF9EQVRBLCBKU09OLnN0cmluZ2lmeShhdXRoRGF0YSkpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHByb3h5UmVxdWVzdCA9IG5ldyBSZXF1ZXN0KHVybCwge1xuXHRcdFx0bWV0aG9kOiBcIlBPU1RcIixcblx0XHRcdGJvZHk6IGMucmVxLnJhdy5ib2R5LFxuXHRcdFx0aGVhZGVyczogcHJveHlSZXF1ZXN0SGVhZGVycyxcblx0XHR9KTtcblxuXHRcdHJldHVybiBhd2FpdCBkcml2ZXIucHJveHlSZXF1ZXN0KGMsIHByb3h5UmVxdWVzdCwgYWN0b3JJZCk7XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0bG9nZ2VyKCkuZXJyb3IoXCJlcnJvciBpbiBhY3Rpb24gaGFuZGxlclwiLCB7IGVycm9yOiBzdHJpbmdpZnlFcnJvcihlcnJvcikgfSk7XG5cblx0XHQvLyBVc2UgUHJveHlFcnJvciBpZiBpdCdzIG5vdCBhbHJlYWR5IGFuIEFjdG9yRXJyb3Jcblx0XHRpZiAoIWVycm9ycy5BY3RvckVycm9yLmlzQWN0b3JFcnJvcihlcnJvcikpIHtcblx0XHRcdHRocm93IG5ldyBlcnJvcnMuUHJveHlFcnJvcihcIkFjdGlvbiBjYWxsXCIsIGVycm9yKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogSGFuZGxlIHRoZSByZXNvbHZlIHJlcXVlc3QgdG8gZ2V0IGEgYWN0b3IgSUQgZnJvbSBhIHF1ZXJ5XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVJlc29sdmVSZXF1ZXN0KFxuXHRjOiBIb25vQ29udGV4dCxcblx0cmVnaXN0cnlDb25maWc6IFJlZ2lzdHJ5Q29uZmlnLFxuXHRkcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG5cdGNvbnN0IGVuY29kaW5nID0gZ2V0UmVxdWVzdEVuY29kaW5nKGMucmVxKTtcblx0bG9nZ2VyKCkuZGVidWcoXCJyZXNvbHZlIHJlcXVlc3QgZW5jb2RpbmdcIiwgeyBlbmNvZGluZyB9KTtcblxuXHRjb25zdCBwYXJhbXMgPSBSZXNvbHZlUmVxdWVzdFNjaGVtYS5zYWZlUGFyc2Uoe1xuXHRcdHF1ZXJ5OiBnZXRSZXF1ZXN0UXVlcnkoYyksXG5cdFx0Y29ublBhcmFtczogYy5yZXEuaGVhZGVyKEhFQURFUl9DT05OX1BBUkFNUyksXG5cdH0pO1xuXHRpZiAoIXBhcmFtcy5zdWNjZXNzKSB7XG5cdFx0bG9nZ2VyKCkuZXJyb3IoXCJpbnZhbGlkIGNvbm5lY3Rpb24gcGFyYW1ldGVyc1wiLCB7XG5cdFx0XHRlcnJvcjogcGFyYW1zLmVycm9yLFxuXHRcdH0pO1xuXHRcdHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFJlcXVlc3QocGFyYW1zLmVycm9yKTtcblx0fVxuXG5cdC8vIFBhcnNlIGNvbm5lY3Rpb24gcGFyYW1ldGVycyBmb3IgYXV0aGVudGljYXRpb25cblx0Y29uc3QgY29ublBhcmFtcyA9IHBhcmFtcy5kYXRhLmNvbm5QYXJhbXNcblx0XHQ/IEpTT04ucGFyc2UocGFyYW1zLmRhdGEuY29ublBhcmFtcylcblx0XHQ6IHVuZGVmaW5lZDtcblxuXHRjb25zdCBxdWVyeSA9IHBhcmFtcy5kYXRhLnF1ZXJ5O1xuXG5cdC8vIEF1dGhlbnRpY2F0ZSB0aGUgcmVxdWVzdFxuXHRhd2FpdCBhdXRoZW50aWNhdGVFbmRwb2ludChjLCBkcml2ZXIsIHJlZ2lzdHJ5Q29uZmlnLCBxdWVyeSwgW10sIGNvbm5QYXJhbXMpO1xuXG5cdC8vIEdldCB0aGUgYWN0b3IgSURcblx0Y29uc3QgeyBhY3RvcklkIH0gPSBhd2FpdCBxdWVyeUFjdG9yKGMsIHF1ZXJ5LCBkcml2ZXIpO1xuXHRsb2dnZXIoKS5kZWJ1ZyhcInJlc29sdmVkIGFjdG9yXCIsIHsgYWN0b3JJZCB9KTtcblx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHQvLyBGb3JtYXQgcmVzcG9uc2UgYWNjb3JkaW5nIHRvIHByb3RvY29sXG5cdGNvbnN0IHJlc3BvbnNlOiBwcm90b2NvbC5IdHRwUmVzb2x2ZVJlc3BvbnNlID0ge1xuXHRcdGFjdG9ySWQsXG5cdH07XG5cdGNvbnN0IHNlcmlhbGl6ZWQgPSBzZXJpYWxpemVXaXRoRW5jb2RpbmcoXG5cdFx0ZW5jb2RpbmcsXG5cdFx0cmVzcG9uc2UsXG5cdFx0SFRUUF9SRVNPTFZFX1JFU1BPTlNFX1ZFUlNJT05FRCxcblx0KTtcblx0cmV0dXJuIGMuYm9keShzZXJpYWxpemVkKTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgcmF3IEhUVFAgcmVxdWVzdHMgdG8gYW4gYWN0b3JcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmF3SHR0cFJlcXVlc3QoXG5cdGM6IEhvbm9Db250ZXh0LFxuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdF9ydW5Db25maWc6IFJ1bkNvbmZpZyxcblx0ZHJpdmVyOiBNYW5hZ2VyRHJpdmVyLFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IHN1YnBhdGggPSBjLnJlcS5wYXRoLnNwbGl0KFwiL3Jhdy9odHRwL1wiKVsxXSB8fCBcIlwiO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwicmF3IGh0dHAgcmVxdWVzdCByZWNlaXZlZFwiLCB7IHN1YnBhdGggfSk7XG5cblx0XHQvLyBHZXQgYWN0b3IgcXVlcnkgZnJvbSBoZWFkZXIgKGNvbnNpc3RlbnQgd2l0aCBvdGhlciBlbmRwb2ludHMpXG5cdFx0Y29uc3QgcXVlcnlIZWFkZXIgPSBjLnJlcS5oZWFkZXIoSEVBREVSX0FDVE9SX1FVRVJZKTtcblx0XHRpZiAoIXF1ZXJ5SGVhZGVyKSB7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRSZXF1ZXN0KFwiTWlzc2luZyBhY3RvciBxdWVyeSBoZWFkZXJcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHF1ZXJ5OiBBY3RvclF1ZXJ5ID0gSlNPTi5wYXJzZShxdWVyeUhlYWRlcik7XG5cblx0XHQvLyBQYXJzZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZm9yIGF1dGhlbnRpY2F0aW9uXG5cdFx0Y29uc3QgY29ublBhcmFtc0hlYWRlciA9IGMucmVxLmhlYWRlcihIRUFERVJfQ09OTl9QQVJBTVMpO1xuXHRcdGNvbnN0IGNvbm5QYXJhbXMgPSBjb25uUGFyYW1zSGVhZGVyXG5cdFx0XHQ/IEpTT04ucGFyc2UoY29ublBhcmFtc0hlYWRlcilcblx0XHRcdDogdW5kZWZpbmVkO1xuXG5cdFx0Ly8gQXV0aGVudGljYXRlIHRoZSByZXF1ZXN0XG5cdFx0Y29uc3QgYXV0aERhdGEgPSBhd2FpdCBhdXRoZW50aWNhdGVFbmRwb2ludChcblx0XHRcdGMsXG5cdFx0XHRkcml2ZXIsXG5cdFx0XHRyZWdpc3RyeUNvbmZpZyxcblx0XHRcdHF1ZXJ5LFxuXHRcdFx0W1wiYWN0aW9uXCJdLFxuXHRcdFx0Y29ublBhcmFtcyxcblx0XHQpO1xuXG5cdFx0Ly8gR2V0IHRoZSBhY3RvciBJRFxuXHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgcXVlcnlBY3RvcihjLCBxdWVyeSwgZHJpdmVyKTtcblx0XHRsb2dnZXIoKS5kZWJ1ZyhcImZvdW5kIGFjdG9yIGZvciByYXcgaHR0cFwiLCB7IGFjdG9ySWQgfSk7XG5cdFx0aW52YXJpYW50KGFjdG9ySWQsIFwiTWlzc2luZyBhY3RvciBJRFwiKTtcblxuXHRcdC8vIFByZXNlcnZlIHRoZSBvcmlnaW5hbCBVUkwncyBxdWVyeSBwYXJhbWV0ZXJzXG5cdFx0Y29uc3Qgb3JpZ2luYWxVcmwgPSBuZXcgVVJMKGMucmVxLnVybCk7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChcblx0XHRcdGBodHRwOi8vYWN0b3IvcmF3L2h0dHAvJHtzdWJwYXRofSR7b3JpZ2luYWxVcmwuc2VhcmNofWAsXG5cdFx0KTtcblxuXHRcdC8vIEZvcndhcmQgdGhlIHJlcXVlc3QgdG8gdGhlIGFjdG9yXG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInJld3JpdGluZyBodHRwIHVybFwiLCB7XG5cdFx0XHRmcm9tOiBjLnJlcS51cmwsXG5cdFx0XHR0bzogdXJsLFxuXHRcdH0pO1xuXG5cdFx0Y29uc3QgcHJveHlSZXF1ZXN0SGVhZGVycyA9IG5ldyBIZWFkZXJzKGMucmVxLnJhdy5oZWFkZXJzKTtcblx0XHRpZiAoY29ublBhcmFtcykge1xuXHRcdFx0cHJveHlSZXF1ZXN0SGVhZGVycy5zZXQoSEVBREVSX0NPTk5fUEFSQU1TLCBKU09OLnN0cmluZ2lmeShjb25uUGFyYW1zKSk7XG5cdFx0fVxuXHRcdGlmIChhdXRoRGF0YSkge1xuXHRcdFx0cHJveHlSZXF1ZXN0SGVhZGVycy5zZXQoSEVBREVSX0FVVEhfREFUQSwgSlNPTi5zdHJpbmdpZnkoYXV0aERhdGEpKTtcblx0XHR9XG5cblx0XHRjb25zdCBwcm94eVJlcXVlc3QgPSBuZXcgUmVxdWVzdCh1cmwsIHtcblx0XHRcdG1ldGhvZDogYy5yZXEubWV0aG9kLFxuXHRcdFx0aGVhZGVyczogcHJveHlSZXF1ZXN0SGVhZGVycyxcblx0XHRcdGJvZHk6IGMucmVxLnJhdy5ib2R5LFxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIGF3YWl0IGRyaXZlci5wcm94eVJlcXVlc3QoYywgcHJveHlSZXF1ZXN0LCBhY3RvcklkKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRsb2dnZXIoKS5lcnJvcihcImVycm9yIGluIHJhdyBodHRwIGhhbmRsZXJcIiwge1xuXHRcdFx0ZXJyb3I6IHN0cmluZ2lmeUVycm9yKGVycm9yKSxcblx0XHR9KTtcblxuXHRcdC8vIFVzZSBQcm94eUVycm9yIGlmIGl0J3Mgbm90IGFscmVhZHkgYW4gQWN0b3JFcnJvclxuXHRcdGlmICghZXJyb3JzLkFjdG9yRXJyb3IuaXNBY3RvckVycm9yKGVycm9yKSkge1xuXHRcdFx0dGhyb3cgbmV3IGVycm9ycy5Qcm94eUVycm9yKFwiUmF3IEhUVFAgcmVxdWVzdFwiLCBlcnJvcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEhhbmRsZSByYXcgV2ViU29ja2V0IHJlcXVlc3RzIHRvIGFuIGFjdG9yXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVJhd1dlYlNvY2tldFJlcXVlc3QoXG5cdGM6IEhvbm9Db250ZXh0LFxuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdHJ1bkNvbmZpZzogUnVuQ29uZmlnLFxuXHRkcml2ZXI6IE1hbmFnZXJEcml2ZXIsXG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG5cdGNvbnN0IHVwZ3JhZGVXZWJTb2NrZXQgPSBydW5Db25maWcuZ2V0VXBncmFkZVdlYlNvY2tldD8uKCk7XG5cdGlmICghdXBncmFkZVdlYlNvY2tldCkge1xuXHRcdHJldHVybiBjLnRleHQoXCJXZWJTb2NrZXRzIGFyZSBub3QgZW5hYmxlZCBmb3IgdGhpcyBkcml2ZXIuXCIsIDQwMCk7XG5cdH1cblxuXHR0cnkge1xuXHRcdGNvbnN0IHN1YnBhdGggPSBjLnJlcS5wYXRoLnNwbGl0KFwiL3Jhdy93ZWJzb2NrZXQvXCIpWzFdIHx8IFwiXCI7XG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJyYXcgd2Vic29ja2V0IHJlcXVlc3QgcmVjZWl2ZWRcIiwgeyBzdWJwYXRoIH0pO1xuXG5cdFx0Ly8gUGFyc2UgcHJvdG9jb2xzIGZyb20gU2VjLVdlYlNvY2tldC1Qcm90b2NvbCBoZWFkZXJcblx0XHRjb25zdCBwcm90b2NvbHMgPSBjLnJlcS5oZWFkZXIoXCJzZWMtd2Vic29ja2V0LXByb3RvY29sXCIpO1xuXHRcdGNvbnN0IHtcblx0XHRcdHF1ZXJ5UmF3OiBxdWVyeUZyb21Qcm90b2NvbCxcblx0XHRcdGNvbm5QYXJhbXNSYXc6IGNvbm5QYXJhbXNGcm9tUHJvdG9jb2wsXG5cdFx0fSA9IHBhcnNlV2ViU29ja2V0UHJvdG9jb2xzKHByb3RvY29scyk7XG5cblx0XHRpZiAoIXF1ZXJ5RnJvbVByb3RvY29sKSB7XG5cdFx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRSZXF1ZXN0KFwiTWlzc2luZyBxdWVyeSBpbiBXZWJTb2NrZXQgcHJvdG9jb2xcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHF1ZXJ5ID0gSlNPTi5wYXJzZShxdWVyeUZyb21Qcm90b2NvbCk7XG5cblx0XHQvLyBQYXJzZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBwcm90b2NvbFxuXHRcdGxldCBjb25uUGFyYW1zOiB1bmtub3duO1xuXHRcdGlmIChjb25uUGFyYW1zRnJvbVByb3RvY29sKSB7XG5cdFx0XHRjb25uUGFyYW1zID0gSlNPTi5wYXJzZShjb25uUGFyYW1zRnJvbVByb3RvY29sKTtcblx0XHR9XG5cblx0XHQvLyBBdXRoZW50aWNhdGUgdGhlIHJlcXVlc3Rcblx0XHRjb25zdCBhdXRoRGF0YSA9IGF3YWl0IGF1dGhlbnRpY2F0ZUVuZHBvaW50KFxuXHRcdFx0Yyxcblx0XHRcdGRyaXZlcixcblx0XHRcdHJlZ2lzdHJ5Q29uZmlnLFxuXHRcdFx0cXVlcnksXG5cdFx0XHRbXCJhY3Rpb25cIl0sXG5cdFx0XHRjb25uUGFyYW1zLFxuXHRcdCk7XG5cblx0XHQvLyBHZXQgdGhlIGFjdG9yIElEXG5cdFx0Y29uc3QgeyBhY3RvcklkIH0gPSBhd2FpdCBxdWVyeUFjdG9yKGMsIHF1ZXJ5LCBkcml2ZXIpO1xuXHRcdGxvZ2dlcigpLmRlYnVnKFwiZm91bmQgYWN0b3IgZm9yIHJhdyB3ZWJzb2NrZXRcIiwgeyBhY3RvcklkIH0pO1xuXHRcdGludmFyaWFudChhY3RvcklkLCBcIk1pc3NpbmcgYWN0b3IgSURcIik7XG5cblx0XHRsb2dnZXIoKS5kZWJ1ZyhcInVzaW5nIGN1c3RvbSBwcm94eSBtb2RlIGZvciByYXcgd2Vic29ja2V0XCIpO1xuXG5cdFx0Ly8gUHJlc2VydmUgdGhlIG9yaWdpbmFsIFVSTCdzIHF1ZXJ5IHBhcmFtZXRlcnNcblx0XHRjb25zdCBvcmlnaW5hbFVybCA9IG5ldyBVUkwoYy5yZXEudXJsKTtcblx0XHRjb25zdCBwcm94eVBhdGggPSBgJHtQQVRIX1JBV19XRUJTT0NLRVRfUFJFRklYfSR7c3VicGF0aH0ke29yaWdpbmFsVXJsLnNlYXJjaH1gO1xuXG5cdFx0bG9nZ2VyKCkuZGVidWcoXCJtYW5hZ2VyIHJvdXRlciBwcm94eVdlYlNvY2tldFwiLCB7XG5cdFx0XHRvcmlnaW5hbFVybDogYy5yZXEudXJsLFxuXHRcdFx0c3VicGF0aCxcblx0XHRcdHNlYXJjaDogb3JpZ2luYWxVcmwuc2VhcmNoLFxuXHRcdFx0cHJveHlQYXRoLFxuXHRcdH0pO1xuXG5cdFx0Ly8gRm9yIHJhdyBXZWJTb2NrZXQsIHdlIG5lZWQgdG8gdXNlIHByb3h5V2ViU29ja2V0IGluc3RlYWQgb2YgcHJveHlSZXF1ZXN0XG5cdFx0cmV0dXJuIGF3YWl0IGRyaXZlci5wcm94eVdlYlNvY2tldChcblx0XHRcdGMsXG5cdFx0XHRwcm94eVBhdGgsXG5cdFx0XHRhY3RvcklkLFxuXHRcdFx0XCJqc29uXCIsIC8vIERlZmF1bHQgZW5jb2RpbmcgZm9yIHJhdyBXZWJTb2NrZXRcblx0XHRcdGNvbm5QYXJhbXMsXG5cdFx0XHRhdXRoRGF0YSxcblx0XHQpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdC8vIElmIHdlIHJlY2VpdmUgYW4gZXJyb3IgZHVyaW5nIHNldHVwLCB3ZSBzZW5kIHRoZSBlcnJvciBhbmQgY2xvc2UgdGhlIHNvY2tldCBpbW1lZGlhdGVseVxuXHRcdC8vXG5cdFx0Ly8gV2UgaGF2ZSB0byByZXR1cm4gdGhlIGVycm9yIG92ZXIgV1Mgc2luY2UgV2ViU29ja2V0IGNsaWVudHMgY2Fubm90IHJlYWQgdmFuaWxsYSBIVFRQIHJlc3BvbnNlc1xuXG5cdFx0Y29uc3QgeyBjb2RlIH0gPSBkZWNvbnN0cnVjdEVycm9yKGVycm9yLCBsb2dnZXIoKSwge1xuXHRcdFx0d3NFdmVudDogXCJzZXR1cFwiLFxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIGF3YWl0IHVwZ3JhZGVXZWJTb2NrZXQoKCkgPT4gKHtcblx0XHRcdG9uT3BlbjogKF9ldnQ6IHVua25vd24sIHdzOiBXU0NvbnRleHQpID0+IHtcblx0XHRcdFx0Ly8gQ2xvc2Ugd2l0aCBtZXNzYWdlIHNvIHdlIGNhbiBzZWUgdGhlIGVycm9yIG9uIHRoZSBjbGllbnRcblx0XHRcdFx0d3MuY2xvc2UoMTAxMSwgY29kZSk7XG5cdFx0XHR9LFxuXHRcdH0pKShjLCBub29wTmV4dCgpKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1bml2ZXJzYWxBY3RvclByb3h5KHtcblx0cmVnaXN0cnlDb25maWcsXG5cdHJ1bkNvbmZpZyxcblx0ZHJpdmVyLFxufToge1xuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWc7XG5cdHJ1bkNvbmZpZzogUnVuQ29uZmlnO1xuXHRkcml2ZXI6IE1hbmFnZXJEcml2ZXI7XG59KTogTWlkZGxld2FyZUhhbmRsZXIge1xuXHRyZXR1cm4gYXN5bmMgKGMsIF9uZXh0KSA9PiB7XG5cdFx0aWYgKGMucmVxLmhlYWRlcihcInVwZ3JhZGVcIikgPT09IFwid2Vic29ja2V0XCIpIHtcblx0XHRcdHJldHVybiBoYW5kbGVSYXdXZWJTb2NrZXRSZXF1ZXN0KGMsIHJlZ2lzdHJ5Q29uZmlnLCBydW5Db25maWcsIGRyaXZlcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IHF1ZXJ5SGVhZGVyID0gYy5yZXEuaGVhZGVyKEhFQURFUl9BQ1RPUl9RVUVSWSk7XG5cdFx0XHRpZiAoIXF1ZXJ5SGVhZGVyKSB7XG5cdFx0XHRcdHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFJlcXVlc3QoXCJNaXNzaW5nIGFjdG9yIHF1ZXJ5IGhlYWRlclwiKTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHF1ZXJ5ID0gQWN0b3JRdWVyeVNjaGVtYS5wYXJzZShKU09OLnBhcnNlKHF1ZXJ5SGVhZGVyKSk7XG5cblx0XHRcdGNvbnN0IHsgYWN0b3JJZCB9ID0gYXdhaXQgcXVlcnlBY3RvcihjLCBxdWVyeSwgZHJpdmVyKTtcblxuXHRcdFx0Y29uc3QgdXJsID0gbmV3IFVSTChjLnJlcS51cmwpO1xuXHRcdFx0dXJsLmhvc3RuYW1lID0gXCJhY3RvclwiO1xuXHRcdFx0dXJsLnBhdGhuYW1lID0gdXJsLnBhdGhuYW1lXG5cdFx0XHRcdC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4ke3J1bkNvbmZpZy5iYXNlUGF0aH1gLCBcIlwiKSwgXCJcIilcblx0XHRcdFx0LnJlcGxhY2UoL15cXC8/cmVnaXN0cnlcXC9hY3RvcnMvLCBcIlwiKVxuXHRcdFx0XHQucmVwbGFjZSgvXlxcLz9hY3RvcnMvLCBcIlwiKTsgLy8gUmVtb3ZlIC9yZWdpc3RyeSBwcmVmaXggaWYgcHJlc2VudFxuXG5cdFx0XHRjb25zdCBwcm94eVJlcXVlc3QgPSBuZXcgUmVxdWVzdCh1cmwsIHtcblx0XHRcdFx0bWV0aG9kOiBjLnJlcS5tZXRob2QsXG5cdFx0XHRcdGhlYWRlcnM6IGMucmVxLnJhdy5oZWFkZXJzLFxuXHRcdFx0XHRib2R5OiBjLnJlcS5yYXcuYm9keSxcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuIGF3YWl0IGRyaXZlci5wcm94eVJlcXVlc3QoYywgcHJveHlSZXF1ZXN0LCBhY3RvcklkKTtcblx0XHR9XG5cdH07XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9tYW5hZ2VyL2F1dGgudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvbWFuYWdlclwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9tYW5hZ2VyL2F1dGgudHNcIjtpbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSG9ub0NvbnRleHQgfSBmcm9tIFwiaG9ub1wiO1xuaW1wb3J0IHR5cGUgeyBBdXRoSW50ZW50IH0gZnJvbSBcIkAvYWN0b3IvY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFjdG9yRGVmaW5pdGlvbiB9IGZyb20gXCJAL2FjdG9yL2RlZmluaXRpb25cIjtcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tIFwiQC9hY3Rvci9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgUmVnaXN0cnlDb25maWcgfSBmcm9tIFwiQC9yZWdpc3RyeS9jb25maWdcIjtcbmltcG9ydCB7IHN0cmluZ2lmeUVycm9yIH0gZnJvbSBcIkAvdXRpbHNcIjtcbmltcG9ydCB0eXBlIHsgTWFuYWdlckRyaXZlciB9IGZyb20gXCIuL2RyaXZlclwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQgdHlwZSB7IEFjdG9yUXVlcnkgfSBmcm9tIFwiLi9wcm90b2NvbC9xdWVyeVwiO1xuXG4vKipcbiAqIEdldCBhdXRoZW50aWNhdGlvbiBpbnRlbnRzIGZyb20gYSBhY3RvciBxdWVyeVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW50ZW50c0Zyb21RdWVyeShxdWVyeTogQWN0b3JRdWVyeSk6IFNldDxBdXRoSW50ZW50PiB7XG5cdGNvbnN0IGludGVudHMgPSBuZXcgU2V0PEF1dGhJbnRlbnQ+KCk7XG5cblx0aWYgKFwiZ2V0Rm9ySWRcIiBpbiBxdWVyeSkge1xuXHRcdGludGVudHMuYWRkKFwiZ2V0XCIpO1xuXHR9IGVsc2UgaWYgKFwiZ2V0Rm9yS2V5XCIgaW4gcXVlcnkpIHtcblx0XHRpbnRlbnRzLmFkZChcImdldFwiKTtcblx0fSBlbHNlIGlmIChcImdldE9yQ3JlYXRlRm9yS2V5XCIgaW4gcXVlcnkpIHtcblx0XHRpbnRlbnRzLmFkZChcImdldFwiKTtcblx0XHRpbnRlbnRzLmFkZChcImNyZWF0ZVwiKTtcblx0fSBlbHNlIGlmIChcImNyZWF0ZVwiIGluIHF1ZXJ5KSB7XG5cdFx0aW50ZW50cy5hZGQoXCJjcmVhdGVcIik7XG5cdH1cblxuXHRyZXR1cm4gaW50ZW50cztcbn1cblxuLyoqXG4gKiBHZXQgYWN0b3IgbmFtZSBmcm9tIGEgYWN0b3IgcXVlcnlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFjdG9yTmFtZUZyb21RdWVyeShcblx0YzogSG9ub0NvbnRleHQsXG5cdGRyaXZlcjogTWFuYWdlckRyaXZlcixcblx0cXVlcnk6IEFjdG9yUXVlcnksXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuXHRpZiAoXCJnZXRGb3JJZFwiIGluIHF1ZXJ5KSB7XG5cdFx0Ly8gVE9ETzogVGhpcyB3aWxsIGhhdmUgYSBkdXBsaWNhdGUgY2FsbCB0byBnZXRGb3JJZCBiZXR3ZWVuIHRoaXMgYW5kIHF1ZXJ5QWN0b3Jcblx0XHRjb25zdCBvdXRwdXQgPSBhd2FpdCBkcml2ZXIuZ2V0Rm9ySWQoe1xuXHRcdFx0Yyxcblx0XHRcdG5hbWU6IHF1ZXJ5LmdldEZvcklkLm5hbWUsXG5cdFx0XHRhY3RvcklkOiBxdWVyeS5nZXRGb3JJZC5hY3RvcklkLFxuXHRcdH0pO1xuXHRcdGlmICghb3V0cHV0KSB0aHJvdyBuZXcgZXJyb3JzLkFjdG9yTm90Rm91bmQocXVlcnkuZ2V0Rm9ySWQuYWN0b3JJZCk7XG5cdFx0cmV0dXJuIG91dHB1dC5uYW1lO1xuXHR9IGVsc2UgaWYgKFwiZ2V0Rm9yS2V5XCIgaW4gcXVlcnkpIHtcblx0XHRyZXR1cm4gcXVlcnkuZ2V0Rm9yS2V5Lm5hbWU7XG5cdH0gZWxzZSBpZiAoXCJnZXRPckNyZWF0ZUZvcktleVwiIGluIHF1ZXJ5KSB7XG5cdFx0cmV0dXJuIHF1ZXJ5LmdldE9yQ3JlYXRlRm9yS2V5Lm5hbWU7XG5cdH0gZWxzZSBpZiAoXCJjcmVhdGVcIiBpbiBxdWVyeSkge1xuXHRcdHJldHVybiBxdWVyeS5jcmVhdGUubmFtZTtcblx0fSBlbHNlIHtcblx0XHR0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRSZXF1ZXN0KFwiSW52YWxpZCBxdWVyeSBmb3JtYXRcIik7XG5cdH1cbn1cblxuLyoqXG4gKiBBdXRoZW50aWNhdGUgYSByZXF1ZXN0IHVzaW5nIHRoZSBhY3RvcidzIG9uQXV0aCBmdW5jdGlvblxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXV0aGVudGljYXRlUmVxdWVzdChcblx0YzogSG9ub0NvbnRleHQsXG5cdGFjdG9yRGVmaW5pdGlvbjogQW55QWN0b3JEZWZpbml0aW9uLFxuXHRpbnRlbnRzOiBTZXQ8QXV0aEludGVudD4sXG5cdHBhcmFtczogdW5rbm93bixcbik6IFByb21pc2U8dW5rbm93bj4ge1xuXHRpZiAoIShcIm9uQXV0aFwiIGluIGFjdG9yRGVmaW5pdGlvbi5jb25maWcpKSB7XG5cdFx0dGhyb3cgbmV3IGVycm9ycy5Gb3JiaWRkZW4oXG5cdFx0XHRcIkFjdG9yIHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uIGJ1dCBubyBvbkF1dGggaGFuZGxlciBpcyBkZWZpbmVkIChodHRwczovL3JpdmV0LmdnL2RvY3MvYWN0b3JzL2F1dGhlbnRpY2F0aW9uLykuIFByb3ZpZGUgYW4gZW1wdHkgaGFuZGxlciB0byBkaXNhYmxlIGF1dGg6IGBvbkF1dGg6ICgpID0+IHt9YFwiLFxuXHRcdCk7XG5cdH1cblxuXHR0cnkge1xuXHRcdGNvbnN0IGRhdGFPclByb21pc2UgPSBhY3RvckRlZmluaXRpb24uY29uZmlnLm9uQXV0aChcblx0XHRcdHtcblx0XHRcdFx0cmVxdWVzdDogYy5yZXEucmF3LFxuXHRcdFx0XHRpbnRlbnRzLFxuXHRcdFx0fSxcblx0XHRcdHBhcmFtcyxcblx0XHQpO1xuXHRcdGlmIChkYXRhT3JQcm9taXNlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuXHRcdFx0cmV0dXJuIGF3YWl0IGRhdGFPclByb21pc2U7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBkYXRhT3JQcm9taXNlO1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRsb2dnZXIoKS5pbmZvKFwiYXV0aGVudGljYXRpb24gZXJyb3JcIiwgeyBlcnJvcjogc3RyaW5naWZ5RXJyb3IoZXJyb3IpIH0pO1xuXHRcdHRocm93IGVycm9yO1xuXHR9XG59XG5cbi8qKlxuICogU2ltcGxpZmllZCBhdXRoZW50aWNhdGlvbiBmb3IgZW5kcG9pbnRzIHRoYXQgY29tYmluZXMgYWxsIGF1dGggc3RlcHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF1dGhlbnRpY2F0ZUVuZHBvaW50KFxuXHRjOiBIb25vQ29udGV4dCxcblx0ZHJpdmVyOiBNYW5hZ2VyRHJpdmVyLFxuXHRyZWdpc3RyeUNvbmZpZzogUmVnaXN0cnlDb25maWcsXG5cdHF1ZXJ5OiBBY3RvclF1ZXJ5LFxuXHRhZGRpdGlvbmFsSW50ZW50czogQXV0aEludGVudFtdLFxuXHRwYXJhbXM6IHVua25vd24sXG4pOiBQcm9taXNlPHVua25vd24+IHtcblx0Ly8gR2V0IGJhc2UgaW50ZW50cyBmcm9tIHF1ZXJ5XG5cdGNvbnN0IGludGVudHMgPSBnZXRJbnRlbnRzRnJvbVF1ZXJ5KHF1ZXJ5KTtcblxuXHQvLyBBZGQgZW5kcG9pbnQtc3BlY2lmaWMgaW50ZW50c1xuXHRmb3IgKGNvbnN0IGludGVudCBvZiBhZGRpdGlvbmFsSW50ZW50cykge1xuXHRcdGludGVudHMuYWRkKGludGVudCk7XG5cdH1cblxuXHQvLyBHZXQgYWN0b3IgZGVmaW5pdGlvblxuXHRjb25zdCBhY3Rvck5hbWUgPSBhd2FpdCBnZXRBY3Rvck5hbWVGcm9tUXVlcnkoYywgZHJpdmVyLCBxdWVyeSk7XG5cdGNvbnN0IGFjdG9yRGVmaW5pdGlvbiA9IHJlZ2lzdHJ5Q29uZmlnLnVzZVthY3Rvck5hbWVdO1xuXHRpZiAoIWFjdG9yRGVmaW5pdGlvbikge1xuXHRcdHRocm93IG5ldyBlcnJvcnMuQWN0b3JOb3RGb3VuZChhY3Rvck5hbWUpO1xuXHR9XG5cblx0Ly8gQXV0aGVudGljYXRlXG5cdHJldHVybiBhd2FpdCBhdXRoZW50aWNhdGVSZXF1ZXN0KGMsIGFjdG9yRGVmaW5pdGlvbiwgaW50ZW50cywgcGFyYW1zKTtcbn1cbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3JlZ2lzdHJ5L2NvbmZpZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeS9jb25maWcudHNcIjsvLyEgVGhlc2UgY29uZmlncyBjb25maWdzIGhvbGQgYW55dGhpbmcgdGhhdCdzIG5vdCBwbGF0Zm9ybS1zcGVjaWZpYyBhYm91dCBydW5uaW5nIGFjdG9ycy5cblxuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQWN0b3JEZWZpbml0aW9uLCBBbnlBY3RvckRlZmluaXRpb24gfSBmcm9tIFwiQC9hY3Rvci9kZWZpbml0aW9uXCI7XG5cbmV4cG9ydCBjb25zdCBBY3RvcnNTY2hlbWEgPSB6LnJlY29yZChcblx0ei5zdHJpbmcoKSxcblx0ei5jdXN0b208QWN0b3JEZWZpbml0aW9uPGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55Pj4oKSxcbik7XG5leHBvcnQgdHlwZSBSZWdpc3RyeUFjdG9ycyA9IHouaW5mZXI8dHlwZW9mIEFjdG9yc1NjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBUZXN0Q29uZmlnU2NoZW1hID0gei5vYmplY3QoeyBlbmFibGVkOiB6LmJvb2xlYW4oKSB9KTtcbmV4cG9ydCB0eXBlIFRlc3RDb25maWcgPSB6LmluZmVyPHR5cGVvZiBUZXN0Q29uZmlnU2NoZW1hPjtcblxuLyoqIEJhc2UgY29uZmlnIHVzZWQgZm9yIHRoZSBhY3RvciBjb25maWcgYWNyb3NzIGFsbCBwbGF0Zm9ybXMuICovXG5leHBvcnQgY29uc3QgUmVnaXN0cnlDb25maWdTY2hlbWEgPSB6Lm9iamVjdCh7XG5cdHVzZTogei5yZWNvcmQoei5zdHJpbmcoKSwgei5jdXN0b208QW55QWN0b3JEZWZpbml0aW9uPigpKSxcblxuXHQvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSBvZiBwYXNzaW5nIGFyb3VuZCB0aGUgdGVzdCBjb25maWdcblx0LyoqXG5cdCAqIFRlc3QgY29uZmlndXJhdGlvbi5cblx0ICpcblx0ICogRE8gTk9UIE1BTlVBTExZIEVOQUJMRS4gVEhJUyBJUyBVU0VEIElOVEVSTkFMTFkuXG5cdCAqIEBpbnRlcm5hbFxuXHQgKiovXG5cdHRlc3Q6IFRlc3RDb25maWdTY2hlbWEub3B0aW9uYWwoKS5kZWZhdWx0KHsgZW5hYmxlZDogZmFsc2UgfSksXG59KTtcbmV4cG9ydCB0eXBlIFJlZ2lzdHJ5Q29uZmlnID0gei5pbmZlcjx0eXBlb2YgUmVnaXN0cnlDb25maWdTY2hlbWE+O1xuZXhwb3J0IHR5cGUgUmVnaXN0cnlDb25maWdJbnB1dDxBIGV4dGVuZHMgUmVnaXN0cnlBY3RvcnM+ID0gT21pdDxcblx0ei5pbnB1dDx0eXBlb2YgUmVnaXN0cnlDb25maWdTY2hlbWE+LFxuXHRcInVzZVwiXG4+ICYgeyB1c2U6IEEgfTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvc3JjL3JlZ2lzdHJ5L2xvZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeS9sb2cudHNcIjtpbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQC9jb21tb24vL2xvZ1wiO1xuXG5leHBvcnQgY29uc3QgTE9HR0VSX05BTUUgPSBcInJlZ2lzdHJ5XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dnZXIoKSB7XG5cdHJldHVybiBnZXRMb2dnZXIoTE9HR0VSX05BTUUpO1xufVxuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnkvc2VydmUudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnlcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnkvc2VydmUudHNcIjtpbXBvcnQgeyBIb25vIH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB7IGdldEVudlVuaXZlcnNhbCB9IGZyb20gXCJAL3V0aWxzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyb3NzUGxhdGZvcm1TZXJ2ZShcblx0cml2ZXRLaXRSb3V0ZXI6IEhvbm88YW55Pixcblx0dXNlclJvdXRlcjogSG9ubyB8IHVuZGVmaW5lZCxcbikge1xuXHRjb25zdCBhcHAgPSB1c2VyUm91dGVyID8/IG5ldyBIb25vKCk7XG5cblx0Ly8gSW1wb3J0IEBob25vL25vZGUtc2VydmVyXG5cdGxldCBzZXJ2ZTogYW55O1xuXHR0cnkge1xuXHRcdGNvbnN0IGRlcCA9IGF3YWl0IGltcG9ydChcIkBob25vL25vZGUtc2VydmVyXCIpO1xuXHRcdHNlcnZlID0gZGVwLnNlcnZlO1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRsb2dnZXIoKS5lcnJvcihcblx0XHRcdFwiZmFpbGVkIHRvIGltcG9ydCBAaG9uby9ub2RlLXNlcnZlci4gcGxlYXNlIHJ1biAnbnBtIGluc3RhbGwgQGhvbm8vbm9kZS1zZXJ2ZXIgQGhvbm8vbm9kZS13cydcIixcblx0XHQpO1xuXHRcdHByb2Nlc3MuZXhpdCgxKTtcblx0fVxuXG5cdC8vIE1vdW50IHJlZ2lzdHJ5XG5cdGFwcC5yb3V0ZShcIi9yZWdpc3RyeVwiLCByaXZldEtpdFJvdXRlcik7XG5cblx0Ly8gSW1wb3J0IEBob25vL25vZGUtd3Ncblx0bGV0IGNyZWF0ZU5vZGVXZWJTb2NrZXQ6IGFueTtcblx0dHJ5IHtcblx0XHRjb25zdCBkZXAgPSBhd2FpdCBpbXBvcnQoXCJAaG9uby9ub2RlLXdzXCIpO1xuXHRcdGNyZWF0ZU5vZGVXZWJTb2NrZXQgPSBkZXAuY3JlYXRlTm9kZVdlYlNvY2tldDtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0bG9nZ2VyKCkuZXJyb3IoXG5cdFx0XHRcImZhaWxlZCB0byBpbXBvcnQgQGhvbm8vbm9kZS13cy4gcGxlYXNlIHJ1biAnbnBtIGluc3RhbGwgQGhvbm8vbm9kZS1zZXJ2ZXIgQGhvbm8vbm9kZS13cydcIixcblx0XHQpO1xuXHRcdHByb2Nlc3MuZXhpdCgxKTtcblx0fVxuXG5cdC8vIEluamVjdCBXU1xuXHRjb25zdCB7IGluamVjdFdlYlNvY2tldCwgdXBncmFkZVdlYlNvY2tldCB9ID0gY3JlYXRlTm9kZVdlYlNvY2tldCh7XG5cdFx0YXBwLFxuXHR9KTtcblxuXHQvLyBTdGFydCBzZXJ2ZXJcblx0Y29uc3QgcG9ydCA9IE51bWJlci5wYXJzZUludChcblx0XHRnZXRFbnZVbml2ZXJzYWwoXCJQT1JUXCIpID8/IGdldEVudlVuaXZlcnNhbChcIlBPUlRfSFRUUFwiKSA/PyBcIjgwODBcIixcblx0KTtcblx0Y29uc3Qgc2VydmVyID0gc2VydmUoeyBmZXRjaDogYXBwLmZldGNoLCBwb3J0IH0sICgpID0+XG5cdFx0bG9nZ2VyKCkuaW5mbyhcInNlcnZlciBsaXN0ZW5pbmdcIiwgeyBwb3J0IH0pLFxuXHQpO1xuXHRpbmplY3RXZWJTb2NrZXQoc2VydmVyKTtcblxuXHRyZXR1cm4geyB1cGdyYWRlV2ViU29ja2V0IH07XG59XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L3NyYy9yZWdpc3RyeS9tb2QudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnlcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9zcmMvcmVnaXN0cnkvbW9kLnRzXCI7aW1wb3J0IHR5cGUgeyBIb25vIH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB7IGNyZWF0ZUFjdG9yUm91dGVyIH0gZnJvbSBcIkAvYWN0b3Ivcm91dGVyXCI7XG5pbXBvcnQgeyB0eXBlIENsaWVudCwgY3JlYXRlQ2xpZW50V2l0aERyaXZlciB9IGZyb20gXCJAL2NsaWVudC9jbGllbnRcIjtcbmltcG9ydCB7IGNob29zZURlZmF1bHREcml2ZXIgfSBmcm9tIFwiQC9kcml2ZXJzL2RlZmF1bHRcIjtcbmltcG9ydCB7IGNyZWF0ZUlubGluZUNsaWVudERyaXZlciB9IGZyb20gXCJAL2lubGluZS1jbGllbnQtZHJpdmVyL21vZFwiO1xuaW1wb3J0IHsgZ2V0SW5zcGVjdG9yVXJsIH0gZnJvbSBcIkAvaW5zcGVjdG9yL3V0aWxzXCI7XG5pbXBvcnQgeyBjcmVhdGVNYW5hZ2VyUm91dGVyIH0gZnJvbSBcIkAvbWFuYWdlci9yb3V0ZXJcIjtcbmltcG9ydCB7XG5cdHR5cGUgUmVnaXN0cnlBY3RvcnMsXG5cdHR5cGUgUmVnaXN0cnlDb25maWcsXG5cdHR5cGUgUmVnaXN0cnlDb25maWdJbnB1dCxcblx0UmVnaXN0cnlDb25maWdTY2hlbWEsXG59IGZyb20gXCIuL2NvbmZpZ1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nXCI7XG5pbXBvcnQge1xuXHR0eXBlIERyaXZlckNvbmZpZyxcblx0dHlwZSBSdW5Db25maWcsXG5cdHR5cGUgUnVuQ29uZmlnSW5wdXQsXG5cdFJ1bkNvbmZpZ1NjaGVtYSxcbn0gZnJvbSBcIi4vcnVuLWNvbmZpZ1wiO1xuaW1wb3J0IHsgY3Jvc3NQbGF0Zm9ybVNlcnZlIH0gZnJvbSBcIi4vc2VydmVcIjtcblxuaW50ZXJmYWNlIFNlcnZlck91dHB1dDxBIGV4dGVuZHMgUmVnaXN0cnk8YW55Pj4ge1xuXHRjbGllbnQ6IENsaWVudDxBPjtcblx0aG9ubzogSG9ubztcblx0aGFuZGxlcjogKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT47XG5cdHNlcnZlOiAoaG9ubz86IEhvbm8pID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBSZWdpc3RyeTxBIGV4dGVuZHMgUmVnaXN0cnlBY3RvcnM+IHtcblx0I2NvbmZpZzogUmVnaXN0cnlDb25maWc7XG5cblx0cHVibGljIGdldCBjb25maWcoKTogUmVnaXN0cnlDb25maWcge1xuXHRcdHJldHVybiB0aGlzLiNjb25maWc7XG5cdH1cblxuXHRjb25zdHJ1Y3Rvcihjb25maWc6IFJlZ2lzdHJ5Q29uZmlnKSB7XG5cdFx0dGhpcy4jY29uZmlnID0gY29uZmlnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIHJlZ2lzdHJ5IGZvciBhIHNlcnZlci5cblx0ICovXG5cdHB1YmxpYyBjcmVhdGVTZXJ2ZXIoaW5wdXRDb25maWc/OiBSdW5Db25maWdJbnB1dCk6IFNlcnZlck91dHB1dDx0aGlzPiB7XG5cdFx0Y29uc3QgY29uZmlnID0gUnVuQ29uZmlnU2NoZW1hLnBhcnNlKGlucHV0Q29uZmlnKTtcblxuXHRcdC8vIENob29zZSB0aGUgZHJpdmVyIGJhc2VkIG9uIGNvbmZpZ3VyYXRpb25cblx0XHRjb25zdCBkcml2ZXIgPSBjaG9vc2VEZWZhdWx0RHJpdmVyKGNvbmZpZyk7XG5cblx0XHQvLyBDb25maWd1cmUgZ2V0VXBncmFkZVdlYlNvY2tldCBsYXppbHkgc28gd2UgY2FuIGFzc2lnbiBpdCBpbiBjcm9zc1BsYXRmb3JtU2VydmVcblx0XHRsZXQgdXBncmFkZVdlYlNvY2tldDogYW55O1xuXHRcdGlmICghY29uZmlnLmdldFVwZ3JhZGVXZWJTb2NrZXQpIHtcblx0XHRcdGNvbmZpZy5nZXRVcGdyYWRlV2ViU29ja2V0ID0gKCkgPT4gdXBncmFkZVdlYlNvY2tldCE7XG5cdFx0fVxuXG5cdFx0Ly8gQ3JlYXRlIHJvdXRlclxuXHRcdGNvbnN0IG1hbmFnZXJEcml2ZXIgPSBkcml2ZXIubWFuYWdlcih0aGlzLiNjb25maWcsIGNvbmZpZyk7XG5cdFx0Y29uc3QgY2xpZW50RHJpdmVyID0gY3JlYXRlSW5saW5lQ2xpZW50RHJpdmVyKG1hbmFnZXJEcml2ZXIpO1xuXHRcdGNvbnN0IHsgcm91dGVyOiBob25vIH0gPSBjcmVhdGVNYW5hZ2VyUm91dGVyKFxuXHRcdFx0dGhpcy4jY29uZmlnLFxuXHRcdFx0Y29uZmlnLFxuXHRcdFx0Y2xpZW50RHJpdmVyLFxuXHRcdFx0bWFuYWdlckRyaXZlcixcblx0XHRcdGZhbHNlLFxuXHRcdCk7XG5cblx0XHQvLyBDcmVhdGUgY2xpZW50XG5cdFx0Y29uc3QgY2xpZW50ID0gY3JlYXRlQ2xpZW50V2l0aERyaXZlcjx0aGlzPihjbGllbnREcml2ZXIpO1xuXG5cdFx0Y29uc3QgZHJpdmVyTG9nID0gbWFuYWdlckRyaXZlci5leHRyYVN0YXJ0dXBMb2c/LigpID8/IHt9O1xuXHRcdGxvZ2dlcigpLmluZm8oXCJyaXZldGtpdCByZWFkeVwiLCB7XG5cdFx0XHRkcml2ZXI6IGRyaXZlci5uYW1lLFxuXHRcdFx0ZGVmaW5pdGlvbnM6IE9iamVjdC5rZXlzKHRoaXMuI2NvbmZpZy51c2UpLmxlbmd0aCxcblx0XHRcdC4uLmRyaXZlckxvZyxcblx0XHR9KTtcblx0XHRpZiAoY29uZmlnLmluc3BlY3Rvcj8uZW5hYmxlZCkge1xuXHRcdFx0bG9nZ2VyKCkuaW5mbyhcImluc3BlY3RvciByZWFkeVwiLCB7XG5cdFx0XHRcdHVybDogZ2V0SW5zcGVjdG9yVXJsKGNvbmZpZyksXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHQvLyBDcmVhdGUgcnVubmVyXG5cdFx0aWYgKGNvbmZpZy5yb2xlID09PSBcImFsbFwiIHx8IGNvbmZpZy5yb2xlID09PSBcInJ1bm5lclwiKSB7XG5cdFx0XHRjb25zdCBpbmxpbmVDbGllbnQgPSBjcmVhdGVDbGllbnRXaXRoRHJpdmVyKFxuXHRcdFx0XHRjcmVhdGVJbmxpbmVDbGllbnREcml2ZXIobWFuYWdlckRyaXZlciksXG5cdFx0XHQpO1xuXHRcdFx0Y29uc3QgX2FjdG9yRHJpdmVyID0gZHJpdmVyLmFjdG9yKFxuXHRcdFx0XHR0aGlzLiNjb25maWcsXG5cdFx0XHRcdGNvbmZpZyxcblx0XHRcdFx0bWFuYWdlckRyaXZlcixcblx0XHRcdFx0aW5saW5lQ2xpZW50LFxuXHRcdFx0KTtcblx0XHRcdC8vIFRPRE86IFdoYXQgZG8gd2UgZG8gd2l0aCB0aGUgYWN0b3IgZHJpdmVyIGhlcmU/XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHtcblx0XHRcdGNsaWVudCxcblx0XHRcdGhvbm8sXG5cdFx0XHRoYW5kbGVyOiBhc3luYyAocmVxOiBSZXF1ZXN0KSA9PiBhd2FpdCBob25vLmZldGNoKHJlcSksXG5cdFx0XHRzZXJ2ZTogYXN5bmMgKGFwcCkgPT4ge1xuXHRcdFx0XHRjb25zdCBvdXQgPSBhd2FpdCBjcm9zc1BsYXRmb3JtU2VydmUoaG9ubywgYXBwKTtcblx0XHRcdFx0dXBncmFkZVdlYlNvY2tldCA9IG91dC51cGdyYWRlV2ViU29ja2V0O1xuXHRcdFx0fSxcblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIHJlZ2lzdHJ5IGFzIGEgc3RhbmRhbG9uZSBzZXJ2ZXIuXG5cdCAqL1xuXHRwdWJsaWMgYXN5bmMgcnVuU2VydmVyKGlucHV0Q29uZmlnPzogUnVuQ29uZmlnSW5wdXQpIHtcblx0XHRjb25zdCB7IHNlcnZlIH0gPSB0aGlzLmNyZWF0ZVNlcnZlcihpbnB1dENvbmZpZyk7XG5cdFx0c2VydmUoKTtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXA8QSBleHRlbmRzIFJlZ2lzdHJ5QWN0b3JzPihcblx0aW5wdXQ6IFJlZ2lzdHJ5Q29uZmlnSW5wdXQ8QT4sXG4pOiBSZWdpc3RyeTxBPiB7XG5cdGNvbnN0IGNvbmZpZyA9IFJlZ2lzdHJ5Q29uZmlnU2NoZW1hLnBhcnNlKGlucHV0KTtcblx0cmV0dXJuIG5ldyBSZWdpc3RyeShjb25maWcpO1xufVxuXG5leHBvcnQgdHlwZSB7IFJlZ2lzdHJ5Q29uZmlnLCBSZWdpc3RyeUFjdG9ycywgUnVuQ29uZmlnLCBEcml2ZXJDb25maWcgfTtcbmV4cG9ydCB7IFJlZ2lzdHJ5Q29uZmlnU2NoZW1hIH07XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2FjdGlvbi1pbnB1dHMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2FjdGlvbi1pbnB1dHMudHNcIjtpbXBvcnQgeyBhY3RvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlIHtcblx0aW5pdGlhbElucHV0PzogdW5rbm93bjtcblx0b25DcmVhdGVJbnB1dD86IHVua25vd247XG59XG5cbi8vIFRlc3QgYWN0b3IgdGhhdCBjYW4gY2FwdHVyZSBpbnB1dCBkdXJpbmcgY3JlYXRpb25cbmV4cG9ydCBjb25zdCBpbnB1dEFjdG9yID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRjcmVhdGVTdGF0ZTogKGMsIGlucHV0KTogU3RhdGUgPT4ge1xuXHRcdHJldHVybiB7XG5cdFx0XHRpbml0aWFsSW5wdXQ6IGlucHV0LFxuXHRcdFx0b25DcmVhdGVJbnB1dDogdW5kZWZpbmVkLFxuXHRcdH07XG5cdH0sXG5cblx0b25DcmVhdGU6IChjLCBpbnB1dCkgPT4ge1xuXHRcdGMuc3RhdGUub25DcmVhdGVJbnB1dCA9IGlucHV0O1xuXHR9LFxuXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRJbnB1dHM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRpbml0aWFsSW5wdXQ6IGMuc3RhdGUuaW5pdGlhbElucHV0LFxuXHRcdFx0XHRvbkNyZWF0ZUlucHV0OiBjLnN0YXRlLm9uQ3JlYXRlSW5wdXQsXG5cdFx0XHR9O1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvYWN0aW9uLXRpbWVvdXQudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2FjdGlvbi10aW1lb3V0LnRzXCI7aW1wb3J0IHsgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuLy8gU2hvcnQgdGltZW91dCBhY3RvclxuZXhwb3J0IGNvbnN0IHNob3J0VGltZW91dEFjdG9yID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZTogeyB2YWx1ZTogMCB9LFxuXHRvcHRpb25zOiB7XG5cdFx0YWN0aW9uVGltZW91dDogNTAsIC8vIDUwbXMgdGltZW91dFxuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0cXVpY2tBY3Rpb246IGFzeW5jIChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gXCJxdWljayByZXNwb25zZVwiO1xuXHRcdH0sXG5cdFx0c2xvd0FjdGlvbjogYXN5bmMgKGMpID0+IHtcblx0XHRcdC8vIFRoaXMgYWN0aW9uIHNob3VsZCB0aW1lb3V0XG5cdFx0XHRhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDApKTtcblx0XHRcdHJldHVybiBcInNsb3cgcmVzcG9uc2VcIjtcblx0XHR9LFxuXHR9LFxufSk7XG5cbi8vIExvbmcgdGltZW91dCBhY3RvclxuZXhwb3J0IGNvbnN0IGxvbmdUaW1lb3V0QWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHZhbHVlOiAwIH0sXG5cdG9wdGlvbnM6IHtcblx0XHRhY3Rpb25UaW1lb3V0OiAyMDAsIC8vIDIwMG1zIHRpbWVvdXRcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGRlbGF5ZWRBY3Rpb246IGFzeW5jIChjKSA9PiB7XG5cdFx0XHQvLyBUaGlzIGFjdGlvbiBzaG91bGQgY29tcGxldGUgd2l0aGluIHRpbWVvdXRcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCkpO1xuXHRcdFx0cmV0dXJuIFwiZGVsYXllZCByZXNwb25zZVwiO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gRGVmYXVsdCB0aW1lb3V0IGFjdG9yXG5leHBvcnQgY29uc3QgZGVmYXVsdFRpbWVvdXRBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0YWN0aW9uczoge1xuXHRcdG5vcm1hbEFjdGlvbjogYXN5bmMgKGMpID0+IHtcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDUwKSk7XG5cdFx0XHRyZXR1cm4gXCJub3JtYWwgcmVzcG9uc2VcIjtcblx0XHR9LFxuXHR9LFxufSk7XG5cbi8vIFN5bmMgYWN0b3IgKHRpbWVvdXQgc2hvdWxkbid0IGFwcGx5KVxuZXhwb3J0IGNvbnN0IHN5bmNUaW1lb3V0QWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHZhbHVlOiAwIH0sXG5cdG9wdGlvbnM6IHtcblx0XHRhY3Rpb25UaW1lb3V0OiA1MCwgLy8gNTBtcyB0aW1lb3V0XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRzeW5jQWN0aW9uOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIFwic3luYyByZXNwb25zZVwiO1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvYWN0aW9uLXR5cGVzLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9hY3Rpb24tdHlwZXMudHNcIjtpbXBvcnQgeyBhY3RvciwgVXNlckVycm9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbi8vIEFjdG9yIHdpdGggc3luY2hyb25vdXMgYWN0aW9uc1xuZXhwb3J0IGNvbnN0IHN5bmNBY3Rpb25BY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0YWN0aW9uczoge1xuXHRcdC8vIFNpbXBsZSBzeW5jaHJvbm91cyBhY3Rpb24gdGhhdCByZXR1cm5zIGEgdmFsdWUgZGlyZWN0bHlcblx0XHRpbmNyZW1lbnQ6IChjLCBhbW91bnQgPSAxKSA9PiB7XG5cdFx0XHRjLnN0YXRlLnZhbHVlICs9IGFtb3VudDtcblx0XHRcdHJldHVybiBjLnN0YXRlLnZhbHVlO1xuXHRcdH0sXG5cdFx0Ly8gU3luY2hyb25vdXMgYWN0aW9uIHRoYXQgcmV0dXJucyBhbiBvYmplY3Rcblx0XHRnZXRJbmZvOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0Y3VycmVudFZhbHVlOiBjLnN0YXRlLnZhbHVlLFxuXHRcdFx0XHR0aW1lc3RhbXA6IERhdGUubm93KCksXG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0Ly8gU3luY2hyb25vdXMgYWN0aW9uIHdpdGggbm8gcmV0dXJuIHZhbHVlICh2b2lkKVxuXHRcdHJlc2V0OiAoYykgPT4ge1xuXHRcdFx0Yy5zdGF0ZS52YWx1ZSA9IDA7XG5cdFx0fSxcblx0fSxcbn0pO1xuXG4vLyBBY3RvciB3aXRoIGFzeW5jaHJvbm91cyBhY3Rpb25zXG5leHBvcnQgY29uc3QgYXN5bmNBY3Rpb25BY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAsIGRhdGE6IG51bGwgYXMgYW55IH0sXG5cdGFjdGlvbnM6IHtcblx0XHQvLyBBc3luYyBhY3Rpb24gd2l0aCBhIGRlbGF5XG5cdFx0ZGVsYXllZEluY3JlbWVudDogYXN5bmMgKGMsIGFtb3VudCA9IDEpID0+IHtcblx0XHRcdGF3YWl0IFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdFx0Yy5zdGF0ZS52YWx1ZSArPSBhbW91bnQ7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS52YWx1ZTtcblx0XHR9LFxuXHRcdC8vIEFzeW5jIGFjdGlvbiB0aGF0IHNpbXVsYXRlcyBhbiBBUEkgY2FsbFxuXHRcdGZldGNoRGF0YTogYXN5bmMgKGMsIGlkOiBzdHJpbmcpID0+IHtcblx0XHRcdGF3YWl0IFByb21pc2UucmVzb2x2ZSgpO1xuXG5cdFx0XHQvLyBTaW11bGF0ZSByZXNwb25zZSBkYXRhXG5cdFx0XHRjb25zdCBkYXRhID0geyBpZCwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH07XG5cdFx0XHRjLnN0YXRlLmRhdGEgPSBkYXRhO1xuXHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0fSxcblx0XHQvLyBBc3luYyBhY3Rpb24gd2l0aCBlcnJvciBoYW5kbGluZ1xuXHRcdGFzeW5jV2l0aEVycm9yOiBhc3luYyAoYywgc2hvdWxkRXJyb3I6IGJvb2xlYW4pID0+IHtcblx0XHRcdGF3YWl0IFByb21pc2UucmVzb2x2ZSgpO1xuXG5cdFx0XHRpZiAoc2hvdWxkRXJyb3IpIHtcblx0XHRcdFx0dGhyb3cgbmV3IFVzZXJFcnJvcihcIkludGVudGlvbmFsIGVycm9yXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gXCJTdWNjZXNzXCI7XG5cdFx0fSxcblx0fSxcbn0pO1xuXG4vLyBBY3RvciB3aXRoIHByb21pc2UgYWN0aW9uc1xuZXhwb3J0IGNvbnN0IHByb21pc2VBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgcmVzdWx0czogW10gYXMgc3RyaW5nW10gfSxcblx0YWN0aW9uczoge1xuXHRcdC8vIEFjdGlvbiB0aGF0IHJldHVybnMgYSByZXNvbHZlZCBwcm9taXNlXG5cdFx0cmVzb2x2ZWRQcm9taXNlOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZShcInJlc29sdmVkIHZhbHVlXCIpO1xuXHRcdH0sXG5cdFx0Ly8gQWN0aW9uIHRoYXQgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciBhIGRlbGF5XG5cdFx0ZGVsYXllZFByb21pc2U6IChjKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcblx0XHRcdHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlKSA9PiB7XG5cdFx0XHRcdGMuc3RhdGUucmVzdWx0cy5wdXNoKFwiZGVsYXllZFwiKTtcblx0XHRcdFx0cmVzb2x2ZShcImRlbGF5ZWQgdmFsdWVcIik7XG5cdFx0XHR9KTtcblx0XHR9LFxuXHRcdC8vIEFjdGlvbiB0aGF0IHJldHVybnMgYSByZWplY3RlZCBwcm9taXNlXG5cdFx0cmVqZWN0ZWRQcm9taXNlOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBVc2VyRXJyb3IoXCJwcm9taXNlZCByZWplY3Rpb25cIikpO1xuXHRcdH0sXG5cdFx0Ly8gQWN0aW9uIHRvIGNoZWNrIHRoZSBjb2xsZWN0ZWQgcmVzdWx0c1xuXHRcdGdldFJlc3VsdHM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5yZXN1bHRzO1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvYWN0b3Itb25zdGF0ZWNoYW5nZS50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvYWN0b3Itb25zdGF0ZWNoYW5nZS50c1wiO2ltcG9ydCB7IGFjdG9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbmV4cG9ydCBjb25zdCBvblN0YXRlQ2hhbmdlQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7XG5cdFx0dmFsdWU6IDAsXG5cdFx0Y2hhbmdlQ291bnQ6IDAsXG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHQvLyBBY3Rpb24gdGhhdCBtb2RpZmllcyBzdGF0ZSAtIHNob3VsZCB0cmlnZ2VyIG9uU3RhdGVDaGFuZ2Vcblx0XHRzZXRWYWx1ZTogKGMsIG5ld1ZhbHVlOiBudW1iZXIpID0+IHtcblx0XHRcdGMuc3RhdGUudmFsdWUgPSBuZXdWYWx1ZTtcblx0XHRcdHJldHVybiBjLnN0YXRlLnZhbHVlO1xuXHRcdH0sXG5cdFx0Ly8gQWN0aW9uIHRoYXQgbW9kaWZpZXMgc3RhdGUgbXVsdGlwbGUgdGltZXMgLSBzaG91bGQgdHJpZ2dlciBvblN0YXRlQ2hhbmdlIGZvciBlYWNoIGNoYW5nZVxuXHRcdGluY3JlbWVudE11bHRpcGxlOiAoYywgdGltZXM6IG51bWJlcikgPT4ge1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aW1lczsgaSsrKSB7XG5cdFx0XHRcdGMuc3RhdGUudmFsdWUrKztcblx0XHRcdH1cblx0XHRcdHJldHVybiBjLnN0YXRlLnZhbHVlO1xuXHRcdH0sXG5cdFx0Ly8gQWN0aW9uIHRoYXQgZG9lc24ndCBtb2RpZnkgc3RhdGUgLSBzaG91bGQgTk9UIHRyaWdnZXIgb25TdGF0ZUNoYW5nZVxuXHRcdGdldFZhbHVlOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUudmFsdWU7XG5cdFx0fSxcblx0XHQvLyBBY3Rpb24gdGhhdCByZWFkcyBhbmQgcmV0dXJucyB3aXRob3V0IG1vZGlmeWluZyAtIHNob3VsZCBOT1QgdHJpZ2dlciBvblN0YXRlQ2hhbmdlXG5cdFx0Z2V0RG91YmxlZDogKGMpID0+IHtcblx0XHRcdGNvbnN0IGRvdWJsZWQgPSBjLnN0YXRlLnZhbHVlICogMjtcblx0XHRcdHJldHVybiBkb3VibGVkO1xuXHRcdH0sXG5cdFx0Ly8gR2V0IHRoZSBjb3VudCBvZiBob3cgbWFueSB0aW1lcyBvblN0YXRlQ2hhbmdlIHdhcyBjYWxsZWRcblx0XHRnZXRDaGFuZ2VDb3VudDogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnN0YXRlLmNoYW5nZUNvdW50O1xuXHRcdH0sXG5cdFx0Ly8gUmVzZXQgY2hhbmdlIGNvdW50ZXIgZm9yIHRlc3Rpbmdcblx0XHRyZXNldENoYW5nZUNvdW50OiAoYykgPT4ge1xuXHRcdFx0Yy5zdGF0ZS5jaGFuZ2VDb3VudCA9IDA7XG5cdFx0fSxcblx0fSxcblx0Ly8gVHJhY2sgb25TdGF0ZUNoYW5nZSBjYWxsc1xuXHRvblN0YXRlQ2hhbmdlOiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuY2hhbmdlQ291bnQrKztcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9hdXRoLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9hdXRoLnRzXCI7aW1wb3J0IHsgYWN0b3IsIFVzZXJFcnJvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG4vLyBCYXNpYyBhdXRoIGFjdG9yIC0gcmVxdWlyZXMgQVBJIGtleVxuZXhwb3J0IGNvbnN0IGF1dGhBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHsgcmVxdWVzdHM6IDAgfSxcblx0b25BdXRoOiAob3B0cywgcGFyYW1zOiB7IGFwaUtleT86IHN0cmluZyB9IHwgdW5kZWZpbmVkKSA9PiB7XG5cdFx0Y29uc3QgYXBpS2V5ID0gcGFyYW1zPy5hcGlLZXk7XG5cdFx0aWYgKCFhcGlLZXkpIHtcblx0XHRcdHRocm93IG5ldyBVc2VyRXJyb3IoXCJBUEkga2V5IHJlcXVpcmVkXCIsIHsgY29kZTogXCJtaXNzaW5nX2F1dGhcIiB9KTtcblx0XHR9XG5cblx0XHRpZiAoYXBpS2V5ICE9PSBcInZhbGlkLWFwaS1rZXlcIikge1xuXHRcdFx0dGhyb3cgbmV3IFVzZXJFcnJvcihcIkludmFsaWQgQVBJIGtleVwiLCB7IGNvZGU6IFwiaW52YWxpZF9hdXRoXCIgfSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHsgdXNlcklkOiBcInVzZXIxMjNcIiwgdG9rZW46IGFwaUtleSB9O1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0UmVxdWVzdHM6IChjKSA9PiB7XG5cdFx0XHRjLnN0YXRlLnJlcXVlc3RzKys7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5yZXF1ZXN0cztcblx0XHR9LFxuXHRcdGdldFVzZXJBdXRoOiAoYykgPT4gYy5jb25uLmF1dGgsXG5cdH0sXG59KTtcblxuLy8gSW50ZW50LXNwZWNpZmljIGF1dGggYWN0b3IgLSBjaGVja3MgZGlmZmVyZW50IHBlcm1pc3Npb25zIGZvciBkaWZmZXJlbnQgaW50ZW50c1xuZXhwb3J0IGNvbnN0IGludGVudEF1dGhBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0b25BdXRoOiAoeyByZXF1ZXN0LCBpbnRlbnRzIH0sIHBhcmFtczogeyByb2xlOiBzdHJpbmcgfSkgPT4ge1xuXHRcdGNvbnNvbGUubG9nKFwiaW50ZW50c1wiLCBpbnRlbnRzLCBwYXJhbXMpO1xuXHRcdGNvbnN0IHJvbGUgPSBwYXJhbXMucm9sZTtcblxuXHRcdGlmIChpbnRlbnRzLmhhcyhcImNyZWF0ZVwiKSAmJiByb2xlICE9PSBcImFkbWluXCIpIHtcblx0XHRcdHRocm93IG5ldyBVc2VyRXJyb3IoXCJBZG1pbiByb2xlIHJlcXVpcmVkIGZvciBjcmVhdGUgb3BlcmF0aW9uc1wiLCB7XG5cdFx0XHRcdGNvZGU6IFwiaW5zdWZmaWNpZW50X3Blcm1pc3Npb25zXCIsXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoaW50ZW50cy5oYXMoXCJhY3Rpb25cIikgJiYgIVtcImFkbWluXCIsIFwidXNlclwiXS5pbmNsdWRlcyhyb2xlIHx8IFwiXCIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVXNlckVycm9yKFwiVXNlciBvciBhZG1pbiByb2xlIHJlcXVpcmVkIGZvciBhY3Rpb25zXCIsIHtcblx0XHRcdFx0Y29kZTogXCJpbnN1ZmZpY2llbnRfcGVybWlzc2lvbnNcIixcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiB7IHJvbGUsIHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9O1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0VmFsdWU6IChjKSA9PiBjLnN0YXRlLnZhbHVlLFxuXHRcdHNldFZhbHVlOiAoYywgdmFsdWU6IG51bWJlcikgPT4ge1xuXHRcdFx0Yy5zdGF0ZS52YWx1ZSA9IHZhbHVlO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH0sXG5cdFx0Z2V0QXV0aDogKGMpID0+IGMuY29ubi5hdXRoLFxuXHR9LFxufSk7XG5cbi8vIFB1YmxpYyBhY3RvciAtIGVtcHR5IG9uQXV0aCB0byBhbGxvdyBwdWJsaWMgYWNjZXNzXG5leHBvcnQgY29uc3QgcHVibGljQWN0b3IgPSBhY3Rvcih7XG5cdHN0YXRlOiB7IHZpc2l0b3JzOiAwIH0sXG5cdG9uQXV0aDogKCkgPT4ge1xuXHRcdHJldHVybiBudWxsOyAvLyBBbGxvdyBwdWJsaWMgYWNjZXNzXG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHR2aXNpdDogKGMpID0+IHtcblx0XHRcdGMuc3RhdGUudmlzaXRvcnMrKztcblx0XHRcdHJldHVybiBjLnN0YXRlLnZpc2l0b3JzO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gTm8gYXV0aCBhY3RvciAtIHNob3VsZCBmYWlsIHdoZW4gYWNjZXNzZWQgcHVibGljbHkgKG5vIG9uQXV0aCBkZWZpbmVkKVxuZXhwb3J0IGNvbnN0IG5vQXV0aEFjdG9yID0gYWN0b3Ioe1xuXHRzdGF0ZTogeyB2YWx1ZTogNDIgfSxcblx0YWN0aW9uczoge1xuXHRcdGdldFZhbHVlOiAoYykgPT4gYy5zdGF0ZS52YWx1ZSxcblx0fSxcbn0pO1xuXG4vLyBBc3luYyBhdXRoIGFjdG9yIC0gdGVzdHMgcHJvbWlzZS1iYXNlZCBhdXRoZW50aWNhdGlvblxuZXhwb3J0IGNvbnN0IGFzeW5jQXV0aEFjdG9yID0gYWN0b3Ioe1xuXHRzdGF0ZTogeyBjb3VudDogMCB9LFxuXHRvbkF1dGg6IGFzeW5jIChvcHRzLCBwYXJhbXM6IHsgdG9rZW4/OiBzdHJpbmcgfSB8IHVuZGVmaW5lZCkgPT4ge1xuXHRcdGNvbnN0IHRva2VuID0gcGFyYW1zPy50b2tlbjtcblx0XHRpZiAoIXRva2VuKSB7XG5cdFx0XHR0aHJvdyBuZXcgVXNlckVycm9yKFwiVG9rZW4gcmVxdWlyZWRcIiwgeyBjb2RlOiBcIm1pc3NpbmdfdG9rZW5cIiB9KTtcblx0XHR9XG5cblx0XHQvLyBTaW11bGF0ZSB0b2tlbiB2YWxpZGF0aW9uXG5cdFx0aWYgKHRva2VuID09PSBcImludmFsaWRcIikge1xuXHRcdFx0dGhyb3cgbmV3IFVzZXJFcnJvcihcIlRva2VuIGlzIGludmFsaWRcIiwgeyBjb2RlOiBcImludmFsaWRfdG9rZW5cIiB9KTtcblx0XHR9XG5cblx0XHRyZXR1cm4geyB1c2VySWQ6IGB1c2VyLSR7dG9rZW59YCwgdmFsaWRhdGVkOiB0cnVlIH07XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRpbmNyZW1lbnQ6IChjKSA9PiB7XG5cdFx0XHRjLnN0YXRlLmNvdW50Kys7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudDtcblx0XHR9LFxuXHRcdGdldEF1dGhEYXRhOiAoYykgPT4gYy5jb25uLmF1dGgsXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvY29ubi1saXZlbmVzcy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvY29ubi1saXZlbmVzcy50c1wiO2ltcG9ydCB7IGFjdG9yLCBDT05ORUNUSU9OX0RSSVZFUl9XRUJTT0NLRVQgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuZXhwb3J0IGNvbnN0IGNvbm5MaXZlbmVzc0FjdG9yID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZToge1xuXHRcdGNvdW50ZXI6IDAsXG5cdFx0YWNjZXB0aW5nQ29ubmVjdGlvbnM6IHRydWUsXG5cdH0sXG5cdG9wdGlvbnM6IHtcblx0XHRjb25uZWN0aW9uTGl2ZW5lc3NJbnRlcnZhbDogNV8wMDAsXG5cdFx0Y29ubmVjdGlvbkxpdmVuZXNzVGltZW91dDogMl81MDAsXG5cdH0sXG5cdG9uQ29ubmVjdDogKGMsIGNvbm4pID0+IHtcblx0XHRpZiAoIWMuc3RhdGUuYWNjZXB0aW5nQ29ubmVjdGlvbnMpIHtcblx0XHRcdGNvbm4uZGlzY29ubmVjdCgpO1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiQWN0b3IgaXMgbm90IGFjY2VwdGluZyBjb25uZWN0aW9uc1wiKTtcblx0XHR9XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRXc0Nvbm5lY3Rpb25zTGl2ZW5lc3M6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gQXJyYXkuZnJvbShjLmNvbm5zLnZhbHVlcygpKVxuXHRcdFx0XHQuZmlsdGVyKChjb25uKSA9PiBjb25uLmRyaXZlciA9PT0gQ09OTkVDVElPTl9EUklWRVJfV0VCU09DS0VUKVxuXHRcdFx0XHQubWFwKChjb25uKSA9PiAoe1xuXHRcdFx0XHRcdGlkOiBjb25uLmlkLFxuXHRcdFx0XHRcdHN0YXR1czogY29ubi5zdGF0dXMsXG5cdFx0XHRcdFx0bGFzdFNlZW46IGNvbm4ubGFzdFNlZW4sXG5cdFx0XHRcdH0pKTtcblx0XHR9LFxuXHRcdGdldENvbm5lY3Rpb25JZDogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLmNvbm4uaWQ7XG5cdFx0fSxcblx0XHRraWxsOiAoYywgY29ubklkOiBzdHJpbmcpID0+IHtcblx0XHRcdGMuc3RhdGUuYWNjZXB0aW5nQ29ubmVjdGlvbnMgPSBmYWxzZTtcblx0XHRcdC8vIERpc2Nvbm5lY3QgdGhlIGNvbm5lY3Rpb24gd2l0aCB0aGUgZ2l2ZW4gSURcblx0XHRcdC8vIFRoaXMgc2ltdWxhdGVzIGEgbmV0d29yayBmYWlsdXJlIG9yIGEgbWFudWFsIGRpc2Nvbm5lY3Rpb25cblx0XHRcdC8vIFRoZSBjb25uZWN0aW9uIHdpbGwgYmUgY2xlYW5lZCB1cCBieSB0aGUgYWN0b3IgbWFuYWdlciBhZnRlciB0aGUgdGltZW91dFxuXHRcdFx0Y29uc3QgY29ubiA9IGMuY29ubnMuZ2V0KGNvbm5JZCk7XG5cdFx0XHRpZiAoY29ubikge1xuXHRcdFx0XHRjb25uLmRpc2Nvbm5lY3QoKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGdldENvdW50ZXI6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudGVyO1xuXHRcdH0sXG5cdFx0aW5jcmVtZW50OiAoYywgYW1vdW50OiBudW1iZXIpID0+IHtcblx0XHRcdGMuc3RhdGUuY291bnRlciArPSBhbW91bnQ7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudGVyO1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvY29ubi1wYXJhbXMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2Nvbm4tcGFyYW1zLnRzXCI7aW1wb3J0IHsgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuZXhwb3J0IGNvbnN0IGNvdW50ZXJXaXRoUGFyYW1zID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZTogeyBjb3VudDogMCwgaW5pdGlhbGl6ZXJzOiBbXSBhcyBzdHJpbmdbXSB9LFxuXHRjcmVhdGVDb25uU3RhdGU6IChjLCBvcHRzLCBwYXJhbXM6IHsgbmFtZT86IHN0cmluZyB9KSA9PiB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdG5hbWU6IHBhcmFtcy5uYW1lIHx8IFwiYW5vbnltb3VzXCIsXG5cdFx0fTtcblx0fSxcblx0b25Db25uZWN0OiAoYywgY29ubikgPT4ge1xuXHRcdC8vIFJlY29yZCBjb25uZWN0aW9uIG5hbWVcblx0XHRjLnN0YXRlLmluaXRpYWxpemVycy5wdXNoKGNvbm4uc3RhdGUubmFtZSk7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRpbmNyZW1lbnQ6IChjLCB4OiBudW1iZXIpID0+IHtcblx0XHRcdGMuc3RhdGUuY291bnQgKz0geDtcblx0XHRcdGMuYnJvYWRjYXN0KFwibmV3Q291bnRcIiwge1xuXHRcdFx0XHRjb3VudDogYy5zdGF0ZS5jb3VudCxcblx0XHRcdFx0Ynk6IGMuY29ubi5zdGF0ZS5uYW1lLFxuXHRcdFx0fSk7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudDtcblx0XHR9LFxuXHRcdGdldEluaXRpYWxpemVyczogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnN0YXRlLmluaXRpYWxpemVycztcblx0XHR9LFxuXHR9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2Nvbm4tc3RhdGUudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2Nvbm4tc3RhdGUudHNcIjtpbXBvcnQgeyBhY3RvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG5leHBvcnQgdHlwZSBDb25uU3RhdGUgPSB7XG5cdHVzZXJuYW1lOiBzdHJpbmc7XG5cdHJvbGU6IHN0cmluZztcblx0Y291bnRlcjogbnVtYmVyO1xuXHRjcmVhdGVkQXQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjb25zdCBjb25uU3RhdGVBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHtcblx0XHRzaGFyZWRDb3VudGVyOiAwLFxuXHRcdGRpc2Nvbm5lY3Rpb25Db3VudDogMCxcblx0fSxcblx0Ly8gRGVmaW5lIGNvbm5lY3Rpb24gc3RhdGVcblx0Y3JlYXRlQ29ublN0YXRlOiAoXG5cdFx0Yyxcblx0XHRvcHRzLFxuXHRcdHBhcmFtczogeyB1c2VybmFtZT86IHN0cmluZzsgcm9sZT86IHN0cmluZyB9LFxuXHQpOiBDb25uU3RhdGUgPT4ge1xuXHRcdHJldHVybiB7XG5cdFx0XHR1c2VybmFtZTogcGFyYW1zPy51c2VybmFtZSB8fCBcImFub255bW91c1wiLFxuXHRcdFx0cm9sZTogcGFyYW1zPy5yb2xlIHx8IFwidXNlclwiLFxuXHRcdFx0Y291bnRlcjogMCxcblx0XHRcdGNyZWF0ZWRBdDogRGF0ZS5ub3coKSxcblx0XHR9O1xuXHR9LFxuXHQvLyBMaWZlY3ljbGUgaG9vayB3aGVuIGEgY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZFxuXHRvbkNvbm5lY3Q6IChjLCBjb25uKSA9PiB7XG5cdFx0Ly8gQnJvYWRjYXN0IGV2ZW50IGFib3V0IHRoZSBuZXcgY29ubmVjdGlvblxuXHRcdGMuYnJvYWRjYXN0KFwidXNlckNvbm5lY3RlZFwiLCB7XG5cdFx0XHRpZDogY29ubi5pZCxcblx0XHRcdHVzZXJuYW1lOiBcImFub255bW91c1wiLFxuXHRcdFx0cm9sZTogXCJ1c2VyXCIsXG5cdFx0fSk7XG5cdH0sXG5cdC8vIExpZmVjeWNsZSBob29rIHdoZW4gYSBjb25uZWN0aW9uIGlzIGNsb3NlZFxuXHRvbkRpc2Nvbm5lY3Q6IChjLCBjb25uKSA9PiB7XG5cdFx0Yy5zdGF0ZS5kaXNjb25uZWN0aW9uQ291bnQgKz0gMTtcblx0XHRjLmJyb2FkY2FzdChcInVzZXJEaXNjb25uZWN0ZWRcIiwge1xuXHRcdFx0aWQ6IGNvbm4uaWQsXG5cdFx0fSk7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHQvLyBBY3Rpb24gdG8gaW5jcmVtZW50IHRoZSBjb25uZWN0aW9uJ3MgY291bnRlclxuXHRcdGluY3JlbWVudENvbm5Db3VudGVyOiAoYywgYW1vdW50ID0gMSkgPT4ge1xuXHRcdFx0Yy5jb25uLnN0YXRlLmNvdW50ZXIgKz0gYW1vdW50O1xuXHRcdH0sXG5cblx0XHQvLyBBY3Rpb24gdG8gaW5jcmVtZW50IHRoZSBzaGFyZWQgY291bnRlclxuXHRcdGluY3JlbWVudFNoYXJlZENvdW50ZXI6IChjLCBhbW91bnQgPSAxKSA9PiB7XG5cdFx0XHRjLnN0YXRlLnNoYXJlZENvdW50ZXIgKz0gYW1vdW50O1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUuc2hhcmVkQ291bnRlcjtcblx0XHR9LFxuXG5cdFx0Ly8gR2V0IHRoZSBjb25uZWN0aW9uIHN0YXRlXG5cdFx0Z2V0Q29ubmVjdGlvblN0YXRlOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHsgaWQ6IGMuY29ubi5pZCwgLi4uYy5jb25uLnN0YXRlIH07XG5cdFx0fSxcblxuXHRcdC8vIENoZWNrIGFsbCBhY3RpdmUgY29ubmVjdGlvbnNcblx0XHRnZXRDb25uZWN0aW9uSWRzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuY29ubnMua2V5cygpLnRvQXJyYXkoKTtcblx0XHR9LFxuXG5cdFx0Ly8gR2V0IGRpc2Nvbm5lY3Rpb24gY291bnRcblx0XHRnZXREaXNjb25uZWN0aW9uQ291bnQ6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5kaXNjb25uZWN0aW9uQ291bnQ7XG5cdFx0fSxcblxuXHRcdC8vIEdldCBhbGwgYWN0aXZlIGNvbm5lY3Rpb24gc3RhdGVzXG5cdFx0Z2V0QWxsQ29ubmVjdGlvblN0YXRlczogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLmNvbm5zXG5cdFx0XHRcdC5lbnRyaWVzKClcblx0XHRcdFx0Lm1hcCgoW2lkLCBjb25uXSkgPT4gKHsgaWQsIC4uLmNvbm4uc3RhdGUgfSkpXG5cdFx0XHRcdC50b0FycmF5KCk7XG5cdFx0fSxcblxuXHRcdC8vIFNlbmQgbWVzc2FnZSB0byBhIHNwZWNpZmljIGNvbm5lY3Rpb24gd2l0aCBtYXRjaGluZyBJRFxuXHRcdHNlbmRUb0Nvbm5lY3Rpb246IChjLCB0YXJnZXRJZDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHtcblx0XHRcdGlmIChjLmNvbm5zLmhhcyh0YXJnZXRJZCkpIHtcblx0XHRcdFx0Yy5jb25uc1xuXHRcdFx0XHRcdC5nZXQodGFyZ2V0SWQpIVxuXHRcdFx0XHRcdC5zZW5kKFwiZGlyZWN0TWVzc2FnZVwiLCB7IGZyb206IGMuY29ubi5pZCwgbWVzc2FnZSB9KTtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8vIFVwZGF0ZSBjb25uZWN0aW9uIHN0YXRlIChzaW11bGF0ZWQgZm9yIHRlc3RzKVxuXHRcdHVwZGF0ZUNvbm5lY3Rpb246IChcblx0XHRcdGMsXG5cdFx0XHR1cGRhdGVzOiBQYXJ0aWFsPHsgdXNlcm5hbWU6IHN0cmluZzsgcm9sZTogc3RyaW5nIH0+LFxuXHRcdCkgPT4ge1xuXHRcdFx0aWYgKHVwZGF0ZXMudXNlcm5hbWUpIGMuY29ubi5zdGF0ZS51c2VybmFtZSA9IHVwZGF0ZXMudXNlcm5hbWU7XG5cdFx0XHRpZiAodXBkYXRlcy5yb2xlKSBjLmNvbm4uc3RhdGUucm9sZSA9IHVwZGF0ZXMucm9sZTtcblx0XHRcdHJldHVybiBjLmNvbm4uc3RhdGU7XG5cdFx0fSxcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9jb3VudGVyLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9jb3VudGVyLnRzXCI7aW1wb3J0IHsgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuZXhwb3J0IGNvbnN0IGNvdW50ZXIgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IGNvdW50OiAwIH0sXG5cdGFjdGlvbnM6IHtcblx0XHRpbmNyZW1lbnQ6IChjLCB4OiBudW1iZXIpID0+IHtcblx0XHRcdGMuc3RhdGUuY291bnQgKz0geDtcblx0XHRcdGMuYnJvYWRjYXN0KFwibmV3Q291bnRcIiwgYy5zdGF0ZS5jb3VudCk7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudDtcblx0XHR9LFxuXHRcdGdldENvdW50OiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUuY291bnQ7XG5cdFx0fSxcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9lcnJvci1oYW5kbGluZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvZXJyb3ItaGFuZGxpbmcudHNcIjtpbXBvcnQgeyBhY3RvciwgVXNlckVycm9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbmV4cG9ydCBjb25zdCBlcnJvckhhbmRsaW5nQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7XG5cdFx0ZXJyb3JMb2c6IFtdIGFzIHN0cmluZ1tdLFxuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Ly8gQWN0aW9uIHRoYXQgdGhyb3dzIGEgVXNlckVycm9yIHdpdGgganVzdCBhIG1lc3NhZ2Vcblx0XHR0aHJvd1NpbXBsZUVycm9yOiAoKSA9PiB7XG5cdFx0XHR0aHJvdyBuZXcgVXNlckVycm9yKFwiU2ltcGxlIGVycm9yIG1lc3NhZ2VcIik7XG5cdFx0fSxcblxuXHRcdC8vIEFjdGlvbiB0aGF0IHRocm93cyBhIFVzZXJFcnJvciB3aXRoIGNvZGUgYW5kIG1ldGFkYXRhXG5cdFx0dGhyb3dEZXRhaWxlZEVycm9yOiAoKSA9PiB7XG5cdFx0XHR0aHJvdyBuZXcgVXNlckVycm9yKFwiRGV0YWlsZWQgZXJyb3IgbWVzc2FnZVwiLCB7XG5cdFx0XHRcdGNvZGU6IFwiZGV0YWlsZWRfZXJyb3JcIixcblx0XHRcdFx0bWV0YWRhdGE6IHtcblx0XHRcdFx0XHRyZWFzb246IFwidGVzdFwiLFxuXHRcdFx0XHRcdHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcblx0XHRcdFx0fSxcblx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHQvLyBBY3Rpb24gdGhhdCB0aHJvd3MgYW4gaW50ZXJuYWwgZXJyb3Jcblx0XHR0aHJvd0ludGVybmFsRXJyb3I6ICgpID0+IHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlRoaXMgaXMgYW4gaW50ZXJuYWwgZXJyb3JcIik7XG5cdFx0fSxcblxuXHRcdC8vIEFjdGlvbiB0aGF0IHJldHVybnMgc3VjY2Vzc2Z1bGx5XG5cdFx0c3VjY2Vzc2Z1bEFjdGlvbjogKCkgPT4ge1xuXHRcdFx0cmV0dXJuIFwic3VjY2Vzc1wiO1xuXHRcdH0sXG5cblx0XHQvLyBBY3Rpb24gdGhhdCB0aW1lcyBvdXQgKHNpbXVsYXRlZCB3aXRoIGEgbG9uZyBkZWxheSlcblx0XHR0aW1lb3V0QWN0aW9uOiBhc3luYyAoYykgPT4ge1xuXHRcdFx0Ly8gVGhpcyBhY3Rpb24gc2hvdWxkIHRpbWUgb3V0IGlmIHRoZSB0aW1lb3V0IGlzIGNvbmZpZ3VyZWRcblx0XHRcdHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0XHRyZXNvbHZlKFwiVGhpcyBzaG91bGQgbm90IGJlIHJlYWNoZWQgaWYgdGltZW91dCB3b3Jrc1wiKTtcblx0XHRcdFx0fSwgMTAwMDApOyAvLyAxMCBzZWNvbmRzXG5cdFx0XHR9KTtcblx0XHR9LFxuXG5cdFx0Ly8gQWN0aW9uIHdpdGggY29uZmlndXJhYmxlIGRlbGF5IHRvIHRlc3QgdGltZW91dCBlZGdlIGNhc2VzXG5cdFx0ZGVsYXllZEFjdGlvbjogYXN5bmMgKGMsIGRlbGF5TXM6IG51bWJlcikgPT4ge1xuXHRcdFx0cmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdHJlc29sdmUoYENvbXBsZXRlZCBhZnRlciAke2RlbGF5TXN9bXNgKTtcblx0XHRcdFx0fSwgZGVsYXlNcyk7XG5cdFx0XHR9KTtcblx0XHR9LFxuXG5cdFx0Ly8gTG9nIGFuIGVycm9yIGZvciBpbnNwZWN0aW9uXG5cdFx0bG9nRXJyb3I6IChjLCBlcnJvcjogc3RyaW5nKSA9PiB7XG5cdFx0XHRjLnN0YXRlLmVycm9yTG9nLnB1c2goZXJyb3IpO1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUuZXJyb3JMb2c7XG5cdFx0fSxcblxuXHRcdC8vIEdldCB0aGUgZXJyb3IgbG9nXG5cdFx0Z2V0RXJyb3JMb2c6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5lcnJvckxvZztcblx0XHR9LFxuXG5cdFx0Ly8gQ2xlYXIgdGhlIGVycm9yIGxvZ1xuXHRcdGNsZWFyRXJyb3JMb2c6IChjKSA9PiB7XG5cdFx0XHRjLnN0YXRlLmVycm9yTG9nID0gW107XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9LFxuXHR9LFxuXHRvcHRpb25zOiB7XG5cdFx0YWN0aW9uVGltZW91dDogNTAwLCAvLyA1MDBtcyB0aW1lb3V0IGZvciBhY3Rpb25zXG5cdH0sXG59KTtcblxuLy8gQWN0b3Igd2l0aCBjdXN0b20gdGltZW91dFxuZXhwb3J0IGNvbnN0IGN1c3RvbVRpbWVvdXRBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHt9LFxuXHRhY3Rpb25zOiB7XG5cdFx0cXVpY2tBY3Rpb246IGFzeW5jICgpID0+IHtcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDUwKSk7XG5cdFx0XHRyZXR1cm4gXCJRdWljayBhY3Rpb24gY29tcGxldGVkXCI7XG5cdFx0fSxcblx0XHRzbG93QWN0aW9uOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAzMDApKTtcblx0XHRcdHJldHVybiBcIlNsb3cgYWN0aW9uIGNvbXBsZXRlZFwiO1xuXHRcdH0sXG5cdH0sXG5cdG9wdGlvbnM6IHtcblx0XHRhY3Rpb25UaW1lb3V0OiAyMDAsIC8vIDIwMG1zIHRpbWVvdXRcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9pbmxpbmUtY2xpZW50LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9pbmxpbmUtY2xpZW50LnRzXCI7aW1wb3J0IHsgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcbmltcG9ydCB0eXBlIHsgcmVnaXN0cnkgfSBmcm9tIFwiLi9yZWdpc3RyeVwiO1xuXG5leHBvcnQgY29uc3QgaW5saW5lQ2xpZW50QWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IG1lc3NhZ2VzOiBbXSBhcyBzdHJpbmdbXSB9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Ly8gQWN0aW9uIHRoYXQgdXNlcyBjbGllbnQgdG8gY2FsbCBhbm90aGVyIGFjdG9yIChzdGF0ZWxlc3MpXG5cdFx0Y2FsbENvdW50ZXJJbmNyZW1lbnQ6IGFzeW5jIChjLCBhbW91bnQ6IG51bWJlcikgPT4ge1xuXHRcdFx0Y29uc3QgY2xpZW50ID0gYy5jbGllbnQ8dHlwZW9mIHJlZ2lzdHJ5PigpO1xuXHRcdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgY2xpZW50LmNvdW50ZXJcblx0XHRcdFx0LmdldE9yQ3JlYXRlKFtcImlubGluZS10ZXN0XCJdKVxuXHRcdFx0XHQuaW5jcmVtZW50KGFtb3VudCk7XG5cdFx0XHRjLnN0YXRlLm1lc3NhZ2VzLnB1c2goXG5cdFx0XHRcdGBDYWxsZWQgY291bnRlci5pbmNyZW1lbnQoJHthbW91bnR9KSwgcmVzdWx0OiAke3Jlc3VsdH1gLFxuXHRcdFx0KTtcblx0XHRcdHJldHVybiByZXN1bHQ7XG5cdFx0fSxcblxuXHRcdC8vIEFjdGlvbiB0aGF0IHVzZXMgY2xpZW50IHRvIGdldCBjb3VudGVyIHN0YXRlIChzdGF0ZWxlc3MpXG5cdFx0Z2V0Q291bnRlclN0YXRlOiBhc3luYyAoYykgPT4ge1xuXHRcdFx0Y29uc3QgY2xpZW50ID0gYy5jbGllbnQ8dHlwZW9mIHJlZ2lzdHJ5PigpO1xuXHRcdFx0Y29uc3QgY291bnQgPSBhd2FpdCBjbGllbnQuY291bnRlclxuXHRcdFx0XHQuZ2V0T3JDcmVhdGUoW1wiaW5saW5lLXRlc3RcIl0pXG5cdFx0XHRcdC5nZXRDb3VudCgpO1xuXHRcdFx0Yy5zdGF0ZS5tZXNzYWdlcy5wdXNoKGBHb3QgY291bnRlciBzdGF0ZTogJHtjb3VudH1gKTtcblx0XHRcdHJldHVybiBjb3VudDtcblx0XHR9LFxuXG5cdFx0Ly8gQWN0aW9uIHRoYXQgdXNlcyBjbGllbnQgd2l0aCAuY29ubmVjdCgpIGZvciBzdGF0ZWZ1bCBjb21tdW5pY2F0aW9uXG5cdFx0Y29ubmVjdFRvQ291bnRlckFuZEluY3JlbWVudDogYXN5bmMgKGMsIGFtb3VudDogbnVtYmVyKSA9PiB7XG5cdFx0XHRjb25zdCBjbGllbnQgPSBjLmNsaWVudDx0eXBlb2YgcmVnaXN0cnk+KCk7XG5cdFx0XHRjb25zdCBoYW5kbGUgPSBjbGllbnQuY291bnRlci5nZXRPckNyZWF0ZShbXCJpbmxpbmUtdGVzdC1zdGF0ZWZ1bFwiXSk7XG5cdFx0XHRjb25zdCBjb25uZWN0aW9uID0gaGFuZGxlLmNvbm5lY3QoKTtcblxuXHRcdFx0Ly8gU2V0IHVwIGV2ZW50IGxpc3RlbmVyXG5cdFx0XHRjb25zdCBldmVudHM6IG51bWJlcltdID0gW107XG5cdFx0XHRjb25uZWN0aW9uLm9uKFwibmV3Q291bnRcIiwgKGNvdW50OiBudW1iZXIpID0+IHtcblx0XHRcdFx0ZXZlbnRzLnB1c2goY291bnQpO1xuXHRcdFx0fSk7XG5cblx0XHRcdC8vIFBlcmZvcm0gaW5jcmVtZW50c1xuXHRcdFx0Y29uc3QgcmVzdWx0MSA9IGF3YWl0IGNvbm5lY3Rpb24uaW5jcmVtZW50KGFtb3VudCk7XG5cdFx0XHRjb25zdCByZXN1bHQyID0gYXdhaXQgY29ubmVjdGlvbi5pbmNyZW1lbnQoYW1vdW50ICogMik7XG5cblx0XHRcdGF3YWl0IGNvbm5lY3Rpb24uZGlzcG9zZSgpO1xuXG5cdFx0XHRjLnN0YXRlLm1lc3NhZ2VzLnB1c2goXG5cdFx0XHRcdGBDb25uZWN0ZWQgdG8gY291bnRlciwgaW5jcmVtZW50ZWQgYnkgJHthbW91bnR9IGFuZCAke2Ftb3VudCAqIDJ9LCByZXN1bHRzOiAke3Jlc3VsdDF9LCAke3Jlc3VsdDJ9LCBldmVudHM6ICR7SlNPTi5zdHJpbmdpZnkoZXZlbnRzKX1gLFxuXHRcdFx0KTtcblxuXHRcdFx0cmV0dXJuIHsgcmVzdWx0MSwgcmVzdWx0MiwgZXZlbnRzIH07XG5cdFx0fSxcblxuXHRcdC8vIEdldCBhbGwgbWVzc2FnZXMgZnJvbSB0aGlzIGFjdG9yJ3Mgc3RhdGVcblx0XHRnZXRNZXNzYWdlczogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnN0YXRlLm1lc3NhZ2VzO1xuXHRcdH0sXG5cblx0XHQvLyBDbGVhciBtZXNzYWdlc1xuXHRcdGNsZWFyTWVzc2FnZXM6IChjKSA9PiB7XG5cdFx0XHRjLnN0YXRlLm1lc3NhZ2VzID0gW107XG5cdFx0fSxcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9saWZlY3ljbGUudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL2xpZmVjeWNsZS50c1wiO2ltcG9ydCB7IGFjdG9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbnR5cGUgQ29ublBhcmFtcyA9IHsgdHJhY2tMaWZlY3ljbGU/OiBib29sZWFuIH0gfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBjb25zdCBjb3VudGVyV2l0aExpZmVjeWNsZSA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHtcblx0XHRjb3VudDogMCxcblx0XHRldmVudHM6IFtdIGFzIHN0cmluZ1tdLFxuXHR9LFxuXHRjcmVhdGVDb25uU3RhdGU6IChjLCBvcHRzLCBwYXJhbXM6IENvbm5QYXJhbXMpID0+ICh7XG5cdFx0am9pblRpbWU6IERhdGUubm93KCksXG5cdH0pLFxuXHRvblN0YXJ0OiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuZXZlbnRzLnB1c2goXCJvblN0YXJ0XCIpO1xuXHR9LFxuXHRvbkJlZm9yZUNvbm5lY3Q6IChjLCBvcHRzLCBwYXJhbXM6IENvbm5QYXJhbXMpID0+IHtcblx0XHRpZiAocGFyYW1zPy50cmFja0xpZmVjeWNsZSkgYy5zdGF0ZS5ldmVudHMucHVzaChcIm9uQmVmb3JlQ29ubmVjdFwiKTtcblx0fSxcblx0b25Db25uZWN0OiAoYywgY29ubikgPT4ge1xuXHRcdGlmIChjb25uLnBhcmFtcz8udHJhY2tMaWZlY3ljbGUpIGMuc3RhdGUuZXZlbnRzLnB1c2goXCJvbkNvbm5lY3RcIik7XG5cdH0sXG5cdG9uRGlzY29ubmVjdDogKGMsIGNvbm4pID0+IHtcblx0XHRpZiAoY29ubi5wYXJhbXM/LnRyYWNrTGlmZWN5Y2xlKSBjLnN0YXRlLmV2ZW50cy5wdXNoKFwib25EaXNjb25uZWN0XCIpO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0RXZlbnRzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUuZXZlbnRzO1xuXHRcdH0sXG5cdFx0aW5jcmVtZW50OiAoYywgeDogbnVtYmVyKSA9PiB7XG5cdFx0XHRjLnN0YXRlLmNvdW50ICs9IHg7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5jb3VudDtcblx0XHR9LFxuXHR9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL21ldGFkYXRhLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9tZXRhZGF0YS50c1wiO2ltcG9ydCB7IGFjdG9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbi8vIE5vdGU6IEZvciB0ZXN0aW5nIG9ubHkgLSBtZXRhZGF0YSBBUEkgd2lsbCBuZWVkIHRvIGJlIG1vY2tlZFxuLy8gaW4gdGVzdHMgc2luY2UgdGhpcyBpcyBpbXBsZW1lbnRhdGlvbi1zcGVjaWZpY1xuZXhwb3J0IGNvbnN0IG1ldGFkYXRhQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7XG5cdFx0bGFzdE1ldGFkYXRhOiBudWxsIGFzIGFueSxcblx0XHRhY3Rvck5hbWU6IFwiXCIsXG5cdFx0Ly8gU3RvcmUgdGFncyBhbmQgcmVnaW9uIGluIHN0YXRlIGZvciB0ZXN0aW5nIHNpbmNlIHRoZXkgbWF5IG5vdCBiZVxuXHRcdC8vIGF2YWlsYWJsZSBpbiB0aGUgY29udGV4dCBpbiBhbGwgZW52aXJvbm1lbnRzXG5cdFx0c3RvcmVkVGFnczoge30gYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPixcblx0XHRzdG9yZWRSZWdpb246IG51bGwgYXMgc3RyaW5nIHwgbnVsbCxcblx0fSxcblx0b25TdGFydDogKGMpID0+IHtcblx0XHQvLyBTdG9yZSB0aGUgYWN0b3IgbmFtZSBkdXJpbmcgaW5pdGlhbGl6YXRpb25cblx0XHRjLnN0YXRlLmFjdG9yTmFtZSA9IGMubmFtZTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdC8vIFNldCB1cCB0ZXN0IHRhZ3MgLSB0aGlzIHdpbGwgYmUgY2FsbGVkIGJ5IHRlc3RzIHRvIHNpbXVsYXRlIHRhZ3Ncblx0XHRzZXR1cFRlc3RUYWdzOiAoYywgdGFnczogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4ge1xuXHRcdFx0Yy5zdGF0ZS5zdG9yZWRUYWdzID0gdGFncztcblx0XHRcdHJldHVybiB0YWdzO1xuXHRcdH0sXG5cblx0XHQvLyBTZXQgdXAgdGVzdCByZWdpb24gLSB0aGlzIHdpbGwgYmUgY2FsbGVkIGJ5IHRlc3RzIHRvIHNpbXVsYXRlIHJlZ2lvblxuXHRcdHNldHVwVGVzdFJlZ2lvbjogKGMsIHJlZ2lvbjogc3RyaW5nKSA9PiB7XG5cdFx0XHRjLnN0YXRlLnN0b3JlZFJlZ2lvbiA9IHJlZ2lvbjtcblx0XHRcdHJldHVybiByZWdpb247XG5cdFx0fSxcblxuXHRcdC8vIEdldCBhbGwgYXZhaWxhYmxlIG1ldGFkYXRhXG5cdFx0Z2V0TWV0YWRhdGE6IChjKSA9PiB7XG5cdFx0XHQvLyBDcmVhdGUgbWV0YWRhdGEgb2JqZWN0IGZyb20gc3RvcmVkIHZhbHVlc1xuXHRcdFx0Y29uc3QgbWV0YWRhdGEgPSB7XG5cdFx0XHRcdG5hbWU6IGMubmFtZSxcblx0XHRcdFx0dGFnczogYy5zdGF0ZS5zdG9yZWRUYWdzLFxuXHRcdFx0XHRyZWdpb246IGMuc3RhdGUuc3RvcmVkUmVnaW9uLFxuXHRcdFx0fTtcblxuXHRcdFx0Ly8gU3RvcmUgZm9yIGxhdGVyIGluc3BlY3Rpb25cblx0XHRcdGMuc3RhdGUubGFzdE1ldGFkYXRhID0gbWV0YWRhdGE7XG5cdFx0XHRyZXR1cm4gbWV0YWRhdGE7XG5cdFx0fSxcblxuXHRcdC8vIEdldCB0aGUgYWN0b3IgbmFtZVxuXHRcdGdldEFjdG9yTmFtZTogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLm5hbWU7XG5cdFx0fSxcblxuXHRcdC8vIEdldCBhIHNwZWNpZmljIHRhZyBieSBrZXlcblx0XHRnZXRUYWc6IChjLCBrZXk6IHN0cmluZykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUuc3RvcmVkVGFnc1trZXldIHx8IG51bGw7XG5cdFx0fSxcblxuXHRcdC8vIEdldCBhbGwgdGFnc1xuXHRcdGdldFRhZ3M6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5zdG9yZWRUYWdzO1xuXHRcdH0sXG5cblx0XHQvLyBHZXQgdGhlIHJlZ2lvblxuXHRcdGdldFJlZ2lvbjogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnN0YXRlLnN0b3JlZFJlZ2lvbjtcblx0XHR9LFxuXG5cdFx0Ly8gR2V0IHRoZSBzdG9yZWQgYWN0b3IgbmFtZSAoZnJvbSBvblN0YXJ0KVxuXHRcdGdldFN0b3JlZEFjdG9yTmFtZTogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnN0YXRlLmFjdG9yTmFtZTtcblx0XHR9LFxuXG5cdFx0Ly8gR2V0IGxhc3QgcmV0cmlldmVkIG1ldGFkYXRhXG5cdFx0Z2V0TGFzdE1ldGFkYXRhOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUubGFzdE1ldGFkYXRhO1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmF3LWh0dHAudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy1odHRwLnRzXCI7aW1wb3J0IHsgSG9ubyB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyB0eXBlIEFjdG9yQ29udGV4dCwgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuZXhwb3J0IGNvbnN0IHJhd0h0dHBBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHtcblx0XHRyZXF1ZXN0Q291bnQ6IDAsXG5cdH0sXG5cdG9uQXV0aCgpIHtcblx0XHQvLyBBbGxvdyBwdWJsaWMgYWNjZXNzIC0gZW1wdHkgb25BdXRoXG5cdFx0cmV0dXJuIHt9O1xuXHR9LFxuXHRvbkZldGNoKFxuXHRcdGN0eDogQWN0b3JDb250ZXh0PGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueT4sXG5cdFx0cmVxdWVzdDogUmVxdWVzdCxcblx0KSB7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChyZXF1ZXN0LnVybCk7XG5cdFx0Y29uc3QgbWV0aG9kID0gcmVxdWVzdC5tZXRob2Q7XG5cblx0XHQvLyBUcmFjayByZXF1ZXN0IGNvdW50XG5cdFx0Y3R4LnN0YXRlLnJlcXVlc3RDb3VudCsrO1xuXG5cdFx0Ly8gSGFuZGxlIGRpZmZlcmVudCBlbmRwb2ludHNcblx0XHRpZiAodXJsLnBhdGhuYW1lID09PSBcIi9hcGkvaGVsbG9cIikge1xuXHRcdFx0cmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IG1lc3NhZ2U6IFwiSGVsbG8gZnJvbSBhY3RvciFcIiB9KSwge1xuXHRcdFx0XHRoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAodXJsLnBhdGhuYW1lID09PSBcIi9hcGkvZWNob1wiICYmIG1ldGhvZCA9PT0gXCJQT1NUXCIpIHtcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UocmVxdWVzdC5ib2R5LCB7XG5cdFx0XHRcdGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdGlmICh1cmwucGF0aG5hbWUgPT09IFwiL2FwaS9zdGF0ZVwiKSB7XG5cdFx0XHRyZXR1cm4gbmV3IFJlc3BvbnNlKFxuXHRcdFx0XHRKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0cmVxdWVzdENvdW50OiBjdHguc3RhdGUucmVxdWVzdENvdW50LFxuXHRcdFx0XHR9KSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcblx0XHRcdFx0fSxcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0aWYgKHVybC5wYXRobmFtZSA9PT0gXCIvYXBpL2hlYWRlcnNcIikge1xuXHRcdFx0Y29uc3QgaGVhZGVycyA9IE9iamVjdC5mcm9tRW50cmllcyhyZXF1ZXN0LmhlYWRlcnMuZW50cmllcygpKTtcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UoSlNPTi5zdHJpbmdpZnkoaGVhZGVycyksIHtcblx0XHRcdFx0aGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIDQwNCBmb3IgdW5oYW5kbGVkIHBhdGhzXG5cdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcIk5vdCBGb3VuZFwiLCB7IHN0YXR1czogNDA0IH0pO1xuXHR9LFxuXHRhY3Rpb25zOiB7fSxcbn0pO1xuXG5leHBvcnQgY29uc3QgcmF3SHR0cE5vSGFuZGxlckFjdG9yID0gYWN0b3Ioe1xuXHQvLyBObyBvbkZldGNoIGhhbmRsZXIgLSBhbGwgcmVxdWVzdHMgc2hvdWxkIHJldHVybiA0MDRcblx0b25BdXRoKCkge1xuXHRcdC8vIEFsbG93IHB1YmxpYyBhY2Nlc3MgLSBlbXB0eSBvbkF1dGhcblx0XHRyZXR1cm4ge307XG5cdH0sXG5cdGFjdGlvbnM6IHt9LFxufSk7XG5cbmV4cG9ydCBjb25zdCByYXdIdHRwVm9pZFJldHVybkFjdG9yID0gYWN0b3Ioe1xuXHRvbkF1dGgoKSB7XG5cdFx0Ly8gQWxsb3cgcHVibGljIGFjY2VzcyAtIGVtcHR5IG9uQXV0aFxuXHRcdHJldHVybiB7fTtcblx0fSxcblx0b25GZXRjaChjdHgsIHJlcXVlc3QpIHtcblx0XHQvLyBJbnRlbnRpb25hbGx5IHJldHVybiB2b2lkIHRvIHRlc3QgZXJyb3IgaGFuZGxpbmdcblx0XHRyZXR1cm4gdW5kZWZpbmVkIGFzIGFueTtcblx0fSxcblx0YWN0aW9uczoge30sXG59KTtcblxuZXhwb3J0IGNvbnN0IHJhd0h0dHBIb25vQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aCgpIHtcblx0XHQvLyBBbGxvdyBwdWJsaWMgYWNjZXNzXG5cdFx0cmV0dXJuIHt9O1xuXHR9LFxuXHRjcmVhdGVWYXJzKCkge1xuXHRcdGNvbnN0IHJvdXRlciA9IG5ldyBIb25vKCk7XG5cblx0XHQvLyBTZXQgdXAgcm91dGVzXG5cdFx0cm91dGVyLmdldChcIi9cIiwgKGM6IGFueSkgPT4gYy5qc29uKHsgbWVzc2FnZTogXCJXZWxjb21lIHRvIEhvbm8gYWN0b3IhXCIgfSkpO1xuXG5cdFx0cm91dGVyLmdldChcIi91c2Vyc1wiLCAoYzogYW55KSA9PlxuXHRcdFx0Yy5qc29uKFtcblx0XHRcdFx0eyBpZDogMSwgbmFtZTogXCJBbGljZVwiIH0sXG5cdFx0XHRcdHsgaWQ6IDIsIG5hbWU6IFwiQm9iXCIgfSxcblx0XHRcdF0pLFxuXHRcdCk7XG5cblx0XHRyb3V0ZXIuZ2V0KFwiL3VzZXJzLzppZFwiLCAoYzogYW55KSA9PiB7XG5cdFx0XHRjb25zdCBpZCA9IGMucmVxLnBhcmFtKFwiaWRcIik7XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgaWQ6IHBhcnNlSW50KGlkKSwgbmFtZTogaWQgPT09IFwiMVwiID8gXCJBbGljZVwiIDogXCJCb2JcIiB9KTtcblx0XHR9KTtcblxuXHRcdHJvdXRlci5wb3N0KFwiL3VzZXJzXCIsIGFzeW5jIChjOiBhbnkpID0+IHtcblx0XHRcdGNvbnN0IGJvZHkgPSBhd2FpdCBjLnJlcS5qc29uKCk7XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgaWQ6IDMsIC4uLmJvZHkgfSwgMjAxKTtcblx0XHR9KTtcblxuXHRcdHJvdXRlci5wdXQoXCIvdXNlcnMvOmlkXCIsIGFzeW5jIChjOiBhbnkpID0+IHtcblx0XHRcdGNvbnN0IGlkID0gYy5yZXEucGFyYW0oXCJpZFwiKTtcblx0XHRcdGNvbnN0IGJvZHkgPSBhd2FpdCBjLnJlcS5qc29uKCk7XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgaWQ6IHBhcnNlSW50KGlkKSwgLi4uYm9keSB9KTtcblx0XHR9KTtcblxuXHRcdHJvdXRlci5kZWxldGUoXCIvdXNlcnMvOmlkXCIsIChjOiBhbnkpID0+IHtcblx0XHRcdGNvbnN0IGlkID0gYy5yZXEucGFyYW0oXCJpZFwiKTtcblx0XHRcdHJldHVybiBjLmpzb24oeyBtZXNzYWdlOiBgVXNlciAke2lkfSBkZWxldGVkYCB9KTtcblx0XHR9KTtcblxuXHRcdC8vIFJldHVybiB0aGUgcm91dGVyIGFzIGEgdmFyXG5cdFx0cmV0dXJuIHsgcm91dGVyIH07XG5cdH0sXG5cdG9uRmV0Y2goXG5cdFx0Y3R4OiBBY3RvckNvbnRleHQ8YW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55Pixcblx0XHRyZXF1ZXN0OiBSZXF1ZXN0LFxuXHQpIHtcblx0XHQvLyBVc2UgdGhlIEhvbm8gcm91dGVyIGZyb20gdmFyc1xuXHRcdHJldHVybiBjdHgudmFycy5yb3V0ZXIuZmV0Y2gocmVxdWVzdCk7XG5cdH0sXG5cdGFjdGlvbnM6IHt9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy1odHRwLWF1dGgudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy1odHRwLWF1dGgudHNcIjtpbXBvcnQgeyB0eXBlIEFjdG9yQ29udGV4dCwgYWN0b3IsIFVzZXJFcnJvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG4vLyBSYXcgSFRUUCBhY3RvciB3aXRoIGF1dGhlbnRpY2F0aW9uIC0gcmVxdWlyZXMgQVBJIGtleVxuZXhwb3J0IGNvbnN0IHJhd0h0dHBBdXRoQWN0b3IgPSBhY3Rvcih7XG5cdHN0YXRlOiB7XG5cdFx0cmVxdWVzdENvdW50OiAwLFxuXHR9LFxuXHRvbkF1dGg6IChvcHRzLCBwYXJhbXM6IHsgYXBpS2V5Pzogc3RyaW5nIH0pID0+IHtcblx0XHRjb25zdCBhcGlLZXkgPSBwYXJhbXMuYXBpS2V5O1xuXHRcdGlmICghYXBpS2V5KSB7XG5cdFx0XHR0aHJvdyBuZXcgVXNlckVycm9yKFwiQVBJIGtleSByZXF1aXJlZFwiLCB7IGNvZGU6IFwibWlzc2luZ19hdXRoXCIgfSk7XG5cdFx0fVxuXG5cdFx0aWYgKGFwaUtleSAhPT0gXCJ2YWxpZC1hcGkta2V5XCIpIHtcblx0XHRcdHRocm93IG5ldyBVc2VyRXJyb3IoXCJJbnZhbGlkIEFQSSBrZXlcIiwgeyBjb2RlOiBcImludmFsaWRfYXV0aFwiIH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiB7IHVzZXJJZDogXCJ1c2VyMTIzXCIsIHRva2VuOiBhcGlLZXkgfTtcblx0fSxcblx0b25GZXRjaChcblx0XHRjdHg6IEFjdG9yQ29udGV4dDxhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnk+LFxuXHRcdHJlcXVlc3Q6IFJlcXVlc3QsXG5cdCkge1xuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuXHRcdGN0eC5zdGF0ZS5yZXF1ZXN0Q291bnQrKztcblxuXHRcdC8vIEF1dGggaW5mbyBlbmRwb2ludCAtIG9uQXV0aCB3YXMgYWxyZWFkeSBjYWxsZWRcblx0XHRpZiAodXJsLnBhdGhuYW1lID09PSBcIi9hcGkvYXV0aC1pbmZvXCIpIHtcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UoXG5cdFx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRtZXNzYWdlOiBcIkF1dGhlbnRpY2F0ZWQgcmVxdWVzdFwiLFxuXHRcdFx0XHRcdHJlcXVlc3RDb3VudDogY3R4LnN0YXRlLnJlcXVlc3RDb3VudCxcblx0XHRcdFx0fSksXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG5cdFx0XHRcdH0sXG5cdFx0XHQpO1xuXHRcdH1cblxuXHRcdGlmICh1cmwucGF0aG5hbWUgPT09IFwiL2FwaS9wcm90ZWN0ZWRcIikge1xuXHRcdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcblx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdG1lc3NhZ2U6IFwiVGhpcyBpcyBwcm90ZWN0ZWQgY29udGVudFwiLFxuXHRcdFx0XHR9KSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcblx0XHRcdFx0fSxcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcIk5vdCBGb3VuZFwiLCB7IHN0YXR1czogNDA0IH0pO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0UmVxdWVzdENvdW50KGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4gY3R4LnN0YXRlLnJlcXVlc3RDb3VudDtcblx0XHR9LFxuXHRcdGdldEF1dGhGcm9tQ29ubmVjdGlvbnMoY3R4OiBhbnkpIHtcblx0XHRcdC8vIEdldCBhdXRoIGRhdGEgZnJvbSBmaXJzdCBjb25uZWN0aW9uIGlmIGF2YWlsYWJsZVxuXHRcdFx0Y29uc3QgZmlyc3RDb25uID0gY3R4LmNvbm5zLnZhbHVlcygpLm5leHQoKS52YWx1ZTtcblx0XHRcdHJldHVybiBmaXJzdENvbm4/LmF1dGg7XG5cdFx0fSxcblx0fSxcbn0pO1xuXG4vLyBSYXcgSFRUUCBhY3RvciB3aXRob3V0IG9uQXV0aCAtIHNob3VsZCBkZW55IGFjY2Vzc1xuZXhwb3J0IGNvbnN0IHJhd0h0dHBOb0F1dGhBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHtcblx0XHR2YWx1ZTogNDIsXG5cdH0sXG5cdG9uRmV0Y2goXG5cdFx0Y3R4OiBBY3RvckNvbnRleHQ8YW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55Pixcblx0XHRyZXF1ZXN0OiBSZXF1ZXN0LFxuXHQpIHtcblx0XHRyZXR1cm4gbmV3IFJlc3BvbnNlKFxuXHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHR2YWx1ZTogY3R4LnN0YXRlLnZhbHVlLFxuXHRcdFx0fSksXG5cdFx0XHR7XG5cdFx0XHRcdGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcblx0XHRcdH0sXG5cdFx0KTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFZhbHVlKGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4gY3R4LnN0YXRlLnZhbHVlO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gUmF3IEhUVFAgYWN0b3Igd2l0aCBwdWJsaWMgYWNjZXNzIChlbXB0eSBvbkF1dGgpXG5leHBvcnQgY29uc3QgcmF3SHR0cFB1YmxpY0FjdG9yID0gYWN0b3Ioe1xuXHRzdGF0ZToge1xuXHRcdHZpc2l0b3JzOiAwLFxuXHR9LFxuXHRvbkF1dGg6ICgpID0+IHtcblx0XHRyZXR1cm4gbnVsbDsgLy8gQWxsb3cgcHVibGljIGFjY2Vzc1xuXHR9LFxuXHRvbkZldGNoKFxuXHRcdGN0eDogQWN0b3JDb250ZXh0PGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueT4sXG5cdFx0cmVxdWVzdDogUmVxdWVzdCxcblx0KSB7XG5cdFx0Y3R4LnN0YXRlLnZpc2l0b3JzKys7XG5cdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0bWVzc2FnZTogXCJXZWxjb21lIHZpc2l0b3IhXCIsXG5cdFx0XHRcdGNvdW50OiBjdHguc3RhdGUudmlzaXRvcnMsXG5cdFx0XHR9KSxcblx0XHRcdHtcblx0XHRcdFx0aGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuXHRcdFx0fSxcblx0XHQpO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0VmlzaXRvckNvdW50KGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4gY3R4LnN0YXRlLnZpc2l0b3JzO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gUmF3IEhUVFAgYWN0b3Igd2l0aCBjdXN0b20gYXV0aCBpbiBvbkZldGNoIChubyBvbkF1dGgpXG5leHBvcnQgY29uc3QgcmF3SHR0cEN1c3RvbUF1dGhBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHtcblx0XHRhdXRob3JpemVkOiAwLFxuXHRcdHVuYXV0aG9yaXplZDogMCxcblx0fSxcblx0b25BdXRoOiAoKSA9PiB7XG5cdFx0Ly8gQWxsb3cgYWxsIGNvbm5lY3Rpb25zIC0gYXV0aCB3aWxsIGJlIGhhbmRsZWQgaW4gb25GZXRjaFxuXHRcdHJldHVybiB7fTtcblx0fSxcblx0b25GZXRjaChcblx0XHRjdHg6IEFjdG9yQ29udGV4dDxhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnk+LFxuXHRcdHJlcXVlc3Q6IFJlcXVlc3QsXG5cdCkge1xuXHRcdC8vIEN1c3RvbSBhdXRoIGNoZWNrIGluIG9uRmV0Y2hcblx0XHRjb25zdCBhdXRoSGVhZGVyID0gcmVxdWVzdC5oZWFkZXJzLmdldChcIkF1dGhvcml6YXRpb25cIik7XG5cblx0XHRpZiAoIWF1dGhIZWFkZXIgfHwgIWF1dGhIZWFkZXIuc3RhcnRzV2l0aChcIkJlYXJlciBcIikpIHtcblx0XHRcdGN0eC5zdGF0ZS51bmF1dGhvcml6ZWQrKztcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UoSlNPTi5zdHJpbmdpZnkoeyBlcnJvcjogXCJVbmF1dGhvcml6ZWRcIiB9KSwge1xuXHRcdFx0XHRzdGF0dXM6IDQwMSxcblx0XHRcdFx0aGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgdG9rZW4gPSBhdXRoSGVhZGVyLnN1YnN0cmluZyg3KTtcblx0XHRpZiAodG9rZW4gIT09IFwiY3VzdG9tLXRva2VuXCIpIHtcblx0XHRcdGN0eC5zdGF0ZS51bmF1dGhvcml6ZWQrKztcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UoSlNPTi5zdHJpbmdpZnkoeyBlcnJvcjogXCJJbnZhbGlkIHRva2VuXCIgfSksIHtcblx0XHRcdFx0c3RhdHVzOiA0MDMsXG5cdFx0XHRcdGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdGN0eC5zdGF0ZS5hdXRob3JpemVkKys7XG5cdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0bWVzc2FnZTogXCJBdXRob3JpemVkIVwiLFxuXHRcdFx0XHRhdXRob3JpemVkOiBjdHguc3RhdGUuYXV0aG9yaXplZCxcblx0XHRcdH0pLFxuXHRcdFx0e1xuXHRcdFx0XHRoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG5cdFx0XHR9LFxuXHRcdCk7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRTdGF0cyhjdHg6IGFueSkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0YXV0aG9yaXplZDogY3R4LnN0YXRlLmF1dGhvcml6ZWQsXG5cdFx0XHRcdHVuYXV0aG9yaXplZDogY3R4LnN0YXRlLnVuYXV0aG9yaXplZCxcblx0XHRcdH07XG5cdFx0fSxcblx0fSxcbn0pO1xuIiwgImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9yYXctaHR0cC1yZXF1ZXN0LXByb3BlcnRpZXMudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy1odHRwLXJlcXVlc3QtcHJvcGVydGllcy50c1wiO2ltcG9ydCB7IHR5cGUgQWN0b3JDb250ZXh0LCBhY3RvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG5leHBvcnQgY29uc3QgcmF3SHR0cFJlcXVlc3RQcm9wZXJ0aWVzQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aCgpIHtcblx0XHQvLyBBbGxvdyBwdWJsaWMgYWNjZXNzIC0gZW1wdHkgb25BdXRoXG5cdFx0cmV0dXJuIHt9O1xuXHR9LFxuXHRhY3Rpb25zOiB7fSxcblx0b25GZXRjaChcblx0XHRjdHg6IEFjdG9yQ29udGV4dDxhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnk+LFxuXHRcdHJlcXVlc3Q6IFJlcXVlc3QsXG5cdCkge1xuXHRcdC8vIEV4dHJhY3QgYWxsIHJlbGV2YW50IFJlcXVlc3QgcHJvcGVydGllc1xuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuXHRcdGNvbnN0IG1ldGhvZCA9IHJlcXVlc3QubWV0aG9kO1xuXG5cdFx0Ly8gR2V0IGFsbCBoZWFkZXJzXG5cdFx0Y29uc3QgaGVhZGVycyA9IE9iamVjdC5mcm9tRW50cmllcyhyZXF1ZXN0LmhlYWRlcnMuZW50cmllcygpKTtcblxuXHRcdC8vIEhhbmRsZSBib2R5IGJhc2VkIG9uIGNvbnRlbnQgdHlwZVxuXHRcdGNvbnN0IGhhbmRsZUJvZHkgPSBhc3luYyAoKSA9PiB7XG5cdFx0XHRpZiAoIXJlcXVlc3QuYm9keSkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSByZXF1ZXN0LmhlYWRlcnMuZ2V0KFwiY29udGVudC10eXBlXCIpIHx8IFwiXCI7XG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdGlmIChjb250ZW50VHlwZS5pbmNsdWRlcyhcImFwcGxpY2F0aW9uL2pzb25cIikpIHtcblx0XHRcdFx0XHRjb25zdCB0ZXh0ID0gYXdhaXQgcmVxdWVzdC50ZXh0KCk7XG5cdFx0XHRcdFx0cmV0dXJuIHRleHQgPyBKU09OLnBhcnNlKHRleHQpIDogbnVsbDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBGb3Igbm9uLUpTT04sIHJldHVybiBhcyB0ZXh0XG5cdFx0XHRcdFx0Y29uc3QgdGV4dCA9IGF3YWl0IHJlcXVlc3QudGV4dCgpO1xuXHRcdFx0XHRcdHJldHVybiB0ZXh0IHx8IG51bGw7IC8vIFJldHVybiBudWxsIGZvciBlbXB0eSBib2RpZXNcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0Ly8gSWYgYm9keSBwYXJzaW5nIGZhaWxzLCByZXR1cm4gbnVsbFxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gU3BlY2lhbCBoYW5kbGluZyBmb3IgSEVBRCByZXF1ZXN0cyAtIHJldHVybiBlbXB0eSBib2R5XG5cdFx0aWYgKG1ldGhvZCA9PT0gXCJIRUFEXCIpIHtcblx0XHRcdHJldHVybiBuZXcgUmVzcG9uc2UobnVsbCwge1xuXHRcdFx0XHRzdGF0dXM6IDIwMCxcblx0XHRcdFx0aGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIGFsbCByZXF1ZXN0IHByb3BlcnRpZXMgYXMgSlNPTlxuXHRcdHJldHVybiBoYW5kbGVCb2R5KCkudGhlbigoYm9keSkgPT4ge1xuXHRcdFx0Y29uc3QgcmVzcG9uc2VEYXRhID0ge1xuXHRcdFx0XHQvLyBVUkwgcHJvcGVydGllc1xuXHRcdFx0XHR1cmw6IHJlcXVlc3QudXJsLFxuXHRcdFx0XHRwYXRobmFtZTogdXJsLnBhdGhuYW1lLFxuXHRcdFx0XHRzZWFyY2g6IHVybC5zZWFyY2gsXG5cdFx0XHRcdHNlYXJjaFBhcmFtczogT2JqZWN0LmZyb21FbnRyaWVzKHVybC5zZWFyY2hQYXJhbXMuZW50cmllcygpKSxcblx0XHRcdFx0aGFzaDogdXJsLmhhc2gsXG5cblx0XHRcdFx0Ly8gTWV0aG9kXG5cdFx0XHRcdG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG5cblx0XHRcdFx0Ly8gSGVhZGVyc1xuXHRcdFx0XHRoZWFkZXJzOiBoZWFkZXJzLFxuXG5cdFx0XHRcdC8vIEJvZHlcblx0XHRcdFx0Ym9keSxcblx0XHRcdFx0Ym9keVRleHQ6XG5cdFx0XHRcdFx0dHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCJcblx0XHRcdFx0XHRcdD8gYm9keVxuXHRcdFx0XHRcdFx0OiBib2R5ID09PSBudWxsICYmIHJlcXVlc3QuYm9keSAhPT0gbnVsbFxuXHRcdFx0XHRcdFx0XHQ/IFwiXCJcblx0XHRcdFx0XHRcdFx0OiBudWxsLFxuXG5cdFx0XHRcdC8vIEFkZGl0aW9uYWwgcHJvcGVydGllcyB0aGF0IG1pZ2h0IGJlIGF2YWlsYWJsZVxuXHRcdFx0XHQvLyBOb3RlOiBTb21lIHByb3BlcnRpZXMgbGlrZSBjYWNoZSwgY3JlZGVudGlhbHMsIG1vZGUsIGV0Yy5cblx0XHRcdFx0Ly8gbWlnaHQgbm90IGJlIGF2YWlsYWJsZSBpbiBhbGwgZW52aXJvbm1lbnRzXG5cdFx0XHRcdGNhY2hlOiByZXF1ZXN0LmNhY2hlIHx8IG51bGwsXG5cdFx0XHRcdGNyZWRlbnRpYWxzOiByZXF1ZXN0LmNyZWRlbnRpYWxzIHx8IG51bGwsXG5cdFx0XHRcdG1vZGU6IHJlcXVlc3QubW9kZSB8fCBudWxsLFxuXHRcdFx0XHRyZWRpcmVjdDogcmVxdWVzdC5yZWRpcmVjdCB8fCBudWxsLFxuXHRcdFx0XHRyZWZlcnJlcjogcmVxdWVzdC5yZWZlcnJlciB8fCBudWxsLFxuXHRcdFx0fTtcblxuXHRcdFx0cmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeShyZXNwb25zZURhdGEpLCB7XG5cdFx0XHRcdGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy13ZWJzb2NrZXQudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy13ZWJzb2NrZXQudHNcIjtpbXBvcnQgeyB0eXBlIEFjdG9yQ29udGV4dCwgYWN0b3IsIHR5cGUgVW5pdmVyc2FsV2ViU29ja2V0IH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbmV4cG9ydCBjb25zdCByYXdXZWJTb2NrZXRBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHtcblx0XHRjb25uZWN0aW9uQ291bnQ6IDAsXG5cdFx0bWVzc2FnZUNvdW50OiAwLFxuXHR9LFxuXHRvbkF1dGgocGFyYW1zKSB7XG5cdFx0Ly8gQWxsb3cgYWxsIGNvbm5lY3Rpb25zIGFuZCBwYXNzIHRocm91Z2ggY29ubmVjdGlvbiBwYXJhbXNcblx0XHRyZXR1cm4geyBjb25uUGFyYW1zOiBwYXJhbXMgfTtcblx0fSxcblx0b25XZWJTb2NrZXQoY3R4LCB3ZWJzb2NrZXQsIG9wdHMpIHtcblx0XHRjdHguc3RhdGUuY29ubmVjdGlvbkNvdW50ID0gY3R4LnN0YXRlLmNvbm5lY3Rpb25Db3VudCArIDE7XG5cdFx0Y29uc29sZS5sb2coYFtBQ1RPUl0gTmV3IGNvbm5lY3Rpb24sIGNvdW50OiAke2N0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnR9YCk7XG5cblx0XHQvLyBTZW5kIHdlbGNvbWUgbWVzc2FnZVxuXHRcdHdlYnNvY2tldC5zZW5kKFxuXHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHR0eXBlOiBcIndlbGNvbWVcIixcblx0XHRcdFx0Y29ubmVjdGlvbkNvdW50OiBjdHguc3RhdGUuY29ubmVjdGlvbkNvdW50LFxuXHRcdFx0fSksXG5cdFx0KTtcblx0XHRjb25zb2xlLmxvZyhcIltBQ1RPUl0gU2VudCB3ZWxjb21lIG1lc3NhZ2VcIik7XG5cblx0XHQvLyBFY2hvIG1lc3NhZ2VzIGJhY2tcblx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGV2ZW50OiBhbnkpID0+IHtcblx0XHRcdGN0eC5zdGF0ZS5tZXNzYWdlQ291bnQgPSBjdHguc3RhdGUubWVzc2FnZUNvdW50ICsgMTtcblx0XHRcdGNvbnNvbGUubG9nKFxuXHRcdFx0XHRgW0FDVE9SXSBNZXNzYWdlIHJlY2VpdmVkLCB0b3RhbCBjb3VudDogJHtjdHguc3RhdGUubWVzc2FnZUNvdW50fSwgZGF0YTpgLFxuXHRcdFx0XHRldmVudC5kYXRhLFxuXHRcdFx0KTtcblxuXHRcdFx0Y29uc3QgZGF0YSA9IGV2ZW50LmRhdGE7XG5cdFx0XHRpZiAodHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGRhdGEpO1xuXHRcdFx0XHRcdGlmIChwYXJzZWQudHlwZSA9PT0gXCJwaW5nXCIpIHtcblx0XHRcdFx0XHRcdHdlYnNvY2tldC5zZW5kKFxuXHRcdFx0XHRcdFx0XHRKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0XHRcdFx0dHlwZTogXCJwb25nXCIsXG5cdFx0XHRcdFx0XHRcdFx0dGltZXN0YW1wOiBEYXRlLm5vdygpLFxuXHRcdFx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwYXJzZWQudHlwZSA9PT0gXCJnZXRTdGF0c1wiKSB7XG5cdFx0XHRcdFx0XHRjb25zb2xlLmxvZyhcblx0XHRcdFx0XHRcdFx0YFtBQ1RPUl0gU2VuZGluZyBzdGF0cyAtIGNvbm5lY3Rpb25zOiAke2N0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnR9LCBtZXNzYWdlczogJHtjdHguc3RhdGUubWVzc2FnZUNvdW50fWAsXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0d2Vic29ja2V0LnNlbmQoXG5cdFx0XHRcdFx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRcdFx0XHR0eXBlOiBcInN0YXRzXCIsXG5cdFx0XHRcdFx0XHRcdFx0Y29ubmVjdGlvbkNvdW50OiBjdHguc3RhdGUuY29ubmVjdGlvbkNvdW50LFxuXHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2VDb3VudDogY3R4LnN0YXRlLm1lc3NhZ2VDb3VudCxcblx0XHRcdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAocGFyc2VkLnR5cGUgPT09IFwiZ2V0QXV0aERhdGFcIikge1xuXHRcdFx0XHRcdFx0Ly8gQXV0aCBkYXRhIGlzIG5vdCBkaXJlY3RseSBhdmFpbGFibGUgaW4gcmF3IFdlYlNvY2tldCBoYW5kbGVyXG5cdFx0XHRcdFx0XHQvLyBTZW5kIGEgbWVzc2FnZSBpbmRpY2F0aW5nIHRoaXMgbGltaXRhdGlvblxuXHRcdFx0XHRcdFx0d2Vic29ja2V0LnNlbmQoXG5cdFx0XHRcdFx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRcdFx0XHR0eXBlOiBcImF1dGhEYXRhXCIsXG5cdFx0XHRcdFx0XHRcdFx0YXV0aERhdGE6IG51bGwsXG5cdFx0XHRcdFx0XHRcdFx0bWVzc2FnZTogXCJBdXRoIGRhdGEgbm90IGF2YWlsYWJsZSBpbiByYXcgV2ViU29ja2V0IGhhbmRsZXJcIixcblx0XHRcdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAocGFyc2VkLnR5cGUgPT09IFwiZ2V0UmVxdWVzdEluZm9cIikge1xuXHRcdFx0XHRcdFx0Ly8gU2VuZCBiYWNrIHRoZSByZXF1ZXN0IFVSTCBpbmZvXG5cdFx0XHRcdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwicmVxdWVzdEluZm9cIixcblx0XHRcdFx0XHRcdFx0XHR1cmw6IG9wdHMucmVxdWVzdC51cmwsXG5cdFx0XHRcdFx0XHRcdFx0cGF0aG5hbWU6IG5ldyBVUkwob3B0cy5yZXF1ZXN0LnVybCkucGF0aG5hbWUsXG5cdFx0XHRcdFx0XHRcdFx0c2VhcmNoOiBuZXcgVVJMKG9wdHMucmVxdWVzdC51cmwpLnNlYXJjaCxcblx0XHRcdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQvLyBFY2hvIGJhY2tcblx0XHRcdFx0XHRcdHdlYnNvY2tldC5zZW5kKGRhdGEpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdFx0Ly8gSWYgbm90IEpTT04sIGp1c3QgZWNobyBpdCBiYWNrXG5cdFx0XHRcdFx0d2Vic29ja2V0LnNlbmQoZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEVjaG8gYmluYXJ5IGRhdGFcblx0XHRcdFx0d2Vic29ja2V0LnNlbmQoZGF0YSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQvLyBIYW5kbGUgY2xvc2Vcblx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcImNsb3NlXCIsICgpID0+IHtcblx0XHRcdGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQgPSBjdHguc3RhdGUuY29ubmVjdGlvbkNvdW50IC0gMTtcblx0XHRcdGNvbnNvbGUubG9nKFxuXHRcdFx0XHRgW0FDVE9SXSBDb25uZWN0aW9uIGNsb3NlZCwgY291bnQ6ICR7Y3R4LnN0YXRlLmNvbm5lY3Rpb25Db3VudH1gLFxuXHRcdFx0KTtcblx0XHR9KTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFN0YXRzKGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRjb25uZWN0aW9uQ291bnQ6IGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQsXG5cdFx0XHRcdG1lc3NhZ2VDb3VudDogY3R4LnN0YXRlLm1lc3NhZ2VDb3VudCxcblx0XHRcdH07XG5cdFx0fSxcblx0fSxcbn0pO1xuXG5leHBvcnQgY29uc3QgcmF3V2ViU29ja2V0QmluYXJ5QWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aCgpIHtcblx0XHQvLyBBbGxvdyBhbGwgY29ubmVjdGlvbnNcblx0XHRyZXR1cm4ge307XG5cdH0sXG5cdG9uV2ViU29ja2V0KGN0eCwgd2Vic29ja2V0LCBvcHRzKSB7XG5cdFx0Ly8gSGFuZGxlIGJpbmFyeSBkYXRhXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChldmVudDogYW55KSA9PiB7XG5cdFx0XHRjb25zdCBkYXRhID0gZXZlbnQuZGF0YTtcblx0XHRcdGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHwgZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcblx0XHRcdFx0Ly8gUmV2ZXJzZSB0aGUgYnl0ZXMgYW5kIHNlbmQgYmFja1xuXHRcdFx0XHRjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGRhdGEpO1xuXHRcdFx0XHRjb25zdCByZXZlcnNlZCA9IG5ldyBVaW50OEFycmF5KGJ5dGVzLmxlbmd0aCk7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0XHRyZXZlcnNlZFtpXSA9IGJ5dGVzW2J5dGVzLmxlbmd0aCAtIDEgLSBpXTtcblx0XHRcdFx0fVxuXHRcdFx0XHR3ZWJzb2NrZXQuc2VuZChyZXZlcnNlZCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0sXG5cdGFjdGlvbnM6IHt9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3Jhdy13ZWJzb2NrZXQtYXV0aC50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmF3LXdlYnNvY2tldC1hdXRoLnRzXCI7aW1wb3J0IHtcblx0dHlwZSBBY3RvckNvbnRleHQsXG5cdGFjdG9yLFxuXHR0eXBlIFVuaXZlcnNhbFdlYlNvY2tldCxcblx0VXNlckVycm9yLFxufSBmcm9tIFwicml2ZXRraXRcIjtcblxuLy8gUmF3IFdlYlNvY2tldCBhY3RvciB3aXRoIGF1dGhlbnRpY2F0aW9uXG5leHBvcnQgY29uc3QgcmF3V2ViU29ja2V0QXV0aEFjdG9yID0gYWN0b3Ioe1xuXHRzdGF0ZToge1xuXHRcdGNvbm5lY3Rpb25Db3VudDogMCxcblx0XHRtZXNzYWdlQ291bnQ6IDAsXG5cdH0sXG5cdG9uQXV0aDogKG9wdHMsIHBhcmFtczogeyBhcGlLZXk/OiBzdHJpbmcgfSkgPT4ge1xuXHRcdGNvbnN0IGFwaUtleSA9IHBhcmFtcy5hcGlLZXk7XG5cdFx0aWYgKCFhcGlLZXkpIHtcblx0XHRcdHRocm93IG5ldyBVc2VyRXJyb3IoXCJBUEkga2V5IHJlcXVpcmVkXCIsIHsgY29kZTogXCJtaXNzaW5nX2F1dGhcIiB9KTtcblx0XHR9XG5cblx0XHRpZiAoYXBpS2V5ICE9PSBcInZhbGlkLWFwaS1rZXlcIikge1xuXHRcdFx0dGhyb3cgbmV3IFVzZXJFcnJvcihcIkludmFsaWQgQVBJIGtleVwiLCB7IGNvZGU6IFwiaW52YWxpZF9hdXRoXCIgfSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHsgdXNlcklkOiBcInVzZXIxMjNcIiwgdG9rZW46IGFwaUtleSB9O1xuXHR9LFxuXHRvbldlYlNvY2tldChjdHgsIHdlYnNvY2tldCkge1xuXHRcdGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQrKztcblxuXHRcdC8vIFNlbmQgd2VsY29tZSBtZXNzYWdlIG9uIGNvbm5lY3Rcblx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0dHlwZTogXCJ3ZWxjb21lXCIsXG5cdFx0XHRcdG1lc3NhZ2U6IFwiQXV0aGVudGljYXRlZCBXZWJTb2NrZXQgY29ubmVjdGlvblwiLFxuXHRcdFx0XHRjb25uZWN0aW9uQ291bnQ6IGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQsXG5cdFx0XHR9KSxcblx0XHQpO1xuXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChldmVudDogYW55KSA9PiB7XG5cdFx0XHRjdHguc3RhdGUubWVzc2FnZUNvdW50Kys7XG5cdFx0XHRjb25zdCBkYXRhID0gZXZlbnQuZGF0YTtcblxuXHRcdFx0aWYgKHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShkYXRhKTtcblx0XHRcdFx0XHRpZiAocGFyc2VkLnR5cGUgPT09IFwiZ2V0QXV0aFwiKSB7XG5cdFx0XHRcdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwiYXV0aEluZm9cIixcblx0XHRcdFx0XHRcdFx0XHRhdXRoZW50aWNhdGVkOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vIEVjaG8gbWVzc2FnZSBiYWNrXG5cdFx0XHRcdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwiZWNob1wiLFxuXHRcdFx0XHRcdFx0XHRcdG9yaWdpbmFsOiBwYXJzZWQsXG5cdFx0XHRcdFx0XHRcdH0pLFxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdHdlYnNvY2tldC5zZW5kKGRhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcImNsb3NlXCIsICgpID0+IHtcblx0XHRcdGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQtLTtcblx0XHR9KTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFN0YXRzKGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRjb25uZWN0aW9uQ291bnQ6IGN0eC5zdGF0ZS5jb25uZWN0aW9uQ291bnQsXG5cdFx0XHRcdG1lc3NhZ2VDb3VudDogY3R4LnN0YXRlLm1lc3NhZ2VDb3VudCxcblx0XHRcdH07XG5cdFx0fSxcblx0fSxcbn0pO1xuXG4vLyBSYXcgV2ViU29ja2V0IGFjdG9yIHdpdGhvdXQgb25BdXRoIC0gc2hvdWxkIGRlbnkgYWNjZXNzXG5leHBvcnQgY29uc3QgcmF3V2ViU29ja2V0Tm9BdXRoQWN0b3IgPSBhY3Rvcih7XG5cdHN0YXRlOiB7XG5cdFx0Y29ubmVjdGlvbnM6IDAsXG5cdH0sXG5cdG9uV2ViU29ja2V0KGN0eCwgd2Vic29ja2V0KSB7XG5cdFx0Y3R4LnN0YXRlLmNvbm5lY3Rpb25zKys7XG5cdFx0d2Vic29ja2V0LnNlbmQoXG5cdFx0XHRKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdHR5cGU6IFwiY29ubmVjdGVkXCIsXG5cdFx0XHRcdGNvbm5lY3Rpb25zOiBjdHguc3RhdGUuY29ubmVjdGlvbnMsXG5cdFx0XHR9KSxcblx0XHQpO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0Q29ubmVjdGlvbkNvdW50KGN0eDogYW55KSB7XG5cdFx0XHRyZXR1cm4gY3R4LnN0YXRlLmNvbm5lY3Rpb25zO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gUmF3IFdlYlNvY2tldCBhY3RvciB3aXRoIHB1YmxpYyBhY2Nlc3NcbmV4cG9ydCBjb25zdCByYXdXZWJTb2NrZXRQdWJsaWNBY3RvciA9IGFjdG9yKHtcblx0c3RhdGU6IHtcblx0XHR2aXNpdG9yczogMCxcblx0fSxcblx0b25BdXRoOiAoKSA9PiB7XG5cdFx0cmV0dXJuIG51bGw7IC8vIEFsbG93IHB1YmxpYyBhY2Nlc3Ncblx0fSxcblx0b25XZWJTb2NrZXQoY3R4LCB3ZWJzb2NrZXQpIHtcblx0XHRjdHguc3RhdGUudmlzaXRvcnMrKztcblxuXHRcdHdlYnNvY2tldC5zZW5kKFxuXHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHR0eXBlOiBcIndlbGNvbWVcIixcblx0XHRcdFx0bWVzc2FnZTogXCJQdWJsaWMgV2ViU29ja2V0IGNvbm5lY3Rpb25cIixcblx0XHRcdFx0dmlzaXRvck51bWJlcjogY3R4LnN0YXRlLnZpc2l0b3JzLFxuXHRcdFx0fSksXG5cdFx0KTtcblxuXHRcdHdlYnNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCAoZXZlbnQ6IGFueSkgPT4ge1xuXHRcdFx0Ly8gRWNobyBtZXNzYWdlc1xuXHRcdFx0d2Vic29ja2V0LnNlbmQoZXZlbnQuZGF0YSk7XG5cdFx0fSk7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRWaXNpdG9yQ291bnQoY3R4OiBhbnkpIHtcblx0XHRcdHJldHVybiBjdHguc3RhdGUudmlzaXRvcnM7XG5cdFx0fSxcblx0fSxcbn0pO1xuXG4vLyBSYXcgV2ViU29ja2V0IHdpdGggY3VzdG9tIGF1dGggaW4gb25XZWJTb2NrZXRcbmV4cG9ydCBjb25zdCByYXdXZWJTb2NrZXRDdXN0b21BdXRoQWN0b3IgPSBhY3Rvcih7XG5cdHN0YXRlOiB7XG5cdFx0YXV0aG9yaXplZDogMCxcblx0XHR1bmF1dGhvcml6ZWQ6IDAsXG5cdH0sXG5cdG9uQXV0aDogKCkgPT4ge1xuXHRcdC8vIEFsbG93IGFsbCBjb25uZWN0aW9ucyAtIGF1dGggd2lsbCBiZSBoYW5kbGVkIGluIG9uV2ViU29ja2V0XG5cdFx0cmV0dXJuIHt9O1xuXHR9LFxuXHRvbldlYlNvY2tldChjdHgsIHdlYnNvY2tldCwgb3B0cykge1xuXHRcdC8vIENoZWNrIGZvciBhdXRoIHRva2VuIGluIFVSTCBvciBoZWFkZXJzXG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChvcHRzLnJlcXVlc3QudXJsKTtcblx0XHRjb25zdCB0b2tlbiA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KFwidG9rZW5cIik7XG5cblx0XHRpZiAoIXRva2VuIHx8IHRva2VuICE9PSBcImN1c3RvbS13cy10b2tlblwiKSB7XG5cdFx0XHRjdHguc3RhdGUudW5hdXRob3JpemVkKys7XG5cdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdHR5cGU6IFwiZXJyb3JcIixcblx0XHRcdFx0XHRtZXNzYWdlOiBcIlVuYXV0aG9yaXplZFwiLFxuXHRcdFx0XHR9KSxcblx0XHRcdCk7XG5cdFx0XHR3ZWJzb2NrZXQuY2xvc2UoMTAwOCwgXCJVbmF1dGhvcml6ZWRcIik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y3R4LnN0YXRlLmF1dGhvcml6ZWQrKztcblx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0dHlwZTogXCJhdXRob3JpemVkXCIsXG5cdFx0XHRcdG1lc3NhZ2U6IFwiV2VsY29tZSBhdXRoZW50aWNhdGVkIHVzZXIhXCIsXG5cdFx0XHR9KSxcblx0XHQpO1xuXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChldmVudDogYW55KSA9PiB7XG5cdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdHR5cGU6IFwiZWNob1wiLFxuXHRcdFx0XHRcdGRhdGE6IGV2ZW50LmRhdGEsXG5cdFx0XHRcdFx0YXV0aGVudGljYXRlZDogdHJ1ZSxcblx0XHRcdFx0fSksXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0U3RhdHMoY3R4OiBhbnkpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGF1dGhvcml6ZWQ6IGN0eC5zdGF0ZS5hdXRob3JpemVkLFxuXHRcdFx0XHR1bmF1dGhvcml6ZWQ6IGN0eC5zdGF0ZS51bmF1dGhvcml6ZWQsXG5cdFx0XHR9O1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmVxdWVzdC1hY2Nlc3MudHNcIjtjb25zdCBfX2luamVjdGVkX2Rpcm5hbWVfXyA9IFwiL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZVwiO2NvbnN0IF9faW5qZWN0ZWRfaW1wb3J0X21ldGFfdXJsX18gPSBcImZpbGU6Ly8vVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3JlcXVlc3QtYWNjZXNzLnRzXCI7aW1wb3J0IHsgYWN0b3IgfSBmcm9tIFwicml2ZXRraXRcIjtcblxuLyoqXG4gKiBUZXN0IGZpeHR1cmUgdG8gdmVyaWZ5IHJlcXVlc3Qgb2JqZWN0IGFjY2VzcyBpbiBhbGwgbGlmZWN5Y2xlIGhvb2tzXG4gKi9cbmV4cG9ydCBjb25zdCByZXF1ZXN0QWNjZXNzQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sIC8vIEFsbG93IHVuYXV0aGVudGljYXRlZCBjb25uZWN0aW9uc1xuXHRzdGF0ZToge1xuXHRcdC8vIFRyYWNrIHJlcXVlc3QgaW5mbyBmcm9tIGRpZmZlcmVudCBob29rc1xuXHRcdG9uQmVmb3JlQ29ubmVjdFJlcXVlc3Q6IHtcblx0XHRcdGhhc1JlcXVlc3Q6IGZhbHNlLFxuXHRcdFx0cmVxdWVzdFVybDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdE1ldGhvZDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdEhlYWRlcnM6IHt9IGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG5cdFx0fSxcblx0XHRjcmVhdGVDb25uU3RhdGVSZXF1ZXN0OiB7XG5cdFx0XHRoYXNSZXF1ZXN0OiBmYWxzZSxcblx0XHRcdHJlcXVlc3RVcmw6IG51bGwgYXMgc3RyaW5nIHwgbnVsbCxcblx0XHRcdHJlcXVlc3RNZXRob2Q6IG51bGwgYXMgc3RyaW5nIHwgbnVsbCxcblx0XHRcdHJlcXVlc3RIZWFkZXJzOiB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuXHRcdH0sXG5cdFx0b25GZXRjaFJlcXVlc3Q6IHtcblx0XHRcdGhhc1JlcXVlc3Q6IGZhbHNlLFxuXHRcdFx0cmVxdWVzdFVybDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdE1ldGhvZDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdEhlYWRlcnM6IHt9IGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG5cdFx0fSxcblx0XHRvbldlYlNvY2tldFJlcXVlc3Q6IHtcblx0XHRcdGhhc1JlcXVlc3Q6IGZhbHNlLFxuXHRcdFx0cmVxdWVzdFVybDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdE1ldGhvZDogbnVsbCBhcyBzdHJpbmcgfCBudWxsLFxuXHRcdFx0cmVxdWVzdEhlYWRlcnM6IHt9IGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG5cdFx0fSxcblx0fSxcblx0Y3JlYXRlQ29ublN0YXRlOiAoYywgeyByZXF1ZXN0IH0sIHBhcmFtczogeyB0cmFja1JlcXVlc3Q/OiBib29sZWFuIH0pID0+IHtcblx0XHQvLyBJbiBjcmVhdGVDb25uU3RhdGUsIHRoZSBzdGF0ZSBpc24ndCBhdmFpbGFibGUgeWV0LlxuXG5cdFx0cmV0dXJuIHtcblx0XHRcdHRyYWNrUmVxdWVzdDogcGFyYW1zPy50cmFja1JlcXVlc3QgfHwgZmFsc2UsXG5cdFx0XHRyZXF1ZXN0SW5mbzpcblx0XHRcdFx0cGFyYW1zPy50cmFja1JlcXVlc3QgJiYgcmVxdWVzdFxuXHRcdFx0XHRcdD8ge1xuXHRcdFx0XHRcdFx0XHRoYXNSZXF1ZXN0OiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0VXJsOiByZXF1ZXN0LnVybCxcblx0XHRcdFx0XHRcdFx0cmVxdWVzdE1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG5cdFx0XHRcdFx0XHRcdHJlcXVlc3RIZWFkZXJzOiBPYmplY3QuZnJvbUVudHJpZXMocmVxdWVzdC5oZWFkZXJzLmVudHJpZXMoKSksXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0OiBudWxsLFxuXHRcdH07XG5cdH0sXG5cdG9uQ29ubmVjdDogKGMsIGNvbm4pID0+IHtcblx0XHQvLyBDb3B5IHJlcXVlc3QgaW5mbyBmcm9tIGNvbm5lY3Rpb24gc3RhdGUgaWYgaXQgd2FzIHRyYWNrZWRcblx0XHRpZiAoY29ubi5zdGF0ZS5yZXF1ZXN0SW5mbykge1xuXHRcdFx0Yy5zdGF0ZS5jcmVhdGVDb25uU3RhdGVSZXF1ZXN0ID0gY29ubi5zdGF0ZS5yZXF1ZXN0SW5mbztcblx0XHR9XG5cdH0sXG5cdG9uQmVmb3JlQ29ubmVjdDogKGMsIHsgcmVxdWVzdCB9LCBwYXJhbXMpID0+IHtcblx0XHRpZiAocGFyYW1zPy50cmFja1JlcXVlc3QpIHtcblx0XHRcdGlmIChyZXF1ZXN0KSB7XG5cdFx0XHRcdGMuc3RhdGUub25CZWZvcmVDb25uZWN0UmVxdWVzdC5oYXNSZXF1ZXN0ID0gdHJ1ZTtcblx0XHRcdFx0Yy5zdGF0ZS5vbkJlZm9yZUNvbm5lY3RSZXF1ZXN0LnJlcXVlc3RVcmwgPSByZXF1ZXN0LnVybDtcblx0XHRcdFx0Yy5zdGF0ZS5vbkJlZm9yZUNvbm5lY3RSZXF1ZXN0LnJlcXVlc3RNZXRob2QgPSByZXF1ZXN0Lm1ldGhvZDtcblxuXHRcdFx0XHQvLyBTdG9yZSBzZWxlY3QgaGVhZGVyc1xuXHRcdFx0XHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdFx0XHRcdHJlcXVlc3QuaGVhZGVycy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG5cdFx0XHRcdFx0aGVhZGVyc1trZXldID0gdmFsdWU7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRjLnN0YXRlLm9uQmVmb3JlQ29ubmVjdFJlcXVlc3QucmVxdWVzdEhlYWRlcnMgPSBoZWFkZXJzO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gVHJhY2sgdGhhdCB3ZSB0cmllZCBidXQgcmVxdWVzdCB3YXMgbm90IGF2YWlsYWJsZVxuXHRcdFx0XHRjLnN0YXRlLm9uQmVmb3JlQ29ubmVjdFJlcXVlc3QuaGFzUmVxdWVzdCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0b25GZXRjaDogKGMsIHJlcXVlc3QpID0+IHtcblx0XHQvLyBTdG9yZSByZXF1ZXN0IGluZm9cblx0XHRjLnN0YXRlLm9uRmV0Y2hSZXF1ZXN0Lmhhc1JlcXVlc3QgPSB0cnVlO1xuXHRcdGMuc3RhdGUub25GZXRjaFJlcXVlc3QucmVxdWVzdFVybCA9IHJlcXVlc3QudXJsO1xuXHRcdGMuc3RhdGUub25GZXRjaFJlcXVlc3QucmVxdWVzdE1ldGhvZCA9IHJlcXVlc3QubWV0aG9kO1xuXG5cdFx0Ly8gU3RvcmUgc2VsZWN0IGhlYWRlcnNcblx0XHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdFx0cmVxdWVzdC5oZWFkZXJzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcblx0XHRcdGhlYWRlcnNba2V5XSA9IHZhbHVlO1xuXHRcdH0pO1xuXHRcdGMuc3RhdGUub25GZXRjaFJlcXVlc3QucmVxdWVzdEhlYWRlcnMgPSBoZWFkZXJzO1xuXG5cdFx0Ly8gUmV0dXJuIHJlc3BvbnNlIHdpdGggcmVxdWVzdCBpbmZvXG5cdFx0cmV0dXJuIG5ldyBSZXNwb25zZShcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0aGFzUmVxdWVzdDogdHJ1ZSxcblx0XHRcdFx0cmVxdWVzdFVybDogcmVxdWVzdC51cmwsXG5cdFx0XHRcdHJlcXVlc3RNZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuXHRcdFx0XHRyZXF1ZXN0SGVhZGVyczogaGVhZGVycyxcblx0XHRcdH0pLFxuXHRcdFx0e1xuXHRcdFx0XHRzdGF0dXM6IDIwMCxcblx0XHRcdFx0aGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuXHRcdFx0fSxcblx0XHQpO1xuXHR9LFxuXHRvbldlYlNvY2tldDogKGMsIHdlYnNvY2tldCwgeyByZXF1ZXN0IH0pID0+IHtcblx0XHQvLyBTdG9yZSByZXF1ZXN0IGluZm9cblx0XHRjLnN0YXRlLm9uV2ViU29ja2V0UmVxdWVzdC5oYXNSZXF1ZXN0ID0gdHJ1ZTtcblx0XHRjLnN0YXRlLm9uV2ViU29ja2V0UmVxdWVzdC5yZXF1ZXN0VXJsID0gcmVxdWVzdC51cmw7XG5cdFx0Yy5zdGF0ZS5vbldlYlNvY2tldFJlcXVlc3QucmVxdWVzdE1ldGhvZCA9IHJlcXVlc3QubWV0aG9kO1xuXG5cdFx0Ly8gU3RvcmUgc2VsZWN0IGhlYWRlcnNcblx0XHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdFx0cmVxdWVzdC5oZWFkZXJzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcblx0XHRcdGhlYWRlcnNba2V5XSA9IHZhbHVlO1xuXHRcdH0pO1xuXHRcdGMuc3RhdGUub25XZWJTb2NrZXRSZXF1ZXN0LnJlcXVlc3RIZWFkZXJzID0gaGVhZGVycztcblxuXHRcdC8vIFNlbmQgcmVxdWVzdCBpbmZvIG9uIGNvbm5lY3Rpb25cblx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0aGFzUmVxdWVzdDogdHJ1ZSxcblx0XHRcdFx0cmVxdWVzdFVybDogcmVxdWVzdC51cmwsXG5cdFx0XHRcdHJlcXVlc3RNZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuXHRcdFx0XHRyZXF1ZXN0SGVhZGVyczogaGVhZGVycyxcblx0XHRcdH0pLFxuXHRcdCk7XG5cblx0XHQvLyBFY2hvIG1lc3NhZ2VzIGJhY2tcblx0XHR3ZWJzb2NrZXQuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGV2ZW50KSA9PiB7XG5cdFx0XHR3ZWJzb2NrZXQuc2VuZChldmVudC5kYXRhKTtcblx0XHR9KTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFJlcXVlc3RJbmZvOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0b25CZWZvcmVDb25uZWN0OiBjLnN0YXRlLm9uQmVmb3JlQ29ubmVjdFJlcXVlc3QsXG5cdFx0XHRcdGNyZWF0ZUNvbm5TdGF0ZTogYy5zdGF0ZS5jcmVhdGVDb25uU3RhdGVSZXF1ZXN0LFxuXHRcdFx0XHRvbkZldGNoOiBjLnN0YXRlLm9uRmV0Y2hSZXF1ZXN0LFxuXHRcdFx0XHRvbldlYlNvY2tldDogYy5zdGF0ZS5vbldlYlNvY2tldFJlcXVlc3QsXG5cdFx0XHR9O1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmVxdWVzdC1hY2Nlc3MtYXV0aC50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvcmVxdWVzdC1hY2Nlc3MtYXV0aC50c1wiO2ltcG9ydCB7IGFjdG9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbi8qKlxuICogVGVzdCBmaXh0dXJlIHRvIHZlcmlmeSByZXF1ZXN0IG9iamVjdCBhY2Nlc3MgaW4gb25BdXRoIGhvb2tcbiAqIG9uQXV0aCBydW5zIG9uIHRoZSBIVFRQIHNlcnZlciwgbm90IGluIHRoZSBhY3Rvciwgc28gd2UgdGVzdCBpdCBzZXBhcmF0ZWx5XG4gKi9cbmV4cG9ydCBjb25zdCByZXF1ZXN0QWNjZXNzQXV0aEFjdG9yID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICh7IHJlcXVlc3QsIGludGVudHMgfSwgcGFyYW1zOiB7IHRyYWNrUmVxdWVzdD86IGJvb2xlYW4gfSkgPT4ge1xuXHRcdGlmIChwYXJhbXM/LnRyYWNrUmVxdWVzdCkge1xuXHRcdFx0Ly8gRXh0cmFjdCByZXF1ZXN0IGluZm8gYW5kIHJldHVybiBpdCBhcyBhdXRoIGRhdGFcblx0XHRcdGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblx0XHRcdHJlcXVlc3QuaGVhZGVycy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG5cdFx0XHRcdGhlYWRlcnNba2V5XSA9IHZhbHVlO1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGhhc1JlcXVlc3Q6IHRydWUsXG5cdFx0XHRcdHJlcXVlc3RVcmw6IHJlcXVlc3QudXJsLFxuXHRcdFx0XHRyZXF1ZXN0TWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcblx0XHRcdFx0cmVxdWVzdEhlYWRlcnM6IGhlYWRlcnMsXG5cdFx0XHRcdGludGVudHM6IEFycmF5LmZyb20oaW50ZW50cyksXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiBlbXB0eSBhdXRoIGRhdGEgd2hlbiBub3QgdHJhY2tpbmdcblx0XHRyZXR1cm4ge307XG5cdH0sXG5cdHN0YXRlOiB7XG5cdFx0YXV0aERhdGE6IG51bGwgYXMgYW55LFxuXHR9LFxuXHRvbkNvbm5lY3Q6IChjLCBjb25uKSA9PiB7XG5cdFx0Ly8gU3RvcmUgYXV0aCBkYXRhIGluIHN0YXRlIHNvIHdlIGNhbiByZXRyaWV2ZSBpdFxuXHRcdGMuc3RhdGUuYXV0aERhdGEgPSBjb25uLmF1dGg7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRBdXRoUmVxdWVzdEluZm86IChjKSA9PiB7XG5cdFx0XHQvLyBSZXR1cm4gdGhlIHN0b3JlZCBhdXRoIGRhdGEgb3IgYSBkZWZhdWx0IG9iamVjdFxuXHRcdFx0Y29uc3QgYXV0aERhdGEgPSBjLnN0YXRlLmF1dGhEYXRhIHx8IHtcblx0XHRcdFx0aGFzUmVxdWVzdDogZmFsc2UsXG5cdFx0XHRcdHJlcXVlc3RVcmw6IG51bGwsXG5cdFx0XHRcdHJlcXVlc3RNZXRob2Q6IG51bGwsXG5cdFx0XHRcdHJlcXVlc3RIZWFkZXJzOiB7fSxcblx0XHRcdFx0aW50ZW50czogW10sXG5cdFx0XHR9O1xuXHRcdFx0cmV0dXJuIGF1dGhEYXRhO1xuXHRcdH0sXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvc2NoZWR1bGVkLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9zY2hlZHVsZWQudHNcIjtpbXBvcnQgeyBhY3RvciB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG5leHBvcnQgY29uc3Qgc2NoZWR1bGVkID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZToge1xuXHRcdGxhc3RSdW46IDAsXG5cdFx0c2NoZWR1bGVkQ291bnQ6IDAsXG5cdFx0dGFza0hpc3Rvcnk6IFtdIGFzIHN0cmluZ1tdLFxuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Ly8gU2NoZWR1bGUgdXNpbmcgJ2F0JyB3aXRoIHNwZWNpZmljIHRpbWVzdGFtcFxuXHRcdHNjaGVkdWxlVGFza0F0OiAoYywgdGltZXN0YW1wOiBudW1iZXIpID0+IHtcblx0XHRcdGMuc2NoZWR1bGUuYXQodGltZXN0YW1wLCBcIm9uU2NoZWR1bGVkVGFza1wiKTtcblx0XHRcdHJldHVybiB0aW1lc3RhbXA7XG5cdFx0fSxcblxuXHRcdC8vIFNjaGVkdWxlIHVzaW5nICdhZnRlcicgd2l0aCBkZWxheVxuXHRcdHNjaGVkdWxlVGFza0FmdGVyOiAoYywgZGVsYXlNczogbnVtYmVyKSA9PiB7XG5cdFx0XHRjLnNjaGVkdWxlLmFmdGVyKGRlbGF5TXMsIFwib25TY2hlZHVsZWRUYXNrXCIpO1xuXHRcdFx0cmV0dXJuIERhdGUubm93KCkgKyBkZWxheU1zO1xuXHRcdH0sXG5cblx0XHQvLyBTY2hlZHVsZSB3aXRoIGEgdGFzayBJRCBmb3Igb3JkZXJpbmcgdGVzdHNcblx0XHRzY2hlZHVsZVRhc2tBZnRlcldpdGhJZDogKGMsIHRhc2tJZDogc3RyaW5nLCBkZWxheU1zOiBudW1iZXIpID0+IHtcblx0XHRcdGMuc2NoZWR1bGUuYWZ0ZXIoZGVsYXlNcywgXCJvblNjaGVkdWxlZFRhc2tXaXRoSWRcIiwgdGFza0lkKTtcblx0XHRcdHJldHVybiB7IHRhc2tJZCwgc2NoZWR1bGVkRm9yOiBEYXRlLm5vdygpICsgZGVsYXlNcyB9O1xuXHRcdH0sXG5cblx0XHQvLyBPcmlnaW5hbCBtZXRob2QgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcblx0XHRzY2hlZHVsZVRhc2s6IChjLCBkZWxheU1zOiBudW1iZXIpID0+IHtcblx0XHRcdGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCkgKyBkZWxheU1zO1xuXHRcdFx0Yy5zY2hlZHVsZS5hdCh0aW1lc3RhbXAsIFwib25TY2hlZHVsZWRUYXNrXCIpO1xuXHRcdFx0cmV0dXJuIHRpbWVzdGFtcDtcblx0XHR9LFxuXG5cdFx0Ly8gR2V0dGVycyBmb3Igc3RhdGVcblx0XHRnZXRMYXN0UnVuOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMuc3RhdGUubGFzdFJ1bjtcblx0XHR9LFxuXG5cdFx0Z2V0U2NoZWR1bGVkQ291bnQ6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS5zY2hlZHVsZWRDb3VudDtcblx0XHR9LFxuXG5cdFx0Z2V0VGFza0hpc3Rvcnk6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy5zdGF0ZS50YXNrSGlzdG9yeTtcblx0XHR9LFxuXG5cdFx0Y2xlYXJIaXN0b3J5OiAoYykgPT4ge1xuXHRcdFx0Yy5zdGF0ZS50YXNrSGlzdG9yeSA9IFtdO1xuXHRcdFx0Yy5zdGF0ZS5zY2hlZHVsZWRDb3VudCA9IDA7XG5cdFx0XHRjLnN0YXRlLmxhc3RSdW4gPSAwO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblxuXHRcdC8vIFNjaGVkdWxlZCB0YXNrIGhhbmRsZXJzXG5cdFx0b25TY2hlZHVsZWRUYXNrOiAoYykgPT4ge1xuXHRcdFx0Yy5zdGF0ZS5sYXN0UnVuID0gRGF0ZS5ub3coKTtcblx0XHRcdGMuc3RhdGUuc2NoZWR1bGVkQ291bnQrKztcblx0XHRcdGMuYnJvYWRjYXN0KFwic2NoZWR1bGVkXCIsIHtcblx0XHRcdFx0dGltZTogYy5zdGF0ZS5sYXN0UnVuLFxuXHRcdFx0XHRjb3VudDogYy5zdGF0ZS5zY2hlZHVsZWRDb3VudCxcblx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRvblNjaGVkdWxlZFRhc2tXaXRoSWQ6IChjLCB0YXNrSWQ6IHN0cmluZykgPT4ge1xuXHRcdFx0Yy5zdGF0ZS5sYXN0UnVuID0gRGF0ZS5ub3coKTtcblx0XHRcdGMuc3RhdGUuc2NoZWR1bGVkQ291bnQrKztcblx0XHRcdGMuc3RhdGUudGFza0hpc3RvcnkucHVzaCh0YXNrSWQpO1xuXHRcdFx0Yy5icm9hZGNhc3QoXCJzY2hlZHVsZWRXaXRoSWRcIiwge1xuXHRcdFx0XHR0YXNrSWQsXG5cdFx0XHRcdHRpbWU6IGMuc3RhdGUubGFzdFJ1bixcblx0XHRcdFx0Y291bnQ6IGMuc3RhdGUuc2NoZWR1bGVkQ291bnQsXG5cdFx0XHR9KTtcblx0XHR9LFxuXHR9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3NsZWVwLnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9zbGVlcC50c1wiO2ltcG9ydCB7IGFjdG9yLCB0eXBlIFVuaXZlcnNhbFdlYlNvY2tldCB9IGZyb20gXCJyaXZldGtpdFwiO1xuXG5leHBvcnQgY29uc3QgU0xFRVBfVElNRU9VVCA9IDUwMDtcblxuZXhwb3J0IGNvbnN0IHNsZWVwID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZTogeyBzdGFydENvdW50OiAwLCBzbGVlcENvdW50OiAwIH0sXG5cdG9uU3RhcnQ6IChjKSA9PiB7XG5cdFx0Yy5zdGF0ZS5zdGFydENvdW50ICs9IDE7XG5cdH0sXG5cdG9uU3RvcDogKGMpID0+IHtcblx0XHRjLnN0YXRlLnNsZWVwQ291bnQgKz0gMTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdHRyaWdnZXJTbGVlcDogKGMpID0+IHtcblx0XHRcdGMuc2xlZXAoKTtcblx0XHR9LFxuXHRcdGdldENvdW50czogKGMpID0+IHtcblx0XHRcdHJldHVybiB7IHN0YXJ0Q291bnQ6IGMuc3RhdGUuc3RhcnRDb3VudCwgc2xlZXBDb3VudDogYy5zdGF0ZS5zbGVlcENvdW50IH07XG5cdFx0fSxcblx0XHRzZXRBbGFybTogYXN5bmMgKGMsIGR1cmF0aW9uOiBudW1iZXIpID0+IHtcblx0XHRcdGF3YWl0IGMuc2NoZWR1bGUuYWZ0ZXIoZHVyYXRpb24sIFwib25BbGFybVwiKTtcblx0XHR9LFxuXHRcdG9uQWxhcm06IChjKSA9PiB7XG5cdFx0XHRjLmxvZy5pbmZvKFwiYWxhcm0gY2FsbGVkXCIpO1xuXHRcdH0sXG5cdH0sXG5cdG9wdGlvbnM6IHtcblx0XHRzbGVlcFRpbWVvdXQ6IFNMRUVQX1RJTUVPVVQsXG5cdH0sXG59KTtcblxuZXhwb3J0IGNvbnN0IHNsZWVwV2l0aExvbmdScGMgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHN0YXJ0Q291bnQ6IDAsIHNsZWVwQ291bnQ6IDAgfSxcblx0Y3JlYXRlVmFyczogKCkgPT4gKHt9KSBhcyB7IGxvbmdSdW5uaW5nUmVzb2x2ZTogUHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD4gfSxcblx0b25TdGFydDogKGMpID0+IHtcblx0XHRjLnN0YXRlLnN0YXJ0Q291bnQgKz0gMTtcblx0fSxcblx0b25TdG9wOiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuc2xlZXBDb3VudCArPSAxO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0Q291bnRzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHsgc3RhcnRDb3VudDogYy5zdGF0ZS5zdGFydENvdW50LCBzbGVlcENvdW50OiBjLnN0YXRlLnNsZWVwQ291bnQgfTtcblx0XHR9LFxuXHRcdGxvbmdSdW5uaW5nUnBjOiBhc3luYyAoYykgPT4ge1xuXHRcdFx0Yy5sb2cuaW5mbyhcInN0YXJ0aW5nIGxvbmcgcnVubmluZyBycGNcIik7XG5cdFx0XHRjLnZhcnMubG9uZ1J1bm5pbmdSZXNvbHZlID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7XG5cdFx0XHRjLmJyb2FkY2FzdChcIndhaXRpbmdcIik7XG5cdFx0XHRhd2FpdCBjLnZhcnMubG9uZ1J1bm5pbmdSZXNvbHZlLnByb21pc2U7XG5cdFx0XHRjLmxvZy5pbmZvKFwiZmluaXNoZWQgbG9uZyBydW5uaW5nIHJwY1wiKTtcblx0XHR9LFxuXHRcdGZpbmlzaExvbmdSdW5uaW5nUnBjOiAoYykgPT4gYy52YXJzLmxvbmdSdW5uaW5nUmVzb2x2ZT8ucmVzb2x2ZSgpLFxuXHR9LFxuXHRvcHRpb25zOiB7XG5cdFx0c2xlZXBUaW1lb3V0OiBTTEVFUF9USU1FT1VULFxuXHR9LFxufSk7XG5cbmV4cG9ydCBjb25zdCBzbGVlcFdpdGhSYXdIdHRwID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZTogeyBzdGFydENvdW50OiAwLCBzbGVlcENvdW50OiAwLCByZXF1ZXN0Q291bnQ6IDAgfSxcblx0b25TdGFydDogKGMpID0+IHtcblx0XHRjLnN0YXRlLnN0YXJ0Q291bnQgKz0gMTtcblx0fSxcblx0b25TdG9wOiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuc2xlZXBDb3VudCArPSAxO1xuXHR9LFxuXHRvbkZldGNoOiBhc3luYyAoYywgcmVxdWVzdCkgPT4ge1xuXHRcdGMuc3RhdGUucmVxdWVzdENvdW50ICs9IDE7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChyZXF1ZXN0LnVybCk7XG5cblx0XHRpZiAodXJsLnBhdGhuYW1lID09PSBcIi9sb25nLXJlcXVlc3RcIikge1xuXHRcdFx0Y29uc3QgZHVyYXRpb24gPSBwYXJzZUludCh1cmwuc2VhcmNoUGFyYW1zLmdldChcImR1cmF0aW9uXCIpIHx8IFwiMTAwMFwiKTtcblx0XHRcdGMubG9nLmluZm8oXCJzdGFydGluZyBsb25nIGZldGNoIHJlcXVlc3RcIiwgeyBkdXJhdGlvbiB9KTtcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGR1cmF0aW9uKSk7XG5cdFx0XHRjLmxvZy5pbmZvKFwiZmluaXNoZWQgbG9uZyBmZXRjaCByZXF1ZXN0XCIpO1xuXHRcdFx0cmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IGNvbXBsZXRlZDogdHJ1ZSB9KSwge1xuXHRcdFx0XHRoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IFJlc3BvbnNlKFwiTm90IEZvdW5kXCIsIHsgc3RhdHVzOiA0MDQgfSk7XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRDb3VudHM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRzdGFydENvdW50OiBjLnN0YXRlLnN0YXJ0Q291bnQsXG5cdFx0XHRcdHNsZWVwQ291bnQ6IGMuc3RhdGUuc2xlZXBDb3VudCxcblx0XHRcdFx0cmVxdWVzdENvdW50OiBjLnN0YXRlLnJlcXVlc3RDb3VudCxcblx0XHRcdH07XG5cdFx0fSxcblx0fSxcblx0b3B0aW9uczoge1xuXHRcdHNsZWVwVGltZW91dDogU0xFRVBfVElNRU9VVCxcblx0fSxcbn0pO1xuXG5leHBvcnQgY29uc3Qgc2xlZXBXaXRoUmF3V2ViU29ja2V0ID0gYWN0b3Ioe1xuXHRvbkF1dGg6ICgpID0+IHt9LFxuXHRzdGF0ZTogeyBzdGFydENvdW50OiAwLCBzbGVlcENvdW50OiAwLCBjb25uZWN0aW9uQ291bnQ6IDAgfSxcblx0b25TdGFydDogKGMpID0+IHtcblx0XHRjLnN0YXRlLnN0YXJ0Q291bnQgKz0gMTtcblx0fSxcblx0b25TdG9wOiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuc2xlZXBDb3VudCArPSAxO1xuXHR9LFxuXHRvbldlYlNvY2tldDogKGMsIHdlYnNvY2tldDogVW5pdmVyc2FsV2ViU29ja2V0LCBvcHRzKSA9PiB7XG5cdFx0Yy5zdGF0ZS5jb25uZWN0aW9uQ291bnQgKz0gMTtcblx0XHRjLmxvZy5pbmZvKFwid2Vic29ja2V0IGNvbm5lY3RlZFwiLCB7XG5cdFx0XHRjb25uZWN0aW9uQ291bnQ6IGMuc3RhdGUuY29ubmVjdGlvbkNvdW50LFxuXHRcdH0pO1xuXG5cdFx0d2Vic29ja2V0LnNlbmQoXG5cdFx0XHRKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdHR5cGU6IFwiY29ubmVjdGVkXCIsXG5cdFx0XHRcdGNvbm5lY3Rpb25Db3VudDogYy5zdGF0ZS5jb25uZWN0aW9uQ291bnQsXG5cdFx0XHR9KSxcblx0XHQpO1xuXG5cdFx0d2Vic29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChldmVudDogYW55KSA9PiB7XG5cdFx0XHRjb25zdCBkYXRhID0gZXZlbnQuZGF0YTtcblx0XHRcdGlmICh0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoZGF0YSk7XG5cdFx0XHRcdFx0aWYgKHBhcnNlZC50eXBlID09PSBcImdldENvdW50c1wiKSB7XG5cdFx0XHRcdFx0XHR3ZWJzb2NrZXQuc2VuZChcblx0XHRcdFx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwiY291bnRzXCIsXG5cdFx0XHRcdFx0XHRcdFx0c3RhcnRDb3VudDogYy5zdGF0ZS5zdGFydENvdW50LFxuXHRcdFx0XHRcdFx0XHRcdHNsZWVwQ291bnQ6IGMuc3RhdGUuc2xlZXBDb3VudCxcblx0XHRcdFx0XHRcdFx0XHRjb25uZWN0aW9uQ291bnQ6IGMuc3RhdGUuY29ubmVjdGlvbkNvdW50LFxuXHRcdFx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwYXJzZWQudHlwZSA9PT0gXCJrZWVwQWxpdmVcIikge1xuXHRcdFx0XHRcdFx0Ly8gSnVzdCBhY2tub3dsZWRnZSB0byBrZWVwIGNvbm5lY3Rpb24gYWxpdmVcblx0XHRcdFx0XHRcdHdlYnNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsgdHlwZTogXCJhY2tcIiB9KSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGNhdGNoIHtcblx0XHRcdFx0XHQvLyBFY2hvIG5vbi1KU09OIG1lc3NhZ2VzXG5cdFx0XHRcdFx0d2Vic29ja2V0LnNlbmQoZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHdlYnNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwiY2xvc2VcIiwgKCkgPT4ge1xuXHRcdFx0Yy5zdGF0ZS5jb25uZWN0aW9uQ291bnQgLT0gMTtcblx0XHRcdGMubG9nLmluZm8oXCJ3ZWJzb2NrZXQgZGlzY29ubmVjdGVkXCIsIHtcblx0XHRcdFx0Y29ubmVjdGlvbkNvdW50OiBjLnN0YXRlLmNvbm5lY3Rpb25Db3VudCxcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0Q291bnRzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0c3RhcnRDb3VudDogYy5zdGF0ZS5zdGFydENvdW50LFxuXHRcdFx0XHRzbGVlcENvdW50OiBjLnN0YXRlLnNsZWVwQ291bnQsXG5cdFx0XHRcdGNvbm5lY3Rpb25Db3VudDogYy5zdGF0ZS5jb25uZWN0aW9uQ291bnQsXG5cdFx0XHR9O1xuXHRcdH0sXG5cdH0sXG5cdG9wdGlvbnM6IHtcblx0XHRzbGVlcFRpbWVvdXQ6IFNMRUVQX1RJTUVPVVQsXG5cdH0sXG59KTtcblxuZXhwb3J0IGNvbnN0IHNsZWVwV2l0aE5vU2xlZXBPcHRpb24gPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHN0YXJ0Q291bnQ6IDAsIHNsZWVwQ291bnQ6IDAgfSxcblx0b25TdGFydDogKGMpID0+IHtcblx0XHRjLnN0YXRlLnN0YXJ0Q291bnQgKz0gMTtcblx0fSxcblx0b25TdG9wOiAoYykgPT4ge1xuXHRcdGMuc3RhdGUuc2xlZXBDb3VudCArPSAxO1xuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0Q291bnRzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIHsgc3RhcnRDb3VudDogYy5zdGF0ZS5zdGFydENvdW50LCBzbGVlcENvdW50OiBjLnN0YXRlLnNsZWVwQ291bnQgfTtcblx0XHR9LFxuXHR9LFxuXHRvcHRpb25zOiB7XG5cdFx0c2xlZXBUaW1lb3V0OiBTTEVFUF9USU1FT1VULFxuXHRcdG5vU2xlZXA6IHRydWUsXG5cdH0sXG59KTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvdmFycy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlXCI7Y29uc3QgX19pbmplY3RlZF9pbXBvcnRfbWV0YV91cmxfXyA9IFwiZmlsZTovLy9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGUvdmFycy50c1wiO2ltcG9ydCB7IGFjdG9yIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbi8vIEFjdG9yIHdpdGggc3RhdGljIHZhcnNcbmV4cG9ydCBjb25zdCBzdGF0aWNWYXJBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0Y29ublN0YXRlOiB7IGhlbGxvOiBcIndvcmxkXCIgfSxcblx0dmFyczogeyBjb3VudGVyOiA0MiwgbmFtZTogXCJ0ZXN0LWFjdG9yXCIgfSxcblx0YWN0aW9uczoge1xuXHRcdGdldFZhcnM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy52YXJzO1xuXHRcdH0sXG5cdFx0Z2V0TmFtZTogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnZhcnMubmFtZTtcblx0XHR9LFxuXHR9LFxufSk7XG5cbi8vIEFjdG9yIHdpdGggbmVzdGVkIHZhcnNcbmV4cG9ydCBjb25zdCBuZXN0ZWRWYXJBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0Y29ublN0YXRlOiB7IGhlbGxvOiBcIndvcmxkXCIgfSxcblx0dmFyczoge1xuXHRcdGNvdW50ZXI6IDQyLFxuXHRcdG5lc3RlZDoge1xuXHRcdFx0dmFsdWU6IFwib3JpZ2luYWxcIixcblx0XHRcdGFycmF5OiBbMSwgMiwgM10sXG5cdFx0XHRvYmo6IHsga2V5OiBcInZhbHVlXCIgfSxcblx0XHR9LFxuXHR9LFxuXHRhY3Rpb25zOiB7XG5cdFx0Z2V0VmFyczogKGMpID0+IHtcblx0XHRcdHJldHVybiBjLnZhcnM7XG5cdFx0fSxcblx0XHRtb2RpZnlOZXN0ZWQ6IChjKSA9PiB7XG5cdFx0XHQvLyBBdHRlbXB0IHRvIG1vZGlmeSB0aGUgbmVzdGVkIG9iamVjdFxuXHRcdFx0Yy52YXJzLm5lc3RlZC52YWx1ZSA9IFwibW9kaWZpZWRcIjtcblx0XHRcdGMudmFycy5uZXN0ZWQuYXJyYXkucHVzaCg0KTtcblx0XHRcdGMudmFycy5uZXN0ZWQub2JqLmtleSA9IFwibmV3LXZhbHVlXCI7XG5cdFx0XHRyZXR1cm4gYy52YXJzO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gQWN0b3Igd2l0aCBkeW5hbWljIHZhcnNcbmV4cG9ydCBjb25zdCBkeW5hbWljVmFyQWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHZhbHVlOiAwIH0sXG5cdGNvbm5TdGF0ZTogeyBoZWxsbzogXCJ3b3JsZFwiIH0sXG5cdGNyZWF0ZVZhcnM6ICgpID0+IHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cmFuZG9tOiBNYXRoLnJhbmRvbSgpLFxuXHRcdFx0Y29tcHV0ZWQ6IGBBY3Rvci0ke01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMDApfWAsXG5cdFx0fTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFZhcnM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy52YXJzO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gQWN0b3Igd2l0aCB1bmlxdWUgdmFycyBwZXIgaW5zdGFuY2VcbmV4cG9ydCBjb25zdCB1bmlxdWVWYXJBY3RvciA9IGFjdG9yKHtcblx0b25BdXRoOiAoKSA9PiB7fSxcblx0c3RhdGU6IHsgdmFsdWU6IDAgfSxcblx0Y29ublN0YXRlOiB7IGhlbGxvOiBcIndvcmxkXCIgfSxcblx0Y3JlYXRlVmFyczogKCkgPT4ge1xuXHRcdHJldHVybiB7XG5cdFx0XHRpZDogTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMCksXG5cdFx0fTtcblx0fSxcblx0YWN0aW9uczoge1xuXHRcdGdldFZhcnM6IChjKSA9PiB7XG5cdFx0XHRyZXR1cm4gYy52YXJzO1xuXHRcdH0sXG5cdH0sXG59KTtcblxuLy8gQWN0b3IgdGhhdCB1c2VzIGRyaXZlciBjb250ZXh0XG5leHBvcnQgY29uc3QgZHJpdmVyQ3R4QWN0b3IgPSBhY3Rvcih7XG5cdG9uQXV0aDogKCkgPT4ge30sXG5cdHN0YXRlOiB7IHZhbHVlOiAwIH0sXG5cdGNvbm5TdGF0ZTogeyBoZWxsbzogXCJ3b3JsZFwiIH0sXG5cdGNyZWF0ZVZhcnM6IChjLCBkcml2ZXJDdHg6IGFueSkgPT4ge1xuXHRcdHJldHVybiB7XG5cdFx0XHRoYXNEcml2ZXJDdHg6IEJvb2xlYW4oZHJpdmVyQ3R4Py5pc1Rlc3QpLFxuXHRcdH07XG5cdH0sXG5cdGFjdGlvbnM6IHtcblx0XHRnZXRWYXJzOiAoYykgPT4ge1xuXHRcdFx0cmV0dXJuIGMudmFycztcblx0XHR9LFxuXHR9LFxufSk7XG4iLCAiY29uc3QgX19pbmplY3RlZF9maWxlbmFtZV9fID0gXCIvVXNlcnMvbmF0aGFuL3JpdmV0a2l0L3BhY2thZ2VzL3JpdmV0a2l0L2ZpeHR1cmVzL2RyaXZlci10ZXN0LXN1aXRlL3JlZ2lzdHJ5LnRzXCI7Y29uc3QgX19pbmplY3RlZF9kaXJuYW1lX18gPSBcIi9Vc2Vycy9uYXRoYW4vcml2ZXRraXQvcGFja2FnZXMvcml2ZXRraXQvZml4dHVyZXMvZHJpdmVyLXRlc3Qtc3VpdGVcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1VzZXJzL25hdGhhbi9yaXZldGtpdC9wYWNrYWdlcy9yaXZldGtpdC9maXh0dXJlcy9kcml2ZXItdGVzdC1zdWl0ZS9yZWdpc3RyeS50c1wiO2ltcG9ydCB7IHNldHVwIH0gZnJvbSBcInJpdmV0a2l0XCI7XG5cbmltcG9ydCB7IGlucHV0QWN0b3IgfSBmcm9tIFwiLi9hY3Rpb24taW5wdXRzXCI7XG5pbXBvcnQge1xuXHRkZWZhdWx0VGltZW91dEFjdG9yLFxuXHRsb25nVGltZW91dEFjdG9yLFxuXHRzaG9ydFRpbWVvdXRBY3Rvcixcblx0c3luY1RpbWVvdXRBY3Rvcixcbn0gZnJvbSBcIi4vYWN0aW9uLXRpbWVvdXRcIjtcbmltcG9ydCB7XG5cdGFzeW5jQWN0aW9uQWN0b3IsXG5cdHByb21pc2VBY3Rvcixcblx0c3luY0FjdGlvbkFjdG9yLFxufSBmcm9tIFwiLi9hY3Rpb24tdHlwZXNcIjtcbmltcG9ydCB7IG9uU3RhdGVDaGFuZ2VBY3RvciB9IGZyb20gXCIuL2FjdG9yLW9uc3RhdGVjaGFuZ2VcIjtcbmltcG9ydCB7XG5cdGFzeW5jQXV0aEFjdG9yLFxuXHRhdXRoQWN0b3IsXG5cdGludGVudEF1dGhBY3Rvcixcblx0bm9BdXRoQWN0b3IsXG5cdHB1YmxpY0FjdG9yLFxufSBmcm9tIFwiLi9hdXRoXCI7XG5pbXBvcnQgeyBjb25uTGl2ZW5lc3NBY3RvciB9IGZyb20gXCIuL2Nvbm4tbGl2ZW5lc3NcIjtcbmltcG9ydCB7IGNvdW50ZXJXaXRoUGFyYW1zIH0gZnJvbSBcIi4vY29ubi1wYXJhbXNcIjtcbmltcG9ydCB7IGNvbm5TdGF0ZUFjdG9yIH0gZnJvbSBcIi4vY29ubi1zdGF0ZVwiO1xuLy8gSW1wb3J0IGFjdG9ycyBmcm9tIGluZGl2aWR1YWwgZmlsZXNcbmltcG9ydCB7IGNvdW50ZXIgfSBmcm9tIFwiLi9jb3VudGVyXCI7XG5pbXBvcnQgeyBjdXN0b21UaW1lb3V0QWN0b3IsIGVycm9ySGFuZGxpbmdBY3RvciB9IGZyb20gXCIuL2Vycm9yLWhhbmRsaW5nXCI7XG5pbXBvcnQgeyBpbmxpbmVDbGllbnRBY3RvciB9IGZyb20gXCIuL2lubGluZS1jbGllbnRcIjtcbmltcG9ydCB7IGNvdW50ZXJXaXRoTGlmZWN5Y2xlIH0gZnJvbSBcIi4vbGlmZWN5Y2xlXCI7XG5pbXBvcnQgeyBtZXRhZGF0YUFjdG9yIH0gZnJvbSBcIi4vbWV0YWRhdGFcIjtcbmltcG9ydCB7XG5cdHJhd0h0dHBBY3Rvcixcblx0cmF3SHR0cEhvbm9BY3Rvcixcblx0cmF3SHR0cE5vSGFuZGxlckFjdG9yLFxuXHRyYXdIdHRwVm9pZFJldHVybkFjdG9yLFxufSBmcm9tIFwiLi9yYXctaHR0cFwiO1xuaW1wb3J0IHtcblx0cmF3SHR0cEF1dGhBY3Rvcixcblx0cmF3SHR0cEN1c3RvbUF1dGhBY3Rvcixcblx0cmF3SHR0cE5vQXV0aEFjdG9yLFxuXHRyYXdIdHRwUHVibGljQWN0b3IsXG59IGZyb20gXCIuL3Jhdy1odHRwLWF1dGhcIjtcbmltcG9ydCB7IHJhd0h0dHBSZXF1ZXN0UHJvcGVydGllc0FjdG9yIH0gZnJvbSBcIi4vcmF3LWh0dHAtcmVxdWVzdC1wcm9wZXJ0aWVzXCI7XG5pbXBvcnQgeyByYXdXZWJTb2NrZXRBY3RvciwgcmF3V2ViU29ja2V0QmluYXJ5QWN0b3IgfSBmcm9tIFwiLi9yYXctd2Vic29ja2V0XCI7XG5pbXBvcnQge1xuXHRyYXdXZWJTb2NrZXRBdXRoQWN0b3IsXG5cdHJhd1dlYlNvY2tldEN1c3RvbUF1dGhBY3Rvcixcblx0cmF3V2ViU29ja2V0Tm9BdXRoQWN0b3IsXG5cdHJhd1dlYlNvY2tldFB1YmxpY0FjdG9yLFxufSBmcm9tIFwiLi9yYXctd2Vic29ja2V0LWF1dGhcIjtcbmltcG9ydCB7IHJlcXVlc3RBY2Nlc3NBY3RvciB9IGZyb20gXCIuL3JlcXVlc3QtYWNjZXNzXCI7XG5pbXBvcnQgeyByZXF1ZXN0QWNjZXNzQXV0aEFjdG9yIH0gZnJvbSBcIi4vcmVxdWVzdC1hY2Nlc3MtYXV0aFwiO1xuaW1wb3J0IHsgc2NoZWR1bGVkIH0gZnJvbSBcIi4vc2NoZWR1bGVkXCI7XG5pbXBvcnQge1xuXHRzbGVlcCxcblx0c2xlZXBXaXRoTG9uZ1JwYyxcblx0c2xlZXBXaXRoTm9TbGVlcE9wdGlvbixcblx0c2xlZXBXaXRoUmF3SHR0cCxcblx0c2xlZXBXaXRoUmF3V2ViU29ja2V0LFxufSBmcm9tIFwiLi9zbGVlcFwiO1xuaW1wb3J0IHtcblx0ZHJpdmVyQ3R4QWN0b3IsXG5cdGR5bmFtaWNWYXJBY3Rvcixcblx0bmVzdGVkVmFyQWN0b3IsXG5cdHN0YXRpY1ZhckFjdG9yLFxuXHR1bmlxdWVWYXJBY3Rvcixcbn0gZnJvbSBcIi4vdmFyc1wiO1xuXG4vLyBDb25zb2xpZGF0ZWQgc2V0dXAgd2l0aCBhbGwgYWN0b3JzXG5leHBvcnQgY29uc3QgcmVnaXN0cnkgPSBzZXR1cCh7XG5cdHVzZToge1xuXHRcdC8vIEZyb20gY291bnRlci50c1xuXHRcdGNvdW50ZXIsXG5cdFx0Ly8gRnJvbSBsaWZlY3ljbGUudHNcblx0XHRjb3VudGVyV2l0aExpZmVjeWNsZSxcblx0XHQvLyBGcm9tIHNjaGVkdWxlZC50c1xuXHRcdHNjaGVkdWxlZCxcblx0XHQvLyBGcm9tIHNsZWVwLnRzXG5cdFx0c2xlZXAsXG5cdFx0c2xlZXBXaXRoTG9uZ1JwYyxcblx0XHRzbGVlcFdpdGhSYXdIdHRwLFxuXHRcdHNsZWVwV2l0aFJhd1dlYlNvY2tldCxcblx0XHRzbGVlcFdpdGhOb1NsZWVwT3B0aW9uLFxuXHRcdC8vIEZyb20gZXJyb3ItaGFuZGxpbmcudHNcblx0XHRlcnJvckhhbmRsaW5nQWN0b3IsXG5cdFx0Y3VzdG9tVGltZW91dEFjdG9yLFxuXHRcdC8vIEZyb20gaW5saW5lLWNsaWVudC50c1xuXHRcdGlubGluZUNsaWVudEFjdG9yLFxuXHRcdC8vIEZyb20gYWN0aW9uLWlucHV0cy50c1xuXHRcdGlucHV0QWN0b3IsXG5cdFx0Ly8gRnJvbSBhY3Rpb24tdGltZW91dC50c1xuXHRcdHNob3J0VGltZW91dEFjdG9yLFxuXHRcdGxvbmdUaW1lb3V0QWN0b3IsXG5cdFx0ZGVmYXVsdFRpbWVvdXRBY3Rvcixcblx0XHRzeW5jVGltZW91dEFjdG9yLFxuXHRcdC8vIEZyb20gYWN0aW9uLXR5cGVzLnRzXG5cdFx0c3luY0FjdGlvbkFjdG9yLFxuXHRcdGFzeW5jQWN0aW9uQWN0b3IsXG5cdFx0cHJvbWlzZUFjdG9yLFxuXHRcdC8vIEZyb20gY29ubi1wYXJhbXMudHNcblx0XHRjb3VudGVyV2l0aFBhcmFtcyxcblx0XHQvLyBGcm9tIGNvbm4tc3RhdGUudHNcblx0XHRjb25uU3RhdGVBY3Rvcixcblx0XHQvLyBGcm9tIGFjdG9yLWNvbm4udHNcblx0XHRjb25uTGl2ZW5lc3NBY3Rvcixcblx0XHQvLyBGcm9tIG1ldGFkYXRhLnRzXG5cdFx0bWV0YWRhdGFBY3Rvcixcblx0XHQvLyBGcm9tIHZhcnMudHNcblx0XHRzdGF0aWNWYXJBY3Rvcixcblx0XHRuZXN0ZWRWYXJBY3Rvcixcblx0XHRkeW5hbWljVmFyQWN0b3IsXG5cdFx0dW5pcXVlVmFyQWN0b3IsXG5cdFx0ZHJpdmVyQ3R4QWN0b3IsXG5cdFx0Ly8gRnJvbSBhdXRoLnRzXG5cdFx0YXV0aEFjdG9yLFxuXHRcdGludGVudEF1dGhBY3Rvcixcblx0XHRwdWJsaWNBY3Rvcixcblx0XHRub0F1dGhBY3Rvcixcblx0XHRhc3luY0F1dGhBY3Rvcixcblx0XHQvLyBGcm9tIHJhdy1odHRwLnRzXG5cdFx0cmF3SHR0cEFjdG9yLFxuXHRcdHJhd0h0dHBOb0hhbmRsZXJBY3Rvcixcblx0XHRyYXdIdHRwVm9pZFJldHVybkFjdG9yLFxuXHRcdHJhd0h0dHBIb25vQWN0b3IsXG5cdFx0Ly8gRnJvbSByYXctaHR0cC1hdXRoLnRzXG5cdFx0cmF3SHR0cEF1dGhBY3Rvcixcblx0XHRyYXdIdHRwTm9BdXRoQWN0b3IsXG5cdFx0cmF3SHR0cFB1YmxpY0FjdG9yLFxuXHRcdHJhd0h0dHBDdXN0b21BdXRoQWN0b3IsXG5cdFx0Ly8gRnJvbSByYXctaHR0cC1yZXF1ZXN0LXByb3BlcnRpZXMudHNcblx0XHRyYXdIdHRwUmVxdWVzdFByb3BlcnRpZXNBY3Rvcixcblx0XHQvLyBGcm9tIHJhdy13ZWJzb2NrZXQudHNcblx0XHRyYXdXZWJTb2NrZXRBY3Rvcixcblx0XHRyYXdXZWJTb2NrZXRCaW5hcnlBY3Rvcixcblx0XHQvLyBGcm9tIHJhdy13ZWJzb2NrZXQtYXV0aC50c1xuXHRcdHJhd1dlYlNvY2tldEF1dGhBY3Rvcixcblx0XHRyYXdXZWJTb2NrZXROb0F1dGhBY3Rvcixcblx0XHRyYXdXZWJTb2NrZXRQdWJsaWNBY3Rvcixcblx0XHRyYXdXZWJTb2NrZXRDdXN0b21BdXRoQWN0b3IsXG5cdFx0Ly8gRnJvbSByZXF1ZXN0LWFjY2Vzcy50c1xuXHRcdHJlcXVlc3RBY2Nlc3NBY3Rvcixcblx0XHRyZXF1ZXN0QWNjZXNzQXV0aEFjdG9yLFxuXHRcdC8vIEZyb20gYWN0b3Itb25zdGF0ZWNoYW5nZS50c1xuXHRcdG9uU3RhdGVDaGFuZ2VBY3Rvcixcblx0fSxcbn0pO1xuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFrUyxZQUFZQSxXQUFVOzs7QUNjalQsSUFBTSx1QkFBTixNQUE4QjtBQUFBLEVBQ3BDLFlBQW9CQyxTQUFnQztBQUFoQyxrQkFBQUE7QUFBQSxFQUFpQztBQUFBLEVBRXJELDZCQUE2QixNQUFx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QVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsV0FBVztBQUFBLE1BQ1QsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0Esb0JBQW9CO0FBQUEsTUFDbEIsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsOEJBQThCO0FBQUEsTUFDNUIsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsdUJBQXVCO0FBQUEsTUFDckIsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsMkJBQTJCO0FBQUEsTUFDekIsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsMEJBQTBCO0FBQUEsTUFDeEIsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFBQ1QsU0FBVztBQUFBLE1BQ2I7QUFBQSxNQUNBLFNBQVc7QUFBQSxRQUNULE9BQVM7QUFBQSxRQUNULFNBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsUUFBVTtBQUFBLFFBQ1IsT0FBUztBQUFBLFFB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QUE7QUFBQSxJQUVBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBO0FBQUEsSUFFQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUFBLElBRUE7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUFBLElBRUE7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUFBLElBRUE7QUFBQTtBQUFBLElBRUE7QUFBQSxJQUNBO0FBQUE7QUFBQSxJQUVBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUE7QUFBQSxJQUVBO0FBQUEsSUFDQTtBQUFBO0FBQUEsSUFFQTtBQUFBLEVBQ0Q7QUFDRCxDQUFDOyIsCiAgIm5hbWVzIjogWyJjYm9yIiwgImNvbmZpZyIsICJsb2dnZXIiLCAiYXNzZXJ0VW5yZWFjaGFibGUiLCAiYXNzZXJ0VW5yZWFjaGFibGUiLCAiYWN0b3IiLCAieiIsICJ6IiwgImNib3IiLCAiaW52YXJpYW50IiwgInN0cmVhbVNTRSIsICJ6IiwgInoiLCAieiIsICJjYm9yIiwgImxvZ2dlciIsICJsb2dnZXIiLCAiY2JvciIsICJ6IiwgInoiLCAiYWN0b3IiLCAibWVzc2FnZSIsICJhY3RvciIsICJwYXRoIiwgInoiLCAieiIsICJBY3RvckZlYXR1cmUiLCAieiIsICJzdHJlYW1TU0UiLCAiYmFyZSIsICJjb25maWciLCAicmVhZDAiLCAid3JpdGUwIiwgInJlYWQxIiwgIndyaXRlMSIsICJDVVJSRU5UX1ZFUlNJT04iLCAibWlncmF0aW9ucyIsICJhY3RvciIsICJhY3RvciIsICJjb25maWciLCAicGF0aCIsICJpbnZhcmlhbnQiLCAiYmFyZURhdGEiLCAiY29ubiIsICJzbGVlcCIsICJyZXMiLCAiY29uZmlnIiwgImFjdG9yIiwgIkhvbm8iLCAiaW52YXJpYW50IiwgImNib3IiLCAibG9nZ2VyIiwgInBhdGgiLCAiY3J5cHRvIiwgImNyeXB0byIsICJIb25vIiwgImMiLCAiYWN0b3IiLCAiaW52YXJpYW50IiwgImNvbmZpZyIsICJjYm9yIiwgImludmFyaWFudCIsICJJbnRlcm5hbEVycm9yIiwgIkFjdG9yRXJyb3IiLCAiTE9HR0VSX05BTUUiLCAibG9nZ2VyIiwgImNib3IiLCAiaW52YXJpYW50IiwgImxvZ2dlciIsICJpbnZhcmlhbnQiLCAiQWN0b3JFcnJvciIsICJsb2dnZXIiLCAiQWN0b3JFcnJvciIsICJJbnRlcm5hbEVycm9yIiwgImludmFyaWFudCIsICJpbnZhcmlhbnQiLCAicGF0aCIsICJsb2dnZXIiLCAicGF0aCIsICJhc3NlcnRVbnJlYWNoYWJsZSIsICJpbnZhcmlhbnQiLCAibG9nZ2VyIiwgIm9wdHMiLCAiTE9HR0VSX05BTUUiLCAibG9nZ2VyIiwgImNib3IiLCAiV1NDb250ZXh0IiwgImludmFyaWFudCIsICJ6IiwgInoiLCAieiIsICJ6IiwgImNib3IiLCAiTE9HR0VSX05BTUUiLCAibG9nZ2VyIiwgImNvbmZpZyIsICJsb2dnZXIiLCAiYWN0b3IiLCAiaW52YXJpYW50IiwgIldTQ29udGV4dCIsICJ6IiwgInoiLCAiY2JvciIsICJpbnZhcmlhbnQiLCAibG9nZ2VyIiwgInBhdGgiLCAibG9nZ2VyIiwgImNvbmZpZyIsICJXZWJTb2NrZXQiLCAibG9nZ2VyIiwgImV2ZW50IiwgImNvbmZpZyIsICJsb2dnZXIiLCAicGF0aCIsICJXZWJTb2NrZXQiLCAiaW52YXJpYW50IiwgImNvbmZpZyIsICJhY3RvciIsICJjcnlwdG8iLCAiZnNTeW5jIiwgImZzIiwgInBhdGgiLCAiaW52YXJpYW50IiwgImJhcmUiLCAiY29uZmlnIiwgInJlYWQwIiwgIndyaXRlMCIsICJDVVJSRU5UX1ZFUlNJT04iLCAibWlncmF0aW9ucyIsICJMT0dHRVJfTkFNRSIsICJsb2dnZXIiLCAiY3J5cHRvIiwgInBhdGgiLCAibG9nZ2VyIiwgImludmFyaWFudCIsICJhY3RvciIsICJpbnZhcmlhbnQiLCAiY2JvciIsICJpbnZhcmlhbnQiLCAib25DaGFuZ2UiLCAibG9nZ2VyIiwgIkxPR0dFUl9OQU1FIiwgImxvZ2dlciIsICJsb2dnZXIiLCAiaW52YXJpYW50IiwgIkFjdG9yRXJyb3IiLCAicGF0aCIsICJzVmFsaWRhdG9yIiwgIkhvbm8iLCAiSG9ubyIsICJzVmFsaWRhdG9yIiwgImFjdG9yIiwgInRyYW5zZm9ybUFjdG9yIiwgImFjdG9yIiwgInBhdGgiLCAiaW52YXJpYW50IiwgImxvZ2dlciIsICJjYm9yIiwgIkhvbm8iLCAic3RyZWFtU1NFIiwgImludmFyaWFudCIsICJ6IiwgImxvZ2dlciIsICJ6IiwgImxvZ2dlciIsICJwYXRoIiwgImMiLCAiSG9ubyIsICJpbnZhcmlhbnQiLCAicXVlcnlBY3RvciIsICJzdHJlYW1TU0UiLCAieiIsICJ6IiwgIkxPR0dFUl9OQU1FIiwgImxvZ2dlciIsICJIb25vIiwgIkhvbm8iLCAibG9nZ2VyIiwgImNvbmZpZyIsICJsb2dnZXIiLCAiSG9ubyIsICJIb25vIl0KfQo= diff --git a/packages/rivetkit/fixtures/driver-test-suite/registry.ts b/packages/rivetkit/fixtures/driver-test-suite/registry.ts index 22d051d63..bffd29b2f 100644 --- a/packages/rivetkit/fixtures/driver-test-suite/registry.ts +++ b/packages/rivetkit/fixtures/driver-test-suite/registry.ts @@ -12,6 +12,7 @@ import { promiseActor, syncActionActor, } from "./action-types"; +import { onStateChangeActor } from "./actor-onstatechange"; import { asyncAuthActor, authActor, @@ -140,5 +141,7 @@ export const registry = setup({ // From request-access.ts requestAccessActor, requestAccessAuthActor, + // From actor-onstatechange.ts + onStateChangeActor, }, }); diff --git a/packages/rivetkit/src/actor/config.ts b/packages/rivetkit/src/actor/config.ts index 69ffbd957..8c91d09e8 100644 --- a/packages/rivetkit/src/actor/config.ts +++ b/packages/rivetkit/src/actor/config.ts @@ -347,6 +347,9 @@ interface BaseActorConfig< * Use this hook to react to state changes, such as updating * external systems or triggering events. * + * State changes made within this hook will NOT trigger + * another onStateChange call, preventing infinite recursion. + * * @param newState The updated state */ onStateChange?: ( diff --git a/packages/rivetkit/src/actor/instance.ts b/packages/rivetkit/src/actor/instance.ts index 6231640e9..5327c020d 100644 --- a/packages/rivetkit/src/actor/instance.ts +++ b/packages/rivetkit/src/actor/instance.ts @@ -142,6 +142,7 @@ export class ActorInstance< } #persistChanged = false; + #isInOnStateChange = false; /** * The proxied state that notifies of changes automatically. @@ -648,8 +649,14 @@ export class ActorInstance< this.inspector.emitter.emit("stateUpdated", this.#persist.state); // Call onStateChange if it exists - if (this.#config.onStateChange && this.#ready) { + // Skip if we're already inside onStateChange to prevent infinite recursion + if ( + this.#config.onStateChange && + this.#ready && + !this.#isInOnStateChange + ) { try { + this.#isInOnStateChange = true; this.#config.onStateChange( this.actorContext, this.#persistRaw.state, @@ -658,6 +665,8 @@ export class ActorInstance< logger().error("error in `_onStateChange`", { error: stringifyError(error), }); + } finally { + this.#isInOnStateChange = false; } } diff --git a/packages/rivetkit/src/driver-test-suite/mod.ts b/packages/rivetkit/src/driver-test-suite/mod.ts index c3885700b..73d074787 100644 --- a/packages/rivetkit/src/driver-test-suite/mod.ts +++ b/packages/rivetkit/src/driver-test-suite/mod.ts @@ -22,6 +22,7 @@ import { runActorHandleTests } from "./tests/actor-handle"; import { runActorInlineClientTests } from "./tests/actor-inline-client"; import { runActorInspectorTests } from "./tests/actor-inspector"; import { runActorMetadataTests } from "./tests/actor-metadata"; +import { runActorOnStateChangeTests } from "./tests/actor-onstatechange"; import { runActorVarsTests } from "./tests/actor-vars"; import { runManagerDriverTests } from "./tests/manager-driver"; import { runRawHttpTests } from "./tests/raw-http"; @@ -109,6 +110,8 @@ export function runDriverTests( runActorMetadataTests(driverTestConfig); + runActorOnStateChangeTests(driverTestConfig); + runActorErrorHandlingTests(driverTestConfig); runActorAuthTests(driverTestConfig); diff --git a/packages/rivetkit/src/driver-test-suite/tests/actor-onstatechange.ts b/packages/rivetkit/src/driver-test-suite/tests/actor-onstatechange.ts new file mode 100644 index 000000000..fe8bc2840 --- /dev/null +++ b/packages/rivetkit/src/driver-test-suite/tests/actor-onstatechange.ts @@ -0,0 +1,75 @@ +import { describe, expect, test } from "vitest"; +import type { DriverTestConfig } from "@/driver-test-suite/mod"; +import { setupDriverTest } from "@/driver-test-suite/utils"; + +export function runActorOnStateChangeTests(driverTestConfig: DriverTestConfig) { + describe("Actor onStateChange Tests", () => { + test("triggers onStateChange when state is modified", async (c) => { + const { client } = await setupDriverTest(c, driverTestConfig); + + const actor = client.onStateChangeActor.getOrCreate(); + + // Modify state - should trigger onChange + await actor.setValue(10); + + // Check that onChange was called + const changeCount = await actor.getChangeCount(); + expect(changeCount).toBe(1); + }); + + test("triggers onChange multiple times for multiple state changes", async (c) => { + const { client } = await setupDriverTest(c, driverTestConfig); + + const actor = client.onStateChangeActor.getOrCreate(); + + // Modify state multiple times + await actor.incrementMultiple(3); + + // Check that onChange was called for each modification + const changeCount = await actor.getChangeCount(); + expect(changeCount).toBe(3); + }); + + test("does NOT trigger onChange for read-only actions", async (c) => { + const { client } = await setupDriverTest(c, driverTestConfig); + + const actor = client.onStateChangeActor.getOrCreate(); + + // Set initial value + await actor.setValue(5); + + // Read value without modifying - should NOT trigger onChange + const value = await actor.getValue(); + expect(value).toBe(5); + + // Check that onChange was NOT called + const changeCount = await actor.getChangeCount(); + expect(changeCount).toBe(1); + }); + + test("does NOT trigger onChange for computed values", async (c) => { + const { client } = await setupDriverTest(c, driverTestConfig); + + const actor = client.onStateChangeActor.getOrCreate(); + + // Set initial value + await actor.setValue(3); + + // Check that onChange was called + { + const changeCount = await actor.getChangeCount(); + expect(changeCount).toBe(1); + } + + // Compute value without modifying state - should NOT trigger onChange + const doubled = await actor.getDoubled(); + expect(doubled).toBe(6); + + // Check that onChange was NOT called + { + const changeCount = await actor.getChangeCount(); + expect(changeCount).toBe(1); + } + }); + }); +}