@workflow/core 5.0.0-beta.4 → 5.0.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attribute-changes.d.ts +7 -0
- package/dist/attribute-changes.d.ts.map +1 -0
- package/dist/attribute-changes.js +25 -0
- package/dist/capabilities.d.ts +33 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +71 -4
- package/dist/capture-stack.d.ts +16 -0
- package/dist/capture-stack.d.ts.map +1 -0
- package/dist/capture-stack.js +21 -0
- package/dist/class-serialization.d.ts +32 -0
- package/dist/class-serialization.d.ts.map +1 -1
- package/dist/class-serialization.js +37 -1
- package/dist/classify-error.d.ts +26 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +109 -6
- package/dist/context-errors.d.ts +27 -0
- package/dist/context-errors.d.ts.map +1 -0
- package/dist/context-errors.js +101 -0
- package/dist/context-violation-error.d.ts +97 -0
- package/dist/context-violation-error.d.ts.map +1 -0
- package/dist/context-violation-error.js +149 -0
- package/dist/correlation-id.d.ts +109 -0
- package/dist/correlation-id.d.ts.map +1 -0
- package/dist/correlation-id.js +139 -0
- package/dist/create-hook.d.ts +62 -4
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +4 -3
- package/dist/define-hook.d.ts.map +1 -1
- package/dist/define-hook.js +20 -5
- package/dist/describe-error.d.ts +70 -0
- package/dist/describe-error.d.ts.map +1 -0
- package/dist/describe-error.js +189 -0
- package/dist/encryption.d.ts +37 -3
- package/dist/encryption.d.ts.map +1 -1
- package/dist/encryption.js +97 -31
- package/dist/events-consumer.d.ts +26 -1
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +105 -18
- package/dist/flushable-stream.d.ts +65 -10
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +131 -18
- package/dist/global.d.ts +37 -1
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +21 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/log-format.d.ts +25 -0
- package/dist/log-format.d.ts.map +1 -0
- package/dist/log-format.js +250 -0
- package/dist/logger.d.ts +29 -30
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +82 -32
- package/dist/private.d.ts +178 -9
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +273 -9
- package/dist/replay-payload-cache.d.ts +68 -0
- package/dist/replay-payload-cache.d.ts.map +1 -0
- package/dist/replay-payload-cache.js +160 -0
- package/dist/runtime/compute-instance.d.ts +12 -0
- package/dist/runtime/compute-instance.d.ts.map +1 -0
- package/dist/runtime/compute-instance.js +13 -0
- package/dist/runtime/constants.d.ts +237 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +405 -15
- package/dist/runtime/count-step-started-events.d.ts +52 -0
- package/dist/runtime/count-step-started-events.d.ts.map +1 -0
- package/dist/runtime/count-step-started-events.js +72 -0
- package/dist/runtime/deployment-guard.d.ts +99 -0
- package/dist/runtime/deployment-guard.d.ts.map +1 -0
- package/dist/runtime/deployment-guard.js +154 -0
- package/dist/runtime/get-port-lazy.d.ts +25 -0
- package/dist/runtime/get-port-lazy.d.ts.map +1 -0
- package/dist/runtime/get-port-lazy.js +92 -0
- package/dist/runtime/get-world-lazy.d.ts +23 -0
- package/dist/runtime/get-world-lazy.d.ts.map +1 -0
- package/dist/runtime/get-world-lazy.js +46 -0
- package/dist/runtime/helpers.d.ts +219 -10
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +414 -40
- package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
- package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
- package/dist/runtime/quickjs-assets.generated.js +30 -0
- package/dist/runtime/quickjs-entrypoint.d.ts +124 -0
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
- package/dist/runtime/quickjs-entrypoint.js +1429 -0
- package/dist/runtime/quickjs-runtime.d.ts +193 -0
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
- package/dist/runtime/quickjs-runtime.js +1944 -0
- package/dist/runtime/replay-budget.d.ts +98 -0
- package/dist/runtime/replay-budget.d.ts.map +1 -0
- package/dist/runtime/replay-budget.js +192 -0
- package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
- package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
- package/dist/runtime/replay-recovery-reporter.js +64 -0
- package/dist/runtime/resume-hook.d.ts +27 -4
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +448 -76
- package/dist/runtime/run-id-time.d.ts +19 -0
- package/dist/runtime/run-id-time.d.ts.map +1 -0
- package/dist/runtime/run-id-time.js +42 -0
- package/dist/runtime/run.d.ts +8 -2
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +62 -15
- package/dist/runtime/runs.d.ts +54 -3
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +117 -10
- package/dist/runtime/start.d.ts +70 -1
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +312 -54
- package/dist/runtime/step-executor.d.ts +177 -0
- package/dist/runtime/step-executor.d.ts.map +1 -0
- package/dist/runtime/step-executor.js +949 -0
- package/dist/runtime/step-latency.d.ts +197 -0
- package/dist/runtime/step-latency.d.ts.map +1 -0
- package/dist/runtime/step-latency.js +207 -0
- package/dist/runtime/step-ownership.d.ts +72 -0
- package/dist/runtime/step-ownership.d.ts.map +1 -0
- package/dist/runtime/step-ownership.js +114 -0
- package/dist/runtime/step-single-flight.d.ts +12 -0
- package/dist/runtime/step-single-flight.d.ts.map +1 -0
- package/dist/runtime/step-single-flight.js +69 -0
- package/dist/runtime/suspension-handler.d.ts +102 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +439 -140
- package/dist/runtime/vm-mode.d.ts +44 -0
- package/dist/runtime/vm-mode.d.ts.map +1 -0
- package/dist/runtime/vm-mode.js +62 -0
- package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
- package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
- package/dist/runtime/vm-serde-bundle.generated.js +16 -0
- package/dist/runtime/wait-continuation.d.ts +84 -0
- package/dist/runtime/wait-continuation.d.ts.map +1 -0
- package/dist/runtime/wait-continuation.js +105 -0
- package/dist/runtime/wait-until.d.ts +18 -0
- package/dist/runtime/wait-until.d.ts.map +1 -0
- package/dist/runtime/wait-until.js +42 -0
- package/dist/runtime/world-compatibility.d.ts +5 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -0
- package/dist/runtime/world-compatibility.js +12 -0
- package/dist/runtime/world-init.d.ts +50 -0
- package/dist/runtime/world-init.d.ts.map +1 -0
- package/dist/runtime/world-init.js +50 -0
- package/dist/runtime/world.d.ts +14 -2
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +101 -26
- package/dist/runtime.d.ts +17 -12
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +3078 -327
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/sealed-box.d.ts +167 -0
- package/dist/sealed-box.d.ts.map +1 -0
- package/dist/sealed-box.js +571 -0
- package/dist/serialization/client.d.ts +17 -0
- package/dist/serialization/client.d.ts.map +1 -0
- package/dist/serialization/client.js +48 -0
- package/dist/serialization/codec-devalue-vm.d.ts +9 -0
- package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
- package/dist/serialization/codec-devalue-vm.js +137 -0
- package/dist/serialization/codec-devalue.d.ts +14 -0
- package/dist/serialization/codec-devalue.d.ts.map +1 -0
- package/dist/serialization/codec-devalue.js +105 -0
- package/dist/serialization/codec.d.ts +125 -0
- package/dist/serialization/codec.d.ts.map +1 -0
- package/dist/serialization/codec.js +17 -0
- package/dist/serialization/compression.d.ts +104 -0
- package/dist/serialization/compression.d.ts.map +1 -0
- package/dist/serialization/compression.js +260 -0
- package/dist/serialization/encryption.d.ts +134 -0
- package/dist/serialization/encryption.d.ts.map +1 -0
- package/dist/serialization/encryption.js +186 -0
- package/dist/serialization/errors.d.ts +34 -0
- package/dist/serialization/errors.d.ts.map +1 -0
- package/dist/serialization/errors.js +59 -0
- package/dist/serialization/format.d.ts +60 -0
- package/dist/serialization/format.d.ts.map +1 -0
- package/dist/serialization/format.js +97 -0
- package/dist/serialization/hardened.d.ts +155 -0
- package/dist/serialization/hardened.d.ts.map +1 -0
- package/dist/serialization/hardened.js +523 -0
- package/dist/serialization/index.d.ts +20 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +22 -0
- package/dist/serialization/reducers/class-vm.d.ts +20 -0
- package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/class-vm.js +77 -0
- package/dist/serialization/reducers/class.d.ts +11 -0
- package/dist/serialization/reducers/class.d.ts.map +1 -0
- package/dist/serialization/reducers/class.js +73 -0
- package/dist/serialization/reducers/common-vm.d.ts +15 -0
- package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/common-vm.js +579 -0
- package/dist/serialization/reducers/common.d.ts +16 -0
- package/dist/serialization/reducers/common.d.ts.map +1 -0
- package/dist/serialization/reducers/common.js +478 -0
- package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
- package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function-vm.js +97 -0
- package/dist/serialization/reducers/step-function.d.ts +35 -0
- package/dist/serialization/reducers/step-function.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function.js +104 -0
- package/dist/serialization/step.d.ts +17 -0
- package/dist/serialization/step.d.ts.map +1 -0
- package/dist/serialization/step.js +48 -0
- package/dist/serialization/types.d.ts +273 -0
- package/dist/serialization/types.d.ts.map +1 -0
- package/dist/serialization/types.js +35 -0
- package/dist/serialization/vm-bundle-entry.d.ts +12 -0
- package/dist/serialization/vm-bundle-entry.d.ts.map +1 -0
- package/dist/serialization/vm-bundle-entry.js +58 -0
- package/dist/serialization/workflow-vm.d.ts +24 -0
- package/dist/serialization/workflow-vm.d.ts.map +1 -0
- package/dist/serialization/workflow-vm.js +66 -0
- package/dist/serialization/workflow.d.ts +29 -0
- package/dist/serialization/workflow.d.ts.map +1 -0
- package/dist/serialization/workflow.js +54 -0
- package/dist/serialization-format.d.ts +60 -4
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +276 -56
- package/dist/serialization.d.ts +374 -221
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +2300 -783
- package/dist/set-attributes.d.ts +13 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +60 -0
- package/dist/sleep.d.ts.map +1 -1
- package/dist/sleep.js +3 -2
- package/dist/source-map.d.ts +25 -0
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +148 -10
- package/dist/step/context-storage.d.ts +61 -2
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +7 -5
- package/dist/step/get-closure-vars.d.ts.map +1 -1
- package/dist/step/get-closure-vars.js +3 -2
- package/dist/step/get-step-metadata.d.ts.map +1 -1
- package/dist/step/get-step-metadata.js +3 -2
- package/dist/step/get-workflow-metadata.d.ts.map +1 -1
- package/dist/step/get-workflow-metadata.js +3 -2
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +71 -7
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +226 -30
- package/dist/symbols.d.ts +54 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +55 -1
- package/dist/telemetry/semantic-conventions.d.ts +242 -2
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +173 -1
- package/dist/telemetry.d.ts +73 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +153 -16
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -1
- package/dist/util.d.ts +16 -6
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +25 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +77 -9
- package/dist/vm/script-cache.d.ts +28 -0
- package/dist/vm/script-cache.d.ts.map +1 -0
- package/dist/vm/script-cache.js +140 -0
- package/dist/workflow/abort-controller.d.ts +65 -0
- package/dist/workflow/abort-controller.d.ts.map +1 -0
- package/dist/workflow/abort-controller.js +314 -0
- package/dist/workflow/attribute-dispatcher.d.ts +6 -0
- package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
- package/dist/workflow/attribute-dispatcher.js +48 -0
- package/dist/workflow/create-hook.d.ts.map +1 -1
- package/dist/workflow/create-hook.js +25 -3
- package/dist/workflow/define-hook.d.ts +1 -1
- package/dist/workflow/define-hook.d.ts.map +1 -1
- package/dist/workflow/define-hook.js +8 -4
- package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
- package/dist/workflow/get-workflow-metadata.js +14 -3
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +303 -37
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +5 -3
- package/dist/workflow/set-attributes.d.ts +68 -0
- package/dist/workflow/set-attributes.d.ts.map +1 -0
- package/dist/workflow/set-attributes.js +60 -0
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +58 -9
- package/dist/workflow/world-init-stub.d.ts +15 -0
- package/dist/workflow/world-init-stub.d.ts.map +1 -0
- package/dist/workflow/world-init-stub.js +15 -0
- package/dist/workflow.d.ts +69 -3
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +791 -554
- package/docs/api-reference/create-hook.mdx +79 -0
- package/docs/api-reference/create-webhook.mdx +1 -0
- package/docs/api-reference/define-hook.mdx +26 -24
- package/docs/api-reference/fatal-error.mdx +29 -7
- package/docs/api-reference/fetch.mdx +8 -4
- package/docs/api-reference/index.mdx +3 -0
- package/docs/api-reference/set-attributes.mdx +61 -0
- package/docs/api-reference/sleep.mdx +1 -1
- package/docs/foundations/cancellation.mdx +459 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/hooks.mdx +29 -0
- package/docs/foundations/idempotency.mdx +243 -11
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +3 -1
- package/docs/foundations/serialization.mdx +77 -41
- package/docs/foundations/starting-workflows.mdx +79 -2
- package/docs/foundations/streaming.mdx +14 -23
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +21 -17
- package/docs/how-it-works/encryption.mdx +5 -5
- package/docs/how-it-works/event-sourcing.mdx +6 -6
- package/docs/how-it-works/framework-integrations.mdx +96 -337
- package/docs/how-it-works/meta.json +2 -1
- package/package.json +31 -13
- package/dist/runtime/step-handler.d.ts +0 -2
- package/dist/runtime/step-handler.d.ts.map +0 -1
- package/dist/runtime/step-handler.js +0 -678
|
@@ -1,35 +1,138 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { EntityConflictError, ERROR_SLUGS, HookNotFoundError, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
|
|
2
|
+
import { HOOK_RESUME_DEDUP_VERSION, HOOK_RESUME_INPUT_VERSION, isLegacySpecVersion, isTerminalWorkflowRunStatus, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
|
|
3
|
+
import { monotonicFactory } from 'ulid';
|
|
4
4
|
import { getRunCapabilities } from '../capabilities.js';
|
|
5
|
+
import { isRetryableWorldError } from '../classify-error.js';
|
|
5
6
|
import { importKey } from '../encryption.js';
|
|
6
|
-
import {
|
|
7
|
+
import { runtimeLogger } from '../logger.js';
|
|
8
|
+
import { decodeRunPublicKey } from '../sealed-box.js';
|
|
9
|
+
import { deriveRunPayloadKeys } from '../serialization/encryption.js';
|
|
10
|
+
import { dehydrateStepReturnValue, hydrateStepArguments, SerializationFormat, sealTo, } from '../serialization.js';
|
|
7
11
|
import { WEBHOOK_RESPONSE_WRITABLE } from '../symbols.js';
|
|
8
12
|
import * as Attribute from '../telemetry/semantic-conventions.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
13
|
+
import { linkToTraceCarrier, trace } from '../telemetry.js';
|
|
14
|
+
import { getWorldLazy } from './get-world-lazy.js';
|
|
11
15
|
import { getWorkflowQueueName } from './helpers.js';
|
|
12
|
-
import {
|
|
16
|
+
import { safeWaitUntil, waitedUntil } from './wait-until.js';
|
|
17
|
+
/** Monotonic ULID factory for per-call resume idempotency keys. */
|
|
18
|
+
const generateResumeId = monotonicFactory();
|
|
13
19
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
20
|
+
* Upper bound on the serialized hook payload that the parallel fast path will
|
|
21
|
+
* inline into the queue message's `hookInput`. Vercel Queues caps a single
|
|
22
|
+
* message at ~256 KiB, and the message also carries the runId, hookId, token,
|
|
23
|
+
* resumeId, digest, and trace carrier alongside CBOR framing overhead. Staying
|
|
24
|
+
* well under that ceiling keeps the queue publish from rejecting an oversized
|
|
25
|
+
* message — which, on the parallel path, would persist `hook_received` but never
|
|
26
|
+
* re-trigger the run. Above this size we fall back to the sequential path, whose
|
|
27
|
+
* queue message carries only the run ID (the payload lives in the event log).
|
|
16
28
|
*/
|
|
29
|
+
const MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
|
|
30
|
+
/**
|
|
31
|
+
* Hex SHA-256 of the serialized resume payload bytes. Computed once by the
|
|
32
|
+
* producer and forwarded verbatim on both the direct `hook_received` write and
|
|
33
|
+
* the queue `hookInput`, so both writers of the same `resumeId` record an
|
|
34
|
+
* identical digest on the server's `(runId, resumeId)` constraint. Hashing the
|
|
35
|
+
* already-serialized bytes (not the raw value) keeps producer and consumer in
|
|
36
|
+
* lockstep — the consumer forwards this string without recomputing.
|
|
37
|
+
*/
|
|
38
|
+
async function computeResumePayloadDigest(bytes) {
|
|
39
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes);
|
|
40
|
+
const view = new Uint8Array(digest);
|
|
41
|
+
let hex = '';
|
|
42
|
+
for (const b of view) {
|
|
43
|
+
hex += b.toString(16).padStart(2, '0');
|
|
44
|
+
}
|
|
45
|
+
return hex;
|
|
46
|
+
}
|
|
47
|
+
/** Derive a resume context from a full run (fallback for pre-`resumeContext` hooks). */
|
|
48
|
+
function resumeContextFromRun(run) {
|
|
49
|
+
const coreVersion = run.executionContext?.workflowCoreVersion;
|
|
50
|
+
const traceCarrier = run.executionContext?.traceCarrier;
|
|
51
|
+
const hookResumeInputVersion = run.executionContext?.hookResumeInputVersion;
|
|
52
|
+
return {
|
|
53
|
+
deploymentId: run.deploymentId,
|
|
54
|
+
workflowName: run.workflowName,
|
|
55
|
+
runSpecVersion: run.specVersion,
|
|
56
|
+
workflowCoreVersion: typeof coreVersion === 'string' ? coreVersion : undefined,
|
|
57
|
+
traceCarrier: traceCarrier && typeof traceCarrier === 'object'
|
|
58
|
+
? traceCarrier
|
|
59
|
+
: undefined,
|
|
60
|
+
encryptionPublicKey: run.encryptionPublicKey,
|
|
61
|
+
hookResumeInputVersion: typeof hookResumeInputVersion === 'number'
|
|
62
|
+
? hookResumeInputVersion
|
|
63
|
+
: undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve resume context for a hook. Uses the stored `resumeContext` when
|
|
68
|
+
* present (fast path — no run read); otherwise fetches the run and synthesizes
|
|
69
|
+
* it. Does NOT resolve the encryption key — callers do that separately. Only
|
|
70
|
+
* the fallback path can gate key work behind a local terminal-run check (it
|
|
71
|
+
* has the fetched run); the fast path's stored context carries no status, so
|
|
72
|
+
* seal/serialization work may run before the receiving side rejects
|
|
73
|
+
* `hook_received` for an ended run.
|
|
74
|
+
*/
|
|
75
|
+
async function resolveHookResumeInfo(hook) {
|
|
76
|
+
if (hook.resumeContext) {
|
|
77
|
+
return { resumeContext: hook.resumeContext, source: 'hook' };
|
|
78
|
+
}
|
|
79
|
+
const run = await (await getWorldLazy()).runs.get(hook.runId);
|
|
80
|
+
return {
|
|
81
|
+
resumeContext: resumeContextFromRun(run),
|
|
82
|
+
source: 'run_fallback',
|
|
83
|
+
run,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve the run's symmetric key for a payload WRITE, as a bare `CryptoKey`
|
|
88
|
+
* (`importKey`) — the `encr` write fallback used when the run published no
|
|
89
|
+
* public key to seal to. Writing needs only the AES key, not the read-side
|
|
90
|
+
* keypair. On the fast path this needs only `runId` + `deploymentId` (no run
|
|
91
|
+
* entity); on the fallback path the already fetched run is reused.
|
|
92
|
+
*/
|
|
93
|
+
async function resolveHookEncryptionKey(hook, info) {
|
|
94
|
+
const world = await getWorldLazy();
|
|
95
|
+
const rawKey = info.run
|
|
96
|
+
? await world.getEncryptionKeyForRun?.(info.run)
|
|
97
|
+
: await world.getEncryptionKeyForRun?.(hook.runId, {
|
|
98
|
+
deploymentId: info.resumeContext.deploymentId,
|
|
99
|
+
});
|
|
100
|
+
return rawKey ? await importKey(rawKey) : undefined;
|
|
101
|
+
}
|
|
17
102
|
async function getHookByTokenWithKey(token) {
|
|
18
|
-
const world = await
|
|
103
|
+
const world = await getWorldLazy();
|
|
19
104
|
const hook = await world.hooks.getByToken(token);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
105
|
+
// Only a hook that actually carries metadata needs the run's key resolved
|
|
106
|
+
// here: hydrating that metadata is a READ, so derive the full RunPayloadKeys
|
|
107
|
+
// (which opens sealed `encp` metadata, not just symmetric `encr`). The common
|
|
108
|
+
// default webhook — createWebhook() with no `respondWith` — stores no
|
|
109
|
+
// metadata, so it skips this entirely: no ~350ms `run-key` API round trip,
|
|
110
|
+
// and, crucially, no resolved key handed to `resumeHook`, leaving it free to
|
|
111
|
+
// seal the payload to the run's published public key instead. Metadata-
|
|
112
|
+
// bearing webhooks still legitimately pay one lookup to hydrate.
|
|
113
|
+
let encryptionKey;
|
|
23
114
|
if (typeof hook.metadata !== 'undefined') {
|
|
115
|
+
const info = await resolveHookResumeInfo(hook);
|
|
116
|
+
// On the fast path this resolves the key by runId + deploymentId (no run
|
|
117
|
+
// read); on the fallback path it reuses the already-fetched run.
|
|
118
|
+
const rawKey = info.run
|
|
119
|
+
? await world.getEncryptionKeyForRun?.(info.run)
|
|
120
|
+
: await world.getEncryptionKeyForRun?.(hook.runId, {
|
|
121
|
+
deploymentId: info.resumeContext.deploymentId,
|
|
122
|
+
});
|
|
123
|
+
encryptionKey = rawKey ? await deriveRunPayloadKeys(rawKey) : undefined;
|
|
24
124
|
hook.metadata = await hydrateStepArguments(hook.metadata, hook.runId, encryptionKey);
|
|
25
125
|
}
|
|
26
|
-
return { hook,
|
|
126
|
+
return { hook, encryptionKey };
|
|
27
127
|
}
|
|
28
128
|
/**
|
|
29
129
|
* Get the hook by token to find the associated workflow run,
|
|
30
130
|
* and hydrate the `metadata` property if it was set from within
|
|
31
131
|
* the workflow run.
|
|
32
132
|
*
|
|
133
|
+
* A Hook kept by minimum retention remains available here after its run ends,
|
|
134
|
+
* but cannot be resumed.
|
|
135
|
+
*
|
|
33
136
|
* @param token - The unique token identifying the hook
|
|
34
137
|
*/
|
|
35
138
|
export async function getHookByToken(token) {
|
|
@@ -44,8 +147,8 @@ export async function getHookByToken(token) {
|
|
|
44
147
|
*
|
|
45
148
|
* @param tokenOrHook - The unique token identifying the hook, or the hook object itself
|
|
46
149
|
* @param payload - The data payload to send to the hook
|
|
47
|
-
* @returns Promise resolving to the
|
|
48
|
-
* @throws
|
|
150
|
+
* @returns Promise resolving to the {@link ResumedHook}
|
|
151
|
+
* @throws {HookNotFoundError} If the Hook does not exist or its run has ended
|
|
49
152
|
*
|
|
50
153
|
* @example
|
|
51
154
|
*
|
|
@@ -66,83 +169,347 @@ export async function getHookByToken(token) {
|
|
|
66
169
|
* ```
|
|
67
170
|
*/
|
|
68
171
|
export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
|
|
172
|
+
// Public entry point. It never attests hook freshness, so a Hook object
|
|
173
|
+
// supplied here — which may carry a `resumeCapabilities` cached before a
|
|
174
|
+
// server rollback or kill switch — is ignored by the dynamic-dedup gate and
|
|
175
|
+
// fails closed to the sequential path. Only `resumeWebhook`, which fetches
|
|
176
|
+
// the hook by token in-line during the same resume, reaches the internal
|
|
177
|
+
// implementation with the fresh attestation set. Keeping the freshness flag
|
|
178
|
+
// off the exported signature prevents a caller from passing a stale Hook plus
|
|
179
|
+
// `true` and reactivating dynamic dedup against a rolled-back backend.
|
|
180
|
+
return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Internal implementation of {@link resumeHook}. NOT exported: the
|
|
184
|
+
* `hookFreshlyLookedUp` attestation must never be reachable by public callers
|
|
185
|
+
* (see the wrapper above).
|
|
186
|
+
*
|
|
187
|
+
* @param hookFreshlyLookedUp - Attests that a supplied Hook object was fetched
|
|
188
|
+
* by token during THIS resume, so its response-only `resumeCapabilities`
|
|
189
|
+
* reflects the live backend and may be trusted for the dynamic-dedup gate.
|
|
190
|
+
* A token string is always fetched fresh here, so it is implicitly fresh.
|
|
191
|
+
*/
|
|
192
|
+
async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp) {
|
|
69
193
|
return await waitedUntil(() => {
|
|
70
194
|
return trace('hook.resume', async (span) => {
|
|
71
|
-
const world = await
|
|
195
|
+
const world = await getWorldLazy();
|
|
72
196
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
hook = tokenOrHook;
|
|
84
|
-
workflowRun = await world.runs.get(hook.runId);
|
|
85
|
-
if (encryptionKeyOverride) {
|
|
86
|
-
encryptionKey = encryptionKeyOverride;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const rawKey = await world.getEncryptionKeyForRun?.(workflowRun);
|
|
90
|
-
encryptionKey = rawKey ? await importKey(rawKey) : undefined;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
197
|
+
const suppliedToken = typeof tokenOrHook === 'string';
|
|
198
|
+
const hook = suppliedToken
|
|
199
|
+
? await world.hooks.getByToken(tokenOrHook)
|
|
200
|
+
: tokenOrHook;
|
|
201
|
+
// The dynamic, response-only `resumeCapabilities` may only be trusted
|
|
202
|
+
// when it came from a by-token lookup performed during this resume.
|
|
203
|
+
const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
|
|
204
|
+
const info = await resolveHookResumeInfo(hook);
|
|
205
|
+
const { resumeContext } = info;
|
|
93
206
|
span?.setAttributes({
|
|
94
207
|
...Attribute.HookToken(hook.token),
|
|
95
208
|
...Attribute.HookId(hook.hookId),
|
|
96
209
|
...Attribute.WorkflowRunId(hook.runId),
|
|
210
|
+
'workflow.hook.resume_context_source': info.source,
|
|
97
211
|
});
|
|
212
|
+
// The stored `resumeContext` intentionally omits the run's mutable
|
|
213
|
+
// status, so this early client-side rejection only runs on the
|
|
214
|
+
// fallback path (which fetched the run). On the fast path the terminal
|
|
215
|
+
// check happens server-side: `hook_received` against an ended run is
|
|
216
|
+
// rejected, which the catch around `world.events.create` below re-keys
|
|
217
|
+
// to HookNotFoundError — same public contract, no run pre-fetch.
|
|
218
|
+
if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
|
|
219
|
+
throw new HookNotFoundError(hook.token);
|
|
220
|
+
}
|
|
98
221
|
// Check the target run's capabilities to ensure we encode the
|
|
99
222
|
// payload in a format the run's deployment can decode. For example,
|
|
100
223
|
// runs created before encryption support was added cannot decode
|
|
101
|
-
// the 'encr' serialization format
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
224
|
+
// the 'encr' serialization format, and runs created before
|
|
225
|
+
// byte-stream framing support cannot decode framed byte streams.
|
|
226
|
+
const capabilities = getRunCapabilities(resumeContext.workflowCoreVersion);
|
|
227
|
+
// Resolve how to encrypt the payload for the target run (a WRITE).
|
|
228
|
+
//
|
|
229
|
+
// Preferred path: seal to the run's published X25519 public key, which
|
|
230
|
+
// the stored `resumeContext` carries inline. On the fast path this is
|
|
231
|
+
// the whole win — no run read AND no `getEncryptionKeyForRun`, whose
|
|
232
|
+
// ~350ms `run-key` API round trip dominates cross-deployment hook
|
|
233
|
+
// resumption latency. (On the fallback path the key is synthesized
|
|
234
|
+
// from the fetched run, which also carries it.)
|
|
235
|
+
//
|
|
236
|
+
// Sealing also drops privilege: the resumer ends up able to write a
|
|
237
|
+
// payload for the run without being able to read anything of the
|
|
238
|
+
// run's, where fetching the symmetric key grants both.
|
|
239
|
+
//
|
|
240
|
+
// Deliberately NOT gated on `capabilities.supportedFormats` the way
|
|
241
|
+
// the symmetric fallback below gates `encr`: presence of the public key
|
|
242
|
+
// is itself the gate. A run only carries one if the runtime that
|
|
243
|
+
// created it could also open a sealed payload, and runs are pinned to
|
|
244
|
+
// their creating deployment, so presence is a more reliable attestation
|
|
245
|
+
// than a version compare — and it stays correct even when package
|
|
246
|
+
// versions drift.
|
|
247
|
+
let payloadKey;
|
|
248
|
+
const runPublicKey = encryptionKeyOverride
|
|
249
|
+
? // The caller already holds a key (resumeWebhook resolved one to
|
|
250
|
+
// hydrate hook metadata), so sealing would add an ECDH for no
|
|
251
|
+
// saved round trip. Reuse what it resolved.
|
|
252
|
+
undefined
|
|
253
|
+
: decodeRunPublicKey(resumeContext.encryptionPublicKey);
|
|
254
|
+
if (runPublicKey) {
|
|
255
|
+
payloadKey = sealTo(runPublicKey);
|
|
106
256
|
}
|
|
257
|
+
else {
|
|
258
|
+
// Symmetric `encr` write fallback: needs only the AES key
|
|
259
|
+
// (a bare CryptoKey via `resolveHookEncryptionKey`), not the
|
|
260
|
+
// read-side RunPayloadKeys.
|
|
261
|
+
let encryptionKey = encryptionKeyOverride ??
|
|
262
|
+
(await resolveHookEncryptionKey(hook, info));
|
|
263
|
+
if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
|
|
264
|
+
encryptionKey = undefined;
|
|
265
|
+
}
|
|
266
|
+
payloadKey = encryptionKey;
|
|
267
|
+
}
|
|
268
|
+
// Compress only when the target run and its deployment support the
|
|
269
|
+
// compression formats introduced with spec version 5.
|
|
270
|
+
const compression = (resumeContext.runSpecVersion ?? 0) >=
|
|
271
|
+
SPEC_VERSION_SUPPORTS_COMPRESSION &&
|
|
272
|
+
capabilities.supportedFormats.has(SerializationFormat.GZIP);
|
|
107
273
|
// Dehydrate the payload for storage
|
|
108
274
|
const ops = [];
|
|
109
275
|
const v1Compat = isLegacySpecVersion(hook.specVersion);
|
|
110
|
-
const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId,
|
|
111
|
-
//
|
|
112
|
-
waitUntil(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
276
|
+
const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression);
|
|
277
|
+
// These payload-stream ops are flushed in the background; the
|
|
278
|
+
// promise handed to waitUntil must never reject (an unconsumed
|
|
279
|
+
// waitUntil rejection crashes the process as unhandledRejection),
|
|
280
|
+
// so unexpected failures are logged instead.
|
|
281
|
+
// NOTE: rejections with `undefined` are an expected artifact of the
|
|
282
|
+
// webhook bundle and are ignored entirely.
|
|
283
|
+
safeWaitUntil(Promise.all(ops), (err) => {
|
|
284
|
+
if (err === undefined)
|
|
285
|
+
return;
|
|
286
|
+
runtimeLogger.warn('Background flush of hook payload ops failed', {
|
|
287
|
+
workflowRunId: hook.runId,
|
|
288
|
+
hookId: hook.hookId,
|
|
289
|
+
error: err instanceof Error ? err.message : String(err),
|
|
290
|
+
});
|
|
291
|
+
});
|
|
125
292
|
span?.setAttributes({
|
|
126
|
-
...Attribute.WorkflowName(
|
|
293
|
+
...Attribute.WorkflowName(resumeContext.workflowName),
|
|
127
294
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
295
|
+
// Link to the run-origin context from the stored trace carrier
|
|
296
|
+
// (skipped when absent or invalid). Resolved before dispatch so both
|
|
297
|
+
// the sequential and parallel paths attach it.
|
|
298
|
+
const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
|
|
299
|
+
if (originLink) {
|
|
300
|
+
span?.addLink?.(originLink);
|
|
134
301
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
302
|
+
const eventData = {
|
|
303
|
+
...(v1Compat ? {} : { token: hook.token }),
|
|
304
|
+
payload: dehydratedPayload,
|
|
305
|
+
};
|
|
306
|
+
const queueName = getWorkflowQueueName(resumeContext.workflowName);
|
|
307
|
+
const queueOptions = {
|
|
308
|
+
deploymentId: resumeContext.deploymentId,
|
|
309
|
+
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY,
|
|
310
|
+
};
|
|
311
|
+
// Decide whether to parallelize the `hook_received` write and the queue
|
|
312
|
+
// publish. The fast path is only safe when EVERY precondition holds; the
|
|
313
|
+
// first that fails names the fallback reason (emitted as a span
|
|
314
|
+
// attribute for observability, and to make "why did this run sequential"
|
|
315
|
+
// answerable in production). All conditions:
|
|
316
|
+
//
|
|
317
|
+
// - kill switch: `WORKFLOW_DISABLE_LAZY_HOOK_RESUME` forces sequential
|
|
318
|
+
// if the fast path ever misbehaves. It is an SDK-deployment env var,
|
|
319
|
+
// so changing it generally requires redeploying the workflow
|
|
320
|
+
// deployment. (The backend can independently drop new resumes to the
|
|
321
|
+
// sequential path fleet-wide by ceasing to attest dedup support on
|
|
322
|
+
// the by-token lookup — see the backend-dedup condition below.)
|
|
323
|
+
// - backend dedup: the live backend must enforce the
|
|
324
|
+
// `(runId, resumeId)` constraint, or the two writers would commit two
|
|
325
|
+
// `hook_received` events. Fail closed. Attested by EITHER a fresh,
|
|
326
|
+
// response-only `hook.resumeCapabilities.hookResumeDedupVersion` from
|
|
327
|
+
// the by-token lookup (world-vercel — recomputed every read, so a
|
|
328
|
+
// server rollback or kill switch drops to sequential immediately) OR
|
|
329
|
+
// the static `world.capabilities.hookResumeDedup` (world-local, whose
|
|
330
|
+
// adapter and backend ship together). The response-only capability is
|
|
331
|
+
// trusted ONLY when the hook was looked up by token during this
|
|
332
|
+
// resume (`hookResumeCapabilitiesAreFresh`); a Hook object handed in
|
|
333
|
+
// by a public caller may carry a capability cached before a rollback,
|
|
334
|
+
// so it is ignored and the path falls back to sequential.
|
|
335
|
+
// - consumer support: the target run's deployment must re-ensure the
|
|
336
|
+
// event from `hookInput` on replay. Attested by the run's explicit
|
|
337
|
+
// `hookResumeInputVersion` execution-context marker (mirrored onto
|
|
338
|
+
// resumeContext), NOT a version-compare against a predicted release
|
|
339
|
+
// cutoff. Absent → a lost producer write would be a lost resume.
|
|
340
|
+
// - not legacy: v1Compat runs omit `token` from the producer's event
|
|
341
|
+
// body but the consumer's re-ensure always includes it, so the two
|
|
342
|
+
// writers would disagree on the event body. Legacy stays sequential.
|
|
343
|
+
// - CBOR transport: the run must use CBOR queue transport so the binary
|
|
344
|
+
// payload survives the queue message.
|
|
345
|
+
// - raw bytes: the dehydrated payload must be a `Uint8Array` (the
|
|
346
|
+
// content digest that keys the dedup constraint is over these bytes).
|
|
347
|
+
// - size: a payload above the queue's message ceiling would fail the
|
|
348
|
+
// publish — which, on the parallel path, would persist the event but
|
|
349
|
+
// never re-trigger the run — so oversized payloads stay sequential
|
|
350
|
+
// (their queue message carries only the run ID).
|
|
351
|
+
const parallelResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === '1';
|
|
352
|
+
// Backend dedup is supported when EITHER the live server attests it
|
|
353
|
+
// fresh on this by-token hook (world-vercel: response-only, recomputed
|
|
354
|
+
// every read, so rollback/kill-switch take effect immediately) OR the
|
|
355
|
+
// static world capability is set (world-local: adapter + backend ship
|
|
356
|
+
// together). Both are re-evaluated per resume, so every rollout and
|
|
357
|
+
// rollback direction degrades safely to the sequential path.
|
|
358
|
+
const backendDedupSupported = (hookResumeCapabilitiesAreFresh
|
|
359
|
+
? (hook.resumeCapabilities?.hookResumeDedupVersion ?? 0)
|
|
360
|
+
: 0) >= HOOK_RESUME_DEDUP_VERSION ||
|
|
361
|
+
world.capabilities?.hookResumeDedup === true;
|
|
362
|
+
const fallbackReason = parallelResumeDisabled
|
|
363
|
+
? 'disabled'
|
|
364
|
+
: !backendDedupSupported
|
|
365
|
+
? 'backend_unsupported'
|
|
366
|
+
: (resumeContext.hookResumeInputVersion ?? 0) <
|
|
367
|
+
HOOK_RESUME_INPUT_VERSION
|
|
368
|
+
? 'consumer_unsupported'
|
|
369
|
+
: v1Compat
|
|
370
|
+
? 'legacy'
|
|
371
|
+
: (resumeContext.runSpecVersion ?? 0) <
|
|
372
|
+
SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT
|
|
373
|
+
? 'non_cbor_transport'
|
|
374
|
+
: !(dehydratedPayload instanceof Uint8Array)
|
|
375
|
+
? 'non_bytes'
|
|
376
|
+
: dehydratedPayload.byteLength >
|
|
377
|
+
MAX_INLINE_RESUME_PAYLOAD_BYTES
|
|
378
|
+
? 'oversized'
|
|
379
|
+
: null;
|
|
380
|
+
const useParallelResume = fallbackReason === null;
|
|
381
|
+
span?.setAttributes({
|
|
382
|
+
'workflow.hook.resume_strategy': useParallelResume
|
|
383
|
+
? 'parallel'
|
|
384
|
+
: 'sequential',
|
|
385
|
+
...(fallbackReason
|
|
386
|
+
? { 'workflow.hook.resume_fallback_reason': fallbackReason }
|
|
387
|
+
: {}),
|
|
144
388
|
});
|
|
145
|
-
|
|
389
|
+
// Re-key any "hook can no longer be received" rejection to
|
|
390
|
+
// HookNotFoundError(hook.token) so `.token` matches the pre-fast-path
|
|
391
|
+
// contract, where resumeHook threw `HookNotFoundError(hook.token)`
|
|
392
|
+
// after its own terminal check. The specific error depends on the
|
|
393
|
+
// World:
|
|
394
|
+
// - a genuinely missing hook maps to HookNotFoundError (keyed on the
|
|
395
|
+
// event correlationId / hook ID);
|
|
396
|
+
// - a terminal run on Vercel rejects hook_received with 404, which
|
|
397
|
+
// world-vercel maps to HookNotFoundError;
|
|
398
|
+
// - a terminal run on world-local / world-postgres rejects with
|
|
399
|
+
// RunExpiredError.
|
|
400
|
+
//
|
|
401
|
+
// On the SEQUENTIAL path an EntityConflictError (HTTP 409) is also
|
|
402
|
+
// treated as "hook gone" for historical / conflict-shaped-rejection
|
|
403
|
+
// compatibility: there is no queue message in flight, so a conflict has
|
|
404
|
+
// no re-ensuring consumer to converge on. The PARALLEL path handles 409
|
|
405
|
+
// differently (see below) — it published the queue message before the
|
|
406
|
+
// conflict, so the consumer will converge the event.
|
|
407
|
+
const isHookGoneError = (err) => HookNotFoundError.is(err) ||
|
|
408
|
+
EntityConflictError.is(err) ||
|
|
409
|
+
RunExpiredError.is(err);
|
|
410
|
+
if (!useParallelResume) {
|
|
411
|
+
// Sequential path: create a hook_received event, then re-trigger.
|
|
412
|
+
try {
|
|
413
|
+
await world.events.create(hook.runId, {
|
|
414
|
+
eventType: 'hook_received',
|
|
415
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
416
|
+
correlationId: hook.hookId,
|
|
417
|
+
eventData,
|
|
418
|
+
}, { v1Compat });
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
if (isHookGoneError(err)) {
|
|
422
|
+
throw new HookNotFoundError(hook.token);
|
|
423
|
+
}
|
|
424
|
+
throw err;
|
|
425
|
+
}
|
|
426
|
+
await world.queue(queueName, {
|
|
427
|
+
runId: hook.runId,
|
|
428
|
+
traceCarrier: resumeContext.traceCarrier ?? undefined,
|
|
429
|
+
}, queueOptions);
|
|
430
|
+
return hook;
|
|
431
|
+
}
|
|
432
|
+
// Parallel fast path. A stable idempotency key ties the direct write to
|
|
433
|
+
// the queue consumer's re-ensure; the payload digest lets the server
|
|
434
|
+
// detect key reuse across byte-identical payloads.
|
|
435
|
+
const resumeId = generateResumeId();
|
|
436
|
+
const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
|
|
437
|
+
span?.setAttributes({ 'workflow.hook.resume_id': resumeId });
|
|
438
|
+
const [eventResult, queueResult] = await Promise.allSettled([
|
|
439
|
+
world.events.create(hook.runId, {
|
|
440
|
+
eventType: 'hook_received',
|
|
441
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
442
|
+
correlationId: hook.hookId,
|
|
443
|
+
eventData,
|
|
444
|
+
}, { v1Compat, resumeId, resumePayloadDigest: payloadDigest }),
|
|
445
|
+
world.queue(queueName, {
|
|
446
|
+
runId: hook.runId,
|
|
447
|
+
traceCarrier: resumeContext.traceCarrier ?? undefined,
|
|
448
|
+
hookInput: {
|
|
449
|
+
resumeId,
|
|
450
|
+
hookId: hook.hookId,
|
|
451
|
+
token: hook.token,
|
|
452
|
+
payload: dehydratedPayload,
|
|
453
|
+
payloadDigest,
|
|
454
|
+
},
|
|
455
|
+
}, queueOptions),
|
|
456
|
+
]);
|
|
457
|
+
// Queue failure is always fatal — the run was not re-triggered, so no
|
|
458
|
+
// consumer will re-ensure the event.
|
|
459
|
+
if (queueResult.status === 'rejected') {
|
|
460
|
+
throw queueResult.reason;
|
|
461
|
+
}
|
|
462
|
+
// Set when the direct write did not land but the queue dispatch did, so
|
|
463
|
+
// the consumer materializes the event before replay. Surfaced to the
|
|
464
|
+
// caller as `ResumedHook.resilientResume` and on the span.
|
|
465
|
+
let resilientResume = false;
|
|
466
|
+
if (eventResult.status === 'rejected') {
|
|
467
|
+
const err = eventResult.reason;
|
|
468
|
+
if (HookNotFoundError.is(err) || RunExpiredError.is(err)) {
|
|
469
|
+
// The hook's run has genuinely ended: surface the same contract as
|
|
470
|
+
// the sequential path. The queue message already went out, but the
|
|
471
|
+
// consumer's re-ensure will also reject against the terminal run
|
|
472
|
+
// and no-op, so the workflow does not resume.
|
|
473
|
+
throw new HookNotFoundError(hook.token);
|
|
474
|
+
}
|
|
475
|
+
if (EntityConflictError.is(err) || isRetryableWorldError(err)) {
|
|
476
|
+
// Resilient. Two shapes reach here, both non-terminal:
|
|
477
|
+
// - EntityConflict (409): this write raced its own re-ensuring
|
|
478
|
+
// consumer (or a redrive) on the shared `resumeId` — the run is
|
|
479
|
+
// NOT gone, and the consumer converges on the one committed
|
|
480
|
+
// event. Unlike the sequential path, a 409 here is expected
|
|
481
|
+
// concurrency, not a vanished hook.
|
|
482
|
+
// - 429 / 5xx / transport: a transient backend failure.
|
|
483
|
+
// In both cases the run WAS re-triggered via the queue and the
|
|
484
|
+
// consumer idempotently ensures the hook_received before replay, so
|
|
485
|
+
// swallow rather than failing the caller.
|
|
486
|
+
//
|
|
487
|
+
// Producer telemetry: record that the direct write did not land but
|
|
488
|
+
// the resume is still guaranteed via queue-delivered `hookInput`.
|
|
489
|
+
// This is the operational signal that the recovery path fired,
|
|
490
|
+
// surfaced both on the span and as the public `resilientResume`
|
|
491
|
+
// flag on the returned hook (the resume outcome is otherwise
|
|
492
|
+
// identical to the happy path from the caller's perspective).
|
|
493
|
+
resilientResume = true;
|
|
494
|
+
span?.setAttributes({
|
|
495
|
+
...Attribute.HookResilientResume(true),
|
|
496
|
+
'workflow.hook.resume_event_write_recovered': true,
|
|
497
|
+
'workflow.hook.resume_event_write_error': err instanceof Error ? err.name : 'unknown',
|
|
498
|
+
});
|
|
499
|
+
runtimeLogger.warn('Hook resume event write failed, but the run was re-triggered via ' +
|
|
500
|
+
'the queue. The hook_received event will be ensured by the ' +
|
|
501
|
+
'queue consumer.', {
|
|
502
|
+
workflowRunId: hook.runId,
|
|
503
|
+
hookId: hook.hookId,
|
|
504
|
+
resumeId,
|
|
505
|
+
error: err instanceof Error ? err.message : String(err),
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
throw err;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return (resilientResume ? { ...hook, resilientResume: true } : hook);
|
|
146
513
|
}
|
|
147
514
|
catch (err) {
|
|
148
515
|
span?.setAttributes({
|
|
@@ -221,7 +588,12 @@ export async function resumeWebhook(token, request) {
|
|
|
221
588
|
// No `respondWith` value implies the default behavior of returning a 202
|
|
222
589
|
response = new Response(null, { status: 202 });
|
|
223
590
|
}
|
|
224
|
-
|
|
591
|
+
// `hook` was just fetched via `getHookByTokenWithKey` (a fresh by-token
|
|
592
|
+
// lookup) above, so its response-only `resumeCapabilities` reflects the live
|
|
593
|
+
// backend — call the internal implementation with the fresh attestation so
|
|
594
|
+
// the parallel fast path stays available without a second GET. (The public
|
|
595
|
+
// `resumeHook` never sets this, so a caller cannot forge it.)
|
|
596
|
+
await resumeHookImpl(hook, request, encryptionKey, true);
|
|
225
597
|
if (responseReadable) {
|
|
226
598
|
// Wait for the readable stream to emit one chunk,
|
|
227
599
|
// which is the `Response` object
|
|
@@ -239,4 +611,4 @@ export async function resumeWebhook(token, request) {
|
|
|
239
611
|
}
|
|
240
612
|
return response;
|
|
241
613
|
}
|
|
242
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUNMLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsb0JBQW9CLEdBQ3JCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUVMLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsbUJBQW1CLEdBR3BCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDeEQsT0FBTyxFQUFrQixTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3RCxPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNwQixtQkFBbUIsR0FDcEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0Qzs7O0dBR0c7QUFDSCxLQUFLLFVBQVUscUJBQXFCLENBQUMsS0FBYTtJQUtoRCxNQUFNLEtBQUssR0FBRyxNQUFNLFFBQVEsRUFBRSxDQUFDO0lBQy9CLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakQsTUFBTSxHQUFH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QUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxFQUM3RCxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsa0NBQWtDLEVBQUUsQ0FDekQsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLHlFQUF5RTtRQUN6RSxRQUFRLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVELE1BQU0sVUFBVSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFFL0MsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLGtEQUFrRDtRQUNsRCxpQ0FBaUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsUUFBUSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDekIsQ0FBQztRQUNELE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsTUFBTSxJQUFJLG9CQUFvQixDQUFDLHNDQUFzQyxFQUFFO1lBQ3JFLElBQUksRUFBRSxXQUFXLENBQUMseUJBQXlCO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRVJST1JfU0xVR1MsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBXb3JrZmxvd1J1bnRpbWVFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICB0eXBlIEhvb2ssXG4gIGlzTGVnYWN5U3BlY1ZlcnNpb24sXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICB0eXBlIFdvcmtmbG93SW52b2tlUGF5bG9hZCxcbiAgdHlwZSBXb3JrZmxvd1J1bixcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGdldFJ1bkNhcGFiaWxpdGllcyB9IGZyb20gJy4uL2NhcGFiaWxpdGllcy5qcyc7XG5pbXBvcnQgeyB0eXBlIENyeXB0b0tleSwgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQge1xuICBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUsXG4gIGh5ZHJhdGVTdGVwQXJndW1lbnRzLFxuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUgfSBmcm9tICcuLi9zeW1ib2xzLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgZ2V0U3BhbkNvbnRleHRGb3JUcmFjZUNhcnJpZXIsIHRyYWNlIH0gZnJvbSAnLi4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7IHdhaXRlZFVudGlsIH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBnZXRXb3JrZmxvd1F1ZXVlTmFtZSB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZCB9IGZyb20gJy4vd29ybGQuanMnO1xuXG4vKipcbiAqIEludGVybmFsIGhlbHBlciB0aGF0IHJldHVybnMgdGhlIGhvb2ssIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bixcbiAqIGFuZCB0aGUgcmVzb2x2ZWQgZW5jcnlwdGlvbiBrZXkuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldEhvb2tCeVRva2VuV2l0aEtleSh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTx7XG4gIGhvb2s6IEhvb2s7XG4gIHJ1bjogV29ya2Zsb3dSdW47XG4gIGVuY3J5cHRpb25LZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICBjb25zdCBob29rID0gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbik7XG4gIGNvbnN0IHJ1biA9IGF3YWl0IHdvcmxkLnJ1bnMuZ2V0KGhvb2sucnVuSWQpO1xuICBjb25zdCByYXdLZXkgPSBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4ocnVuKTtcbiAgY29uc3QgZW5jcnlwdGlvbktleSA9IHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIGhvb2subWV0YWRhdGEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaG9vay5tZXRhZGF0YSA9IGF3YWl0IGh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgaG9vay5tZXRhZGF0YSBhcyBhbnksXG4gICAgICBob29rLnJ1bklkLFxuICAgICAgZW5jcnlwdGlvbktleVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHsgaG9vaywgcnVuLCBlbmNyeXB0aW9uS2V5IH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBob29rIGJ5IHRva2VuIHRvIGZpbmQgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLFxuICogYW5kIGh5ZHJhdGUgdGhlIGBtZXRhZGF0YWAgcHJvcGVydHkgaWYgaXQgd2FzIHNldCBmcm9tIHdpdGhpblxuICogdGhlIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxIb29rPiB7XG4gIGNvbnN0IHsgaG9vayB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcbiAgcmV0dXJuIGhvb2s7XG59XG5cbi8qKlxuICogUmVzdW1lcyBhIHdvcmtmbG93IHJ1biBieSBzZW5kaW5nIGEgcGF5bG9hZCB0byBhIGhvb2sgaWRlbnRpZmllZCBieSBpdHMgdG9rZW4uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXh0ZXJuYWxseSAoZS5nLiwgZnJvbSBhbiBBUEkgcm91dGUgb3Igc2VydmVyIGFjdGlvbilcbiAqIHRvIHNlbmQgZGF0YSB0byBhIGhvb2sgYW5kIHJlc3VtZSB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4uXG4gKlxuICogQHBhcmFtIHRva2VuT3JIb29rIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9vaywgb3IgdGhlIGhvb2sgb2JqZWN0IGl0c2VsZlxuICogQHBhcmFtIHBheWxvYWQgLSBUaGUgZGF0YSBwYXlsb2FkIHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBob29rXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBob29rIGlzIG5vdCBmb3VuZCBvciBpZiB0aGVyZSdzIGFuIGVycm9yIGR1cmluZyB0aGUgcHJvY2Vzc1xuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lSG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgeyB0b2tlbiwgZGF0YSB9ID0gYXdhaXQgcmVxdWVzdC5qc29uKCk7XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IGhvb2sgPSBhd2FpdCByZXN1bWVIb29rKHRva2VuLCBkYXRhKTtcbiAqICAgICByZXR1cm4gUmVzcG9uc2UuanNvbih7IHJ1bklkOiBob29rLnJ1bklkIH0pO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ0hvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVIb29rPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlPzogQ3J5cHRvS2V5XG4pOiBQcm9taXNlPEhvb2s+IHtcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICByZXR1cm4gdHJhY2UoJ2hvb2sucmVzdW1lJywgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGQoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IGhvb2s6IEhvb2s7XG4gICAgICAgIGxldCB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW47XG4gICAgICAgIGxldCBlbmNyeXB0aW9uS2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuT3JIb29rKTtcbiAgICAgICAgICBob29rID0gcmVzdWx0Lmhvb2s7XG4gICAgICAgICAgd29ya2Zsb3dSdW4gPSByZXN1bHQucnVuO1xuICAgICAgICAgIGVuY3J5cHRpb25LZXkgPSBlbmNyeXB0aW9uS2V5T3ZlcnJpZGUgPz8gcmVzdWx0LmVuY3J5cHRpb25LZXk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaG9vayA9IHRva2VuT3JIb29rO1xuICAgICAgICAgIHdvcmtmbG93UnVuID0gYXdhaXQgd29ybGQucnVucy5nZXQoaG9vay5ydW5JZCk7XG4gICAgICAgICAgaWYgKGVuY3J5cHRpb25LZXlPdmVycmlkZSkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcmF3S2V5ID0gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHdvcmtmbG93UnVuKTtcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXkgPSByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LlxuICAgICAgICBjb25zdCByYXdWZXJzaW9uID0gd29ya2Zsb3dSdW4uZXhlY3V0aW9uQ29udGV4dD8ud29ya2Zsb3dDb3JlVmVyc2lvbjtcbiAgICAgICAgY29uc3QgeyBzdXBwb3J0ZWRGb3JtYXRzIH0gPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgdHlwZW9mIHJhd1ZlcnNpb24gPT09ICdzdHJpbmcnID8gcmF3VmVyc2lvbiA6IHVuZGVmaW5lZFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKSkge1xuICAgICAgICAgIGVuY3J5cHRpb25LZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIHBheWxvYWQgZm9yIHN0b3JhZ2VcbiAgICAgICAgY29uc3Qgb3BzOiBQcm9taXNlPGFueT5bXSA9IFtdO1xuICAgICAgICBjb25zdCB2MUNvbXBhdCA9IGlzTGVnYWN5U3BlY1ZlcnNpb24oaG9vay5zcGVjVmVyc2lvbik7XG4gICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRQYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcFJldHVyblZhbHVlKFxuICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgaG9vay5ydW5JZCxcbiAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgIG9wcyxcbiAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgIHYxQ29tcGF0XG4gICAgICAgICk7XG4gICAgICAgIC8vIE5PVEU6IFdvcmthcm91bmQgaW5zdGVhZCBvZiBpbmplY3RpbmcgY2F0Y2hpbmcgdW5kZWZpbmVkIHVuaGFuZGxlZCByZWplY3Rpb25zIGluIHdlYmhvb2sgYnVuZGxlXG4gICAgICAgIHdhaXRVbnRpbChcbiAgICAgICAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIgIT09IHVuZGVmaW5lZCkgdGhyb3cgZXJyO1xuICAgICAgICAgIH0pXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGEgaG9va19yZWNlaXZlZCBldmVudCB3aXRoIHRoZSBwYXlsb2FkXG4gICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgaG9vay5ydW5JZCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHBheWxvYWQ6IGRlaHlkcmF0ZWRQYXlsb2FkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgdjFDb21wYXQgfVxuICAgICAgICApO1xuXG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gd29ya2Zsb3dSdW4uZXhlY3V0aW9uQ29udGV4dD8udHJhY2VDYXJyaWVyO1xuXG4gICAgICAgIGlmICh0cmFjZUNhcnJpZXIpIHtcbiAgICAgICAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgZ2V0U3BhbkNvbnRleHRGb3JUcmFjZUNhcnJpZXIodHJhY2VDYXJyaWVyKTtcbiAgICAgICAgICBpZiAoY29udGV4dCkge1xuICAgICAgICAgICAgc3Bhbj8uYWRkTGluaz8uKHsgY29udGV4dCB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZS10cmlnZ2VyIHRoZSB3b3JrZmxvdyBhZ2FpbnN0IHRoZSBkZXBsb3ltZW50IElEIGFzc29jaWF0ZWRcbiAgICAgICAgLy8gd2l0aCB0aGUgd29ya2Zsb3cgcnVuIHRoYXQgdGhlIGhvb2sgYmVsb25ncyB0b1xuICAgICAgICBhd2FpdCB3b3JsZC5xdWV1ZShcbiAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd1J1bi53b3JrZmxvd05hbWUpLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJ1bklkOiBob29rLnJ1bklkLFxuICAgICAgICAgICAgLy8gYXR0YWNoIHRoZSB0cmFjZSBjYXJyaWVyIGZyb20gdGhlIHdvcmtmbG93IHJ1blxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyOlxuICAgICAgICAgICAgICB3b3JrZmxvd1J1bi5leGVjdXRpb25Db250ZXh0Py50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgIH0gc2F0aXNmaWVzIFdvcmtmbG93SW52b2tlUGF5bG9hZCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBkZXBsb3ltZW50SWQ6IHdvcmtmbG93UnVuLmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiB3b3JrZmxvd1J1bi5zcGVjVmVyc2lvbiA/PyBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gaG9vaztcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKFxuICAgICAgICAgICAgdHlwZW9mIHRva2VuT3JIb29rID09PSAnc3RyaW5nJyA/IHRva2VuT3JIb29rIDogdG9rZW5Pckhvb2sudG9rZW5cbiAgICAgICAgICApLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rRm91bmQoZmFsc2UpLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBSZXN1bWVzIGEgd2ViaG9vayBieSBzZW5kaW5nIGEge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SZXF1ZXN0IHwgUmVxdWVzdH1cbiAqIG9iamVjdCB0byBhIGhvb2sgaWRlbnRpZmllZCBieSBpdHMgdG9rZW4uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXh0ZXJuYWxseSAoZS5nLiwgZnJvbSBhbiBBUEkgcm91dGUgb3Igc2VydmVyIGFjdGlvbilcbiAqIHRvIHNlbmQgYSByZXF1ZXN0IHRvIGEgd2ViaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKiBAcGFyYW0gcmVxdWVzdCAtIFRoZSByZXF1ZXN0IHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXNwb25zZVxuICogQHRocm93cyBFcnJvciBpZiB0aGUgaG9vayBpcyBub3QgZm91bmQgb3IgaWYgdGhlcmUncyBhbiBlcnJvciBkdXJpbmcgdGhlIHByb2Nlc3NcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYHRzXG4gKiAvLyBJbiBhbiBBUEkgcm91dGVcbiAqIGltcG9ydCB7IHJlc3VtZVdlYmhvb2sgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG4gKiAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuICogICBjb25zdCB0b2tlbiA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0b2tlbicpO1xuICpcbiAqICAgaWYgKCF0b2tlbikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ01pc3NpbmcgdG9rZW4nLCB7IHN0YXR1czogNDAwIH0pO1xuICogICB9XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVzdW1lV2ViaG9vayh0b2tlbiwgcmVxdWVzdCk7XG4gKiAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ1dlYmhvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVXZWJob29rKFxuICB0b2tlbjogc3RyaW5nLFxuICByZXF1ZXN0OiBSZXF1ZXN0XG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gIGNvbnN0IHsgaG9vaywgZW5jcnlwdGlvbktleSB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcblxuICAvLyBPbmx5IHdlYmhvb2tzIGNhbiBiZSByZXN1bWVkIHZpYSB0aGUgcHVibGljIGVuZHBvaW50LlxuICAvLyBJZiB0aGUgaG9vayB3YXMgY3JlYXRlZCB2aWEgY3JlYXRlSG9vaygpIChpc1dlYmhvb2sgIT09IHRydWUpLFxuICAvLyB0aHJvdyB0aGUgc2FtZSBcIm5vdCBmb3VuZFwiIGVycm9yIHRoZSB3b3JsZCB3b3VsZCB0aHJvdyBmb3IgYSBtaXNzaW5nXG4gIC8vIHRva2VuLiBUaGlzIHByZXZlbnRzIGxlYWtpbmcgdGhhdCB0aGUgdG9rZW4gaXMgdmFsaWQuXG4gIGlmIChob29rLmlzV2ViaG9vayA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IodG9rZW4pO1xuICB9XG5cbiAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgbGV0IHJlc3BvbnNlUmVhZGFibGU6IFJlYWRhYmxlU3RyZWFtPFJlc3BvbnNlPiB8IHVuZGVmaW5lZDtcbiAgaWYgKFxuICAgIGhvb2subWV0YWRhdGEgJiZcbiAgICB0eXBlb2YgaG9vay5tZXRhZGF0YSA9PT0gJ29iamVjdCcgJiZcbiAgICAncmVzcG9uZFdpdGgnIGluIGhvb2subWV0YWRhdGFcbiAgKSB7XG4gICAgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggPT09ICdtYW51YWwnKSB7XG4gICAgICBjb25zdCB7IHJlYWRhYmxlLCB3cml0YWJsZSB9ID0gbmV3IFRyYW5zZm9ybVN0cmVhbTxSZXNwb25zZSwgUmVzcG9uc2U+KCk7XG4gICAgICByZXNwb25zZVJlYWRhYmxlID0gcmVhZGFibGU7XG5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IGluc3RhbmNlIGluY2x1ZGVzIHRoZSB3cml0YWJsZSBzdHJlYW0gd2hpY2ggd2lsbCBiZSB1c2VkXG4gICAgICAvLyB0byB3cml0ZSB0aGUgcmVzcG9uc2UgdG8gdGhlIGNsaWVudCBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgcnVuXG4gICAgICAocmVxdWVzdCBhcyBhbnkpW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdID0gd3JpdGFibGU7XG4gICAgfSBlbHNlIGlmIChob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoIGluc3RhbmNlb2YgUmVzcG9uc2UpIHtcbiAgICAgIHJlc3BvbnNlID0gaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICBgSW52YWxpZCBcXGByZXNwb25kV2l0aFxcYCB2YWx1ZTogJHtob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRofWAsXG4gICAgICAgIHsgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19JTlZBTElEX1JFU1BPTkRfV0lUSF9WQUxVRSB9XG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBObyBgcmVzcG9uZFdpdGhgIHZhbHVlIGltcGxpZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgcmV0dXJuaW5nIGEgMjAyXG4gICAgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwgeyBzdGF0dXM6IDIwMiB9KTtcbiAgfVxuXG4gIGF3YWl0IHJlc3VtZUhvb2soaG9vaywgcmVxdWVzdCwgZW5jcnlwdGlvbktleSk7XG5cbiAgaWYgKHJlc3BvbnNlUmVhZGFibGUpIHtcbiAgICAvLyBXYWl0IGZvciB0aGUgcmVhZGFibGUgc3RyZWFtIHRvIGVtaXQgb25lIGNodW5rLFxuICAgIC8vIHdoaWNoIGlzIHRoZSBgUmVzcG9uc2VgIG9iamVjdFxuICAgIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlUmVhZGFibGUuZ2V0UmVhZGVyKCk7XG4gICAgY29uc3QgY2h1bmsgPSBhd2FpdCByZWFkZXIucmVhZCgpO1xuICAgIGlmIChjaHVuay52YWx1ZSkge1xuICAgICAgcmVzcG9uc2UgPSBjaHVuay52YWx1ZTtcbiAgICB9XG4gICAgcmVhZGVyLmNhbmNlbCgpO1xuICB9XG5cbiAgaWYgKCFyZXNwb25zZSkge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcignV29ya2Zsb3cgcnVuIGRpZCBub3Qgc2VuZCBhIHJlc3BvbnNlJywge1xuICAgICAgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19SRVNQT05TRV9OT1RfU0VOVCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiByZXNwb25zZTtcbn1cbiJdfQ==
|
|
614
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBR3pCLG1CQUFtQixFQUNuQiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLG1CQUFtQixFQUNuQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBRXBCLG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFB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RUFBRSxXQUFXLENBQUMseUJBQXlCO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRVJST1JfU0xVR1MsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEhPT0tfUkVTVU1FX0RFRFVQX1ZFUlNJT04sXG4gIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT04sXG4gIHR5cGUgSG9vayxcbiAgdHlwZSBIb29rUmVzdW1lQ29udGV4dCxcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NCT1JfUVVFVUVfVFJBTlNQT1JULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04sXG4gIHR5cGUgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICB0eXBlIFdvcmtmbG93UnVuLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgbW9ub3RvbmljRmFjdG9yeSB9IGZyb20gJ3VsaWQnO1xuaW1wb3J0IHsgZ2V0UnVuQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vY2FwYWJpbGl0aWVzLmpzJztcbmltcG9ydCB7IGlzUmV0cnlhYmxlV29ybGRFcnJvciB9IGZyb20gJy4uL2NsYXNzaWZ5LWVycm9yLmpzJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWNvZGVSdW5QdWJsaWNLZXkgfSBmcm9tICcuLi9zZWFsZWQtYm94LmpzJztcbmltcG9ydCB7IGRlcml2ZVJ1blBheWxvYWRLZXlzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIHR5cGUgUGF5bG9hZEtleSxcbiAgU2VyaWFsaXphdGlvbkZvcm1hdCxcbiAgc2VhbFRvLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUgfSBmcm9tICcuLi9zeW1ib2xzLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgbGlua1RvVHJhY2VDYXJyaWVyLCB0cmFjZSB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UXVldWVOYW1lIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IHNhZmVXYWl0VW50aWwsIHdhaXRlZFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcblxuLyoqIE1vbm90b25pYyBVTElEIGZhY3RvcnkgZm9yIHBlci1jYWxsIHJlc3VtZSBpZGVtcG90ZW5jeSBrZXlzLiAqL1xuY29uc3QgZ2VuZXJhdGVSZXN1bWVJZCA9IG1vbm90b25pY0ZhY3RvcnkoKTtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBvbiB0aGUgc2VyaWFsaXplZCBob29rIHBheWxvYWQgdGhhdCB0aGUgcGFyYWxsZWwgZmFzdCBwYXRoIHdpbGxcbiAqIGlubGluZSBpbnRvIHRoZSBxdWV1ZSBtZXNzYWdlJ3MgYGhvb2tJbnB1dGAuIFZlcmNlbCBRdWV1ZXMgY2FwcyBhIHNpbmdsZVxuICogbWVzc2FnZSBhdCB+MjU2IEtpQiwgYW5kIHRoZSBtZXNzYWdlIGFsc28gY2FycmllcyB0aGUgcnVuSWQsIGhvb2tJZCwgdG9rZW4sXG4gKiByZXN1bWVJZCwgZGlnZXN0LCBhbmQgdHJhY2UgY2FycmllciBhbG9uZ3NpZGUgQ0JPUiBmcmFtaW5nIG92ZXJoZWFkLiBTdGF5aW5nXG4gKiB3ZWxsIHVuZGVyIHRoYXQgY2VpbGluZyBrZWVwcyB0aGUgcXVldWUgcHVibGlzaCBmcm9tIHJlamVjdGluZyBhbiBvdmVyc2l6ZWRcbiAqIG1lc3NhZ2Ug4oCUIHdoaWNoLCBvbiB0aGUgcGFyYWxsZWwgcGF0aCwgd291bGQgcGVyc2lzdCBgaG9va19yZWNlaXZlZGAgYnV0IG5ldmVyXG4gKiByZS10cmlnZ2VyIHRoZSBydW4uIEFib3ZlIHRoaXMgc2l6ZSB3ZSBmYWxsIGJhY2sgdG8gdGhlIHNlcXVlbnRpYWwgcGF0aCwgd2hvc2VcbiAqIHF1ZXVlIG1lc3NhZ2UgY2FycmllcyBvbmx5IHRoZSBydW4gSUQgKHRoZSBwYXlsb2FkIGxpdmVzIGluIHRoZSBldmVudCBsb2cpLlxuICovXG5jb25zdCBNQVhfSU5MSU5FX1JFU1VNRV9QQVlMT0FEX0JZVEVTID0gMTI4ICogMTAyNDtcblxuLyoqXG4gKiBIZXggU0hBLTI1NiBvZiB0aGUgc2VyaWFsaXplZCByZXN1bWUgcGF5bG9hZCBieXRlcy4gQ29tcHV0ZWQgb25jZSBieSB0aGVcbiAqIHByb2R1Y2VyIGFuZCBmb3J3YXJkZWQgdmVyYmF0aW0gb24gYm90aCB0aGUgZGlyZWN0IGBob29rX3JlY2VpdmVkYCB3cml0ZSBhbmRcbiAqIHRoZSBxdWV1ZSBgaG9va0lucHV0YCwgc28gYm90aCB3cml0ZXJzIG9mIHRoZSBzYW1lIGByZXN1bWVJZGAgcmVjb3JkIGFuXG4gKiBpZGVudGljYWwgZGlnZXN0IG9uIHRoZSBzZXJ2ZXIncyBgKHJ1bklkLCByZXN1bWVJZClgIGNvbnN0cmFpbnQuIEhhc2hpbmcgdGhlXG4gKiBhbHJlYWR5LXNlcmlhbGl6ZWQgYnl0ZXMgKG5vdCB0aGUgcmF3IHZhbHVlKSBrZWVwcyBwcm9kdWNlciBhbmQgY29uc3VtZXIgaW5cbiAqIGxvY2tzdGVwIOKAlCB0aGUgY29uc3VtZXIgZm9yd2FyZHMgdGhpcyBzdHJpbmcgd2l0aG91dCByZWNvbXB1dGluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVJlc3VtZVBheWxvYWREaWdlc3QoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBkaWdlc3QgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRpZ2VzdCgnU0hBLTI1NicsIGJ5dGVzKTtcbiAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGRpZ2VzdCk7XG4gIGxldCBoZXggPSAnJztcbiAgZm9yIChjb25zdCBiIG9mIHZpZXcpIHtcbiAgICBoZXggKz0gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKTtcbiAgfVxuICByZXR1cm4gaGV4O1xufVxuXG4vKipcbiAqIFRoZSByZXN1bWUgY29udGV4dCBmb3IgYSBob29rIHBsdXMgd2hlcmUgaXQgY2FtZSBmcm9tLiBgcnVuYCBpcyBwcmVzZW50IG9ubHlcbiAqIG9uIHRoZSBmYWxsYmFjayBwYXRoIChwcmUtYHJlc3VtZUNvbnRleHRgIGhvb2tzKSwgd2hlcmUgaXQgYWxzbyBjYXJyaWVzIHRoZVxuICogcnVuJ3MgbXV0YWJsZSBzdGF0dXMgZm9yIHRoZSB0ZXJtaW5hbC1ydW4gY2hlY2suIEtleSByZXNvbHV0aW9uIGlzIGtlcHRcbiAqIHNlcGFyYXRlIHNvIGNhbGxlcnMgY2FuIGdhdGUgaXQgYmVoaW5kIHRoYXQgY2hlY2suXG4gKi9cbmludGVyZmFjZSBIb29rUmVzdW1lSW5mbyB7XG4gIHJlc3VtZUNvbnRleHQ6IEhvb2tSZXN1bWVDb250ZXh0O1xuICBzb3VyY2U6ICdob29rJyB8ICdydW5fZmFsbGJhY2snO1xuICBydW4/OiBXb3JrZmxvd1J1bjtcbn1cblxuLyoqIERlcml2ZSBhIHJlc3VtZSBjb250ZXh0IGZyb20gYSBmdWxsIHJ1biAoZmFsbGJhY2sgZm9yIHByZS1gcmVzdW1lQ29udGV4dGAgaG9va3MpLiAqL1xuZnVuY3Rpb24gcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuOiBXb3JrZmxvd1J1bik6IEhvb2tSZXN1bWVDb250ZXh0IHtcbiAgY29uc3QgY29yZVZlcnNpb24gPSBydW4uZXhlY3V0aW9uQ29udGV4dD8ud29ya2Zsb3dDb3JlVmVyc2lvbjtcbiAgY29uc3QgdHJhY2VDYXJyaWVyID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/LnRyYWNlQ2FycmllcjtcbiAgY29uc3QgaG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py5ob29rUmVzdW1lSW5wdXRWZXJzaW9uO1xuICByZXR1cm4ge1xuICAgIGRlcGxveW1lbnRJZDogcnVuLmRlcGxveW1lbnRJZCxcbiAgICB3b3JrZmxvd05hbWU6IHJ1bi53b3JrZmxvd05hbWUsXG4gICAgcnVuU3BlY1ZlcnNpb246IHJ1bi5zcGVjVmVyc2lvbixcbiAgICB3b3JrZmxvd0NvcmVWZXJzaW9uOlxuICAgICAgdHlwZW9mIGNvcmVWZXJzaW9uID09PSAnc3RyaW5nJyA/IGNvcmVWZXJzaW9uIDogdW5kZWZpbmVkLFxuICAgIHRyYWNlQ2FycmllcjpcbiAgICAgIHRyYWNlQ2FycmllciAmJiB0eXBlb2YgdHJhY2VDYXJyaWVyID09PSAnb2JqZWN0J1xuICAgICAgICA/ICh0cmFjZUNhcnJpZXIgYXMgSG9va1Jlc3VtZUNvbnRleHRbJ3RyYWNlQ2FycmllciddKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICBlbmNyeXB0aW9uUHVibGljS2V5OiBydW4uZW5jcnlwdGlvblB1YmxpY0tleSxcbiAgICBob29rUmVzdW1lSW5wdXRWZXJzaW9uOlxuICAgICAgdHlwZW9mIGhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPT09ICdudW1iZXInXG4gICAgICAgID8gaG9va1Jlc3VtZUlucHV0VmVyc2lvblxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHJlc3VtZSBjb250ZXh0IGZvciBhIGhvb2suIFVzZXMgdGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgd2hlblxuICogcHJlc2VudCAoZmFzdCBwYXRoIOKAlCBubyBydW4gcmVhZCk7IG90aGVyd2lzZSBmZXRjaGVzIHRoZSBydW4gYW5kIHN5bnRoZXNpemVzXG4gKiBpdC4gRG9lcyBOT1QgcmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXkg4oCUIGNhbGxlcnMgZG8gdGhhdCBzZXBhcmF0ZWx5LiBPbmx5XG4gKiB0aGUgZmFsbGJhY2sgcGF0aCBjYW4gZ2F0ZSBrZXkgd29yayBiZWhpbmQgYSBsb2NhbCB0ZXJtaW5hbC1ydW4gY2hlY2sgKGl0XG4gKiBoYXMgdGhlIGZldGNoZWQgcnVuKTsgdGhlIGZhc3QgcGF0aCdzIHN0b3JlZCBjb250ZXh0IGNhcnJpZXMgbm8gc3RhdHVzLCBzb1xuICogc2VhbC9zZXJpYWxpemF0aW9uIHdvcmsgbWF5IHJ1biBiZWZvcmUgdGhlIHJlY2VpdmluZyBzaWRlIHJlamVjdHNcbiAqIGBob29rX3JlY2VpdmVkYCBmb3IgYW4gZW5kZWQgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vazogSG9vayk6IFByb21pc2U8SG9va1Jlc3VtZUluZm8+IHtcbiAgaWYgKGhvb2sucmVzdW1lQ29udGV4dCkge1xuICAgIHJldHVybiB7IHJlc3VtZUNvbnRleHQ6IGhvb2sucmVzdW1lQ29udGV4dCwgc291cmNlOiAnaG9vaycgfTtcbiAgfVxuICBjb25zdCBydW4gPSBhd2FpdCAoYXdhaXQgZ2V0V29ybGRMYXp5KCkpLnJ1bnMuZ2V0KGhvb2sucnVuSWQpO1xuICByZXR1cm4ge1xuICAgIHJlc3VtZUNvbnRleHQ6IHJlc3VtZUNvbnRleHRGcm9tUnVuKHJ1biksXG4gICAgc291cmNlOiAncnVuX2ZhbGxiYWNrJyxcbiAgICBydW4sXG4gIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgcnVuJ3Mgc3ltbWV0cmljIGtleSBmb3IgYSBwYXlsb2FkIFdSSVRFLCBhcyBhIGJhcmUgYENyeXB0b0tleWBcbiAqIChgaW1wb3J0S2V5YCkg4oCUIHRoZSBgZW5jcmAgd3JpdGUgZmFsbGJhY2sgdXNlZCB3aGVuIHRoZSBydW4gcHVibGlzaGVkIG5vXG4gKiBwdWJsaWMga2V5IHRvIHNlYWwgdG8uIFdyaXRpbmcgbmVlZHMgb25seSB0aGUgQUVTIGtleSwgbm90IHRoZSByZWFkLXNpZGVcbiAqIGtleXBhaXIuIE9uIHRoZSBmYXN0IHBhdGggdGhpcyBuZWVkcyBvbmx5IGBydW5JZGAgKyBgZGVwbG95bWVudElkYCAobm8gcnVuXG4gKiBlbnRpdHkpOyBvbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUgYWxyZWFkeSBmZXRjaGVkIHJ1biBpcyByZXVzZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rRW5jcnlwdGlvbktleShcbiAgaG9vazogSG9vayxcbiAgaW5mbzogSG9va1Jlc3VtZUluZm9cbik6IFByb21pc2U8QXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBpbXBvcnRLZXk+PiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgID8gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGluZm8ucnVuKVxuICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgfSk7XG4gIHJldHVybiByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgaG9vazogSG9vaztcbiAgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgY29uc3QgaG9vayA9IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW4pO1xuXG4gIC8vIE9ubHkgYSBob29rIHRoYXQgYWN0dWFsbHkgY2FycmllcyBtZXRhZGF0YSBuZWVkcyB0aGUgcnVuJ3Mga2V5IHJlc29sdmVkXG4gIC8vIGhlcmU6IGh5ZHJhdGluZyB0aGF0IG1ldGFkYXRhIGlzIGEgUkVBRCwgc28gZGVyaXZlIHRoZSBmdWxsIFJ1blBheWxvYWRLZXlzXG4gIC8vICh3aGljaCBvcGVucyBzZWFsZWQgYGVuY3BgIG1ldGFkYXRhLCBub3QganVzdCBzeW1tZXRyaWMgYGVuY3JgKS4gVGhlIGNvbW1vblxuICAvLyBkZWZhdWx0IHdlYmhvb2sg4oCUIGNyZWF0ZVdlYmhvb2soKSB3aXRoIG5vIGByZXNwb25kV2l0aGAg4oCUIHN0b3JlcyBub1xuICAvLyBtZXRhZGF0YSwgc28gaXQgc2tpcHMgdGhpcyBlbnRpcmVseTogbm8gfjM1MG1zIGBydW4ta2V5YCBBUEkgcm91bmQgdHJpcCxcbiAgLy8gYW5kLCBjcnVjaWFsbHksIG5vIHJlc29sdmVkIGtleSBoYW5kZWQgdG8gYHJlc3VtZUhvb2tgLCBsZWF2aW5nIGl0IGZyZWUgdG9cbiAgLy8gc2VhbCB0aGUgcGF5bG9hZCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIHB1YmxpYyBrZXkgaW5zdGVhZC4gTWV0YWRhdGEtXG4gIC8vIGJlYXJpbmcgd2ViaG9va3Mgc3RpbGwgbGVnaXRpbWF0ZWx5IHBheSBvbmUgbG9va3VwIHRvIGh5ZHJhdGUuXG4gIGxldCBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIGhvb2subWV0YWRhdGEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgY29uc3QgaW5mbyA9IGF3YWl0IHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rKTtcbiAgICAvLyBPbiB0aGUgZmFzdCBwYXRoIHRoaXMgcmVzb2x2ZXMgdGhlIGtleSBieSBydW5JZCArIGRlcGxveW1lbnRJZCAobm8gcnVuXG4gICAgLy8gcmVhZCk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIGl0IHJldXNlcyB0aGUgYWxyZWFkeS1mZXRjaGVkIHJ1bi5cbiAgICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgICA6IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/Lihob29rLnJ1bklkLCB7XG4gICAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICB9KTtcbiAgICBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgZGVyaXZlUnVuUGF5bG9hZEtleXMocmF3S2V5KSA6IHVuZGVmaW5lZDtcbiAgICBob29rLm1ldGFkYXRhID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICBob29rLm1ldGFkYXRhIGFzIGFueSxcbiAgICAgIGhvb2sucnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5XG4gICAgKTtcbiAgfVxuICByZXR1cm4geyBob29rLCBlbmNyeXB0aW9uS2V5IH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBob29rIGJ5IHRva2VuIHRvIGZpbmQgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLFxuICogYW5kIGh5ZHJhdGUgdGhlIGBtZXRhZGF0YWAgcHJvcGVydHkgaWYgaXQgd2FzIHNldCBmcm9tIHdpdGhpblxuICogdGhlIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBBIEhvb2sga2VwdCBieSBtaW5pbXVtIHJldGVudGlvbiByZW1haW5zIGF2YWlsYWJsZSBoZXJlIGFmdGVyIGl0cyBydW4gZW5kcyxcbiAqIGJ1dCBjYW5ub3QgYmUgcmVzdW1lZC5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxIb29rPiB7XG4gIGNvbnN0IHsgaG9vayB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcbiAgcmV0dXJuIGhvb2s7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgcmVzdW1lSG9va306IGEge0BsaW5rIEhvb2t9IGF1Z21lbnRlZCB3aXRoIGFuIG9wdGlvbmFsXG4gKiByZXNpbGllbmNlIHNpZ25hbC5cbiAqXG4gKiBPbiB0aGUgcGFyYWxsZWwgZmFzdCBwYXRoLCBgcmVzdW1lSG9vaygpYCB3cml0ZXMgdGhlIGBob29rX3JlY2VpdmVkYCBldmVudCBhbmRcbiAqIGRpc3BhdGNoZXMgdGhlIHdvcmtmbG93IHF1ZXVlIG1lc3NhZ2UgY29uY3VycmVudGx5LiBXaGVuIHRoZSBkaXJlY3QgZXZlbnRcbiAqIHdyaXRlIGZhaWxzICp0cmFuc2llbnRseSog4oCUIGEgNDI5LzV4eCwgYSB0cmFuc3BvcnQgZXJyb3IsIG9yIGFuIGV4cGVjdGVkXG4gKiBgKHJ1bklkLCByZXN1bWVJZClgIGNvbmZsaWN0IHdpdGggaXRzIG93biByZS1lbnN1cmluZyBjb25zdW1lciDigJQgYnV0IHRoZSBxdWV1ZVxuICogZGlzcGF0Y2ggc3VjY2VlZHMsIHRoZSByZXN1bWUgaXMgc3RpbGwgZ3VhcmFudGVlZDogdGhlIHF1ZXVlIGNvbnN1bWVyXG4gKiBpZGVtcG90ZW50bHkgbWF0ZXJpYWxpemVzIHRoZSBgaG9va19yZWNlaXZlZGAgZXZlbnQgZnJvbSB0aGUgcGF5bG9hZCBjYXJyaWVkXG4gKiBvbiB0aGUgbWVzc2FnZSBiZWZvcmUgcmVwbGF5LiBJbiB0aGF0IHJlY292ZXJlZCBjYXNlIHRoZSByZXR1cm5lZCBob29rIGNhcnJpZXNcbiAqIGByZXNpbGllbnRSZXN1bWU6IHRydWVgLlxuICpcbiAqIE9uIHRoZSBoYXBweSBwYXRoICh0aGUgZGlyZWN0IHdyaXRlIGxhbmRlZCkgYW5kIG9uIHRoZSBzZXF1ZW50aWFsIGZhbGxiYWNrXG4gKiBwYXRoLCB0aGUgZmxhZyBpcyBhYnNlbnQgKGB1bmRlZmluZWRgKS4gQ2FsbGVycyB0aGF0IGRvbid0IGNhcmUgYWJvdXQgdGhlXG4gKiBkaXN0aW5jdGlvbiBjYW4gdHJlYXQgdGhlIHJlc3VsdCBhcyBhIHBsYWluIHtAbGluayBIb29rfS5cbiAqL1xuZXhwb3J0IHR5cGUgUmVzdW1lZEhvb2sgPSBIb29rICYgeyByZXNpbGllbnRSZXN1bWU/OiBib29sZWFuIH07XG5cbi8qKlxuICogUmVzdW1lcyBhIHdvcmtmbG93IHJ1biBieSBzZW5kaW5nIGEgcGF5bG9hZCB0byBhIGhvb2sgaWRlbnRpZmllZCBieSBpdHMgdG9rZW4uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXh0ZXJuYWxseSAoZS5nLiwgZnJvbSBhbiBBUEkgcm91dGUgb3Igc2VydmVyIGFjdGlvbilcbiAqIHRvIHNlbmQgZGF0YSB0byBhIGhvb2sgYW5kIHJlc3VtZSB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4uXG4gKlxuICogQHBhcmFtIHRva2VuT3JIb29rIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9vaywgb3IgdGhlIGhvb2sgb2JqZWN0IGl0c2VsZlxuICogQHBhcmFtIHBheWxvYWQgLSBUaGUgZGF0YSBwYXlsb2FkIHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB7QGxpbmsgUmVzdW1lZEhvb2t9XG4gKiBAdGhyb3dzIHtIb29rTm90Rm91bmRFcnJvcn0gSWYgdGhlIEhvb2sgZG9lcyBub3QgZXhpc3Qgb3IgaXRzIHJ1biBoYXMgZW5kZWRcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYHRzXG4gKiAvLyBJbiBhbiBBUEkgcm91dGVcbiAqIGltcG9ydCB7IHJlc3VtZUhvb2sgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG4gKiAgIGNvbnN0IHsgdG9rZW4sIGRhdGEgfSA9IGF3YWl0IHJlcXVlc3QuanNvbigpO1xuICpcbiAqICAgdHJ5IHtcbiAqICAgICBjb25zdCBob29rID0gYXdhaXQgcmVzdW1lSG9vayh0b2tlbiwgZGF0YSk7XG4gKiAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oeyBydW5JZDogaG9vay5ydW5JZCB9KTtcbiAqICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdIb29rIG5vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDQgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdW1lSG9vazxUID0gYW55PihcbiAgdG9rZW5Pckhvb2s6IHN0cmluZyB8IEhvb2ssXG4gIHBheWxvYWQ6IFQsXG4gIGVuY3J5cHRpb25LZXlPdmVycmlkZT86IFBheWxvYWRLZXlcbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgLy8gUHVibGljIGVudHJ5IHBvaW50LiBJdCBuZXZlciBhdHRlc3RzIGhvb2sgZnJlc2huZXNzLCBzbyBhIEhvb2sgb2JqZWN0XG4gIC8vIHN1cHBsaWVkIGhlcmUg4oCUIHdoaWNoIG1heSBjYXJyeSBhIGByZXN1bWVDYXBhYmlsaXRpZXNgIGNhY2hlZCBiZWZvcmUgYVxuICAvLyBzZXJ2ZXIgcm9sbGJhY2sgb3Iga2lsbCBzd2l0Y2gg4oCUIGlzIGlnbm9yZWQgYnkgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZSBhbmRcbiAgLy8gZmFpbHMgY2xvc2VkIHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguIE9ubHkgYHJlc3VtZVdlYmhvb2tgLCB3aGljaCBmZXRjaGVzXG4gIC8vIHRoZSBob29rIGJ5IHRva2VuIGluLWxpbmUgZHVyaW5nIHRoZSBzYW1lIHJlc3VtZSwgcmVhY2hlcyB0aGUgaW50ZXJuYWxcbiAgLy8gaW1wbGVtZW50YXRpb24gd2l0aCB0aGUgZnJlc2ggYXR0ZXN0YXRpb24gc2V0LiBLZWVwaW5nIHRoZSBmcmVzaG5lc3MgZmxhZ1xuICAvLyBvZmYgdGhlIGV4cG9ydGVkIHNpZ25hdHVyZSBwcmV2ZW50cyBhIGNhbGxlciBmcm9tIHBhc3NpbmcgYSBzdGFsZSBIb29rIHBsdXNcbiAgLy8gYHRydWVgIGFuZCByZWFjdGl2YXRpbmcgZHluYW1pYyBkZWR1cCBhZ2FpbnN0IGEgcm9sbGVkLWJhY2sgYmFja2VuZC5cbiAgcmV0dXJuIHJlc3VtZUhvb2tJbXBsKHRva2VuT3JIb29rLCBwYXlsb2FkLCBlbmNyeXB0aW9uS2V5T3ZlcnJpZGUsIGZhbHNlKTtcbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiB7QGxpbmsgcmVzdW1lSG9va30uIE5PVCBleHBvcnRlZDogdGhlXG4gKiBgaG9va0ZyZXNobHlMb29rZWRVcGAgYXR0ZXN0YXRpb24gbXVzdCBuZXZlciBiZSByZWFjaGFibGUgYnkgcHVibGljIGNhbGxlcnNcbiAqIChzZWUgdGhlIHdyYXBwZXIgYWJvdmUpLlxuICpcbiAqIEBwYXJhbSBob29rRnJlc2hseUxvb2tlZFVwIC0gQXR0ZXN0cyB0aGF0IGEgc3VwcGxpZWQgSG9vayBvYmplY3Qgd2FzIGZldGNoZWRcbiAqICAgYnkgdG9rZW4gZHVyaW5nIFRISVMgcmVzdW1lLCBzbyBpdHMgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYFxuICogICByZWZsZWN0cyB0aGUgbGl2ZSBiYWNrZW5kIGFuZCBtYXkgYmUgdHJ1c3RlZCBmb3IgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZS5cbiAqICAgQSB0b2tlbiBzdHJpbmcgaXMgYWx3YXlzIGZldGNoZWQgZnJlc2ggaGVyZSwgc28gaXQgaXMgaW1wbGljaXRseSBmcmVzaC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzdW1lSG9va0ltcGw8VCA9IGFueT4oXG4gIHRva2VuT3JIb29rOiBzdHJpbmcgfCBIb29rLFxuICBwYXlsb2FkOiBULFxuICBlbmNyeXB0aW9uS2V5T3ZlcnJpZGU6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQsXG4gIGhvb2tGcmVzaGx5TG9va2VkVXA6IGJvb2xlYW5cbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICByZXR1cm4gdHJhY2UoJ2hvb2sucmVzdW1lJywgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN1cHBsaWVkVG9rZW4gPSB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnO1xuICAgICAgICBjb25zdCBob29rOiBIb29rID0gc3VwcGxpZWRUb2tlblxuICAgICAgICAgID8gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbk9ySG9vaylcbiAgICAgICAgICA6IHRva2VuT3JIb29rO1xuICAgICAgICAvLyBUaGUgZHluYW1pYywgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCBtYXkgb25seSBiZSB0cnVzdGVkXG4gICAgICAgIC8vIHdoZW4gaXQgY2FtZSBmcm9tIGEgYnktdG9rZW4gbG9va3VwIHBlcmZvcm1lZCBkdXJpbmcgdGhpcyByZXN1bWUuXG4gICAgICAgIGNvbnN0IGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaCA9XG4gICAgICAgICAgc3VwcGxpZWRUb2tlbiB8fCBob29rRnJlc2hseUxvb2tlZFVwO1xuXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vayk7XG4gICAgICAgIGNvbnN0IHsgcmVzdW1lQ29udGV4dCB9ID0gaW5mbztcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9jb250ZXh0X3NvdXJjZSc6IGluZm8uc291cmNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUaGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBpbnRlbnRpb25hbGx5IG9taXRzIHRoZSBydW4ncyBtdXRhYmxlXG4gICAgICAgIC8vIHN0YXR1cywgc28gdGhpcyBlYXJseSBjbGllbnQtc2lkZSByZWplY3Rpb24gb25seSBydW5zIG9uIHRoZVxuICAgICAgICAvLyBmYWxsYmFjayBwYXRoICh3aGljaCBmZXRjaGVkIHRoZSBydW4pLiBPbiB0aGUgZmFzdCBwYXRoIHRoZSB0ZXJtaW5hbFxuICAgICAgICAvLyBjaGVjayBoYXBwZW5zIHNlcnZlci1zaWRlOiBgaG9va19yZWNlaXZlZGAgYWdhaW5zdCBhbiBlbmRlZCBydW4gaXNcbiAgICAgICAgLy8gcmVqZWN0ZWQsIHdoaWNoIHRoZSBjYXRjaCBhcm91bmQgYHdvcmxkLmV2ZW50cy5jcmVhdGVgIGJlbG93IHJlLWtleXNcbiAgICAgICAgLy8gdG8gSG9va05vdEZvdW5kRXJyb3Ig4oCUIHNhbWUgcHVibGljIGNvbnRyYWN0LCBubyBydW4gcHJlLWZldGNoLlxuICAgICAgICBpZiAoaW5mby5ydW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGluZm8ucnVuLnN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LCBhbmQgcnVucyBjcmVhdGVkIGJlZm9yZVxuICAgICAgICAvLyBieXRlLXN0cmVhbSBmcmFtaW5nIHN1cHBvcnQgY2Fubm90IGRlY29kZSBmcmFtZWQgYnl0ZSBzdHJlYW1zLlxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgcmVzdW1lQ29udGV4dC53b3JrZmxvd0NvcmVWZXJzaW9uXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBob3cgdG8gZW5jcnlwdCB0aGUgcGF5bG9hZCBmb3IgdGhlIHRhcmdldCBydW4gKGEgV1JJVEUpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBQcmVmZXJyZWQgcGF0aDogc2VhbCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIFgyNTUxOSBwdWJsaWMga2V5LCB3aGljaFxuICAgICAgICAvLyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBjYXJyaWVzIGlubGluZS4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIGlzXG4gICAgICAgIC8vIHRoZSB3aG9sZSB3aW4g4oCUIG5vIHJ1biByZWFkIEFORCBubyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdob3NlXG4gICAgICAgIC8vIH4zNTBtcyBgcnVuLWtleWAgQVBJIHJvdW5kIHRyaXAgZG9taW5hdGVzIGNyb3NzLWRlcGxveW1lbnQgaG9va1xuICAgICAgICAvLyByZXN1bXB0aW9uIGxhdGVuY3kuIChPbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUga2V5IGlzIHN5bnRoZXNpemVkXG4gICAgICAgIC8vIGZyb20gdGhlIGZldGNoZWQgcnVuLCB3aGljaCBhbHNvIGNhcnJpZXMgaXQuKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWFsaW5nIGFsc28gZHJvcHMgcHJpdmlsZWdlOiB0aGUgcmVzdW1lciBlbmRzIHVwIGFibGUgdG8gd3JpdGUgYVxuICAgICAgICAvLyBwYXlsb2FkIGZvciB0aGUgcnVuIHdpdGhvdXQgYmVpbmcgYWJsZSB0byByZWFkIGFueXRoaW5nIG9mIHRoZVxuICAgICAgICAvLyBydW4ncywgd2hlcmUgZmV0Y2hpbmcgdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGJvdGguXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlbGliZXJhdGVseSBOT1QgZ2F0ZWQgb24gYGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzYCB0aGUgd2F5XG4gICAgICAgIC8vIHRoZSBzeW1tZXRyaWMgZmFsbGJhY2sgYmVsb3cgZ2F0ZXMgYGVuY3JgOiBwcmVzZW5jZSBvZiB0aGUgcHVibGljIGtleVxuICAgICAgICAvLyBpcyBpdHNlbGYgdGhlIGdhdGUuIEEgcnVuIG9ubHkgY2FycmllcyBvbmUgaWYgdGhlIHJ1bnRpbWUgdGhhdFxuICAgICAgICAvLyBjcmVhdGVkIGl0IGNvdWxkIGFsc28gb3BlbiBhIHNlYWxlZCBwYXlsb2FkLCBhbmQgcnVucyBhcmUgcGlubmVkIHRvXG4gICAgICAgIC8vIHRoZWlyIGNyZWF0aW5nIGRlcGxveW1lbnQsIHNvIHByZXNlbmNlIGlzIGEgbW9yZSByZWxpYWJsZSBhdHRlc3RhdGlvblxuICAgICAgICAvLyB0aGFuIGEgdmVyc2lvbiBjb21wYXJlIOKAlCBhbmQgaXQgc3RheXMgY29ycmVjdCBldmVuIHdoZW4gcGFja2FnZVxuICAgICAgICAvLyB2ZXJzaW9ucyBkcmlmdC5cbiAgICAgICAgbGV0IHBheWxvYWRLZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJ1blB1YmxpY0tleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZVxuICAgICAgICAgID8gLy8gVGhlIGNhbGxlciBhbHJlYWR5IGhvbGRzIGEga2V5IChyZXN1bWVXZWJob29rIHJlc29sdmVkIG9uZSB0b1xuICAgICAgICAgICAgLy8gaHlkcmF0ZSBob29rIG1ldGFkYXRhKSwgc28gc2VhbGluZyB3b3VsZCBhZGQgYW4gRUNESCBmb3Igbm9cbiAgICAgICAgICAgIC8vIHNhdmVkIHJvdW5kIHRyaXAuIFJldXNlIHdoYXQgaXQgcmVzb2x2ZWQuXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICA6IGRlY29kZVJ1blB1YmxpY0tleShyZXN1bWVDb250ZXh0LmVuY3J5cHRpb25QdWJsaWNLZXkpO1xuXG4gICAgICAgIGlmIChydW5QdWJsaWNLZXkpIHtcbiAgICAgICAgICBwYXlsb2FkS2V5ID0gc2VhbFRvKHJ1blB1YmxpY0tleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3ltbWV0cmljIGBlbmNyYCB3cml0ZSBmYWxsYmFjazogbmVlZHMgb25seSB0aGUgQUVTIGtleVxuICAgICAgICAgIC8vIChhIGJhcmUgQ3J5cHRvS2V5IHZpYSBgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5YCksIG5vdCB0aGVcbiAgICAgICAgICAvLyByZWFkLXNpZGUgUnVuUGF5bG9hZEtleXMuXG4gICAgICAgICAgbGV0IGVuY3J5cHRpb25LZXkgPVxuICAgICAgICAgICAgZW5jcnlwdGlvbktleU92ZXJyaWRlID8/XG4gICAgICAgICAgICAoYXdhaXQgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KGhvb2ssIGluZm8pKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhY2FwYWJpbGl0aWVzLnN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF5bG9hZEtleSA9IGVuY3J5cHRpb25LZXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wcmVzcyBvbmx5IHdoZW4gdGhlIHRhcmdldCBydW4gYW5kIGl0cyBkZXBsb3ltZW50IHN1cHBvcnQgdGhlXG4gICAgICAgIC8vIGNvbXByZXNzaW9uIGZvcm1hdHMgaW50cm9kdWNlZCB3aXRoIHNwZWMgdmVyc2lvbiA1LlxuICAgICAgICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgICAgICAgKHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTiAmJlxuICAgICAgICAgIGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVApO1xuXG4gICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihob29rLnNwZWNWZXJzaW9uKTtcbiAgICAgICAgY29uc3QgZGVoeWRyYXRlZFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcGF5bG9hZCxcbiAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgIHBheWxvYWRLZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgdjFDb21wYXQsXG4gICAgICAgICAgY2FwYWJpbGl0aWVzLmZyYW1lZEJ5dGVTdHJlYW1zLFxuICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICk7XG4gICAgICAgIC8vIFRoZXNlIHBheWxvYWQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIC8vIE5PVEU6IHJlamVjdGlvbnMgd2l0aCBgdW5kZWZpbmVkYCBhcmUgYW4gZXhwZWN0ZWQgYXJ0aWZhY3Qgb2YgdGhlXG4gICAgICAgIC8vIHdlYmhvb2sgYnVuZGxlIGFuZCBhcmUgaWdub3JlZCBlbnRpcmVseS5cbiAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyciA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdCYWNrZ3JvdW5kIGZsdXNoIG9mIGhvb2sgcGF5bG9hZCBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTGluayB0byB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHN0b3JlZCB0cmFjZSBjYXJyaWVyXG4gICAgICAgIC8vIChza2lwcGVkIHdoZW4gYWJzZW50IG9yIGludmFsaWQpLiBSZXNvbHZlZCBiZWZvcmUgZGlzcGF0Y2ggc28gYm90aFxuICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBhbmQgcGFyYWxsZWwgcGF0aHMgYXR0YWNoIGl0LlxuICAgICAgICBjb25zdCBvcmlnaW5MaW5rID0gYXdhaXQgbGlua1RvVHJhY2VDYXJyaWVyKHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyKTtcbiAgICAgICAgaWYgKG9yaWdpbkxpbmspIHtcbiAgICAgICAgICBzcGFuPy5hZGRMaW5rPy4ob3JpZ2luTGluayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBldmVudERhdGEgPSB7XG4gICAgICAgICAgLi4uKHYxQ29tcGF0ID8ge30gOiB7IHRva2VuOiBob29rLnRva2VuIH0pLFxuICAgICAgICAgIHBheWxvYWQ6IGRlaHlkcmF0ZWRQYXlsb2FkLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHF1ZXVlTmFtZSA9IGdldFdvcmtmbG93UXVldWVOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKTtcbiAgICAgICAgY29uc3QgcXVldWVPcHRpb25zID0ge1xuICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBEZWNpZGUgd2hldGhlciB0byBwYXJhbGxlbGl6ZSB0aGUgYGhvb2tfcmVjZWl2ZWRgIHdyaXRlIGFuZCB0aGUgcXVldWVcbiAgICAgICAgLy8gcHVibGlzaC4gVGhlIGZhc3QgcGF0aCBpcyBvbmx5IHNhZmUgd2hlbiBFVkVSWSBwcmVjb25kaXRpb24gaG9sZHM7IHRoZVxuICAgICAgICAvLyBmaXJzdCB0aGF0IGZhaWxzIG5hbWVzIHRoZSBmYWxsYmFjayByZWFzb24gKGVtaXR0ZWQgYXMgYSBzcGFuXG4gICAgICAgIC8vIGF0dHJpYnV0ZSBmb3Igb2JzZXJ2YWJpbGl0eSwgYW5kIHRvIG1ha2UgXCJ3aHkgZGlkIHRoaXMgcnVuIHNlcXVlbnRpYWxcIlxuICAgICAgICAvLyBhbnN3ZXJhYmxlIGluIHByb2R1Y3Rpb24pLiBBbGwgY29uZGl0aW9uczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gIC0ga2lsbCBzd2l0Y2g6IGBXT1JLRkxPV19ESVNBQkxFX0xBWllfSE9PS19SRVNVTUVgIGZvcmNlcyBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgIGlmIHRoZSBmYXN0IHBhdGggZXZlciBtaXNiZWhhdmVzLiBJdCBpcyBhbiBTREstZGVwbG95bWVudCBlbnYgdmFyLFxuICAgICAgICAvLyAgICBzbyBjaGFuZ2luZyBpdCBnZW5lcmFsbHkgcmVxdWlyZXMgcmVkZXBsb3lpbmcgdGhlIHdvcmtmbG93XG4gICAgICAgIC8vICAgIGRlcGxveW1lbnQuIChUaGUgYmFja2VuZCBjYW4gaW5kZXBlbmRlbnRseSBkcm9wIG5ldyByZXN1bWVzIHRvIHRoZVxuICAgICAgICAvLyAgICBzZXF1ZW50aWFsIHBhdGggZmxlZXQtd2lkZSBieSBjZWFzaW5nIHRvIGF0dGVzdCBkZWR1cCBzdXBwb3J0IG9uXG4gICAgICAgIC8vICAgIHRoZSBieS10b2tlbiBsb29rdXAg4oCUIHNlZSB0aGUgYmFja2VuZC1kZWR1cCBjb25kaXRpb24gYmVsb3cuKVxuICAgICAgICAvLyAgLSBiYWNrZW5kIGRlZHVwOiB0aGUgbGl2ZSBiYWNrZW5kIG11c3QgZW5mb3JjZSB0aGVcbiAgICAgICAgLy8gICAgYChydW5JZCwgcmVzdW1lSWQpYCBjb25zdHJhaW50LCBvciB0aGUgdHdvIHdyaXRlcnMgd291bGQgY29tbWl0IHR3b1xuICAgICAgICAvLyAgICBgaG9va19yZWNlaXZlZGAgZXZlbnRzLiBGYWlsIGNsb3NlZC4gQXR0ZXN0ZWQgYnkgRUlUSEVSIGEgZnJlc2gsXG4gICAgICAgIC8vICAgIHJlc3BvbnNlLW9ubHkgYGhvb2sucmVzdW1lQ2FwYWJpbGl0aWVzLmhvb2tSZXN1bWVEZWR1cFZlcnNpb25gIGZyb21cbiAgICAgICAgLy8gICAgdGhlIGJ5LXRva2VuIGxvb2t1cCAod29ybGQtdmVyY2VsIOKAlCByZWNvbXB1dGVkIGV2ZXJ5IHJlYWQsIHNvIGFcbiAgICAgICAgLy8gICAgc2VydmVyIHJvbGxiYWNrIG9yIGtpbGwgc3dpdGNoIGRyb3BzIHRvIHNlcXVlbnRpYWwgaW1tZWRpYXRlbHkpIE9SXG4gICAgICAgIC8vICAgIHRoZSBzdGF0aWMgYHdvcmxkLmNhcGFiaWxpdGllcy5ob29rUmVzdW1lRGVkdXBgICh3b3JsZC1sb2NhbCwgd2hvc2VcbiAgICAgICAgLy8gICAgYWRhcHRlciBhbmQgYmFja2VuZCBzaGlwIHRvZ2V0aGVyKS4gVGhlIHJlc3BvbnNlLW9ubHkgY2FwYWJpbGl0eSBpc1xuICAgICAgICAvLyAgICB0cnVzdGVkIE9OTFkgd2hlbiB0aGUgaG9vayB3YXMgbG9va2VkIHVwIGJ5IHRva2VuIGR1cmluZyB0aGlzXG4gICAgICAgIC8vICAgIHJlc3VtZSAoYGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaGApOyBhIEhvb2sgb2JqZWN0IGhhbmRlZCBpblxuICAgICAgICAvLyAgICBieSBhIHB1YmxpYyBjYWxsZXIgbWF5IGNhcnJ5IGEgY2FwYWJpbGl0eSBjYWNoZWQgYmVmb3JlIGEgcm9sbGJhY2ssXG4gICAgICAgIC8vICAgIHNvIGl0IGlzIGlnbm9yZWQgYW5kIHRoZSBwYXRoIGZhbGxzIGJhY2sgdG8gc2VxdWVudGlhbC5cbiAgICAgICAgLy8gIC0gY29uc3VtZXIgc3VwcG9ydDogdGhlIHRhcmdldCBydW4ncyBkZXBsb3ltZW50IG11c3QgcmUtZW5zdXJlIHRoZVxuICAgICAgICAvLyAgICBldmVudCBmcm9tIGBob29rSW5wdXRgIG9uIHJlcGxheS4gQXR0ZXN0ZWQgYnkgdGhlIHJ1bidzIGV4cGxpY2l0XG4gICAgICAgIC8vICAgIGBob29rUmVzdW1lSW5wdXRWZXJzaW9uYCBleGVjdXRpb24tY29udGV4dCBtYXJrZXIgKG1pcnJvcmVkIG9udG9cbiAgICAgICAgLy8gICAgcmVzdW1lQ29udGV4dCksIE5PVCBhIHZlcnNpb24tY29tcGFyZSBhZ2FpbnN0IGEgcHJlZGljdGVkIHJlbGVhc2VcbiAgICAgICAgLy8gICAgY3V0b2ZmLiBBYnNlbnQg4oaSIGEgbG9zdCBwcm9kdWNlciB3cml0ZSB3b3VsZCBiZSBhIGxvc3QgcmVzdW1lLlxuICAgICAgICAvLyAgLSBub3QgbGVnYWN5OiB2MUNvbXBhdCBydW5zIG9taXQgYHRva2VuYCBmcm9tIHRoZSBwcm9kdWNlcidzIGV2ZW50XG4gICAgICAgIC8vICAgIGJvZHkgYnV0IHRoZSBjb25zdW1lcidzIHJlLWVuc3VyZSBhbHdheXMgaW5jbHVkZXMgaXQsIHNvIHRoZSB0d29cbiAgICAgICAgLy8gICAgd3JpdGVycyB3b3VsZCBkaXNhZ3JlZSBvbiB0aGUgZXZlbnQgYm9keS4gTGVnYWN5IHN0YXlzIHNlcXVlbnRpYWwuXG4gICAgICAgIC8vICAtIENCT1IgdHJhbnNwb3J0OiB0aGUgcnVuIG11c3QgdXNlIENCT1IgcXVldWUgdHJhbnNwb3J0IHNvIHRoZSBiaW5hcnlcbiAgICAgICAgLy8gICAgcGF5bG9hZCBzdXJ2aXZlcyB0aGUgcXVldWUgbWVzc2FnZS5cbiAgICAgICAgLy8gIC0gcmF3IGJ5dGVzOiB0aGUgZGVoeWRyYXRlZCBwYXlsb2FkIG11c3QgYmUgYSBgVWludDhBcnJheWAgKHRoZVxuICAgICAgICAvLyAgICBjb250ZW50IGRpZ2VzdCB0aGF0IGtleXMgdGhlIGRlZHVwIGNvbnN0cmFpbnQgaXMgb3ZlciB0aGVzZSBieXRlcykuXG4gICAgICAgIC8vICAtIHNpemU6IGEgcGF5bG9hZCBhYm92ZSB0aGUgcXVldWUncyBtZXNzYWdlIGNlaWxpbmcgd291bGQgZmFpbCB0aGVcbiAgICAgICAgLy8gICAgcHVibGlzaCDigJQgd2hpY2gsIG9uIHRoZSBwYXJhbGxlbCBwYXRoLCB3b3VsZCBwZXJzaXN0IHRoZSBldmVudCBidXRcbiAgICAgICAgLy8gICAgbmV2ZXIgcmUtdHJpZ2dlciB0aGUgcnVuIOKAlCBzbyBvdmVyc2l6ZWQgcGF5bG9hZHMgc3RheSBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgICh0aGVpciBxdWV1ZSBtZXNzYWdlIGNhcnJpZXMgb25seSB0aGUgcnVuIElEKS5cbiAgICAgICAgY29uc3QgcGFyYWxsZWxSZXN1bWVEaXNhYmxlZCA9XG4gICAgICAgICAgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfRElTQUJMRV9MQVpZX0hPT0tfUkVTVU1FID09PSAnMSc7XG4gICAgICAgIC8vIEJhY2tlbmQgZGVkdXAgaXMgc3VwcG9ydGVkIHdoZW4gRUlUSEVSIHRoZSBsaXZlIHNlcnZlciBhdHRlc3RzIGl0XG4gICAgICAgIC8vIGZyZXNoIG9uIHRoaXMgYnktdG9rZW4gaG9vayAod29ybGQtdmVyY2VsOiByZXNwb25zZS1vbmx5LCByZWNvbXB1dGVkXG4gICAgICAgIC8vIGV2ZXJ5IHJlYWQsIHNvIHJvbGxiYWNrL2tpbGwtc3dpdGNoIHRha2UgZWZmZWN0IGltbWVkaWF0ZWx5KSBPUiB0aGVcbiAgICAgICAgLy8gc3RhdGljIHdvcmxkIGNhcGFiaWxpdHkgaXMgc2V0ICh3b3JsZC1sb2NhbDogYWRhcHRlciArIGJhY2tlbmQgc2hpcFxuICAgICAgICAvLyB0b2dldGhlcikuIEJvdGggYXJlIHJlLWV2YWx1YXRlZCBwZXIgcmVzdW1lLCBzbyBldmVyeSByb2xsb3V0IGFuZFxuICAgICAgICAvLyByb2xsYmFjayBkaXJlY3Rpb24gZGVncmFkZXMgc2FmZWx5IHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguXG4gICAgICAgIGNvbnN0IGJhY2tlbmREZWR1cFN1cHBvcnRlZCA9XG4gICAgICAgICAgKGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaFxuICAgICAgICAgICAgPyAoaG9vay5yZXN1bWVDYXBhYmlsaXRpZXM/Lmhvb2tSZXN1bWVEZWR1cFZlcnNpb24gPz8gMClcbiAgICAgICAgICAgIDogMCkgPj0gSE9PS19SRVNVTUVfREVEVVBfVkVSU0lPTiB8fFxuICAgICAgICAgIHdvcmxkLmNhcGFiaWxpdGllcz8uaG9va1Jlc3VtZURlZHVwID09PSB0cnVlO1xuICAgICAgICBjb25zdCBmYWxsYmFja1JlYXNvbjogc3RyaW5nIHwgbnVsbCA9IHBhcmFsbGVsUmVzdW1lRGlzYWJsZWRcbiAgICAgICAgICA/ICdkaXNhYmxlZCdcbiAgICAgICAgICA6ICFiYWNrZW5kRGVkdXBTdXBwb3J0ZWRcbiAgICAgICAgICAgID8gJ2JhY2tlbmRfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICA6IChyZXN1bWVDb250ZXh0Lmhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPz8gMCkgPFxuICAgICAgICAgICAgICAgIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT05cbiAgICAgICAgICAgICAgPyAnY29uc3VtZXJfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICAgIDogdjFDb21wYXRcbiAgICAgICAgICAgICAgICA/ICdsZWdhY3knXG4gICAgICAgICAgICAgICAgOiAocmVzdW1lQ29udGV4dC5ydW5TcGVjVmVyc2lvbiA/PyAwKSA8XG4gICAgICAgICAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVFxuICAgICAgICAgICAgICAgICAgPyAnbm9uX2Nib3JfdHJhbnNwb3J0J1xuICAgICAgICAgICAgICAgICAgOiAhKGRlaHlkcmF0ZWRQYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheSlcbiAgICAgICAgICAgICAgICAgICAgPyAnbm9uX2J5dGVzJ1xuICAgICAgICAgICAgICAgICAgICA6IGRlaHlkcmF0ZWRQYXlsb2FkLmJ5dGVMZW5ndGggPlxuICAgICAgICAgICAgICAgICAgICAgICAgTUFYX0lOTElORV9SRVNVTUVfUEFZTE9BRF9CWVRFU1xuICAgICAgICAgICAgICAgICAgICAgID8gJ292ZXJzaXplZCdcbiAgICAgICAgICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGNvbnN0IHVzZVBhcmFsbGVsUmVzdW1lID0gZmFsbGJhY2tSZWFzb24gPT09IG51bGw7XG5cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX3N0cmF0ZWd5JzogdXNlUGFyYWxsZWxSZXN1bWVcbiAgICAgICAgICAgID8gJ3BhcmFsbGVsJ1xuICAgICAgICAgICAgOiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgLi4uKGZhbGxiYWNrUmVhc29uXG4gICAgICAgICAgICA/IHsgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2ZhbGxiYWNrX3JlYXNvbic6IGZhbGxiYWNrUmVhc29uIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBSZS1rZXkgYW55IFwiaG9vayBjYW4gbm8gbG9uZ2VyIGJlIHJlY2VpdmVkXCIgcmVqZWN0aW9uIHRvXG4gICAgICAgIC8vIEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pIHNvIGAudG9rZW5gIG1hdGNoZXMgdGhlIHByZS1mYXN0LXBhdGhcbiAgICAgICAgLy8gY29udHJhY3QsIHdoZXJlIHJlc3VtZUhvb2sgdGhyZXcgYEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pYFxuICAgICAgICAvLyBhZnRlciBpdHMgb3duIHRlcm1pbmFsIGNoZWNrLiBUaGUgc3BlY2lmaWMgZXJyb3IgZGVwZW5kcyBvbiB0aGVcbiAgICAgICAgLy8gV29ybGQ6XG4gICAgICAgIC8vICAgLSBhIGdlbnVpbmVseSBtaXNzaW5nIGhvb2sgbWFwcyB0byBIb29rTm90Rm91bmRFcnJvciAoa2V5ZWQgb24gdGhlXG4gICAgICAgIC8vICAgICBldmVudCBjb3JyZWxhdGlvbklkIC8gaG9vayBJRCk7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiBWZXJjZWwgcmVqZWN0cyBob29rX3JlY2VpdmVkIHdpdGggNDA0LCB3aGljaFxuICAgICAgICAvLyAgICAgd29ybGQtdmVyY2VsIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3I7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiB3b3JsZC1sb2NhbCAvIHdvcmxkLXBvc3RncmVzIHJlamVjdHMgd2l0aFxuICAgICAgICAvLyAgICAgUnVuRXhwaXJlZEVycm9yLlxuICAgICAgICAvL1xuICAgICAgICAvLyBPbiB0aGUgU0VRVUVOVElBTCBwYXRoIGFuIEVudGl0eUNvbmZsaWN0RXJyb3IgKEhUVFAgNDA5KSBpcyBhbHNvXG4gICAgICAgIC8vIHRyZWF0ZWQgYXMgXCJob29rIGdvbmVcIiBmb3IgaGlzdG9yaWNhbCAvIGNvbmZsaWN0LXNoYXBlZC1yZWplY3Rpb25cbiAgICAgICAgLy8gY29tcGF0aWJpbGl0eTogdGhlcmUgaXMgbm8gcXVldWUgbWVzc2FnZSBpbiBmbGlnaHQsIHNvIGEgY29uZmxpY3QgaGFzXG4gICAgICAgIC8vIG5vIHJlLWVuc3VyaW5nIGNvbnN1bWVyIHRvIGNvbnZlcmdlIG9uLiBUaGUgUEFSQUxMRUwgcGF0aCBoYW5kbGVzIDQwOVxuICAgICAgICAvLyBkaWZmZXJlbnRseSAoc2VlIGJlbG93KSDigJQgaXQgcHVibGlzaGVkIHRoZSBxdWV1ZSBtZXNzYWdlIGJlZm9yZSB0aGVcbiAgICAgICAgLy8gY29uZmxpY3QsIHNvIHRoZSBjb25zdW1lciB3aWxsIGNvbnZlcmdlIHRoZSBldmVudC5cbiAgICAgICAgY29uc3QgaXNIb29rR29uZUVycm9yID0gKGVycjogdW5rbm93bik6IGJvb2xlYW4gPT5cbiAgICAgICAgICBIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycik7XG5cbiAgICAgICAgaWYgKCF1c2VQYXJhbGxlbFJlc3VtZSkge1xuICAgICAgICAgIC8vIFNlcXVlbnRpYWwgcGF0aDogY3JlYXRlIGEgaG9va19yZWNlaXZlZCBldmVudCwgdGhlbiByZS10cmlnZ2VyLlxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgeyB2MUNvbXBhdCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGlzSG9va0dvbmVFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcihob29rLnRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB3b3JsZC5xdWV1ZShcbiAgICAgICAgICAgIHF1ZXVlTmFtZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGhvb2sucnVuSWQsXG4gICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgcXVldWVPcHRpb25zXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHJldHVybiBob29rO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGFyYWxsZWwgZmFzdCBwYXRoLiBBIHN0YWJsZSBpZGVtcG90ZW5jeSBrZXkgdGllcyB0aGUgZGlyZWN0IHdyaXRlIHRvXG4gICAgICAgIC8vIHRoZSBxdWV1ZSBjb25zdW1lcidzIHJlLWVuc3VyZTsgdGhlIHBheWxvYWQgZGlnZXN0IGxldHMgdGhlIHNlcnZlclxuICAgICAgICAvLyBkZXRlY3Qga2V5IHJldXNlIGFjcm9zcyBieXRlLWlkZW50aWNhbCBwYXlsb2Fkcy5cbiAgICAgICAgY29uc3QgcmVzdW1lSWQgPSBnZW5lcmF0ZVJlc3VtZUlkKCk7XG4gICAgICAgIGNvbnN0IHBheWxvYWREaWdlc3QgPSBhd2FpdCBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChcbiAgICAgICAgICBkZWh5ZHJhdGVkUGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICk7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoeyAnd29ya2Zsb3cuaG9vay5yZXN1bWVfaWQnOiByZXN1bWVJZCB9KTtcblxuICAgICAgICBjb25zdCBbZXZlbnRSZXN1bHQsIHF1ZXVlUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgIGhvb2sucnVuSWQsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfcmVjZWl2ZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICBldmVudERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyB2MUNvbXBhdCwgcmVzdW1lSWQsIHJlc3VtZVBheWxvYWREaWdlc3Q6IHBheWxvYWREaWdlc3QgfVxuICAgICAgICAgICksXG4gICAgICAgICAgd29ybGQucXVldWUoXG4gICAgICAgICAgICBxdWV1ZU5hbWUsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJ1bklkOiBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgaG9va0lucHV0OiB7XG4gICAgICAgICAgICAgICAgcmVzdW1lSWQsXG4gICAgICAgICAgICAgICAgaG9va0lkOiBob29rLmhvb2tJZCxcbiAgICAgICAgICAgICAgICB0b2tlbjogaG9vay50b2tlbixcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiBkZWh5ZHJhdGVkUGF5bG9hZCxcbiAgICAgICAgICAgICAgICBwYXlsb2FkRGlnZXN0LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgcXVldWVPcHRpb25zXG4gICAgICAgICAgKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgLy8gUXVldWUgZmFpbHVyZSBpcyBhbHdheXMgZmF0YWwg4oCUIHRoZSBydW4gd2FzIG5vdCByZS10cmlnZ2VyZWQsIHNvIG5vXG4gICAgICAgIC8vIGNvbnN1bWVyIHdpbGwgcmUtZW5zdXJlIHRoZSBldmVudC5cbiAgICAgICAgaWYgKHF1ZXVlUmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xuICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB3aGVuIHRoZSBkaXJlY3Qgd3JpdGUgZGlkIG5vdCBsYW5kIGJ1dCB0aGUgcXVldWUgZGlzcGF0Y2ggZGlkLCBzb1xuICAgICAgICAvLyB0aGUgY29uc3VtZXIgbWF0ZXJpYWxpemVzIHRoZSBldmVudCBiZWZvcmUgcmVwbGF5LiBTdXJmYWNlZCB0byB0aGVcbiAgICAgICAgLy8gY2FsbGVyIGFzIGBSZXN1bWVkSG9vay5yZXNpbGllbnRSZXN1bWVgIGFuZCBvbiB0aGUgc3Bhbi5cbiAgICAgICAgbGV0IHJlc2lsaWVudFJlc3VtZSA9IGZhbHNlO1xuICAgICAgICBpZiAoZXZlbnRSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gZXZlbnRSZXN1bHQucmVhc29uO1xuICAgICAgICAgIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBUaGUgaG9vaydzIHJ1biBoYXMgZ2VudWluZWx5IGVuZGVkOiBzdXJmYWNlIHRoZSBzYW1lIGNvbnRyYWN0IGFzXG4gICAgICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBwYXRoLiBUaGUgcXVldWUgbWVzc2FnZSBhbHJlYWR5IHdlbnQgb3V0LCBidXQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lcidzIHJlLWVuc3VyZSB3aWxsIGFsc28gcmVqZWN0IGFnYWluc3QgdGhlIHRlcm1pbmFsIHJ1blxuICAgICAgICAgICAgLy8gYW5kIG5vLW9wLCBzbyB0aGUgd29ya2Zsb3cgZG9lcyBub3QgcmVzdW1lLlxuICAgICAgICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IGlzUmV0cnlhYmxlV29ybGRFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAvLyBSZXNpbGllbnQuIFR3byBzaGFwZXMgcmVhY2ggaGVyZSwgYm90aCBub24tdGVybWluYWw6XG4gICAgICAgICAgICAvLyAgIC0gRW50aXR5Q29uZmxpY3QgKDQwOSk6IHRoaXMgd3JpdGUgcmFjZWQgaXRzIG93biByZS1lbnN1cmluZ1xuICAgICAgICAgICAgLy8gICAgIGNvbnN1bWVyIChvciBhIHJlZHJpdmUpIG9uIHRoZSBzaGFyZWQgYHJlc3VtZUlkYCDigJQgdGhlIHJ1biBpc1xuICAgICAgICAgICAgLy8gICAgIE5PVCBnb25lLCBhbmQgdGhlIGNvbnN1bWVyIGNvbnZlcmdlcyBvbiB0aGUgb25lIGNvbW1pdHRlZFxuICAgICAgICAgICAgLy8gICAgIGV2ZW50LiBVbmxpa2UgdGhlIHNlcXVlbnRpYWwgcGF0aCwgYSA0MDkgaGVyZSBpcyBleHBlY3RlZFxuICAgICAgICAgICAgLy8gICAgIGNvbmN1cnJlbmN5LCBub3QgYSB2YW5pc2hlZCBob29rLlxuICAgICAgICAgICAgLy8gICAtIDQyOSAvIDV4eCAvIHRyYW5zcG9ydDogYSB0cmFuc2llbnQgYmFja2VuZCBmYWlsdXJlLlxuICAgICAgICAgICAgLy8gSW4gYm90aCBjYXNlcyB0aGUgcnVuIFdBUyByZS10cmlnZ2VyZWQgdmlhIHRoZSBxdWV1ZSBhbmQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lciBpZGVtcG90ZW50bHkgZW5zdXJlcyB0aGUgaG9va19yZWNlaXZlZCBiZWZvcmUgcmVwbGF5LCBzb1xuICAgICAgICAgICAgLy8gc3dhbGxvdyByYXRoZXIgdGhhbiBmYWlsaW5nIHRoZSBjYWxsZXIuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gUHJvZHVjZXIgdGVsZW1ldHJ5OiByZWNvcmQgdGhhdCB0aGUgZGlyZWN0IHdyaXRlIGRpZCBub3QgbGFuZCBidXRcbiAgICAgICAgICAgIC8vIHRoZSByZXN1bWUgaXMgc3RpbGwgZ3VhcmFudGVlZCB2aWEgcXVldWUtZGVsaXZlcmVkIGBob29rSW5wdXRgLlxuICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgb3BlcmF0aW9uYWwgc2lnbmFsIHRoYXQgdGhlIHJlY292ZXJ5IHBhdGggZmlyZWQsXG4gICAgICAgICAgICAvLyBzdXJmYWNlZCBib3RoIG9uIHRoZSBzcGFuIGFuZCBhcyB0aGUgcHVibGljIGByZXNpbGllbnRSZXN1bWVgXG4gICAgICAgICAgICAvLyBmbGFnIG9uIHRoZSByZXR1cm5lZCBob29rICh0aGUgcmVzdW1lIG91dGNvbWUgaXMgb3RoZXJ3aXNlXG4gICAgICAgICAgICAvLyBpZGVudGljYWwgdG8gdGhlIGhhcHB5IHBhdGggZnJvbSB0aGUgY2FsbGVyJ3MgcGVyc3BlY3RpdmUpLlxuICAgICAgICAgICAgcmVzaWxpZW50UmVzdW1lID0gdHJ1ZTtcbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Jlc2lsaWVudFJlc3VtZSh0cnVlKSxcbiAgICAgICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2V2ZW50X3dyaXRlX3JlY292ZXJlZCc6IHRydWUsXG4gICAgICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9ldmVudF93cml0ZV9lcnJvcic6XG4gICAgICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubmFtZSA6ICd1bmtub3duJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAnSG9vayByZXN1bWUgZXZlbnQgd3JpdGUgZmFpbGVkLCBidXQgdGhlIHJ1biB3YXMgcmUtdHJpZ2dlcmVkIHZpYSAnICtcbiAgICAgICAgICAgICAgICAndGhlIHF1ZXVlLiBUaGUgaG9va19yZWNlaXZlZCBldmVudCB3aWxsIGJlIGVuc3VyZWQgYnkgdGhlICcgK1xuICAgICAgICAgICAgICAgICdxdWV1ZSBjb25zdW1lci4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgICAgICBob29rSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIHJlc3VtZUlkLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHJlc2lsaWVudFJlc3VtZSA/IHsgLi4uaG9vaywgcmVzaWxpZW50UmVzdW1lOiB0cnVlIH0gOiBob29rXG4gICAgICAgICkgc2F0aXNmaWVzIFJlc3VtZWRIb29rO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rVG9rZW4oXG4gICAgICAgICAgICB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnID8gdG9rZW5Pckhvb2sgOiB0b2tlbk9ySG9vay50b2tlblxuICAgICAgICAgICksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tGb3VuZChmYWxzZSksXG4gICAgICAgIH0pO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJlc3VtZXMgYSB3ZWJob29rIGJ5IHNlbmRpbmcgYSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JlcXVlc3QgfCBSZXF1ZXN0fVxuICogb2JqZWN0IHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBhIHJlcXVlc3QgdG8gYSB3ZWJob29rIGFuZCByZXN1bWUgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEBwYXJhbSB0b2tlbiAtIFRoZSB1bmlxdWUgdG9rZW4gaWRlbnRpZnlpbmcgdGhlIGhvb2tcbiAqIEBwYXJhbSByZXF1ZXN0IC0gVGhlIHJlcXVlc3QgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJlc3BvbnNlXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBob29rIGlzIG5vdCBmb3VuZCBvciBpZiB0aGVyZSdzIGFuIGVycm9yIGR1cmluZyB0aGUgcHJvY2Vzc1xuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lV2ViaG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXF1ZXN0LnVybCk7XG4gKiAgIGNvbnN0IHRva2VuID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Rva2VuJyk7XG4gKlxuICogICBpZiAoIXRva2VuKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnTWlzc2luZyB0b2tlbicsIHsgc3RhdHVzOiA0MDAgfSk7XG4gKiAgIH1cbiAqXG4gKiAgIHRyeSB7XG4gKiAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXN1bWVXZWJob29rKHRva2VuLCByZXF1ZXN0KTtcbiAqICAgICByZXR1cm4gcmVzcG9uc2U7XG4gKiAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnV2ViaG9vayBub3QgZm91bmQnLCB7IHN0YXR1czogNDA0IH0pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc3VtZVdlYmhvb2soXG4gIHRva2VuOiBzdHJpbmcsXG4gIHJlcXVlc3Q6IFJlcXVlc3Rcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgeyBob29rLCBlbmNyeXB0aW9uS2V5IH0gPSBhd2FpdCBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW4pO1xuXG4gIC8vIE9ubHkgd2ViaG9va3MgY2FuIGJlIHJlc3VtZWQgdmlhIHRoZSBwdWJsaWMgZW5kcG9pbnQuXG4gIC8vIElmIHRoZSBob29rIHdhcyBjcmVhdGVkIHZpYSBjcmVhdGVIb29rKCkgKGlzV2ViaG9vayAhPT0gdHJ1ZSksXG4gIC8vIHRocm93IHRoZSBzYW1lIFwibm90IGZvdW5kXCIgZXJyb3IgdGhlIHdvcmxkIHdvdWxkIHRocm93IGZvciBhIG1pc3NpbmdcbiAgLy8gdG9rZW4uIFRoaXMgcHJldmVudHMgbGVha2luZyB0aGF0IHRoZSB0b2tlbiBpcyB2YWxpZC5cbiAgaWYgKGhvb2suaXNXZWJob29rID09PSBmYWxzZSkge1xuICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcih0b2tlbik7XG4gIH1cblxuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlIHwgdW5kZWZpbmVkO1xuICBsZXQgcmVzcG9uc2VSZWFkYWJsZTogUmVhZGFibGVTdHJlYW08UmVzcG9uc2U+IHwgdW5kZWZpbmVkO1xuICBpZiAoXG4gICAgaG9vay5tZXRhZGF0YSAmJlxuICAgIHR5cGVvZiBob29rLm1ldGFkYXRhID09PSAnb2JqZWN0JyAmJlxuICAgICdyZXNwb25kV2l0aCcgaW4gaG9vay5tZXRhZGF0YVxuICApIHtcbiAgICBpZiAoaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aCA9PT0gJ21hbnVhbCcpIHtcbiAgICAgIGNvbnN0IHsgcmVhZGFibGUsIHdyaXRhYmxlIH0gPSBuZXcgVHJhbnNmb3JtU3RyZWFtPFJlc3BvbnNlLCBSZXNwb25zZT4oKTtcbiAgICAgIHJlc3BvbnNlUmVhZGFibGUgPSByZWFkYWJsZTtcblxuICAgICAgLy8gVGhlIHJlcXVlc3QgaW5zdGFuY2UgaW5jbHVkZXMgdGhlIHdyaXRhYmxlIHN0cmVhbSB3aGljaCB3aWxsIGJlIHVzZWRcbiAgICAgIC8vIHRvIHdyaXRlIHRoZSByZXNwb25zZSB0byB0aGUgY2xpZW50IGZyb20gd2l0aGluIHRoZSB3b3JrZmxvdyBydW5cbiAgICAgIChyZXF1ZXN0IGFzIGFueSlbV0VCSE9PS19SRVNQT05TRV9XUklUQUJMRV0gPSB3cml0YWJsZTtcbiAgICB9IGVsc2UgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggaW5zdGFuY2VvZiBSZXNwb25zZSkge1xuICAgICAgcmVzcG9uc2UgPSBob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIFxcYHJlc3BvbmRXaXRoXFxgIHZhbHVlOiAke2hvb2subWV0YWRhdGEucmVzcG9uZFdpdGh9YCxcbiAgICAgICAgeyBzbHVnOiBFUlJPUl9TTFVHUy5XRUJIT09LX0lOVkFMSURfUkVTUE9ORF9XSVRIX1ZBTFVFIH1cbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIE5vIGByZXNwb25kV2l0aGAgdmFsdWUgaW1wbGllcyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiByZXR1cm5pbmcgYSAyMDJcbiAgICByZXNwb25zZSA9IG5ldyBSZXNwb25zZShudWxsLCB7IHN0YXR1czogMjAyIH0pO1xuICB9XG5cbiAgLy8gYGhvb2tgIHdhcyBqdXN0IGZldGNoZWQgdmlhIGBnZXRIb29rQnlUb2tlbldpdGhLZXlgIChhIGZyZXNoIGJ5LXRva2VuXG4gIC8vIGxvb2t1cCkgYWJvdmUsIHNvIGl0cyByZXNwb25zZS1vbmx5IGByZXN1bWVDYXBhYmlsaXRpZXNgIHJlZmxlY3RzIHRoZSBsaXZlXG4gIC8vIGJhY2tlbmQg4oCUIGNhbGwgdGhlIGludGVybmFsIGltcGxlbWVudGF0aW9uIHdpdGggdGhlIGZyZXNoIGF0dGVzdGF0aW9uIHNvXG4gIC8vIHRoZSBwYXJhbGxlbCBmYXN0IHBhdGggc3RheXMgYXZhaWxhYmxlIHdpdGhvdXQgYSBzZWNvbmQgR0VULiAoVGhlIHB1YmxpY1xuICAvLyBgcmVzdW1lSG9va2AgbmV2ZXIgc2V0cyB0aGlzLCBzbyBhIGNhbGxlciBjYW5ub3QgZm9yZ2UgaXQuKVxuICBhd2FpdCByZXN1bWVIb29rSW1wbChob29rLCByZXF1ZXN0LCBlbmNyeXB0aW9uS2V5LCB0cnVlKTtcblxuICBpZiAocmVzcG9uc2VSZWFkYWJsZSkge1xuICAgIC8vIFdhaXQgZm9yIHRoZSByZWFkYWJsZSBzdHJlYW0gdG8gZW1pdCBvbmUgY2h1bmssXG4gICAgLy8gd2hpY2ggaXMgdGhlIGBSZXNwb25zZWAgb2JqZWN0XG4gICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2VSZWFkYWJsZS5nZXRSZWFkZXIoKTtcbiAgICBjb25zdCBjaHVuayA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGNodW5rLnZhbHVlKSB7XG4gICAgICByZXNwb25zZSA9IGNodW5rLnZhbHVlO1xuICAgIH1cbiAgICByZWFkZXIuY2FuY2VsKCk7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKCdXb3JrZmxvdyBydW4gZGlkIG5vdCBzZW5kIGEgcmVzcG9uc2UnLCB7XG4gICAgICBzbHVnOiBFUlJPUl9TTFVHUy5XRUJIT09LX1JFU1BPTlNFX05PVF9TRU5ULFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3BvbnNlO1xufVxuIl19
|