@workflow/core 5.0.0-beta.5 → 5.0.0-beta.51

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.
Files changed (317) hide show
  1. package/README.md +5 -0
  2. package/dist/attribute-changes.d.ts +5 -0
  3. package/dist/attribute-changes.d.ts.map +1 -0
  4. package/dist/attribute-changes.js +25 -0
  5. package/dist/capabilities.d.ts +35 -2
  6. package/dist/capabilities.d.ts.map +1 -1
  7. package/dist/capabilities.js +74 -5
  8. package/dist/capture-stack.d.ts +1 -1
  9. package/dist/capture-stack.js +2 -2
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +19 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +98 -6
  16. package/dist/context-violation-error.d.ts +5 -5
  17. package/dist/context-violation-error.d.ts.map +1 -1
  18. package/dist/context-violation-error.js +8 -6
  19. package/dist/create-hook.d.ts +72 -7
  20. package/dist/create-hook.d.ts.map +1 -1
  21. package/dist/create-hook.js +1 -1
  22. package/dist/define-hook.js +2 -2
  23. package/dist/describe-error.d.ts +7 -7
  24. package/dist/describe-error.d.ts.map +1 -1
  25. package/dist/describe-error.js +97 -12
  26. package/dist/encryption.d.ts +38 -4
  27. package/dist/encryption.d.ts.map +1 -1
  28. package/dist/encryption.js +96 -14
  29. package/dist/events-consumer.d.ts +297 -0
  30. package/dist/events-consumer.d.ts.map +1 -1
  31. package/dist/events-consumer.js +673 -42
  32. package/dist/flushable-stream.d.ts +97 -1
  33. package/dist/flushable-stream.d.ts.map +1 -1
  34. package/dist/flushable-stream.js +291 -11
  35. package/dist/global.d.ts +36 -2
  36. package/dist/global.d.ts.map +1 -1
  37. package/dist/global.js +21 -6
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -2
  41. package/dist/log-format.d.ts +2 -2
  42. package/dist/log-format.js +19 -12
  43. package/dist/logger.d.ts +1 -0
  44. package/dist/logger.d.ts.map +1 -1
  45. package/dist/logger.js +10 -6
  46. package/dist/private.d.ts +226 -9
  47. package/dist/private.d.ts.map +1 -1
  48. package/dist/private.js +626 -7
  49. package/dist/replay-divergence.d.ts +25 -0
  50. package/dist/replay-divergence.d.ts.map +1 -0
  51. package/dist/replay-divergence.js +61 -0
  52. package/dist/replay-payload-cache.d.ts +64 -0
  53. package/dist/replay-payload-cache.d.ts.map +1 -0
  54. package/dist/replay-payload-cache.js +158 -0
  55. package/dist/runtime/compute-instance.d.ts +13 -0
  56. package/dist/runtime/compute-instance.d.ts.map +1 -0
  57. package/dist/runtime/compute-instance.js +14 -0
  58. package/dist/runtime/constants.d.ts +315 -0
  59. package/dist/runtime/constants.d.ts.map +1 -1
  60. package/dist/runtime/constants.js +502 -16
  61. package/dist/runtime/count-step-started-events.d.ts +52 -0
  62. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  63. package/dist/runtime/count-step-started-events.js +72 -0
  64. package/dist/runtime/deployment-guard.d.ts +99 -0
  65. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  66. package/dist/runtime/deployment-guard.js +154 -0
  67. package/dist/runtime/get-port-lazy.d.ts +15 -0
  68. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  69. package/dist/runtime/get-port-lazy.js +75 -6
  70. package/dist/runtime/get-world-lazy.d.ts +5 -14
  71. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  72. package/dist/runtime/get-world-lazy.js +19 -29
  73. package/dist/runtime/helpers.d.ts +415 -29
  74. package/dist/runtime/helpers.d.ts.map +1 -1
  75. package/dist/runtime/helpers.js +686 -57
  76. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  77. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  78. package/dist/runtime/quickjs-assets.generated.js +30 -0
  79. package/dist/runtime/quickjs-entrypoint.d.ts +158 -0
  80. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  81. package/dist/runtime/quickjs-entrypoint.js +1863 -0
  82. package/dist/runtime/quickjs-log-view.d.ts +129 -0
  83. package/dist/runtime/quickjs-log-view.d.ts.map +1 -0
  84. package/dist/runtime/quickjs-log-view.js +229 -0
  85. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  86. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  87. package/dist/runtime/quickjs-runtime.js +2427 -0
  88. package/dist/runtime/quickjs-serde.d.ts +107 -0
  89. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  90. package/dist/runtime/quickjs-serde.js +2159 -0
  91. package/dist/runtime/replay-budget.d.ts +97 -0
  92. package/dist/runtime/replay-budget.d.ts.map +1 -0
  93. package/dist/runtime/replay-budget.js +139 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  95. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  96. package/dist/runtime/replay-recovery-reporter.js +64 -0
  97. package/dist/runtime/resume-hook.d.ts +91 -8
  98. package/dist/runtime/resume-hook.d.ts.map +1 -1
  99. package/dist/runtime/resume-hook.js +512 -89
  100. package/dist/runtime/resume-latency.d.ts +150 -0
  101. package/dist/runtime/resume-latency.d.ts.map +1 -0
  102. package/dist/runtime/resume-latency.js +155 -0
  103. package/dist/runtime/run-id-time.d.ts +19 -0
  104. package/dist/runtime/run-id-time.d.ts.map +1 -0
  105. package/dist/runtime/run-id-time.js +42 -0
  106. package/dist/runtime/run.d.ts +72 -7
  107. package/dist/runtime/run.d.ts.map +1 -1
  108. package/dist/runtime/run.js +280 -53
  109. package/dist/runtime/runs.d.ts +54 -3
  110. package/dist/runtime/runs.d.ts.map +1 -1
  111. package/dist/runtime/runs.js +126 -16
  112. package/dist/runtime/start.d.ts +101 -2
  113. package/dist/runtime/start.d.ts.map +1 -1
  114. package/dist/runtime/start.js +352 -61
  115. package/dist/runtime/step-executor.d.ts +186 -5
  116. package/dist/runtime/step-executor.d.ts.map +1 -1
  117. package/dist/runtime/step-executor.js +768 -130
  118. package/dist/runtime/step-latency.d.ts +220 -0
  119. package/dist/runtime/step-latency.d.ts.map +1 -0
  120. package/dist/runtime/step-latency.js +215 -0
  121. package/dist/runtime/step-ownership.d.ts +72 -0
  122. package/dist/runtime/step-ownership.d.ts.map +1 -0
  123. package/dist/runtime/step-ownership.js +114 -0
  124. package/dist/runtime/step-single-flight.d.ts +12 -0
  125. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  126. package/dist/runtime/step-single-flight.js +75 -0
  127. package/dist/runtime/suspension-handler.d.ts +247 -7
  128. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  129. package/dist/runtime/suspension-handler.js +1304 -125
  130. package/dist/runtime/unserializable-step.d.ts +34 -0
  131. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  132. package/dist/runtime/unserializable-step.js +52 -0
  133. package/dist/runtime/vm-mode.d.ts +44 -0
  134. package/dist/runtime/vm-mode.d.ts.map +1 -0
  135. package/dist/runtime/vm-mode.js +62 -0
  136. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  137. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  138. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  139. package/dist/runtime/wait-continuation.d.ts +106 -0
  140. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  141. package/dist/runtime/wait-continuation.js +136 -0
  142. package/dist/runtime/wait-until.d.ts +18 -0
  143. package/dist/runtime/wait-until.d.ts.map +1 -0
  144. package/dist/runtime/wait-until.js +42 -0
  145. package/dist/runtime/world-compatibility.d.ts +32 -0
  146. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  147. package/dist/runtime/world-compatibility.js +44 -0
  148. package/dist/runtime/world-init.d.ts +17 -42
  149. package/dist/runtime/world-init.d.ts.map +1 -1
  150. package/dist/runtime/world-init.js +18 -43
  151. package/dist/runtime/world.d.ts +14 -2
  152. package/dist/runtime/world.d.ts.map +1 -1
  153. package/dist/runtime/world.js +75 -19
  154. package/dist/runtime.d.ts +10 -6
  155. package/dist/runtime.d.ts.map +1 -1
  156. package/dist/runtime.js +3911 -489
  157. package/dist/sealed-box.d.ts +167 -0
  158. package/dist/sealed-box.d.ts.map +1 -0
  159. package/dist/sealed-box.js +571 -0
  160. package/dist/serialization/client.d.ts +3 -3
  161. package/dist/serialization/client.d.ts.map +1 -1
  162. package/dist/serialization/client.js +8 -4
  163. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  164. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  165. package/dist/serialization/codec-devalue-vm.js +148 -0
  166. package/dist/serialization/codec-devalue.d.ts +1 -1
  167. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  168. package/dist/serialization/codec-devalue.js +24 -6
  169. package/dist/serialization/codec.d.ts +37 -2
  170. package/dist/serialization/codec.d.ts.map +1 -1
  171. package/dist/serialization/codec.js +2 -2
  172. package/dist/serialization/compression.d.ts +105 -0
  173. package/dist/serialization/compression.d.ts.map +1 -0
  174. package/dist/serialization/compression.js +261 -0
  175. package/dist/serialization/encryption.d.ts +119 -17
  176. package/dist/serialization/encryption.d.ts.map +1 -1
  177. package/dist/serialization/encryption.js +152 -17
  178. package/dist/serialization/errors.d.ts +13 -0
  179. package/dist/serialization/errors.d.ts.map +1 -1
  180. package/dist/serialization/errors.js +20 -2
  181. package/dist/serialization/format.d.ts +6 -6
  182. package/dist/serialization/format.js +7 -7
  183. package/dist/serialization/hardened.d.ts +156 -0
  184. package/dist/serialization/hardened.d.ts.map +1 -0
  185. package/dist/serialization/hardened.js +538 -0
  186. package/dist/serialization/index.d.ts +10 -8
  187. package/dist/serialization/index.d.ts.map +1 -1
  188. package/dist/serialization/index.js +10 -8
  189. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  190. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class-vm.js +77 -0
  192. package/dist/serialization/reducers/class.d.ts.map +1 -1
  193. package/dist/serialization/reducers/class.js +11 -6
  194. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  195. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  196. package/dist/serialization/reducers/common-vm.js +616 -0
  197. package/dist/serialization/reducers/common.d.ts +1 -1
  198. package/dist/serialization/reducers/common.d.ts.map +1 -1
  199. package/dist/serialization/reducers/common.js +202 -62
  200. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  201. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  202. package/dist/serialization/reducers/step-function-vm.js +97 -0
  203. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  204. package/dist/serialization/reducers/step-function.js +25 -9
  205. package/dist/serialization/step.d.ts +4 -4
  206. package/dist/serialization/step.d.ts.map +1 -1
  207. package/dist/serialization/step.js +9 -5
  208. package/dist/serialization/types.d.ts +80 -1
  209. package/dist/serialization/types.d.ts.map +1 -1
  210. package/dist/serialization/types.js +15 -1
  211. package/dist/serialization/workflow-vm.d.ts +29 -0
  212. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  213. package/dist/serialization/workflow-vm.js +74 -0
  214. package/dist/serialization-format.d.ts +64 -8
  215. package/dist/serialization-format.d.ts.map +1 -1
  216. package/dist/serialization-format.js +225 -73
  217. package/dist/serialization.d.ts +262 -34
  218. package/dist/serialization.d.ts.map +1 -1
  219. package/dist/serialization.js +1885 -277
  220. package/dist/set-attributes.d.ts +13 -0
  221. package/dist/set-attributes.d.ts.map +1 -0
  222. package/dist/set-attributes.js +60 -0
  223. package/dist/source-map.d.ts +25 -0
  224. package/dist/source-map.d.ts.map +1 -1
  225. package/dist/source-map.js +154 -10
  226. package/dist/step/context-storage.d.ts +63 -2
  227. package/dist/step/context-storage.d.ts.map +1 -1
  228. package/dist/step/context-storage.js +7 -5
  229. package/dist/step/writable-stream.d.ts +3 -3
  230. package/dist/step/writable-stream.d.ts.map +1 -1
  231. package/dist/step/writable-stream.js +80 -13
  232. package/dist/step.d.ts.map +1 -1
  233. package/dist/step.js +148 -27
  234. package/dist/symbols.d.ts +50 -0
  235. package/dist/symbols.d.ts.map +1 -1
  236. package/dist/symbols.js +51 -1
  237. package/dist/telemetry/semantic-conventions.d.ts +433 -2
  238. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  239. package/dist/telemetry/semantic-conventions.js +319 -3
  240. package/dist/telemetry.d.ts +91 -0
  241. package/dist/telemetry.d.ts.map +1 -1
  242. package/dist/telemetry.js +244 -17
  243. package/dist/test-support/orchestrator-context.d.ts +25 -0
  244. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  245. package/dist/test-support/orchestrator-context.js +107 -0
  246. package/dist/types.d.ts +6 -0
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js +23 -1
  249. package/dist/util.d.ts +0 -5
  250. package/dist/util.d.ts.map +1 -1
  251. package/dist/util.js +1 -15
  252. package/dist/version.d.ts +1 -1
  253. package/dist/version.d.ts.map +1 -1
  254. package/dist/version.js +2 -2
  255. package/dist/vm/index.d.ts.map +1 -1
  256. package/dist/vm/index.js +84 -14
  257. package/dist/vm/script-cache.d.ts +26 -0
  258. package/dist/vm/script-cache.d.ts.map +1 -0
  259. package/dist/vm/script-cache.js +131 -0
  260. package/dist/vm/uint8array-base64.js +1 -1
  261. package/dist/workflow/abort-controller.d.ts +2 -2
  262. package/dist/workflow/abort-controller.d.ts.map +1 -1
  263. package/dist/workflow/abort-controller.js +88 -21
  264. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  265. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  266. package/dist/workflow/attribute-dispatcher.js +45 -0
  267. package/dist/workflow/create-hook.d.ts.map +1 -1
  268. package/dist/workflow/create-hook.js +24 -3
  269. package/dist/workflow/get-workflow-metadata.js +2 -2
  270. package/dist/workflow/hook.d.ts.map +1 -1
  271. package/dist/workflow/hook.js +304 -47
  272. package/dist/workflow/index.d.ts +1 -0
  273. package/dist/workflow/index.d.ts.map +1 -1
  274. package/dist/workflow/index.js +2 -1
  275. package/dist/workflow/set-attributes.d.ts +68 -0
  276. package/dist/workflow/set-attributes.d.ts.map +1 -0
  277. package/dist/workflow/set-attributes.js +60 -0
  278. package/dist/workflow/sleep.d.ts.map +1 -1
  279. package/dist/workflow/sleep.js +58 -12
  280. package/dist/workflow/world-init-stub.d.ts +3 -3
  281. package/dist/workflow/world-init-stub.js +4 -4
  282. package/dist/workflow.d.ts +95 -3
  283. package/dist/workflow.d.ts.map +1 -1
  284. package/dist/workflow.js +900 -561
  285. package/docs/api-reference/create-hook.mdx +89 -10
  286. package/docs/api-reference/create-webhook.mdx +16 -15
  287. package/docs/api-reference/define-hook.mdx +35 -33
  288. package/docs/api-reference/fatal-error.mdx +30 -8
  289. package/docs/api-reference/fetch.mdx +14 -10
  290. package/docs/api-reference/get-step-metadata.mdx +2 -2
  291. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  292. package/docs/api-reference/get-writable.mdx +7 -7
  293. package/docs/api-reference/index.mdx +4 -1
  294. package/docs/api-reference/retryable-error.mdx +1 -1
  295. package/docs/api-reference/set-attributes.mdx +61 -0
  296. package/docs/api-reference/sleep.mdx +4 -4
  297. package/docs/foundations/cancellation.mdx +31 -32
  298. package/docs/foundations/errors-and-retries.mdx +42 -11
  299. package/docs/foundations/hooks.mdx +64 -35
  300. package/docs/foundations/idempotency.mdx +244 -12
  301. package/docs/foundations/index.mdx +1 -23
  302. package/docs/foundations/meta.json +2 -1
  303. package/docs/foundations/serialization.mdx +21 -22
  304. package/docs/foundations/starting-workflows.mdx +106 -30
  305. package/docs/foundations/streaming.mdx +108 -60
  306. package/docs/foundations/versioning.mdx +263 -0
  307. package/docs/foundations/workflows-and-steps.mdx +9 -9
  308. package/docs/how-it-works/cancellation.mdx +63 -63
  309. package/docs/how-it-works/code-transform.mdx +83 -67
  310. package/docs/how-it-works/encryption.mdx +30 -26
  311. package/docs/how-it-works/event-sourcing.mdx +125 -34
  312. package/docs/how-it-works/framework-integrations.mdx +96 -337
  313. package/docs/how-it-works/understanding-directives.mdx +22 -22
  314. package/package.json +24 -15
  315. package/dist/runtime/step-handler.d.ts +0 -2
  316. package/dist/runtime/step-handler.d.ts.map +0 -1
  317. package/dist/runtime/step-handler.js +0 -776
@@ -1,19 +1,80 @@
1
- import { waitUntil } from '@vercel/functions';
2
- import { EntityConflictError, ThrottleError, WorkflowRuntimeError, WorkflowWorldError, } from '@workflow/errors';
3
- import { isLegacySpecVersion, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_EVENT_SOURCING, } from '@workflow/world';
1
+ import { EntityConflictError, WorkflowRuntimeError } from '@workflow/errors';
2
+ import { globalSingleton } from '@workflow/utils';
3
+ import { workflowDisplayName } from '@workflow/utils/parse-name';
4
+ import { HOOK_RESUME_INPUT_VERSION, isLegacySpecVersion, PARENT_RUN_ID_ATTRIBUTE, RETENTION_ATTRIBUTE, ROOT_RUN_ID_ATTRIBUTE, SPEC_VERSION_SUPPORTS_ATTRIBUTES, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, workflowRunIdSchema, } from '@workflow/world';
4
5
  import { monotonicFactory } from 'ulid';
6
+ import { normalizeAttributeChanges } from '../attribute-changes.js';
7
+ import { getRunCapabilities } from '../capabilities.js';
8
+ import { isRetryableWorldError } from '../classify-error.js';
5
9
  import { importKey } from '../encryption.js';
6
10
  import { runtimeLogger } from '../logger.js';
7
- import { dehydrateWorkflowArguments } from '../serialization.js';
11
+ import { bytesToBase64, decodeRunPublicKey, deriveRunKeyPair, } from '../sealed-box.js';
12
+ import { dehydrateWorkflowArguments, SerializationFormat, sealTo, } from '../serialization.js';
13
+ import { contextStorage } from '../step/context-storage.js';
8
14
  import * as Attribute from '../telemetry/semantic-conventions.js';
9
15
  import { serializeTraceCarrier, trace } from '../telemetry.js';
10
- import { waitedUntil } from '../util.js';
11
16
  import { version as workflowCoreVersion } from '../version.js';
12
- import { getWorkflowQueueName } from './helpers.js';
13
- import { Run } from './run.js';
14
17
  import { getWorldLazy } from './get-world-lazy.js';
18
+ import { getWorkflowQueueName, healthCheck } from './helpers.js';
19
+ import { Run } from './run.js';
20
+ import { getWorkflowVmFromEnv } from './vm-mode.js';
21
+ import { safeWaitUntil, waitedUntil } from './wait-until.js';
22
+ import { assertWorldSupportsRuntimeProtocol } from './world-compatibility.js';
23
+ /**
24
+ * Timeout for the cross-deployment capability probe done before
25
+ * dehydrating workflow arguments. Kept tight on purpose: the probe is
26
+ * an optimization (it lets the caller emit the framed byte-stream wire
27
+ * format when the target supports it), and the fallback on timeout is
28
+ * the legacy raw format which always works. Long delays here would
29
+ * make `start({ deploymentId: ... })` slower for users whose target
30
+ * deployments don't recognize the health check at all.
31
+ */
32
+ const CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS = 2_000;
33
+ /**
34
+ * Wire encoding of `retention: 0`. Attribute values are strings, and the
35
+ * `$retention` value is a duration written as a decimal integer — so zero
36
+ * travels as `'0'`, not as the name of a mode.
37
+ */
38
+ const RETENTION_ZERO_ATTRIBUTE_VALUE = '0';
15
39
  /** ULID generator for client-side runId generation */
16
40
  const ulid = monotonicFactory();
41
+ /**
42
+ * Cross-run lineage for a run being started from inside another run.
43
+ *
44
+ * The ambient step context carries the parent run id and the root of its
45
+ * lineage; the runtime fills both from the run it already has loaded, so this
46
+ * is a pure context read with no I/O. The new run records `$parentRunId` (the
47
+ * edge) and inherits the parent's `$rootRunId` (the parent itself when it is a
48
+ * root), so a daisy chain or fan-out of any depth groups under one root id.
49
+ * Returns `undefined` for a top-level `start()`, which has no context, so
50
+ * standalone runs carry no lineage.
51
+ */
52
+ function resolveLineageAttributes() {
53
+ const store = contextStorage.getStore();
54
+ const parentRunId = store?.workflowMetadata?.workflowRunId;
55
+ if (!parentRunId)
56
+ return undefined;
57
+ return {
58
+ [ROOT_RUN_ID_ATTRIBUTE]: store.rootRunId ?? parentRunId,
59
+ [PARENT_RUN_ID_ATTRIBUTE]: parentRunId,
60
+ };
61
+ }
62
+ // `deploymentId: 'latest'` is a no-op in Worlds without atomic deployments.
63
+ // The warning that explains this only needs to fire once per process: a
64
+ // workflow that hardcodes 'latest' for its Vercel deployment would otherwise
65
+ // log it on every local/Postgres run, flooding tight dev loops.
66
+ // On `globalThis` (see `globalSingleton`) so "once per process" is not once
67
+ // per bundler layer.
68
+ const latestNoOpWarning = globalSingleton('@workflow/core//latestNoOpWarning', 1, () => ({ warned: false }));
69
+ /**
70
+ * Reset the `deploymentId: 'latest'` no-op warn-once guard. Test-only,
71
+ * exported so unit tests can exercise the warn path across `start()` calls.
72
+ *
73
+ * @internal
74
+ */
75
+ export function _resetLatestNoOpWarnForTests() {
76
+ latestNoOpWarning.warned = false;
77
+ }
17
78
  export async function start(workflow, argsOrOptions, options) {
18
79
  'use step';
19
80
  return await waitedUntil(() => {
@@ -22,7 +83,8 @@ export async function start(workflow, argsOrOptions, options) {
22
83
  if (!workflowName) {
23
84
  throw new WorkflowRuntimeError(`'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.`, { slug: 'start-invalid-workflow-function' });
24
85
  }
25
- return trace(`workflow.start ${workflowName}`, async (span) => {
86
+ const spanName = `workflow.start ${workflowDisplayName(workflowName)}`;
87
+ return trace(spanName, async (span) => {
26
88
  span?.setAttributes({
27
89
  ...Attribute.WorkflowName(workflowName),
28
90
  ...Attribute.WorkflowOperation('start'),
@@ -38,31 +100,184 @@ export async function start(workflow, argsOrOptions, options) {
38
100
  span?.setAttributes({
39
101
  ...Attribute.WorkflowArgumentsCount(args.length),
40
102
  });
41
- const world = opts?.world ?? (await getWorldLazy());
42
- let deploymentId = opts.deploymentId ?? (await world.getDeploymentId());
103
+ const world = opts.world ?? (await getWorldLazy());
104
+ assertWorldSupportsRuntimeProtocol(world);
105
+ const currentDeploymentId = await world.getDeploymentId();
106
+ let deploymentId = opts.deploymentId ?? currentDeploymentId;
43
107
  // When 'latest' is requested, resolve the actual latest deployment ID
44
108
  // for the current deployment's environment (same production target or
45
109
  // same git branch for preview deployments).
110
+ //
111
+ // Resolving 'latest' only means something in worlds with atomic,
112
+ // immutable deployments (e.g. Vercel), which implement
113
+ // resolveLatestDeploymentId(). Worlds without that concept (local dev,
114
+ // self-hosted Postgres) have nothing to resolve between, so rather than
115
+ // fail a run that works fine on Vercel, we warn and fall back to the
116
+ // current deployment, making 'latest' an effective no-op there.
46
117
  if (deploymentId === 'latest') {
47
- if (!world.resolveLatestDeploymentId) {
48
- throw new WorkflowRuntimeError("deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()");
118
+ if (world.resolveLatestDeploymentId) {
119
+ deploymentId = await world.resolveLatestDeploymentId();
120
+ }
121
+ else {
122
+ // Warn once per process; see latestNoOpWarning.warned above.
123
+ if (!latestNoOpWarning.warned) {
124
+ latestNoOpWarning.warned = true;
125
+ runtimeLogger.warn("deploymentId: 'latest' has no effect in this world and was ignored. " +
126
+ 'It is only supported by worlds with atomic deployments, such as Vercel. ' +
127
+ 'The run will target the current deployment.', { currentDeploymentId });
128
+ }
129
+ deploymentId = currentDeploymentId;
49
130
  }
50
- deploymentId = await world.resolveLatestDeploymentId();
51
131
  }
52
- const ops = [];
132
+ // Decide whether to write byte streams in the framed wire format.
133
+ // For same-deployment starts (the common case) we know the target is
134
+ // running this same SDK version, so framing is safe. For cross-
135
+ // deployment starts (explicit deploymentId or 'latest' that resolves
136
+ // to a different deployment) we probe the target via healthCheck to
137
+ // learn its workflow-core version, then derive the capability. The
138
+ // probe has a tight timeout: on miss/failure we fall back to the
139
+ // legacy raw byte format, which is universally readable.
140
+ //
141
+ // Worlds that don't expose the `streams` API (e.g. minimal test
142
+ // mocks) can't service health checks, so we skip the probe for them.
53
143
  // Generate runId client-side so we have it before serialization
54
- // (required for future E2E encryption where runId is part of the encryption context)
55
- const runId = `wrun_${ulid()}`;
144
+ // (required for future E2E encryption where runId is part of the
145
+ // encryption context). When the World provides a `createRunId()`
146
+ // implementation, use it so worlds can embed implementation-specific
147
+ // metadata (e.g., region) into the ID, forwarding the full options
148
+ // bag so worlds can read whichever fields they recognise; otherwise
149
+ // fall back to a standard monotonic ULID.
150
+ const runId = `wrun_${world.createRunId
151
+ ? world.createRunId(opts)
152
+ : ulid()}`;
153
+ let framedByteStreams;
154
+ let targetSupportsCompression;
155
+ // The consumer's hook-resume protocol version, stamped onto the new
156
+ // run. Current producers write the hook_received event durably before
157
+ // publishing the wake and never read it; OLDER producers gate their
158
+ // lazy (hookInput-carrying) path on the deployment that will actually
159
+ // consume the queue message. `undefined` means "could not attest" and
160
+ // fails that gate closed.
161
+ let targetHookResumeInputVersion;
162
+ // Public key of the target run, when the capability probe was able to
163
+ // supply one (cross-deployment only).
164
+ let probedRunPublicKey;
165
+ if (deploymentId === currentDeploymentId) {
166
+ framedByteStreams = true;
167
+ targetSupportsCompression = true;
168
+ // Same deployment: this process is the consumer, so its own constant
169
+ // is authoritative.
170
+ targetHookResumeInputVersion = HOOK_RESUME_INPUT_VERSION;
171
+ }
172
+ else if (typeof world.streams?.get !== 'function') {
173
+ framedByteStreams = false;
174
+ targetSupportsCompression = false;
175
+ // No probe channel to the target, so we cannot attest the consumer
176
+ // honors `hookInput`; leave the marker off (older producers fail
177
+ // closed to their sequential path).
178
+ targetHookResumeInputVersion = undefined;
179
+ }
180
+ else {
181
+ // Ask for this run's public key while we're here. The probe already
182
+ // blocks `start()` on every cross-deployment call, and the responder
183
+ // executes inside the target deployment where the key material is
184
+ // local, so the key comes back for free on a response we are
185
+ // already awaiting, and we can skip the key-lookup API request
186
+ // entirely. Best-effort: on timeout or an older target, no key comes
187
+ // back and we fall through to the regular lookup below.
188
+ const probe = await healthCheck(world, {
189
+ deploymentId,
190
+ runId,
191
+ timeout: CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS,
192
+ namespace: opts.namespace,
193
+ }).catch(() => undefined);
194
+ probedRunPublicKey = probe?.encryptionPublicKey;
195
+ const capabilities = getRunCapabilities(probe?.workflowCoreVersion);
196
+ framedByteStreams = capabilities.framedByteStreams;
197
+ targetSupportsCompression = capabilities.supportedFormats.has(SerializationFormat.GZIP);
198
+ // The responder runs inside the target deployment, so its
199
+ // `hookResumeInputVersion` reflects the consumer. Undefined on an
200
+ // older target or a probe timeout, leaving the marker off.
201
+ targetHookResumeInputVersion = probe?.hookResumeInputVersion;
202
+ }
203
+ const ops = [];
56
204
  // Serialize current trace context to propagate across queue boundary
57
205
  const traceCarrier = await serializeTraceCarrier();
58
- // Use world-declared specVersion when available (our worlds set this),
59
- // otherwise fall back to the safe baseline that community worlds handle.
60
- // Community worlds built against older @workflow/world reject runs with
61
- // specVersion > their SPEC_VERSION_CURRENT via requiresNewerWorld().
62
- const specVersion = opts.specVersion ??
63
- world.specVersion ??
64
- SPEC_VERSION_SUPPORTS_EVENT_SOURCING;
206
+ // Default new runs to the configured world's spec version. The world
207
+ // itself has already been checked against this runtime's spec version.
208
+ const specVersion = opts.specVersion ?? world.specVersion;
65
209
  const v1Compat = isLegacySpecVersion(specVersion);
210
+ const allowReservedAttributes = opts.allowReservedAttributes === true;
211
+ let attributes;
212
+ if (opts.attributes && Object.keys(opts.attributes).length > 0) {
213
+ if (specVersion < SPEC_VERSION_SUPPORTS_ATTRIBUTES) {
214
+ throw new WorkflowRuntimeError('Initial workflow attributes require a World that supports spec version 4 or later.');
215
+ }
216
+ // `normalizeAttributeChanges` treats `undefined` as "remove this
217
+ // key", which is meaningless at creation time. Reject it up front
218
+ // so JS callers get a clear error instead of a downstream schema
219
+ // failure (the types already forbid non-string values).
220
+ for (const [key, value] of Object.entries(opts.attributes)) {
221
+ if (typeof value !== 'string') {
222
+ throw new WorkflowRuntimeError(`Initial workflow attribute ${JSON.stringify(key)} must be a string value.`);
223
+ }
224
+ }
225
+ const changes = normalizeAttributeChanges(opts.attributes, {
226
+ allowReservedAttributes,
227
+ });
228
+ attributes = Object.fromEntries(changes.map(({ key, value }) => [key, value]));
229
+ }
230
+ // `retention` is the typed spelling of the reserved `$retention`
231
+ // attribute, whose value is a duration written as a decimal integer.
232
+ // `'default'` means "let the World decide", which is already what an
233
+ // absent attribute means, so it is not written: that keeps
234
+ // `'default'` exactly equivalent to omitting the option and spends
235
+ // none of the per-run attribute budget.
236
+ let retentionAttribute;
237
+ if (opts.experimental_retention !== undefined &&
238
+ opts.experimental_retention !== 'default') {
239
+ // The types allow only `0`, but an untyped JS caller can still get
240
+ // here with some other duration — and there is no unit to interpret
241
+ // it in yet, so no World can honor it. Reject it rather than seed a
242
+ // value that would silently resolve to the World's default.
243
+ if (opts.experimental_retention !== 0) {
244
+ throw new WorkflowRuntimeError(`start({ experimental_retention }) must be 0 or 'default'; received ${JSON.stringify(opts.experimental_retention)}.`);
245
+ }
246
+ if (specVersion < SPEC_VERSION_SUPPORTS_ATTRIBUTES) {
247
+ throw new WorkflowRuntimeError('start({ experimental_retention }) requires a World that supports spec version 4 or later.');
248
+ }
249
+ retentionAttribute = {
250
+ [RETENTION_ATTRIBUTE]: RETENTION_ZERO_ATTRIBUTE_VALUE,
251
+ };
252
+ }
253
+ // Cross-run lineage: the reserved keys ride on the run's existing
254
+ // attributes, so they add no extra write. Caller attributes are spread
255
+ // last, so a caller with allowReservedAttributes can deliberately
256
+ // re-parent. `retention` is spread after those: it is the supported
257
+ // spelling, so it wins over a hand-written `$retention` attribute.
258
+ const lineage = specVersion >= SPEC_VERSION_SUPPORTS_ATTRIBUTES
259
+ ? resolveLineageAttributes()
260
+ : undefined;
261
+ const runAttributes = lineage || retentionAttribute
262
+ ? { ...lineage, ...attributes, ...retentionAttribute }
263
+ : attributes;
264
+ // Shared by the run_created event and the resilient-start queue input.
265
+ const attributeSeed = runAttributes
266
+ ? {
267
+ attributes: runAttributes,
268
+ ...(allowReservedAttributes ||
269
+ lineage != null ||
270
+ retentionAttribute != null
271
+ ? { allowReservedAttributes: true }
272
+ : {}),
273
+ }
274
+ : {};
275
+ // `replayedFromRunId` is a foreign key to the source run; reject anything
276
+ // that isn't a real run ID so the lineage link can't point at garbage.
277
+ if (opts.replayedFromRunId !== undefined &&
278
+ !workflowRunIdSchema.safeParse(opts.replayedFromRunId).success) {
279
+ throw new WorkflowRuntimeError(`replayedFromRunId must be a run ID (wrun_<ulid>); received ${JSON.stringify(String(opts.replayedFromRunId).slice(0, 64))}.`);
280
+ }
66
281
  // Resolve encryption key for the new run. The runId has already been
67
282
  // generated above (client-generated ULID) and will be used for both
68
283
  // key derivation and the run_created event. The World implementation
@@ -70,18 +285,95 @@ export async function start(workflow, argsOrOptions, options) {
70
285
  // deploymentId (not just the raw opts) so the World can use it for
71
286
  // key resolution even when deploymentId was inferred from the environment
72
287
  // rather than explicitly provided in opts (e.g., in e2e test runners).
73
- const rawKey = await world.getEncryptionKeyForRun?.(runId, {
74
- ...opts,
75
- deploymentId,
76
- });
77
- const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
288
+ // Resolve how to encrypt the workflow arguments.
289
+ //
290
+ // Preferred: the capability probe already told us this run's public
291
+ // key, so seal to it. That skips `getEncryptionKeyForRun`, which for a
292
+ // cross-deployment start is a `run-key` API request, the last one left
293
+ // on this path. It is also a privilege reduction: the caller ends up
294
+ // able to write the arguments but not read them back, whereas fetching
295
+ // the symmetric key grants full read access to a run it merely
296
+ // launched.
297
+ const probedPublicKey = decodeRunPublicKey(probedRunPublicKey);
298
+ let encryptionKey;
299
+ let encryptionPublicKey;
300
+ if (probedPublicKey) {
301
+ encryptionKey = sealTo(probedPublicKey);
302
+ encryptionPublicKey = probedRunPublicKey;
303
+ }
304
+ else {
305
+ const rawKey = await world.getEncryptionKeyForRun?.(runId, {
306
+ ...opts,
307
+ deploymentId,
308
+ });
309
+ encryptionKey = rawKey ? await importKey(rawKey) : undefined;
310
+ // Publish the run's X25519 public key so that cross-run writers (a
311
+ // hook resumption from another deployment, a sibling writing into a
312
+ // forwarded stream) can seal payloads *to* this run without holding
313
+ // its symmetric key.
314
+ //
315
+ // Presence of this field is the writer-side gate for sealed
316
+ // envelopes, so it must only be stamped when this runtime could
317
+ // itself open one. That holds by construction here: derivation and
318
+ // `encp` dispatch live in the same package, so any core that can
319
+ // stamp can also open. Runs are pinned to their creating deployment,
320
+ // so the capability this attests to is still accurate at resume time.
321
+ encryptionPublicKey = rawKey
322
+ ? bytesToBase64((await deriveRunKeyPair(rawKey)).publicKey)
323
+ : undefined;
324
+ }
78
325
  // Create run via run_created event (event-sourced architecture)
79
326
  // Pass client-generated runId - server will accept and use it
80
- const workflowArguments = await dehydrateWorkflowArguments(args, runId, encryptionKey, ops, globalThis, v1Compat);
327
+ // Compress workflow arguments only when the run itself is marked as
328
+ // possibly containing compressed payloads (specVersion >= 5) AND the
329
+ // target deployment can decode them (same-deployment, or probed
330
+ // capability for cross-deployment starts).
331
+ const compression = targetSupportsCompression &&
332
+ specVersion >= SPEC_VERSION_SUPPORTS_COMPRESSION;
333
+ const workflowArguments = await dehydrateWorkflowArguments(args, runId, encryptionKey, ops, globalThis, v1Compat, framedByteStreams, compression);
334
+ // The environment this caller's own `run_created` write is attributed
335
+ // to. Stamped into the queue message's `runInput` (NOT into
336
+ // `run_created`, whose tenant the backend already knows) so the
337
+ // deployment that consumes the message can tell whether the run it is
338
+ // being asked to resiliently create was created against a different
339
+ // environment than its own.
340
+ //
341
+ // The two writes below go to different places by different routes:
342
+ // `events.create` is attributed to THIS client's tenant, while the queue
343
+ // message is pinned to a deploymentId. When those disagree (a
344
+ // production-credentialed client pinning a preview deployment) the
345
+ // preview consumer can't find the run in its own tenant, falls back to
346
+ // resilient start, and re-creates it: one client-minted run id, two
347
+ // environments, the production copy pending forever and the preview copy
348
+ // executing. Worlds with a single tenant return undefined and the field
349
+ // is absent.
350
+ const creatorEnvironment = world.getEnvironment?.();
351
+ // If WORKFLOW_VM is set on the client starting the run, stamp the
352
+ // engine choice into the run's executionContext so the run keeps
353
+ // executing on the engine it started on (the same deployment can
354
+ // serve both VM engines). Unknown values throw; see
355
+ // getWorkflowVmFromEnv().
356
+ const workflowVm = getWorkflowVmFromEnv();
81
357
  const executionContext = {
82
358
  traceCarrier,
83
359
  workflowCoreVersion,
84
360
  features: { encryption: !!encryptionKey },
361
+ // Attest that the *consumer* deployment's runtime re-ensures a
362
+ // `hook_received` event from a queue message's `hookInput` on replay.
363
+ // An OLDER producer resuming this run reads the marker (mirrored onto
364
+ // the hook's resumeContext by the server) to decide whether its lazy
365
+ // fast path is safe. For a cross-deployment start the consumer is the
366
+ // target deployment, so we stamp the *target's* value carried back on
367
+ // the health-check probe, never the caller's. Omitted when we could
368
+ // not attest the target (older target, timeout, or no probe channel),
369
+ // which fails the resume gate closed to the sequential path.
370
+ ...(targetHookResumeInputVersion !== undefined
371
+ ? { hookResumeInputVersion: targetHookResumeInputVersion }
372
+ : {}),
373
+ ...(workflowVm ? { workflowVm } : {}),
374
+ ...(opts.replayedFromRunId
375
+ ? { replayedFromRunId: opts.replayedFromRunId }
376
+ : {}),
85
377
  };
86
378
  // Call events.create (run_created) and queue in parallel.
87
379
  // If events.create fails with 429/5xx, the run was still accepted
@@ -95,9 +387,11 @@ export async function start(workflow, argsOrOptions, options) {
95
387
  workflowName: workflowName,
96
388
  input: workflowArguments,
97
389
  executionContext,
390
+ ...(encryptionPublicKey ? { encryptionPublicKey } : {}),
391
+ ...attributeSeed,
98
392
  },
99
393
  }, { v1Compat }),
100
- world.queue(getWorkflowQueueName(workflowName), {
394
+ world.queue(getWorkflowQueueName(workflowName, opts.namespace), {
101
395
  runId,
102
396
  traceCarrier,
103
397
  ...(specVersion >= SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT
@@ -108,15 +402,25 @@ export async function start(workflow, argsOrOptions, options) {
108
402
  workflowName,
109
403
  specVersion,
110
404
  executionContext,
405
+ ...(encryptionPublicKey ? { encryptionPublicKey } : {}),
406
+ ...(creatorEnvironment !== undefined
407
+ ? { environment: creatorEnvironment }
408
+ : {}),
409
+ ...attributeSeed,
111
410
  },
112
411
  }
113
412
  : {}),
114
413
  }, {
115
414
  deploymentId,
116
415
  specVersion,
416
+ // Forward any caller-supplied region hint so worlds with
417
+ // per-region queue routing (e.g. world-vercel) can target the
418
+ // matching queue. Worlds without a regional dimension ignore
419
+ // this field.
420
+ ...(opts.region !== undefined ? { region: opts.region } : {}),
117
421
  }),
118
422
  ]);
119
- // Queue failure is always fatal the run was not enqueued
423
+ // Queue failure is always fatal: the run was not enqueued
120
424
  if (queueResult.status === 'rejected') {
121
425
  throw queueResult.reason;
122
426
  }
@@ -130,10 +434,11 @@ export async function start(workflow, argsOrOptions, options) {
130
434
  // + run_started call completes faster. We expect this to be <=1% of cases.
131
435
  // In this case, we can safely return.
132
436
  }
133
- else if (isRetryableStartError(err)) {
134
- // 429 (ThrottleError) and 5xx (WorkflowWorldError with status >= 500)
135
- // are retryable the run was accepted via the queue and creation
136
- // will be re-tried by the runtime when it calls run_started.
437
+ else if (isRetryableWorldError(err)) {
438
+ // 429 (ThrottleError), 5xx, and transient transport failures
439
+ // (TRANSPORT/TIMEOUT) are retryable: the run was accepted via the
440
+ // queue and creation will be re-tried by the runtime when it calls
441
+ // run_started.
137
442
  resilientStart = true;
138
443
  runtimeLogger.warn('Run creation event failed, but the run was accepted via the queue. ' +
139
444
  'The run_created event will be re-tried async by the runtime.', { workflowRunId: runId, error: err.message });
@@ -144,26 +449,25 @@ export async function start(workflow, argsOrOptions, options) {
144
449
  }
145
450
  else {
146
451
  const result = runCreatedResult.value;
147
- // Assert that the run was created
148
- if (!result.run) {
149
- throw new WorkflowRuntimeError("Missing 'run' in server response for 'run_created' event");
150
- }
151
452
  // Verify server accepted our runId
152
453
  if (!v1Compat && result.run.runId !== runId) {
153
454
  throw new WorkflowRuntimeError(`Server returned different runId than requested: expected ${runId}, got ${result.run.runId}`);
154
455
  }
155
456
  }
156
- waitUntil(Promise.all(ops).catch((err) => {
157
- // Ignore expected client disconnect errors (e.g., browser refresh during streaming)
158
- const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
159
- if (!isAbortError)
160
- throw err;
161
- }));
457
+ // These argument-stream ops are flushed in the background; the promise
458
+ // handed to waitUntil must never reject (an unconsumed waitUntil
459
+ // rejection crashes the process as unhandledRejection), so unexpected
460
+ // failures are logged instead.
461
+ safeWaitUntil(Promise.all(ops), (err) => {
462
+ runtimeLogger.warn('Background flush of workflow argument streams failed', {
463
+ workflowRunId: runId,
464
+ error: err instanceof Error ? err.message : String(err),
465
+ });
466
+ });
162
467
  span?.setAttributes({
163
468
  ...Attribute.WorkflowRunId(runId),
164
469
  ...Attribute.DeploymentId(deploymentId),
165
- ...(runCreatedResult.status === 'fulfilled' &&
166
- runCreatedResult.value.run
470
+ ...(runCreatedResult.status === 'fulfilled'
167
471
  ? Attribute.WorkflowRunStatus(runCreatedResult.value.run.status)
168
472
  : {}),
169
473
  });
@@ -171,17 +475,4 @@ export async function start(workflow, argsOrOptions, options) {
171
475
  });
172
476
  });
173
477
  }
174
- /**
175
- * Checks if an error from events.create (run_created) is retryable,
176
- * meaning the queue can re-try creation later via the run_started path.
177
- * - ThrottleError (429): rate limited, will succeed later
178
- * - WorkflowWorldError with status >= 500: server error, will succeed later
179
- */
180
- function isRetryableStartError(err) {
181
- if (ThrottleError.is(err))
182
- return true;
183
- if (WorkflowWorldError.is(err) && err.status && err.status >= 500)
184
- return true;
185
- return false;
186
- }
187
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9zdGFydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBRTFCLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsMENBQTBDLEVBQzFDLG9DQUFvQyxHQUNyQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU3QyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRSxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxPQUFPLElBQUksbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRW5ELHNEQUFzRDtBQUN0RCxNQUFNLElBQUksR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0FBeUZoQyxNQUFNLENBQUMsS0FBSyxVQUFVLEtBQUssQ0FDekIsUUFBNkQsRUFDN0QsYUFBb0Ms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QUFDLE1BQU0sSUFBSSxHQUFHLENBQUMsTUFBTSxJQUFJLEdBQUc7UUFDL0QsT0FBTyxJQUFJLENBQUM7SUFDZCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB3YWl0VW50aWwgfSBmcm9tICdAdmVyY2VsL2Z1bmN0aW9ucyc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBUaHJvdHRsZUVycm9yLFxuICBXb3JrZmxvd1J1bnRpbWVFcnJvcixcbiAgV29ya2Zsb3dXb3JsZEVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB0eXBlIHsgV29ya2Zsb3dJbnZva2VQYXlsb2FkLCBXb3JsZCB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQge1xuICBpc0xlZ2FjeVNwZWNWZXJzaW9uLFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19FVkVOVF9TT1VSQ0lORyxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IG1vbm90b25pY0ZhY3RvcnkgfSBmcm9tICd1bGlkJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IFNlcmlhbGl6YWJsZSB9IGZyb20gJy4uL3NjaGVtYXMuanMnO1xuaW1wb3J0IHsgZGVoeWRyYXRlV29ya2Zsb3dBcmd1bWVudHMgfSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgc2VyaWFsaXplVHJhY2VDYXJyaWVyLCB0cmFjZSB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyB3YWl0ZWRVbnRpbCB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgdmVyc2lvbiBhcyB3b3JrZmxvd0NvcmVWZXJzaW9uIH0gZnJvbSAnLi4vdmVyc2lvbi5qcyc7XG5pbXBvcnQgeyBnZXRXb3JrZmxvd1F1ZXVlTmFtZSB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBSdW4gfSBmcm9tICcuL3J1bi5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcblxuLyoqIFVMSUQgZ2VuZXJhdG9yIGZvciBjbGllbnQtc2lkZSBydW5JZCBnZW5lcmF0aW9uICovXG5jb25zdCB1bGlkID0gbW9ub3RvbmljRmFjdG9yeSgpO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0T3B0aW9uc0Jhc2Uge1xuICAvKipcbiAgICogVGhlIHdvcmxkIHRvIHVzZSBmb3IgdGhlIHdvcmtmbG93IHJ1biBjcmVhdGlvbixcbiAgICogYnkgZGVmYXVsdCB0aGUgd29ybGQgaXMgaW5mZXJyZWQgZnJvbSB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgd29ybGQ/OiBXb3JsZDtcblxuICAvKipcbiAgICogVGhlIHNwZWMgdmVyc2lvbiB0byB1c2UgZm9yIHRoZSB3b3JrZmxvdyBydW4uIERlZmF1bHRzIHRvIHRoZSBsYXRlc3QgdmVyc2lvbi5cbiAgICovXG4gIHNwZWNWZXJzaW9uPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0T3B0aW9uc1dpdGhEZXBsb3ltZW50SWQgZXh0ZW5kcyBTdGFydE9wdGlvbnNCYXNlIHtcbiAgLyoqXG4gICAqIFRoZSBkZXBsb3ltZW50IElEIHRvIHVzZSBmb3IgdGhlIHdvcmtmbG93IHJ1bi5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhpcyBpcyBhdXRvbWF0aWNhbGx5IGluZmVycmVkIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAqIHdoZW4gZGVwbG95aW5nIHRvIFZlcmNlbC5cbiAgICpcbiAgICogU2V0IHRvIGAnbGF0ZXN0J2AgdG8gYXV0b21hdGljYWxseSByZXNvbHZlIHRoZSBtb3N0IHJlY2VudCBkZXBsb3ltZW50XG4gICAqIGZvciB0aGUgY3VycmVudCBlbnZpcm9ubWVudCAoc2FtZSBwcm9kdWN0aW9uIHRhcmdldCBvciBnaXQgYnJhbmNoKS5cbiAgICogVGhpcyBpcyBjdXJyZW50bHkgYSBWZXJjZWwtc3BlY2lmaWMgZmVhdHVyZS5cbiAgICpcbiAgICogKipOb3RlOioqIFdoZW4gYGRlcGxveW1lbnRJZGAgaXMgcHJvdmlkZWQsIHRoZSBhcmd1bWVudCBhbmQgcmV0dXJuIHR5cGVzIGJlY29tZSBgdW5rbm93bmBcbiAgICogc2luY2UgdGhlcmUgaXMgbm8gZ3VhcmFudGVlIHRoZSB0eXBlcyB3aWxsIGJlIGNvbnNpc3RlbnQgYWNyb3NzIGRlcGxveW1lbnRzLlxuICAgKi9cbiAgZGVwbG95bWVudElkOiAnbGF0ZXN0JyB8IChzdHJpbmcgJiB7fSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRPcHRpb25zV2l0aG91dERlcGxveW1lbnRJZCBleHRlbmRzIFN0YXJ0T3B0aW9uc0Jhc2Uge1xuICBkZXBsb3ltZW50SWQ/OiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3Igc3RhcnRpbmcgYSB3b3JrZmxvdyBydW4uXG4gKi9cbmV4cG9ydCB0eXBlIFN0YXJ0T3B0aW9ucyA9XG4gIHwgU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZFxuICB8IFN0YXJ0T3B0aW9uc1dpdGhvdXREZXBsb3ltZW50SWQ7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBpbXBvcnRlZCB3b3JrZmxvdyBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IHR5cGUgV29ya2Zsb3dGdW5jdGlvbjxUQXJncyBleHRlbmRzIHVua25vd25bXSwgVFJlc3VsdD4gPSAoXG4gIC4uLmFyZ3M6IFRBcmdzXG4pID0+IFByb21pc2U8VFJlc3VsdD47XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgZ2VuZXJhdGVkIG1ldGFkYXRhIG9mIGEgd29ya2Zsb3cgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCB0eXBlIFdvcmtmbG93TWV0YWRhdGEgPSB7IHdvcmtmbG93SWQ6IHN0cmluZyB9O1xuXG4vKipcbiAqIFN0YXJ0cyBhIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gd29ya2Zsb3cgLSBUaGUgaW1wb3J0ZWQgd29ya2Zsb3cgZnVuY3Rpb24gdG8gc3RhcnQuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgd29ya2Zsb3cgKG9wdGlvbmFsKS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSB3b3JrZmxvdyBydW4gKG9wdGlvbmFsKS5cbiAqIEByZXR1cm5zIFRoZSB1bmlxdWUgcnVuIElEIGZvciB0aGUgbmV3bHkgc3RhcnRlZCB3b3JrZmxvdyBpbnZvY2F0aW9uLlxuICovXG4vLyBPdmVybG9hZHMgd2l0aCBkZXBsb3ltZW50SWQgLSBhcmdzIGFuZCByZXR1cm4gdHlwZSBiZWNvbWUgdW5rbm93blxuLy8gVXNlcyBnZW5lcmljcyBzbyB0eXBlZCB3b3JrZmxvd3MgYXJlIGFzc2lnbmFibGUgKGF2b2lkcyBjb250cmF2YXJpYW5jZSBpc3N1ZXMpLFxuLy8gYnV0IHRoZSByZXR1cm4gdHlwZSBhbmQgYXJncyBhcmUgc3RpbGwgdW5rbm93biBzaW5jZSB0aGUgZGVwbG95ZWQgdmVyc2lvbiBtYXkgZGlmZmVyLlxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnczogdW5rbm93bltdLFxuICBvcHRpb25zOiBTdGFydE9wdGlvbnNXaXRoRGVwbG95bWVudElkXG4pOiBQcm9taXNlPFJ1bjx1bmtub3duPj47XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydDxUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248W10sIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgb3B0aW9uczogU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZFxuKTogUHJvbWlzZTxSdW48dW5rbm93bj4+O1xuXG4vLyBPdmVybG9hZHMgd2l0aG91dCBkZXBsb3ltZW50SWQgLSBwcmVzZXJ2ZSB0eXBlIGluZmVyZW5jZVxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnczogVEFyZ3MsXG4gIG9wdGlvbnM/OiBTdGFydE9wdGlvbnNXaXRob3V0RGVwbG95bWVudElkXG4pOiBQcm9taXNlPFJ1bjxUUmVzdWx0Pj47XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydDxUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248W10sIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgb3B0aW9ucz86IFN0YXJ0T3B0aW9uc1dpdGhvdXREZXBsb3ltZW50SWRcbik6IFByb21pc2U8UnVuPFRSZXN1bHQ+PjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnc09yT3B0aW9ucz86IFRBcmdzIHwgU3RhcnRPcHRpb25zLFxuICBvcHRpb25zPzogU3RhcnRPcHRpb25zXG4pIHtcbiAgJ3VzZSBzdGVwJztcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHRoaXMgZmllbGQgaXMgYWRkZWQgYnkgb3VyIGNsaWVudCB0cmFuc2Zvcm1cbiAgICBjb25zdCB3b3JrZmxvd05hbWUgPSB3b3JrZmxvdz8ud29ya2Zsb3dJZDtcblxuICAgIGlmICghd29ya2Zsb3dOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgIGAnc3RhcnQnIHJlY2VpdmVkIGFuIGludmFsaWQgd29ya2Zsb3cgZnVuY3Rpb24uIEVuc3VyZSB0aGUgV29ya2Zsb3cgU0RLIGlzIGNvbmZpZ3VyZWQgY29ycmVjdGx5IGFuZCB0aGUgZnVuY3Rpb24gaW5jbHVkZXMgYSAndXNlIHdvcmtmbG93JyBkaXJlY3RpdmUuYCxcbiAgICAgICAgeyBzbHVnOiAnc3RhcnQtaW52YWxpZC13b3JrZmxvdy1mdW5jdGlvbicgfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhY2UoYHdvcmtmbG93LnN0YXJ0ICR7d29ya2Zsb3dOYW1lfWAsIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93TmFtZSh3b3JrZmxvd05hbWUpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dPcGVyYXRpb24oJ3N0YXJ0JyksXG4gICAgICB9KTtcblxuICAgICAgbGV0IGFyZ3M6IFNlcmlhbGl6YWJsZVtdID0gW107XG4gICAgICBsZXQgb3B0czogU3RhcnRPcHRpb25zID0gb3B0aW9ucyA/PyB7fTtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGFyZ3NPck9wdGlvbnMpKSB7XG4gICAgICAgIGFyZ3MgPSBhcmdzT3JPcHRpb25zIGFzIFNlcmlhbGl6YWJsZVtdO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYXJnc09yT3B0aW9ucyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgb3B0cyA9IGFyZ3NPck9wdGlvbnM7XG4gICAgICB9XG5cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dBcmd1bWVudHNDb3VudChhcmdzLmxlbmd0aCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgd29ybGQgPSBvcHRzPy53b3JsZCA/PyAoYXdhaXQgZ2V0V29ybGRMYXp5KCkpO1xuICAgICAgbGV0IGRlcGxveW1lbnRJZCA9IG9wdHMuZGVwbG95bWVudElkID8/IChhd2FpdCB3b3JsZC5nZXREZXBsb3ltZW50SWQoKSk7XG5cbiAgICAgIC8vIFdoZW4gJ2xhdGVzdCcgaXMgcmVxdWVzdGVkLCByZXNvbHZlIHRoZSBhY3R1YWwgbGF0ZXN0IGRlcGxveW1lbnQgSURcbiAgICAgIC8vIGZvciB0aGUgY3VycmVudCBkZXBsb3ltZW50J3MgZW52aXJvbm1lbnQgKHNhbWUgcHJvZHVjdGlvbiB0YXJnZXQgb3JcbiAgICAgIC8vIHNhbWUgZ2l0IGJyYW5jaCBmb3IgcHJldmlldyBkZXBsb3ltZW50cykuXG4gICAgICBpZiAoZGVwbG95bWVudElkID09PSAnbGF0ZXN0Jykge1xuICAgICAgICBpZiAoIXdvcmxkLnJlc29sdmVMYXRlc3REZXBsb3ltZW50SWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICBcImRlcGxveW1lbnRJZCAnbGF0ZXN0JyByZXF1aXJlcyBhIFdvcmxkIHRoYXQgaW1wbGVtZW50cyByZXNvbHZlTGF0ZXN0RGVwbG95bWVudElkKClcIlxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZGVwbG95bWVudElkID0gYXdhaXQgd29ybGQucmVzb2x2ZUxhdGVzdERlcGxveW1lbnRJZCgpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gICAgICAvLyBHZW5lcmF0ZSBydW5JZCBjbGllbnQtc2lkZSBzbyB3ZSBoYXZlIGl0IGJlZm9yZSBzZXJpYWxpemF0aW9uXG4gICAgICAvLyAocmVxdWlyZWQgZm9yIGZ1dHVyZSBFMkUgZW5jcnlwdGlvbiB3aGVyZSBydW5JZCBpcyBwYXJ0IG9mIHRoZSBlbmNyeXB0aW9uIGNvbnRleHQpXG4gICAgICBjb25zdCBydW5JZCA9IGB3cnVuXyR7dWxpZCgpfWA7XG5cbiAgICAgIC8vIFNlcmlhbGl6ZSBjdXJyZW50IHRyYWNlIGNvbnRleHQgdG8gcHJvcGFnYXRlIGFjcm9zcyBxdWV1ZSBib3VuZGFyeVxuICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCk7XG5cbiAgICAgIC8vIFVzZSB3b3JsZC1kZWNsYXJlZCBzcGVjVmVyc2lvbiB3aGVuIGF2YWlsYWJsZSAob3VyIHdvcmxkcyBzZXQgdGhpcyksXG4gICAgICAvLyBvdGhlcndpc2UgZmFsbCBiYWNrIHRvIHRoZSBzYWZlIGJhc2VsaW5lIHRoYXQgY29tbXVuaXR5IHdvcmxkcyBoYW5kbGUuXG4gICAgICAvLyBDb21tdW5pdHkgd29ybGRzIGJ1aWx0IGFnYWluc3Qgb2xkZXIgQHdvcmtmbG93L3dvcmxkIHJlamVjdCBydW5zIHdpdGhcbiAgICAgIC8vIHNwZWNWZXJzaW9uID4gdGhlaXIgU1BFQ19WRVJTSU9OX0NVUlJFTlQgdmlhIHJlcXVpcmVzTmV3ZXJXb3JsZCgpLlxuICAgICAgY29uc3Qgc3BlY1ZlcnNpb24gPVxuICAgICAgICBvcHRzLnNwZWNWZXJzaW9uID8/XG4gICAgICAgIHdvcmxkLnNwZWNWZXJzaW9uID8/XG4gICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19FVkVOVF9TT1VSQ0lORztcbiAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihzcGVjVmVyc2lvbik7XG5cbiAgICAgIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoZSBuZXcgcnVuLiBUaGUgcnVuSWQgaGFzIGFscmVhZHkgYmVlblxuICAgICAgLy8gZ2VuZXJhdGVkIGFib3ZlIChjbGllbnQtZ2VuZXJhdGVkIFVMSUQpIGFuZCB3aWxsIGJlIHVzZWQgZm9yIGJvdGhcbiAgICAgIC8vIGtleSBkZXJpdmF0aW9uIGFuZCB0aGUgcnVuX2NyZWF0ZWQgZXZlbnQuIFRoZSBXb3JsZCBpbXBsZW1lbnRhdGlvblxuICAgICAgLy8gdXNlcyB0aGUgcnVuSWQgZm9yIHBlci1ydW4gSEtERiBrZXkgZGVyaXZhdGlvbi4gV2UgcGFzcyB0aGUgcmVzb2x2ZWRcbiAgICAgIC8vIGRlcGxveW1lbnRJZCAobm90IGp1c3QgdGhlIHJhdyBvcHRzKSBzbyB0aGUgV29ybGQgY2FuIHVzZSBpdCBmb3JcbiAgICAgIC8vIGtleSByZXNvbHV0aW9uIGV2ZW4gd2hlbiBkZXBsb3ltZW50SWQgd2FzIGluZmVycmVkIGZyb20gdGhlIGVudmlyb25tZW50XG4gICAgICAvLyByYXRoZXIgdGhhbiBleHBsaWNpdGx5IHByb3ZpZGVkIGluIG9wdHMgKGUuZy4sIGluIGUyZSB0ZXN0IHJ1bm5lcnMpLlxuICAgICAgY29uc3QgcmF3S2V5ID0gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHJ1bklkLCB7XG4gICAgICAgIC4uLm9wdHMsXG4gICAgICAgIGRlcGxveW1lbnRJZCxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZW5jcnlwdGlvbktleSA9IHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xuXG4gICAgICAvLyBDcmVhdGUgcnVuIHZpYSBydW5fY3JlYXRlZCBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAvLyBQYXNzIGNsaWVudC1nZW5lcmF0ZWQgcnVuSWQgLSBzZXJ2ZXIgd2lsbCBhY2NlcHQgYW5kIHVzZSBpdFxuICAgICAgY29uc3Qgd29ya2Zsb3dBcmd1bWVudHMgPSBhd2FpdCBkZWh5ZHJhdGVXb3JrZmxvd0FyZ3VtZW50cyhcbiAgICAgICAgYXJncyxcbiAgICAgICAgcnVuSWQsXG4gICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgIG9wcyxcbiAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgdjFDb21wYXRcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGV4ZWN1dGlvbkNvbnRleHQgPSB7XG4gICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgd29ya2Zsb3dDb3JlVmVyc2lvbixcbiAgICAgICAgZmVhdHVyZXM6IHsgZW5jcnlwdGlvbjogISFlbmNyeXB0aW9uS2V5IH0sXG4gICAgICB9O1xuXG4gICAgICAvLyBDYWxsIGV2ZW50cy5jcmVhdGUgKHJ1bl9jcmVhdGVkKSBhbmQgcXVldWUgaW4gcGFyYWxsZWwuXG4gICAgICAvLyBJZiBldmVudHMuY3JlYXRlIGZhaWxzIHdpdGggNDI5LzV4eCwgdGhlIHJ1biB3YXMgc3RpbGwgYWNjZXB0ZWRcbiAgICAgIC8vIHZpYSB0aGUgcXVldWUgYW5kIGNyZWF0aW9uIHdpbGwgYmUgcmUtdHJpZWQgYXN5bmMgYnkgdGhlIHJ1bnRpbWUuXG4gICAgICBjb25zdCBbcnVuQ3JlYXRlZFJlc3VsdCwgcXVldWVSZXN1bHRdID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICBydW5JZCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdydW5fY3JlYXRlZCcsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbixcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgIGlucHV0OiB3b3JrZmxvd0FyZ3VtZW50cyxcbiAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IHYxQ29tcGF0IH1cbiAgICAgICAgKSxcbiAgICAgICAgd29ybGQucXVldWUoXG4gICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgIC4uLihzcGVjVmVyc2lvbiA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlRcbiAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICBydW5JbnB1dDoge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dDogd29ya2Zsb3dBcmd1bWVudHMsXG4gICAgICAgICAgICAgICAgICAgIGRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICB9IHNhdGlzZmllcyBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gICAgICAgICAge1xuICAgICAgICAgICAgZGVwbG95bWVudElkLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb24sXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgXSk7XG5cbiAgICAgIC8vIFF1ZXVlIGZhaWx1cmUgaXMgYWx3YXlzIGZhdGFsIOKAlCB0aGUgcnVuIHdhcyBub3QgZW5xdWV1ZWRcbiAgICAgIGlmIChxdWV1ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgdGhyb3cgcXVldWVSZXN1bHQucmVhc29uO1xuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgZXZlbnRzLmNyZWF0ZSByZXN1bHRcbiAgICAgIGxldCByZXNpbGllbnRTdGFydCA9IGZhbHNlO1xuICAgICAgaWYgKHJ1bkNyZWF0ZWRSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgIGNvbnN0IGVyciA9IHJ1bkNyZWF0ZWRSZXN1bHQucmVhc29uO1xuICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgLy8gNDA5OiBUaGUgcnVuIGFscmVhZHkgZXhpc3RzLiBUaGlzIGNhbiBoYXBwZW4gaW4gZXh0cmVtZSBjYXNlcyB3aGVyZVxuICAgICAgICAgIC8vIHRoZSBydW4gY3JlYXRpb24gY2FsbCBnZXRzIGEgY29sZCBzdGFydCBvciBvdGhlciBzbG93ZG93biwgYW5kIHRoZSBxdWV1ZVxuICAgICAgICAgIC8vICsgcnVuX3N0YXJ0ZWQgY2FsbCBjb21wbGV0ZXMgZmFzdGVyLiBXZSBleHBlY3QgdGhpcyB0byBiZSA8PTElIG9mIGNhc2VzLlxuICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgd2UgY2FuIHNhZmVseSByZXR1cm4uXG4gICAgICAgIH0gZWxzZSBpZiAoaXNSZXRyeWFibGVTdGFydEVycm9yKGVycikpIHtcbiAgICAgICAgICAvLyA0MjkgKFRocm90dGxlRXJyb3IpIGFuZCA1eHggKFdvcmtmbG93V29ybGRFcnJvciB3aXRoIHN0YXR1cyA+PSA1MDApXG4gICAgICAgICAgLy8gYXJlIHJldHJ5YWJsZSDigJQgdGhlIHJ1biB3YXMgYWNjZXB0ZWQgdmlhIHRoZSBxdWV1ZSBhbmQgY3JlYXRpb25cbiAgICAgICAgICAvLyB3aWxsIGJlIHJlLXRyaWVkIGJ5IHRoZSBydW50aW1lIHdoZW4gaXQgY2FsbHMgcnVuX3N0YXJ0ZWQuXG4gICAgICAgICAgcmVzaWxpZW50U3RhcnQgPSB0cnVlO1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICdSdW4gY3JlYXRpb24gZXZlbnQgZmFpbGVkLCBidXQgdGhlIHJ1biB3YXMgYWNjZXB0ZWQgdmlhIHRoZSBxdWV1ZS4gJyArXG4gICAgICAgICAgICAgICdUaGUgcnVuX2NyZWF0ZWQgZXZlbnQgd2lsbCBiZSByZS10cmllZCBhc3luYyBieSB0aGUgcnVudGltZS4nLFxuICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCwgZXJyb3I6IGVyci5tZXNzYWdlIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gcnVuQ3JlYXRlZFJlc3VsdC52YWx1ZTtcbiAgICAgICAgLy8gQXNzZXJ0IHRoYXQgdGhlIHJ1biB3YXMgY3JlYXRlZFxuICAgICAgICBpZiAoIXJlc3VsdC5ydW4pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICBcIk1pc3NpbmcgJ3J1bicgaW4gc2VydmVyIHJlc3BvbnNlIGZvciAncnVuX2NyZWF0ZWQnIGV2ZW50XCJcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmVyaWZ5IHNlcnZlciBhY2NlcHRlZCBvdXIgcnVuSWRcbiAgICAgICAgaWYgKCF2MUNvbXBhdCAmJiByZXN1bHQucnVuLnJ1bklkICE9PSBydW5JZCkge1xuICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIGBTZXJ2ZXIgcmV0dXJuZWQgZGlmZmVyZW50IHJ1bklkIHRoYW4gcmVxdWVzdGVkOiBleHBlY3RlZCAke3J1bklkfSwgZ290ICR7cmVzdWx0LnJ1bi5ydW5JZH1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB3YWl0VW50aWwoXG4gICAgICAgIFByb21pc2UuYWxsKG9wcykuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIC8vIElnbm9yZSBleHBlY3RlZCBjbGllbnQgZGlzY29ubmVjdCBlcnJvcnMgKGUuZy4sIGJyb3dzZXIgcmVmcmVzaCBkdXJpbmcgc3RyZWFtaW5nKVxuICAgICAgICAgIGNvbnN0IGlzQWJvcnRFcnJvciA9XG4gICAgICAgICAgICBlcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBlcnI/Lm5hbWUgPT09ICdSZXNwb25zZUFib3J0ZWQnO1xuICAgICAgICAgIGlmICghaXNBYm9ydEVycm9yKSB0aHJvdyBlcnI7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuSWQocnVuSWQpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuRGVwbG95bWVudElkKGRlcGxveW1lbnRJZCksXG4gICAgICAgIC4uLihydW5DcmVhdGVkUmVzdWx0LnN0YXR1cyA9PT0gJ2Z1bGZpbGxlZCcgJiZcbiAgICAgICAgcnVuQ3JlYXRlZFJlc3VsdC52YWx1ZS5ydW5cbiAgICAgICAgICA/IEF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cyhydW5DcmVhdGVkUmVzdWx0LnZhbHVlLnJ1bi5zdGF0dXMpXG4gICAgICAgICAgOiB7fSksXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIG5ldyBSdW48VFJlc3VsdD4ocnVuSWQsIHsgcmVzaWxpZW50U3RhcnQgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBlcnJvciBmcm9tIGV2ZW50cy5jcmVhdGUgKHJ1bl9jcmVhdGVkKSBpcyByZXRyeWFibGUsXG4gKiBtZWFuaW5nIHRoZSBxdWV1ZSBjYW4gcmUtdHJ5IGNyZWF0aW9uIGxhdGVyIHZpYSB0aGUgcnVuX3N0YXJ0ZWQgcGF0aC5cbiAqIC0gVGhyb3R0bGVFcnJvciAoNDI5KTogcmF0ZSBsaW1pdGVkLCB3aWxsIHN1Y2NlZWQgbGF0ZXJcbiAqIC0gV29ya2Zsb3dXb3JsZEVycm9yIHdpdGggc3RhdHVzID49IDUwMDogc2VydmVyIGVycm9yLCB3aWxsIHN1Y2NlZWQgbGF0ZXJcbiAqL1xuZnVuY3Rpb24gaXNSZXRyeWFibGVTdGFydEVycm9yKGVycjogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoVGhyb3R0bGVFcnJvci5pcyhlcnIpKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKFdvcmtmbG93V29ybGRFcnJvci5pcyhlcnIpICYmIGVyci5zdGF0dXMgJiYgZXJyLnN0YXR1cyA+PSA1MDApXG4gICAgcmV0dXJuIHRydWU7XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==
478
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9zdGFydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFNakUsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixtQkFBbUIsRUFDbkIsdUJBQXVCLEVBQ3ZCLG1CQUFtQixFQUNuQixxQkFBcUIsRUFDckIsZ0NBQWdDLEVBQ2hDLDBDQUEwQyxFQUMxQyxpQ0FBaUMsRUFDakMsbUJBQW1CLEdBQ3BCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTdDLE9BQU8sRUFDTCxhQUFhLEVBQ2Isa0JBQWtCLEVBQ2xCLGdCQUFnQixHQUNqQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCwwQkFBMEIsRUFFMUIsbUJBQW1CLEVBQ25CLE1BQU0sR0FDUCxNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFB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O1lBQ3RFLCtCQUErQjtZQUMvQixhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUN0QyxhQUFhLENBQUMsSUFBSSxDQUNoQixzREFBc0QsRUFDdEQ7b0JBQ0UsYUFBYSxFQUFFLEtBQUs7b0JBQ3BCLEtBQUssRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO2lCQUN4RCxDQUNGLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksRUFBRSxhQUFhLENBQUM7Z0JBQ2xCLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUM7Z0JBQ2pDLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUM7Z0JBQ3ZDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEtBQUssV0FBVztvQkFDekMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztvQkFDaEUsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUNSLENBQUMsQ0FBQztZQUVILE9BQU8sSUFBSSxHQUFHLENBQVUsS0FBSyxFQUFFLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVudGl0eUNvbmZsaWN0RXJyb3IsIFdvcmtmbG93UnVudGltZUVycm9yIH0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQgeyBnbG9iYWxTaW5nbGV0b24gfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMnO1xuaW1wb3J0IHsgd29ya2Zsb3dEaXNwbGF5TmFtZSB9IGZyb20gJ0B3b3JrZmxvdy91dGlscy9wYXJzZS1uYW1lJztcbmltcG9ydCB0eXBlIHtcbiAgUnVuUmV0ZW50aW9uLFxuICBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gIFdvcmxkLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHtcbiAgSE9PS19SRVNVTUVfSU5QVVRfVkVSU0lPTixcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgUEFSRU5UX1JVTl9JRF9BVFRSSUJVVEUsXG4gIFJFVEVOVElPTl9BVFRSSUJVVEUsXG4gIFJPT1RfUlVOX0lEX0FUVFJJQlVURSxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0FUVFJJQlVURVMsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVCxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OLFxuICB3b3JrZmxvd1J1bklkU2NoZW1hLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgbW9ub3RvbmljRmFjdG9yeSB9IGZyb20gJ3VsaWQnO1xuaW1wb3J0IHsgbm9ybWFsaXplQXR0cmlidXRlQ2hhbmdlcyB9IGZyb20gJy4uL2F0dHJpYnV0ZS1jaGFuZ2VzLmpzJztcbmltcG9ydCB7IGdldFJ1bkNhcGFiaWxpdGllcyB9IGZyb20gJy4uL2NhcGFiaWxpdGllcy5qcyc7XG5pbXBvcnQgeyBpc1JldHJ5YWJsZVdvcmxkRXJyb3IgfSBmcm9tICcuLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBTZXJpYWxpemFibGUgfSBmcm9tICcuLi9zY2hlbWFzLmpzJztcbmltcG9ydCB7XG4gIGJ5dGVzVG9CYXNlNjQsXG4gIGRlY29kZVJ1blB1YmxpY0tleSxcbiAgZGVyaXZlUnVuS2V5UGFpcixcbn0gZnJvbSAnLi4vc2VhbGVkLWJveC5qcyc7XG5pbXBvcnQge1xuICBkZWh5ZHJhdGVXb3JrZmxvd0FyZ3VtZW50cyxcbiAgdHlwZSBQYXlsb2FkS2V5LFxuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxuICBzZWFsVG8sXG59IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgY29udGV4dFN0b3JhZ2UgfSBmcm9tICcuLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IHNlcmlhbGl6ZVRyYWNlQ2FycmllciwgdHJhY2UgfSBmcm9tICcuLi90ZWxlbWV0cnkuanMnO1xuaW1wb3J0IHsgdmVyc2lvbiBhcyB3b3JrZmxvd0NvcmVWZXJzaW9uIH0gZnJvbSAnLi4vdmVyc2lvbi5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UXVldWVOYW1lLCBoZWFsdGhDaGVjayB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBSdW4gfSBmcm9tICcuL3J1bi5qcyc7XG5pbXBvcnQgeyBnZXRXb3JrZmxvd1ZtRnJvbUVudiB9IGZyb20gJy4vdm0tbW9kZS5qcyc7XG5pbXBvcnQgeyBzYWZlV2FpdFVudGlsLCB3YWl0ZWRVbnRpbCB9IGZyb20gJy4vd2FpdC11bnRpbC5qcyc7XG5pbXBvcnQgeyBhc3NlcnRXb3JsZFN1cHBvcnRzUnVudGltZVByb3RvY29sIH0gZnJvbSAnLi93b3JsZC1jb21wYXRpYmlsaXR5LmpzJztcblxuLyoqXG4gKiBUaW1lb3V0IGZvciB0aGUgY3Jvc3MtZGVwbG95bWVudCBjYXBhYmlsaXR5IHByb2JlIGRvbmUgYmVmb3JlXG4gKiBkZWh5ZHJhdGluZyB3b3JrZmxvdyBhcmd1bWVudHMuIEtlcHQgdGlnaHQgb24gcHVycG9zZTogdGhlIHByb2JlIGlzXG4gKiBhbiBvcHRpbWl6YXRpb24gKGl0IGxldHMgdGhlIGNhbGxlciBlbWl0IHRoZSBmcmFtZWQgYnl0ZS1zdHJlYW0gd2lyZVxuICogZm9ybWF0IHdoZW4gdGhlIHRhcmdldCBzdXBwb3J0cyBpdCksIGFuZCB0aGUgZmFsbGJhY2sgb24gdGltZW91dCBpc1xuICogdGhlIGxlZ2FjeSByYXcgZm9ybWF0IHdoaWNoIGFsd2F5cyB3b3Jrcy4gTG9uZyBkZWxheXMgaGVyZSB3b3VsZFxuICogbWFrZSBgc3RhcnQoeyBkZXBsb3ltZW50SWQ6IC4uLiB9KWAgc2xvd2VyIGZvciB1c2VycyB3aG9zZSB0YXJnZXRcbiAqIGRlcGxveW1lbnRzIGRvbid0IHJlY29nbml6ZSB0aGUgaGVhbHRoIGNoZWNrIGF0IGFsbC5cbiAqL1xuY29uc3QgQ1JPU1NfREVQTE9ZTUVOVF9DQVBBQklMSVRZX1BST0JFX1RJTUVPVVRfTVMgPSAyXzAwMDtcblxuLyoqXG4gKiBXaXJlIGVuY29kaW5nIG9mIGByZXRlbnRpb246IDBgLiBBdHRyaWJ1dGUgdmFsdWVzIGFyZSBzdHJpbmdzLCBhbmQgdGhlXG4gKiBgJHJldGVudGlvbmAgdmFsdWUgaXMgYSBkdXJhdGlvbiB3cml0dGVuIGFzIGEgZGVjaW1hbCBpbnRlZ2VyIOKAlCBzbyB6ZXJvXG4gKiB0cmF2ZWxzIGFzIGAnMCdgLCBub3QgYXMgdGhlIG5hbWUgb2YgYSBtb2RlLlxuICovXG5jb25zdCBSRVRFTlRJT05fWkVST19BVFRSSUJVVEVfVkFMVUUgPSAnMCc7XG5cbi8qKiBVTElEIGdlbmVyYXRvciBmb3IgY2xpZW50LXNpZGUgcnVuSWQgZ2VuZXJhdGlvbiAqL1xuY29uc3QgdWxpZCA9IG1vbm90b25pY0ZhY3RvcnkoKTtcblxuLyoqXG4gKiBDcm9zcy1ydW4gbGluZWFnZSBmb3IgYSBydW4gYmVpbmcgc3RhcnRlZCBmcm9tIGluc2lkZSBhbm90aGVyIHJ1bi5cbiAqXG4gKiBUaGUgYW1iaWVudCBzdGVwIGNvbnRleHQgY2FycmllcyB0aGUgcGFyZW50IHJ1biBpZCBhbmQgdGhlIHJvb3Qgb2YgaXRzXG4gKiBsaW5lYWdlOyB0aGUgcnVudGltZSBmaWxscyBib3RoIGZyb20gdGhlIHJ1biBpdCBhbHJlYWR5IGhhcyBsb2FkZWQsIHNvIHRoaXNcbiAqIGlzIGEgcHVyZSBjb250ZXh0IHJlYWQgd2l0aCBubyBJL08uIFRoZSBuZXcgcnVuIHJlY29yZHMgYCRwYXJlbnRSdW5JZGAgKHRoZVxuICogZWRnZSkgYW5kIGluaGVyaXRzIHRoZSBwYXJlbnQncyBgJHJvb3RSdW5JZGAgKHRoZSBwYXJlbnQgaXRzZWxmIHdoZW4gaXQgaXMgYVxuICogcm9vdCksIHNvIGEgZGFpc3kgY2hhaW4gb3IgZmFuLW91dCBvZiBhbnkgZGVwdGggZ3JvdXBzIHVuZGVyIG9uZSByb290IGlkLlxuICogUmV0dXJucyBgdW5kZWZpbmVkYCBmb3IgYSB0b3AtbGV2ZWwgYHN0YXJ0KClgLCB3aGljaCBoYXMgbm8gY29udGV4dCwgc29cbiAqIHN0YW5kYWxvbmUgcnVucyBjYXJyeSBubyBsaW5lYWdlLlxuICovXG5mdW5jdGlvbiByZXNvbHZlTGluZWFnZUF0dHJpYnV0ZXMoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHN0b3JlID0gY29udGV4dFN0b3JhZ2UuZ2V0U3RvcmUoKTtcbiAgY29uc3QgcGFyZW50UnVuSWQgPSBzdG9yZT8ud29ya2Zsb3dNZXRhZGF0YT8ud29ya2Zsb3dSdW5JZDtcbiAgaWYgKCFwYXJlbnRSdW5JZCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICByZXR1cm4ge1xuICAgIFtST09UX1JVTl9JRF9BVFRSSUJVVEVdOiBzdG9yZS5yb290UnVuSWQgPz8gcGFyZW50UnVuSWQsXG4gICAgW1BBUkVOVF9SVU5fSURfQVRUUklCVVRFXTogcGFyZW50UnVuSWQsXG4gIH07XG59XG5cbi8vIGBkZXBsb3ltZW50SWQ6ICdsYXRlc3QnYCBpcyBhIG5vLW9wIGluIFdvcmxkcyB3aXRob3V0IGF0b21pYyBkZXBsb3ltZW50cy5cbi8vIFRoZSB3YXJuaW5nIHRoYXQgZXhwbGFpbnMgdGhpcyBvbmx5IG5lZWRzIHRvIGZpcmUgb25jZSBwZXIgcHJvY2VzczogYVxuLy8gd29ya2Zsb3cgdGhhdCBoYXJkY29kZXMgJ2xhdGVzdCcgZm9yIGl0cyBWZXJjZWwgZGVwbG95bWVudCB3b3VsZCBvdGhlcndpc2Vcbi8vIGxvZyBpdCBvbiBldmVyeSBsb2NhbC9Qb3N0Z3JlcyBydW4sIGZsb29kaW5nIHRpZ2h0IGRldiBsb29wcy5cbi8vIE9uIGBnbG9iYWxUaGlzYCAoc2VlIGBnbG9iYWxTaW5nbGV0b25gKSBzbyBcIm9uY2UgcGVyIHByb2Nlc3NcIiBpcyBub3Qgb25jZVxuLy8gcGVyIGJ1bmRsZXIgbGF5ZXIuXG5jb25zdCBsYXRlc3ROb09wV2FybmluZyA9IGdsb2JhbFNpbmdsZXRvbihcbiAgJ0B3b3JrZmxvdy9jb3JlLy9sYXRlc3ROb09wV2FybmluZycsXG4gIDEsXG4gICgpID0+ICh7IHdhcm5lZDogZmFsc2UgfSlcbik7XG5cbi8qKlxuICogUmVzZXQgdGhlIGBkZXBsb3ltZW50SWQ6ICdsYXRlc3QnYCBuby1vcCB3YXJuLW9uY2UgZ3VhcmQuIFRlc3Qtb25seSxcbiAqIGV4cG9ydGVkIHNvIHVuaXQgdGVzdHMgY2FuIGV4ZXJjaXNlIHRoZSB3YXJuIHBhdGggYWNyb3NzIGBzdGFydCgpYCBjYWxscy5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9yZXNldExhdGVzdE5vT3BXYXJuRm9yVGVzdHMoKTogdm9pZCB7XG4gIGxhdGVzdE5vT3BXYXJuaW5nLndhcm5lZCA9IGZhbHNlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0T3B0aW9uc0Jhc2Uge1xuICAvKipcbiAgICogVGhlIHdvcmxkIHRvIHVzZSBmb3IgdGhlIHdvcmtmbG93IHJ1biBjcmVhdGlvbixcbiAgICogYnkgZGVmYXVsdCB0aGUgd29ybGQgaXMgaW5mZXJyZWQgZnJvbSB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgd29ybGQ/OiBXb3JsZDtcblxuICAvKipcbiAgICogVGhlIHNwZWMgdmVyc2lvbiB0byB1c2UgZm9yIHRoZSB3b3JrZmxvdyBydW4uIERlZmF1bHRzIHRvIHRoZSBsYXRlc3QgdmVyc2lvbi5cbiAgICovXG4gIHNwZWNWZXJzaW9uPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCByZWdpb24gaWRlbnRpZmllciBmb3IgdGhlIG5ldyBydW4uIEN1cnJlbnRseSBjb25zdW1lZCBvbmx5XG4gICAqIGJ5IGBAd29ya2Zsb3cvd29ybGQtdmVyY2VsYCwgd2hpY2ggZW1iZWRzIHRoZSByZWdpb24gaW50byB0aGUgdGFnZ2VkXG4gICAqIHJ1biBJRCBhbmQgcm91dGVzIHRoZSBpbml0aWFsIHdvcmtmbG93IG1lc3NhZ2UgdG8gdGhlIG1hdGNoaW5nXG4gICAqIHJlZ2lvbmFsIHF1ZXVlLiBXaGVuIG9taXR0ZWQsIHRoZSB3b3JsZCBmYWxscyBiYWNrIHRvIGl0cyBvd25cbiAgICogZGVmYXVsdCAoZm9yIGB3b3JsZC12ZXJjZWxgOiB0aGUgYFZFUkNFTF9SRUdJT05gIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCB0aGVuIHRoZSBzZXJ2ZXItc2lkZSBkZWZhdWx0IHJlZ2lvbiBgaWFkMWA7IGEgY29uY3JldGUsXG4gICAqIHJvdXRhYmxlIHJlZ2lvbiBpcyBhbHdheXMgY2hvc2VuKS5cbiAgICpcbiAgICogV29ybGRzIHdpdGhvdXQgYSByZWdpb25hbCBkaW1lbnNpb24gaWdub3JlIHRoaXMgZmllbGQuXG4gICAqL1xuICByZWdpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFBsYWludGV4dCBhdHRyaWJ1dGVzIHRvIHNlZWQgb24gdGhlIHJ1biBhcyBpdCBpcyBjcmVhdGVkLlxuICAgKlxuICAgKiBBdmFpbGFibGUgZm9yIG5hdGl2ZS1hdHRyaWJ1dGVzIHJ1bnMgKHNwZWMgdmVyc2lvbiA0IGFuZCBsYXRlcikuXG4gICAqL1xuICBhdHRyaWJ1dGVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKipcbiAgICogUGVybWl0IHJlc2VydmVkIGAkYC1wcmVmaXhlZCBrZXlzIGluIGBhdHRyaWJ1dGVzYC4gVGhlIGAkYCBuYW1lc3BhY2VcbiAgICogaXMgcmVzZXJ2ZWQgZm9yIGZyYW1ld29yay9saWJyYXJ5IGNvZGUgYnVpbHQgb24gdG9wIG9mIHRoZSB3b3JrZmxvd1xuICAgKiBTREsgKHRlbGVtZXRyeSwgYWdlbnQgbWV0YWRhdGEsIHBsYXRmb3JtLWVtaXR0ZWQgdGFncywgZXRjLik7IHVzZXJcbiAgICogY29kZSBNVVNUIE5PVCB3cml0ZSBrZXlzIGluIGl0LCBhbmQgdmFsaWRhdGlvbiByZWplY3RzIHRoZW0gc29cbiAgICogYWNjaWRlbnRhbCBjb2xsaXNpb25zIHdpdGggdG9vbGluZy1vd25lZCBrZXlzIGNhbid0IHNsaXAgdGhyb3VnaC5cbiAgICpcbiAgICogT25seSBmbGlwIHRoaXMgdG8gYHRydWVgIGlmIHlvdXIgY2FsbGVyIGlzIGl0c2VsZiBhIGZyYW1ld29yayBvclxuICAgKiBsaWJyYXJ5IHRoYXQgb3ducyBhIGAkYC1wcmVmaXhlZCBzdWItbmFtZXNwYWNlIGFuZCBrbm93cyB0aGVcbiAgICogY29udmVudGlvbnMgb2YgYW55IG90aGVyIHRvb2xzIHdyaXRpbmcgaW50byBpdC4gU2FtZSBzZW1hbnRpY3MgYXNcbiAgICogdGhlIGBzZXRBdHRyaWJ1dGVzYCBvcHRpb24gb2YgdGhlIHNhbWUgbmFtZS5cbiAgICovXG4gIGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogU2V0IGEgcHJlZmVyZW5jZSBmb3IgZGF0YSByZXRlbnRpb24gYWZ0ZXIgcnVuIGNvbXBsZXRpb24uXG4gICAqXG4gICAqICoqRXhwZXJpbWVudGFsLioqIEJvdGggdGhlIHVuaXQgYW5kIHRoZSBzZXQgb2YgYWNjZXB0ZWQgdmFsdWVzIGFyZSBleHBlY3RlZFxuICAgKiB0byBjaGFuZ2UuXG4gICAqXG4gICAqIFdvcmxkcyBjb250cm9sIHRoZSByZXRlbnRpb24gb2YgdXNlciBkYXRhIChldmVudCBwYXlsb2FkcyBhbmQgc3RyZWFtXG4gICAqIGNodW5rcyksIHRoZSBldmVudCBsb2csIGFuZCBhbnkgYW5hbHl0aWNzIGRhdGEuIE9wdGlvbnMgYXJlOlxuICAgKiAtIGAnZGVmYXVsdCdgOiBzYW1lIGFzIG9taXNzaW9uLCB0aGUgV29ybGQgd2lsbCBkZWNpZGUuIE9uIFZlcmNlbCwgdGhpc1xuICAgKiAgIGlzIGJhc2VkIG9uIHlvdXIgdGVhbSdzIHBsYW4uXG4gICAqIC0gYDBgOiBkYXRhIGlzIGRlbGV0ZWQgYXMgc29vbiBhcyB5b3VyIHJ1biBjb21wbGV0ZXMgb3IgZmFpbHMuIE9uXG4gICAqICAgVmVyY2VsLCB1c2VyIGRhdGEgaXMgZGVsZXRlZCwgYnV0IG1ldGFkYXRhIG1heSBwZXJzaXN0IGZvciB5b3VyIHBsYW4nc1xuICAgKiAgIGRlZmF1bHQgcmV0ZW50aW9uIHBlcmlvZC5cbiAgICpcbiAgICogVGhlIHZhbHVlIGlzIGEgZHVyYXRpb24sIHdpdGggemVybyBiZWluZyB0aGUgb25seSB2YWxpZCBvcHRpb24gY3VycmVudGx5LlxuICAgKlxuICAgKiAqKktub3duIGxpbWl0YXRpb24gYXQgYDBgLioqIFRoZSBwdXJnZSByYWNlcyB5b3VyIG93biByZWFkIG9mIHRoZSBydW4nc1xuICAgKiByZXN1bHQgYW5kIGdlbmVyYWxseSB3aW5zLCBzbyBgYXdhaXQgcnVuLnJldHVyblZhbHVlYCBvbiBhXG4gICAqIGBleHBlcmltZW50YWxfcmV0ZW50aW9uOiAwYCBydW4gdXN1YWxseSB0aHJvd3MgYFJ1bkV4cGlyZWRFcnJvcmAgcmF0aGVyXG4gICAqIHRoYW4gcmVzb2x2aW5nLiBJZiB5b3UgbmVlZCB0aGUgcmVzdWx0LCByZXR1cm4gaXQgdGhyb3VnaCBhIGNoYW5uZWwgeW91XG4gICAqIGNvbnRyb2wsIGUuZy4gYSBzdGVwIHRoYXQgd3JpdGVzIGl0IHRvIGV4dGVybmFsIHN0b3JhZ2UuXG4gICAqXG4gICAqIFJlY29yZGVkIG9uIHRoZSBydW4gYXMgdGhlIHJlc2VydmVkIGAkcmV0ZW50aW9uYCBhdHRyaWJ1dGUsIHNvIGl0XG4gICAqIHJlcXVpcmVzIGEgV29ybGQgaW1wbGVtZW50aW5nIHNwZWMgdmVyc2lvbiA0IG9yIGxhdGVyLiBgJ2RlZmF1bHQnYCBpc1xuICAgKiBub3Qgd3JpdHRlbiBhdCBhbGwsIGtlZXBpbmcgaXQgZXhhY3RseSBlcXVpdmFsZW50IHRvIG9taXR0aW5nIHRoZVxuICAgKiBvcHRpb24uIFJldGVudGlvbiBpcyBlbmZvcmNlZCBieSB0aGUgV29ybGQ6IHRoZSBmaXJzdC1wYXJ0eSBXb3JsZHNcbiAgICogKFZlcmNlbCwgTG9jYWwsIFBvc3RncmVzKSBpbXBsZW1lbnQgaXQsIGFuZCBhIFdvcmxkIHRoYXQgZG9lcyBub3RcbiAgICogcmVjb2duaXplIHRoZSB2YWx1ZSBrZWVwcyB0aGUgZGF0YS5cbiAgICovXG4gIGV4cGVyaW1lbnRhbF9yZXRlbnRpb24/OiBSdW5SZXRlbnRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBJRCBvZiBhbiBleGlzdGluZyBydW4gdGhpcyBydW4gaXMgYmVpbmcgcmVwbGF5ZWQgZnJvbSwgaWYgYW55LlxuICAgKlxuICAgKiBSZWNvcmRlZCBvbiB0aGUgbmV3IHJ1bidzIGBleGVjdXRpb25Db250ZXh0YCBhcyBgcmVwbGF5ZWRGcm9tUnVuSWRgIHNvXG4gICAqIHRvb2xpbmcgKGUuZy4gdGhlIGRhc2hib2FyZCBydW5zIGxpc3QpIGNhbiBzaG93IHRoYXQgYSBydW4gb3JpZ2luYXRlZCBhc1xuICAgKiBhIHJlcGxheSBhbmQgbGluayBiYWNrIHRvIGl0cyBzb3VyY2UuIFNldCBhdXRvbWF0aWNhbGx5IGJ5XG4gICAqIHtAbGluayByZWNyZWF0ZVJ1bkZyb21FeGlzdGluZ307IHRoZXJlJ3MgdXN1YWxseSBubyByZWFzb24gdG8gcGFzcyBpdFxuICAgKiBkaXJlY3RseS5cbiAgICpcbiAgICogTXVzdCBiZSBhIHJ1biBJRDogYHdydW5fYCBmb2xsb3dlZCBieSBhIDI2LWNoYXIgVUxJRC4gSXQncyBhIGZvcmVpZ24ga2V5XG4gICAqIHRvIHRoZSBzb3VyY2UgcnVuLCBzbyBgc3RhcnQoKWAgdmFsaWRhdGVzIHRoZSBleGFjdCBzaGFwZSBhbmQgcmVqZWN0c1xuICAgKiBhbnl0aGluZyBlbHNlIHJhdGhlciB0aGFuIHBlcnNpc3QgYSBsaW5lYWdlIGxpbmsgdGhhdCBwb2ludHMgYXQgZ2FyYmFnZS5cbiAgICovXG4gIHJlcGxheWVkRnJvbVJ1bklkPzogc3RyaW5nO1xuICAvKipcbiAgICogUXVldWUgbmFtZXNwYWNlIG9mIHRoZSB0YXJnZXQgZGVwbG95bWVudC4gU2NvcGVzIHRoZSB3b3JrZmxvdyBxdWV1ZVxuICAgKiB0b3BpYyB0byBgX197bmFtZXNwYWNlfV93a2Zfd29ya2Zsb3dfKmAgKGUuZy4gYCdldmUnYCkgaW5zdGVhZCBvZiB0aGVcbiAgICogZGVmYXVsdCBgX193a2Zfd29ya2Zsb3dfKmAsIGFuZCBpcyBhbHNvIHVzZWQgZm9yIHRoZSBjcm9zcy1kZXBsb3ltZW50XG4gICAqIGNhcGFiaWxpdHkgcHJvYmUuIEZhbGxzIGJhY2sgdG8gYFdPUktGTE9XX1FVRVVFX05BTUVTUEFDRWAgaW4gdGhlXG4gICAqIGNhbGxpbmcgcHJvY2Vzcy5cbiAgICpcbiAgICogV2l0aGluIGEgZGVwbG95bWVudCB0aGUgZW52IGZhbGxiYWNrIGlzIGNvcnJlY3QuIENyb3NzLWNvbnRleHQgY2FsbGVyc1xuICAgKiAoZS5nLiB0aGUgb2JzZXJ2YWJpbGl0eSBkYXNoYm9hcmQgcmVwbGF5aW5nIGEgcnVuKSBtdXN0IHBhc3MgdGhlXG4gICAqIFRBUkdFVCBkZXBsb3ltZW50J3MgbmFtZXNwYWNlIGV4cGxpY2l0bHk6IHRoZSBlbnYgZmFsbGJhY2sgcmVzb2x2ZXMgaW5cbiAgICogdGhlIGNhbGxlcidzIHByb2Nlc3MsIGFuZCBhIHJ1biBlbnF1ZXVlZCB0byBhIHRvcGljIHRoZSB0YXJnZXQgaGFzIG5vXG4gICAqIGNvbnN1bWVyIGZvciBpcyBuZXZlciBwaWNrZWQgdXAuXG4gICAqL1xuICBuYW1lc3BhY2U/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZCBleHRlbmRzIFN0YXJ0T3B0aW9uc0Jhc2Uge1xuICAvKipcbiAgICogVGhlIGRlcGxveW1lbnQgSUQgdG8gdXNlIGZvciB0aGUgd29ya2Zsb3cgcnVuLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGlzIGlzIGF1dG9tYXRpY2FsbHkgaW5mZXJyZWQgZnJvbSBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICogd2hlbiBkZXBsb3lpbmcgdG8gVmVyY2VsLlxuICAgKlxuICAgKiBTZXQgdG8gYCdsYXRlc3QnYCB0byBhdXRvbWF0aWNhbGx5IHJlc29sdmUgdGhlIG1vc3QgcmVjZW50IGRlcGxveW1lbnRcbiAgICogZm9yIHRoZSBjdXJyZW50IGVudmlyb25tZW50IChzYW1lIHByb2R1Y3Rpb24gdGFyZ2V0IG9yIGdpdCBicmFuY2gpLlxuICAgKiBUaGlzIGlzIG9ubHkgbWVhbmluZ2Z1bCBpbiB3b3JsZHMgd2l0aCBhdG9taWMsIGltbXV0YWJsZSBkZXBsb3ltZW50c1xuICAgKiAoY3VycmVudGx5IFZlcmNlbCkuIEluIG90aGVyIHdvcmxkcyAobG9jYWwgZGV2LCBQb3N0Z3JlcykgdGhlcmUgaXMgbm9cbiAgICogbm90aW9uIG9mIG11bHRpcGxlIGRlcGxveW1lbnRzIHRvIHJlc29sdmUgYmV0d2Vlbiwgc28gYCdsYXRlc3QnYCBoYXMgbm9cbiAgICogZWZmZWN0OiBhIHdhcm5pbmcgaXMgbG9nZ2VkIGFuZCB0aGUgcnVuIHRhcmdldHMgdGhlIGN1cnJlbnQgZGVwbG95bWVudC5cbiAgICpcbiAgICogKipOb3RlOioqIFdoZW4gYGRlcGxveW1lbnRJZGAgaXMgcHJvdmlkZWQsIHRoZSBhcmd1bWVudCBhbmQgcmV0dXJuIHR5cGVzIGJlY29tZSBgdW5rbm93bmBcbiAgICogc2luY2UgdGhlcmUgaXMgbm8gZ3VhcmFudGVlIHRoZSB0eXBlcyB3aWxsIGJlIGNvbnNpc3RlbnQgYWNyb3NzIGRlcGxveW1lbnRzLlxuICAgKi9cbiAgZGVwbG95bWVudElkOiAnbGF0ZXN0JyB8IChzdHJpbmcgJiB7fSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRPcHRpb25zV2l0aG91dERlcGxveW1lbnRJZCBleHRlbmRzIFN0YXJ0T3B0aW9uc0Jhc2Uge1xuICBkZXBsb3ltZW50SWQ/OiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3Igc3RhcnRpbmcgYSB3b3JrZmxvdyBydW4uXG4gKi9cbmV4cG9ydCB0eXBlIFN0YXJ0T3B0aW9ucyA9XG4gIHwgU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZFxuICB8IFN0YXJ0T3B0aW9uc1dpdGhvdXREZXBsb3ltZW50SWQ7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBpbXBvcnRlZCB3b3JrZmxvdyBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IHR5cGUgV29ya2Zsb3dGdW5jdGlvbjxUQXJncyBleHRlbmRzIHVua25vd25bXSwgVFJlc3VsdD4gPSAoXG4gIC4uLmFyZ3M6IFRBcmdzXG4pID0+IFByb21pc2U8VFJlc3VsdD47XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgZ2VuZXJhdGVkIG1ldGFkYXRhIG9mIGEgd29ya2Zsb3cgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCB0eXBlIFdvcmtmbG93TWV0YWRhdGEgPSB7IHdvcmtmbG93SWQ6IHN0cmluZyB9O1xuXG4vKipcbiAqIFN0YXJ0cyBhIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gd29ya2Zsb3cgLSBUaGUgaW1wb3J0ZWQgd29ya2Zsb3cgZnVuY3Rpb24gdG8gc3RhcnQuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgd29ya2Zsb3cgKG9wdGlvbmFsKS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSB3b3JrZmxvdyBydW4gKG9wdGlvbmFsKS5cbiAqIEByZXR1cm5zIFRoZSB1bmlxdWUgcnVuIElEIGZvciB0aGUgbmV3bHkgc3RhcnRlZCB3b3JrZmxvdyBpbnZvY2F0aW9uLlxuICovXG4vLyBPdmVybG9hZHMgd2l0aCBkZXBsb3ltZW50SWQgLSBhcmdzIGFuZCByZXR1cm4gdHlwZSBiZWNvbWUgdW5rbm93blxuLy8gVXNlcyBnZW5lcmljcyBzbyB0eXBlZCB3b3JrZmxvd3MgYXJlIGFzc2lnbmFibGUgKGF2b2lkcyBjb250cmF2YXJpYW5jZSBpc3N1ZXMpLFxuLy8gYnV0IHRoZSByZXR1cm4gdHlwZSBhbmQgYXJncyBhcmUgc3RpbGwgdW5rbm93biBzaW5jZSB0aGUgZGVwbG95ZWQgdmVyc2lvbiBtYXkgZGlmZmVyLlxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnczogdW5rbm93bltdLFxuICBvcHRpb25zOiBTdGFydE9wdGlvbnNXaXRoRGVwbG95bWVudElkXG4pOiBQcm9taXNlPFJ1bjx1bmtub3duPj47XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydDxUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248W10sIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgb3B0aW9uczogU3RhcnRPcHRpb25zV2l0aERlcGxveW1lbnRJZFxuKTogUHJvbWlzZTxSdW48dW5rbm93bj4+O1xuXG4vLyBPdmVybG9hZHMgd2l0aG91dCBkZXBsb3ltZW50SWQgLSBwcmVzZXJ2ZSB0eXBlIGluZmVyZW5jZVxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnczogVEFyZ3MsXG4gIG9wdGlvbnM/OiBTdGFydE9wdGlvbnNXaXRob3V0RGVwbG95bWVudElkXG4pOiBQcm9taXNlPFJ1bjxUUmVzdWx0Pj47XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydDxUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248W10sIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgb3B0aW9ucz86IFN0YXJ0T3B0aW9uc1dpdGhvdXREZXBsb3ltZW50SWRcbik6IFByb21pc2U8UnVuPFRSZXN1bHQ+PjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0PFRBcmdzIGV4dGVuZHMgdW5rbm93bltdLCBUUmVzdWx0PihcbiAgd29ya2Zsb3c6IFdvcmtmbG93RnVuY3Rpb248VEFyZ3MsIFRSZXN1bHQ+IHwgV29ya2Zsb3dNZXRhZGF0YSxcbiAgYXJnc09yT3B0aW9ucz86IFRBcmdzIHwgU3RhcnRPcHRpb25zLFxuICBvcHRpb25zPzogU3RhcnRPcHRpb25zXG4pIHtcbiAgJ3VzZSBzdGVwJztcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHRoaXMgZmllbGQgaXMgYWRkZWQgYnkgb3VyIGNsaWVudCB0cmFuc2Zvcm1cbiAgICBjb25zdCB3b3JrZmxvd05hbWUgPSB3b3JrZmxvdz8ud29ya2Zsb3dJZDtcblxuICAgIGlmICghd29ya2Zsb3dOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgIGAnc3RhcnQnIHJlY2VpdmVkIGFuIGludmFsaWQgd29ya2Zsb3cgZnVuY3Rpb24uIEVuc3VyZSB0aGUgV29ya2Zsb3cgU0RLIGlzIGNvbmZpZ3VyZWQgY29ycmVjdGx5IGFuZCB0aGUgZnVuY3Rpb24gaW5jbHVkZXMgYSAndXNlIHdvcmtmbG93JyBkaXJlY3RpdmUuYCxcbiAgICAgICAgeyBzbHVnOiAnc3RhcnQtaW52YWxpZC13b3JrZmxvdy1mdW5jdGlvbicgfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBzcGFuTmFtZSA9IGB3b3JrZmxvdy5zdGFydCAke3dvcmtmbG93RGlzcGxheU5hbWUod29ya2Zsb3dOYW1lKX1gO1xuICAgIHJldHVybiB0cmFjZShzcGFuTmFtZSwgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd09wZXJhdGlvbignc3RhcnQnKSxcbiAgICAgIH0pO1xuXG4gICAgICBsZXQgYXJnczogU2VyaWFsaXphYmxlW10gPSBbXTtcbiAgICAgIGxldCBvcHRzOiBTdGFydE9wdGlvbnMgPSBvcHRpb25zID8/IHt9O1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnc09yT3B0aW9ucykpIHtcbiAgICAgICAgYXJncyA9IGFyZ3NPck9wdGlvbnMgYXMgU2VyaWFsaXphYmxlW107XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmdzT3JPcHRpb25zID09PSAnb2JqZWN0Jykge1xuICAgICAgICBvcHRzID0gYXJnc09yT3B0aW9ucztcbiAgICAgIH1cblxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0FyZ3VtZW50c0NvdW50KGFyZ3MubGVuZ3RoKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB3b3JsZCA9IG9wdHMud29ybGQgPz8gKGF3YWl0IGdldFdvcmxkTGF6eSgpKTtcbiAgICAgIGFzc2VydFdvcmxkU3VwcG9ydHNSdW50aW1lUHJvdG9jb2wod29ybGQpO1xuICAgICAgY29uc3QgY3VycmVudERlcGxveW1lbnRJZCA9IGF3YWl0IHdvcmxkLmdldERlcGxveW1lbnRJZCgpO1xuICAgICAgbGV0IGRlcGxveW1lbnRJZCA9IG9wdHMuZGVwbG95bWVudElkID8/IGN1cnJlbnREZXBsb3ltZW50SWQ7XG5cbiAgICAgIC8vIFdoZW4gJ2xhdGVzdCcgaXMgcmVxdWVzdGVkLCByZXNvbHZlIHRoZSBhY3R1YWwgbGF0ZXN0IGRlcGxveW1lbnQgSURcbiAgICAgIC8vIGZvciB0aGUgY3VycmVudCBkZXBsb3ltZW50J3MgZW52aXJvbm1lbnQgKHNhbWUgcHJvZHVjdGlvbiB0YXJnZXQgb3JcbiAgICAgIC8vIHNhbWUgZ2l0IGJyYW5jaCBmb3IgcHJldmlldyBkZXBsb3ltZW50cykuXG4gICAgICAvL1xuICAgICAgLy8gUmVzb2x2aW5nICdsYXRlc3QnIG9ubHkgbWVhbnMgc29tZXRoaW5nIGluIHdvcmxkcyB3aXRoIGF0b21pYyxcbiAgICAgIC8vIGltbXV0YWJsZSBkZXBsb3ltZW50cyAoZS5nLiBWZXJjZWwpLCB3aGljaCBpbXBsZW1lbnRcbiAgICAgIC8vIHJlc29sdmVMYXRlc3REZXBsb3ltZW50SWQoKS4gV29ybGRzIHdpdGhvdXQgdGhhdCBjb25jZXB0IChsb2NhbCBkZXYsXG4gICAgICAvLyBzZWxmLWhvc3RlZCBQb3N0Z3JlcykgaGF2ZSBub3RoaW5nIHRvIHJlc29sdmUgYmV0d2Vlbiwgc28gcmF0aGVyIHRoYW5cbiAgICAgIC8vIGZhaWwgYSBydW4gdGhhdCB3b3JrcyBmaW5lIG9uIFZlcmNlbCwgd2Ugd2FybiBhbmQgZmFsbCBiYWNrIHRvIHRoZVxuICAgICAgLy8gY3VycmVudCBkZXBsb3ltZW50LCBtYWtpbmcgJ2xhdGVzdCcgYW4gZWZmZWN0aXZlIG5vLW9wIHRoZXJlLlxuICAgICAgaWYgKGRlcGxveW1lbnRJZCA9PT0gJ2xhdGVzdCcpIHtcbiAgICAgICAgaWYgKHdvcmxkLnJlc29sdmVMYXRlc3REZXBsb3ltZW50SWQpIHtcbiAgICAgICAgICBkZXBsb3ltZW50SWQgPSBhd2FpdCB3b3JsZC5yZXNvbHZlTGF0ZXN0RGVwbG95bWVudElkKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gV2FybiBvbmNlIHBlciBwcm9jZXNzOyBzZWUgbGF0ZXN0Tm9PcFdhcm5pbmcud2FybmVkIGFib3ZlLlxuICAgICAgICAgIGlmICghbGF0ZXN0Tm9PcFdhcm5pbmcud2FybmVkKSB7XG4gICAgICAgICAgICBsYXRlc3ROb09wV2FybmluZy53YXJuZWQgPSB0cnVlO1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICBcImRlcGxveW1lbnRJZDogJ2xhdGVzdCcgaGFzIG5vIGVmZmVjdCBpbiB0aGlzIHdvcmxkIGFuZCB3YXMgaWdub3JlZC4gXCIgK1xuICAgICAgICAgICAgICAgICdJdCBpcyBvbmx5IHN1cHBvcnRlZCBieSB3b3JsZHMgd2l0aCBhdG9taWMgZGVwbG95bWVudHMsIHN1Y2ggYXMgVmVyY2VsLiAnICtcbiAgICAgICAgICAgICAgICAnVGhlIHJ1biB3aWxsIHRhcmdldCB0aGUgY3VycmVudCBkZXBsb3ltZW50LicsXG4gICAgICAgICAgICAgIHsgY3VycmVudERlcGxveW1lbnRJZCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZXBsb3ltZW50SWQgPSBjdXJyZW50RGVwbG95bWVudElkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIERlY2lkZSB3aGV0aGVyIHRvIHdyaXRlIGJ5dGUgc3RyZWFtcyBpbiB0aGUgZnJhbWVkIHdpcmUgZm9ybWF0LlxuICAgICAgLy8gRm9yIHNhbWUtZGVwbG95bWVudCBzdGFydHMgKHRoZSBjb21tb24gY2FzZSkgd2Uga25vdyB0aGUgdGFyZ2V0IGlzXG4gICAgICAvLyBydW5uaW5nIHRoaXMgc2FtZSBTREsgdmVyc2lvbiwgc28gZnJhbWluZyBpcyBzYWZlLiBGb3IgY3Jvc3MtXG4gICAgICAvLyBkZXBsb3ltZW50IHN0YXJ0cyAoZXhwbGljaXQgZGVwbG95bWVudElkIG9yICdsYXRlc3QnIHRoYXQgcmVzb2x2ZXNcbiAgICAgIC8vIHRvIGEgZGlmZmVyZW50IGRlcGxveW1lbnQpIHdlIHByb2JlIHRoZSB0YXJnZXQgdmlhIGhlYWx0aENoZWNrIHRvXG4gICAgICAvLyBsZWFybiBpdHMgd29ya2Zsb3ctY29yZSB2ZXJzaW9uLCB0aGVuIGRlcml2ZSB0aGUgY2FwYWJpbGl0eS4gVGhlXG4gICAgICAvLyBwcm9iZSBoYXMgYSB0aWdodCB0aW1lb3V0OiBvbiBtaXNzL2ZhaWx1cmUgd2UgZmFsbCBiYWNrIHRvIHRoZVxuICAgICAgLy8gbGVnYWN5IHJhdyBieXRlIGZvcm1hdCwgd2hpY2ggaXMgdW5pdmVyc2FsbHkgcmVhZGFibGUuXG4gICAgICAvL1xuICAgICAgLy8gV29ybGRzIHRoYXQgZG9uJ3QgZXhwb3NlIHRoZSBgc3RyZWFtc2AgQVBJIChlLmcuIG1pbmltYWwgdGVzdFxuICAgICAgLy8gbW9ja3MpIGNhbid0IHNlcnZpY2UgaGVhbHRoIGNoZWNrcywgc28gd2Ugc2tpcCB0aGUgcHJvYmUgZm9yIHRoZW0uXG4gICAgICAvLyBHZW5lcmF0ZSBydW5JZCBjbGllbnQtc2lkZSBzbyB3ZSBoYXZlIGl0IGJlZm9yZSBzZXJpYWxpemF0aW9uXG4gICAgICAvLyAocmVxdWlyZWQgZm9yIGZ1dHVyZSBFMkUgZW5jcnlwdGlvbiB3aGVyZSBydW5JZCBpcyBwYXJ0IG9mIHRoZVxuICAgICAgLy8gZW5jcnlwdGlvbiBjb250ZXh0KS4gV2hlbiB0aGUgV29ybGQgcHJvdmlkZXMgYSBgY3JlYXRlUnVuSWQoKWBcbiAgICAgIC8vIGltcGxlbWVudGF0aW9uLCB1c2UgaXQgc28gd29ybGRzIGNhbiBlbWJlZCBpbXBsZW1lbnRhdGlvbi1zcGVjaWZpY1xuICAgICAgLy8gbWV0YWRhdGEgKGUuZy4sIHJlZ2lvbikgaW50byB0aGUgSUQsIGZvcndhcmRpbmcgdGhlIGZ1bGwgb3B0aW9uc1xuICAgICAgLy8gYmFnIHNvIHdvcmxkcyBjYW4gcmVhZCB3aGljaGV2ZXIgZmllbGRzIHRoZXkgcmVjb2duaXNlOyBvdGhlcndpc2VcbiAgICAgIC8vIGZhbGwgYmFjayB0byBhIHN0YW5kYXJkIG1vbm90b25pYyBVTElELlxuICAgICAgY29uc3QgcnVuSWQgPSBgd3J1bl8ke1xuICAgICAgICB3b3JsZC5jcmVhdGVSdW5JZFxuICAgICAgICAgID8gd29ybGQuY3JlYXRlUnVuSWQob3B0cyBhcyBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pXG4gICAgICAgICAgOiB1bGlkKClcbiAgICAgIH1gO1xuXG4gICAgICBsZXQgZnJhbWVkQnl0ZVN0cmVhbXM6IGJvb2xlYW47XG4gICAgICBsZXQgdGFyZ2V0U3VwcG9ydHNDb21wcmVzc2lvbjogYm9vbGVhbjtcbiAgICAgIC8vIFRoZSBjb25zdW1lcidzIGhvb2stcmVzdW1lIHByb3RvY29sIHZlcnNpb24sIHN0YW1wZWQgb250byB0aGUgbmV3XG4gICAgICAvLyBydW4uIEN1cnJlbnQgcHJvZHVjZXJzIHdyaXRlIHRoZSBob29rX3JlY2VpdmVkIGV2ZW50IGR1cmFibHkgYmVmb3JlXG4gICAgICAvLyBwdWJsaXNoaW5nIHRoZSB3YWtlIGFuZCBuZXZlciByZWFkIGl0OyBPTERFUiBwcm9kdWNlcnMgZ2F0ZSB0aGVpclxuICAgICAgLy8gbGF6eSAoaG9va0lucHV0LWNhcnJ5aW5nKSBwYXRoIG9uIHRoZSBkZXBsb3ltZW50IHRoYXQgd2lsbCBhY3R1YWxseVxuICAgICAgLy8gY29uc3VtZSB0aGUgcXVldWUgbWVzc2FnZS4gYHVuZGVmaW5lZGAgbWVhbnMgXCJjb3VsZCBub3QgYXR0ZXN0XCIgYW5kXG4gICAgICAvLyBmYWlscyB0aGF0IGdhdGUgY2xvc2VkLlxuICAgICAgbGV0IHRhcmdldEhvb2tSZXN1bWVJbnB1dFZlcnNpb246IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgIC8vIFB1YmxpYyBrZXkgb2YgdGhlIHRhcmdldCBydW4sIHdoZW4gdGhlIGNhcGFiaWxpdHkgcHJvYmUgd2FzIGFibGUgdG9cbiAgICAgIC8vIHN1cHBseSBvbmUgKGNyb3NzLWRlcGxveW1lbnQgb25seSkuXG4gICAgICBsZXQgcHJvYmVkUnVuUHVibGljS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoZGVwbG95bWVudElkID09PSBjdXJyZW50RGVwbG95bWVudElkKSB7XG4gICAgICAgIGZyYW1lZEJ5dGVTdHJlYW1zID0gdHJ1ZTtcbiAgICAgICAgdGFyZ2V0U3VwcG9ydHNDb21wcmVzc2lvbiA9IHRydWU7XG4gICAgICAgIC8vIFNhbWUgZGVwbG95bWVudDogdGhpcyBwcm9jZXNzIGlzIHRoZSBjb25zdW1lciwgc28gaXRzIG93biBjb25zdGFudFxuICAgICAgICAvLyBpcyBhdXRob3JpdGF0aXZlLlxuICAgICAgICB0YXJnZXRIb29rUmVzdW1lSW5wdXRWZXJzaW9uID0gSE9PS19SRVNVTUVfSU5QVVRfVkVSU0lPTjtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHdvcmxkLnN0cmVhbXM/LmdldCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBmcmFtZWRCeXRlU3RyZWFtcyA9IGZhbHNlO1xuICAgICAgICB0YXJnZXRTdXBwb3J0c0NvbXByZXNzaW9uID0gZmFsc2U7XG4gICAgICAgIC8vIE5vIHByb2JlIGNoYW5uZWwgdG8gdGhlIHRhcmdldCwgc28gd2UgY2Fubm90IGF0dGVzdCB0aGUgY29uc3VtZXJcbiAgICAgICAgLy8gaG9ub3JzIGBob29rSW5wdXRgOyBsZWF2ZSB0aGUgbWFya2VyIG9mZiAob2xkZXIgcHJvZHVjZXJzIGZhaWxcbiAgICAgICAgLy8gY2xvc2VkIHRvIHRoZWlyIHNlcXVlbnRpYWwgcGF0aCkuXG4gICAgICAgIHRhcmdldEhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBc2sgZm9yIHRoaXMgcnVuJ3MgcHVibGljIGtleSB3aGlsZSB3ZSdyZSBoZXJlLiBUaGUgcHJvYmUgYWxyZWFkeVxuICAgICAgICAvLyBibG9ja3MgYHN0YXJ0KClgIG9uIGV2ZXJ5IGNyb3NzLWRlcGxveW1lbnQgY2FsbCwgYW5kIHRoZSByZXNwb25kZXJcbiAgICAgICAgLy8gZXhlY3V0ZXMgaW5zaWRlIHRoZSB0YXJnZXQgZGVwbG95bWVudCB3aGVyZSB0aGUga2V5IG1hdGVyaWFsIGlzXG4gICAgICAgIC8vIGxvY2FsLCBzbyB0aGUga2V5IGNvbWVzIGJhY2sgZm9yIGZyZWUgb24gYSByZXNwb25zZSB3ZSBhcmVcbiAgICAgICAgLy8gYWxyZWFkeSBhd2FpdGluZywgYW5kIHdlIGNhbiBza2lwIHRoZSBrZXktbG9va3VwIEFQSSByZXF1ZXN0XG4gICAgICAgIC8vIGVudGlyZWx5LiBCZXN0LWVmZm9ydDogb24gdGltZW91dCBvciBhbiBvbGRlciB0YXJnZXQsIG5vIGtleSBjb21lc1xuICAgICAgICAvLyBiYWNrIGFuZCB3ZSBmYWxsIHRocm91Z2ggdG8gdGhlIHJlZ3VsYXIgbG9va3VwIGJlbG93LlxuICAgICAgICBjb25zdCBwcm9iZSA9IGF3YWl0IGhlYWx0aENoZWNrKHdvcmxkLCB7XG4gICAgICAgICAgZGVwbG95bWVudElkLFxuICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgIHRpbWVvdXQ6IENST1NTX0RFUExPWU1FTlRfQ0FQQUJJTElUWV9QUk9CRV9USU1FT1VUX01TLFxuICAgICAgICAgIG5hbWVzcGFjZTogb3B0cy5uYW1lc3BhY2UsXG4gICAgICAgIH0pLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgIHByb2JlZFJ1blB1YmxpY0tleSA9IHByb2JlPy5lbmNyeXB0aW9uUHVibGljS2V5O1xuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMocHJvYmU/LndvcmtmbG93Q29yZVZlcnNpb24pO1xuICAgICAgICBmcmFtZWRCeXRlU3RyZWFtcyA9IGNhcGFiaWxpdGllcy5mcmFtZWRCeXRlU3RyZWFtcztcbiAgICAgICAgdGFyZ2V0U3VwcG9ydHNDb21wcmVzc2lvbiA9IGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhcbiAgICAgICAgICBTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVBcbiAgICAgICAgKTtcbiAgICAgICAgLy8gVGhlIHJlc3BvbmRlciBydW5zIGluc2lkZSB0aGUgdGFyZ2V0IGRlcGxveW1lbnQsIHNvIGl0c1xuICAgICAgICAvLyBgaG9va1Jlc3VtZUlucHV0VmVyc2lvbmAgcmVmbGVjdHMgdGhlIGNvbnN1bWVyLiBVbmRlZmluZWQgb24gYW5cbiAgICAgICAgLy8gb2xkZXIgdGFyZ2V0IG9yIGEgcHJvYmUgdGltZW91dCwgbGVhdmluZyB0aGUgbWFya2VyIG9mZi5cbiAgICAgICAgdGFyZ2V0SG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9IHByb2JlPy5ob29rUmVzdW1lSW5wdXRWZXJzaW9uO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gICAgICAvLyBTZXJpYWxpemUgY3VycmVudCB0cmFjZSBjb250ZXh0IHRvIHByb3BhZ2F0ZSBhY3Jvc3MgcXVldWUgYm91bmRhcnlcbiAgICAgIGNvbnN0IHRyYWNlQ2FycmllciA9IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpO1xuXG4gICAgICAvLyBEZWZhdWx0IG5ldyBydW5zIHRvIHRoZSBjb25maWd1cmVkIHdvcmxkJ3Mgc3BlYyB2ZXJzaW9uLiBUaGUgd29ybGRcbiAgICAgIC8vIGl0c2VsZiBoYXMgYWxyZWFkeSBiZWVuIGNoZWNrZWQgYWdhaW5zdCB0aGlzIHJ1bnRpbWUncyBzcGVjIHZlcnNpb24uXG4gICAgICBjb25zdCBzcGVjVmVyc2lvbiA9IG9wdHMuc3BlY1ZlcnNpb24gPz8gd29ybGQuc3BlY1ZlcnNpb247XG4gICAgICBjb25zdCB2MUNvbXBhdCA9IGlzTGVnYWN5U3BlY1ZlcnNpb24oc3BlY1ZlcnNpb24pO1xuICAgICAgY29uc3QgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXMgPSBvcHRzLmFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzID09PSB0cnVlO1xuICAgICAgbGV0IGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAob3B0cy5hdHRyaWJ1dGVzICYmIE9iamVjdC5rZXlzKG9wdHMuYXR0cmlidXRlcykubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAoc3BlY1ZlcnNpb24gPCBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQVRUUklCVVRFUykge1xuICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgICdJbml0aWFsIHdvcmtmbG93IGF0dHJpYnV0ZXMgcmVxdWlyZSBhIFdvcmxkIHRoYXQgc3VwcG9ydHMgc3BlYyB2ZXJzaW9uIDQgb3IgbGF0ZXIuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYG5vcm1hbGl6ZUF0dHJpYnV0ZUNoYW5nZXNgIHRyZWF0cyBgdW5kZWZpbmVkYCBhcyBcInJlbW92ZSB0aGlzXG4gICAgICAgIC8vIGtleVwiLCB3aGljaCBpcyBtZWFuaW5nbGVzcyBhdCBjcmVhdGlvbiB0aW1lLiBSZWplY3QgaXQgdXAgZnJvbnRcbiAgICAgICAgLy8gc28gSlMgY2FsbGVycyBnZXQgYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIGEgZG93bnN0cmVhbSBzY2hlbWFcbiAgICAgICAgLy8gZmFpbHVyZSAodGhlIHR5cGVzIGFscmVhZHkgZm9yYmlkIG5vbi1zdHJpbmcgdmFsdWVzKS5cbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMob3B0cy5hdHRyaWJ1dGVzKSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICAgIGBJbml0aWFsIHdvcmtmbG93IGF0dHJpYnV0ZSAke0pTT04uc3RyaW5naWZ5KGtleSl9IG11c3QgYmUgYSBzdHJpbmcgdmFsdWUuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hhbmdlcyA9IG5vcm1hbGl6ZUF0dHJpYnV0ZUNoYW5nZXMob3B0cy5hdHRyaWJ1dGVzLCB7XG4gICAgICAgICAgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXMsXG4gICAgICAgIH0pO1xuICAgICAgICBhdHRyaWJ1dGVzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICAgIGNoYW5nZXMubWFwKCh7IGtleSwgdmFsdWUgfSkgPT4gW2tleSwgdmFsdWUgYXMgc3RyaW5nXSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gYHJldGVudGlvbmAgaXMgdGhlIHR5cGVkIHNwZWxsaW5nIG9mIHRoZSByZXNlcnZlZCBgJHJldGVudGlvbmBcbiAgICAgIC8vIGF0dHJpYnV0ZSwgd2hvc2UgdmFsdWUgaXMgYSBkdXJhdGlvbiB3cml0dGVuIGFzIGEgZGVjaW1hbCBpbnRlZ2VyLlxuICAgICAgLy8gYCdkZWZhdWx0J2AgbWVhbnMgXCJsZXQgdGhlIFdvcmxkIGRlY2lkZVwiLCB3aGljaCBpcyBhbHJlYWR5IHdoYXQgYW5cbiAgICAgIC8vIGFic2VudCBhdHRyaWJ1dGUgbWVhbnMsIHNvIGl0IGlzIG5vdCB3cml0dGVuOiB0aGF0IGtlZXBzXG4gICAgICAvLyBgJ2RlZmF1bHQnYCBleGFjdGx5IGVxdWl2YWxlbnQgdG8gb21pdHRpbmcgdGhlIG9wdGlvbiBhbmQgc3BlbmRzXG4gICAgICAvLyBub25lIG9mIHRoZSBwZXItcnVuIGF0dHJpYnV0ZSBidWRnZXQuXG4gICAgICBsZXQgcmV0ZW50aW9uQXR0cmlidXRlOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKFxuICAgICAgICBvcHRzLmV4cGVyaW1lbnRhbF9yZXRlbnRpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBvcHRzLmV4cGVyaW1lbnRhbF9yZXRlbnRpb24gIT09ICdkZWZhdWx0J1xuICAgICAgKSB7XG4gICAgICAgIC8vIFRoZSB0eXBlcyBhbGxvdyBvbmx5IGAwYCwgYnV0IGFuIHVudHlwZWQgSlMgY2FsbGVyIGNhbiBzdGlsbCBnZXRcbiAgICAgICAgLy8gaGVyZSB3aXRoIHNvbWUgb3RoZXIgZHVyYXRpb24g4oCUIGFuZCB0aGVyZSBpcyBubyB1bml0IHRvIGludGVycHJldFxuICAgICAgICAvLyBpdCBpbiB5ZXQsIHNvIG5vIFdvcmxkIGNhbiBob25vciBpdC4gUmVqZWN0IGl0IHJhdGhlciB0aGFuIHNlZWQgYVxuICAgICAgICAvLyB2YWx1ZSB0aGF0IHdvdWxkIHNpbGVudGx5IHJlc29sdmUgdG8gdGhlIFdvcmxkJ3MgZGVmYXVsdC5cbiAgICAgICAgaWYgKG9wdHMuZXhwZXJpbWVudGFsX3JldGVudGlvbiAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIGBzdGFydCh7IGV4cGVyaW1lbnRhbF9yZXRlbnRpb24gfSkgbXVzdCBiZSAwIG9yICdkZWZhdWx0JzsgcmVjZWl2ZWQgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgb3B0cy5leHBlcmltZW50YWxfcmV0ZW50aW9uXG4gICAgICAgICAgICApfS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3BlY1ZlcnNpb24gPCBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQVRUUklCVVRFUykge1xuICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgICdzdGFydCh7IGV4cGVyaW1lbnRhbF9yZXRlbnRpb24gfSkgcmVxdWlyZXMgYSBXb3JsZCB0aGF0IHN1cHBvcnRzIHNwZWMgdmVyc2lvbiA0IG9yIGxhdGVyLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldGVudGlvbkF0dHJpYnV0ZSA9IHtcbiAgICAgICAgICBbUkVURU5USU9OX0FUVFJJQlVURV06IFJFVEVOVElPTl9aRVJPX0FUVFJJQlVURV9WQUxVRSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gQ3Jvc3MtcnVuIGxpbmVhZ2U6IHRoZSByZXNlcnZlZCBrZXlzIHJpZGUgb24gdGhlIHJ1bidzIGV4aXN0aW5nXG4gICAgICAvLyBhdHRyaWJ1dGVzLCBzbyB0aGV5IGFkZCBubyBleHRyYSB3cml0ZS4gQ2FsbGVyIGF0dHJpYnV0ZXMgYXJlIHNwcmVhZFxuICAgICAgLy8gbGFzdCwgc28gYSBjYWxsZXIgd2l0aCBhbGxvd1Jlc2VydmVkQXR0cmlidXRlcyBjYW4gZGVsaWJlcmF0ZWx5XG4gICAgICAvLyByZS1wYXJlbnQuIGByZXRlbnRpb25gIGlzIHNwcmVhZCBhZnRlciB0aG9zZTogaXQgaXMgdGhlIHN1cHBvcnRlZFxuICAgICAgLy8gc3BlbGxpbmcsIHNvIGl0IHdpbnMgb3ZlciBhIGhhbmQtd3JpdHRlbiBgJHJldGVudGlvbmAgYXR0cmlidXRlLlxuICAgICAgY29uc3QgbGluZWFnZSA9XG4gICAgICAgIHNwZWNWZXJzaW9uID49IFNQRUNfVkVSU0lPTl9TVVBQT1JUU19BVFRSSUJVVEVTXG4gICAgICAgICAgPyByZXNvbHZlTGluZWFnZUF0dHJpYnV0ZXMoKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcnVuQXR0cmlidXRlcyA9XG4gICAgICAgIGxpbmVhZ2UgfHwgcmV0ZW50aW9uQXR0cmlidXRlXG4gICAgICAgICAgPyB7IC4uLmxpbmVhZ2UsIC4uLmF0dHJpYnV0ZXMsIC4uLnJldGVudGlvbkF0dHJpYnV0ZSB9XG4gICAgICAgICAgOiBhdHRyaWJ1dGVzO1xuXG4gICAgICAvLyBTaGFyZWQgYnkgdGhlIHJ1bl9jcmVhdGVkIGV2ZW50IGFuZCB0aGUgcmVzaWxpZW50LXN0YXJ0IHF1ZXVlIGlucHV0LlxuICAgICAgY29uc3QgYXR0cmlidXRlU2VlZCA9IHJ1bkF0dHJpYnV0ZXNcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiBydW5BdHRyaWJ1dGVzLFxuICAgICAgICAgICAgLi4uKGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzIHx8XG4gICAgICAgICAgICBsaW5lYWdlICE9IG51bGwgfHxcbiAgICAgICAgICAgIHJldGVudGlvbkF0dHJpYnV0ZSAhPSBudWxsXG4gICAgICAgICAgICAgID8geyBhbGxvd1Jlc2VydmVkQXR0cmlidXRlczogdHJ1ZSBhcyBjb25zdCB9XG4gICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fTtcblxuICAgICAgLy8gYHJlcGxheWVkRnJvbVJ1bklkYCBpcyBhIGZvcmVpZ24ga2V5IHRvIHRoZSBzb3VyY2UgcnVuOyByZWplY3QgYW55dGhpbmdcbiAgICAgIC8vIHRoYXQgaXNuJ3QgYSByZWFsIHJ1biBJRCBzbyB0aGUgbGluZWFnZSBsaW5rIGNhbid0IHBvaW50IGF0IGdhcmJhZ2UuXG4gICAgICBpZiAoXG4gICAgICAgIG9wdHMucmVwbGF5ZWRGcm9tUnVuSWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAhd29ya2Zsb3dSdW5JZFNjaGVtYS5zYWZlUGFyc2Uob3B0cy5yZXBsYXllZEZyb21SdW5JZCkuc3VjY2Vzc1xuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICBgcmVwbGF5ZWRGcm9tUnVuSWQgbXVzdCBiZSBhIHJ1biBJRCAod3J1bl88dWxpZD4pOyByZWNlaXZlZCAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgU3RyaW5nKG9wdHMucmVwbGF5ZWRGcm9tUnVuSWQpLnNsaWNlKDAsIDY0KVxuICAgICAgICAgICl9LmBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVzb2x2ZSBlbmNyeXB0aW9uIGtleSBmb3IgdGhlIG5ldyBydW4uIFRoZSBydW5JZCBoYXMgYWxyZWFkeSBiZWVuXG4gICAgICAvLyBnZW5lcmF0ZWQgYWJvdmUgKGNsaWVudC1nZW5lcmF0ZWQgVUxJRCkgYW5kIHdpbGwgYmUgdXNlZCBmb3IgYm90aFxuICAgICAgLy8ga2V5IGRlcml2YXRpb24gYW5kIHRoZSBydW5fY3JlYXRlZCBldmVudC4gVGhlIFdvcmxkIGltcGxlbWVudGF0aW9uXG4gICAgICAvLyB1c2VzIHRoZSBydW5JZCBmb3IgcGVyLXJ1biBIS0RGIGtleSBkZXJpdmF0aW9uLiBXZSBwYXNzIHRoZSByZXNvbHZlZFxuICAgICAgLy8gZGVwbG95bWVudElkIChub3QganVzdCB0aGUgcmF3IG9wdHMpIHNvIHRoZSBXb3JsZCBjYW4gdXNlIGl0IGZvclxuICAgICAgLy8ga2V5IHJlc29sdXRpb24gZXZlbiB3aGVuIGRlcGxveW1lbnRJZCB3YXMgaW5mZXJyZWQgZnJvbSB0aGUgZW52aXJvbm1lbnRcbiAgICAgIC8vIHJhdGhlciB0aGFuIGV4cGxpY2l0bHkgcHJvdmlkZWQgaW4gb3B0cyAoZS5nLiwgaW4gZTJlIHRlc3QgcnVubmVycykuXG4gICAgICAvLyBSZXNvbHZlIGhvdyB0byBlbmNyeXB0IHRoZSB3b3JrZmxvdyBhcmd1bWVudHMuXG4gICAgICAvL1xuICAgICAgLy8gUHJlZmVycmVkOiB0aGUgY2FwYWJpbGl0eSBwcm9iZSBhbHJlYWR5IHRvbGQgdXMgdGhpcyBydW4ncyBwdWJsaWNcbiAgICAgIC8vIGtleSwgc28gc2VhbCB0byBpdC4gVGhhdCBza2lwcyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdoaWNoIGZvciBhXG4gICAgICAvLyBjcm9zcy1kZXBsb3ltZW50IHN0YXJ0IGlzIGEgYHJ1bi1rZXlgIEFQSSByZXF1ZXN0LCB0aGUgbGFzdCBvbmUgbGVmdFxuICAgICAgLy8gb24gdGhpcyBwYXRoLiBJdCBpcyBhbHNvIGEgcHJpdmlsZWdlIHJlZHVjdGlvbjogdGhlIGNhbGxlciBlbmRzIHVwXG4gICAgICAvLyBhYmxlIHRvIHdyaXRlIHRoZSBhcmd1bWVudHMgYnV0IG5vdCByZWFkIHRoZW0gYmFjaywgd2hlcmVhcyBmZXRjaGluZ1xuICAgICAgLy8gdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGZ1bGwgcmVhZCBhY2Nlc3MgdG8gYSBydW4gaXQgbWVyZWx5XG4gICAgICAvLyBsYXVuY2hlZC5cbiAgICAgIGNvbnN0IHByb2JlZFB1YmxpY0tleSA9IGRlY29kZVJ1blB1YmxpY0tleShwcm9iZWRSdW5QdWJsaWNLZXkpO1xuXG4gICAgICBsZXQgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbiAgICAgIGxldCBlbmNyeXB0aW9uUHVibGljS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChwcm9iZWRQdWJsaWNLZXkpIHtcbiAgICAgICAgZW5jcnlwdGlvbktleSA9IHNlYWxUbyhwcm9iZWRQdWJsaWNLZXkpO1xuICAgICAgICBlbmNyeXB0aW9uUHVibGljS2V5ID0gcHJvYmVkUnVuUHVibGljS2V5O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmF3S2V5ID0gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHJ1bklkLCB7XG4gICAgICAgICAgLi4ub3B0cyxcbiAgICAgICAgICBkZXBsb3ltZW50SWQsXG4gICAgICAgIH0pO1xuICAgICAgICBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gUHVibGlzaCB0aGUgcnVuJ3MgWDI1NTE5IHB1YmxpYyBrZXkgc28gdGhhdCBjcm9zcy1ydW4gd3JpdGVycyAoYVxuICAgICAgICAvLyBob29rIHJlc3VtcHRpb24gZnJvbSBhbm90aGVyIGRlcGxveW1lbnQsIGEgc2libGluZyB3cml0aW5nIGludG8gYVxuICAgICAgICAvLyBmb3J3YXJkZWQgc3RyZWFtKSBjYW4gc2VhbCBwYXlsb2FkcyAqdG8qIHRoaXMgcnVuIHdpdGhvdXQgaG9sZGluZ1xuICAgICAgICAvLyBpdHMgc3ltbWV0cmljIGtleS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gUHJlc2VuY2Ugb2YgdGhpcyBmaWVsZCBpcyB0aGUgd3JpdGVyLXNpZGUgZ2F0ZSBmb3Igc2VhbGVkXG4gICAgICAgIC8vIGVudmVsb3Blcywgc28gaXQgbXVzdCBvbmx5IGJlIHN0YW1wZWQgd2hlbiB0aGlzIHJ1bnRpbWUgY291bGRcbiAgICAgICAgLy8gaXRzZWxmIG9wZW4gb25lLiBUaGF0IGhvbGRzIGJ5IGNvbnN0cnVjdGlvbiBoZXJlOiBkZXJpdmF0aW9uIGFuZFxuICAgICAgICAvLyBgZW5jcGAgZGlzcGF0Y2ggbGl2ZSBpbiB0aGUgc2FtZSBwYWNrYWdlLCBzbyBhbnkgY29yZSB0aGF0IGNhblxuICAgICAgICAvLyBzdGFtcCBjYW4gYWxzbyBvcGVuLiBSdW5zIGFyZSBwaW5uZWQgdG8gdGhlaXIgY3JlYXRpbmcgZGVwbG95bWVudCxcbiAgICAgICAgLy8gc28gdGhlIGNhcGFiaWxpdHkgdGhpcyBhdHRlc3RzIHRvIGlzIHN0aWxsIGFjY3VyYXRlIGF0IHJlc3VtZSB0aW1lLlxuICAgICAgICBlbmNyeXB0aW9uUHVibGljS2V5ID0gcmF3S2V5XG4gICAgICAgICAgPyBieXRlc1RvQmFzZTY0KChhd2FpdCBkZXJpdmVSdW5LZXlQYWlyKHJhd0tleSkpLnB1YmxpY0tleSlcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIHJ1biB2aWEgcnVuX2NyZWF0ZWQgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKVxuICAgICAgLy8gUGFzcyBjbGllbnQtZ2VuZXJhdGVkIHJ1bklkIC0gc2VydmVyIHdpbGwgYWNjZXB0IGFuZCB1c2UgaXRcbiAgICAgIC8vIENvbXByZXNzIHdvcmtmbG93IGFyZ3VtZW50cyBvbmx5IHdoZW4gdGhlIHJ1biBpdHNlbGYgaXMgbWFya2VkIGFzXG4gICAgICAvLyBwb3NzaWJseSBjb250YWluaW5nIGNvbXByZXNzZWQgcGF5bG9hZHMgKHNwZWNWZXJzaW9uID49IDUpIEFORCB0aGVcbiAgICAgIC8vIHRhcmdldCBkZXBsb3ltZW50IGNhbiBkZWNvZGUgdGhlbSAoc2FtZS1kZXBsb3ltZW50LCBvciBwcm9iZWRcbiAgICAgIC8vIGNhcGFiaWxpdHkgZm9yIGNyb3NzLWRlcGxveW1lbnQgc3RhcnRzKS5cbiAgICAgIGNvbnN0IGNvbXByZXNzaW9uID1cbiAgICAgICAgdGFyZ2V0U3VwcG9ydHNDb21wcmVzc2lvbiAmJlxuICAgICAgICBzcGVjVmVyc2lvbiA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT047XG4gICAgICBjb25zdCB3b3JrZmxvd0FyZ3VtZW50cyA9IGF3YWl0IGRlaHlkcmF0ZVdvcmtmbG93QXJndW1lbnRzKFxuICAgICAgICBhcmdzLFxuICAgICAgICBydW5JZCxcbiAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgb3BzLFxuICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICB2MUNvbXBhdCxcbiAgICAgICAgZnJhbWVkQnl0ZVN0cmVhbXMsXG4gICAgICAgIGNvbXByZXNzaW9uXG4gICAgICApO1xuXG4gICAgICAvLyBUaGUgZW52aXJvbm1lbnQgdGhpcyBjYWxsZXIncyBvd24gYHJ1bl9jcmVhdGVkYCB3cml0ZSBpcyBhdHRyaWJ1dGVkXG4gICAgICAvLyB0by4gU3RhbXBlZCBpbnRvIHRoZSBxdWV1ZSBtZXNzYWdlJ3MgYHJ1bklucHV0YCAoTk9UIGludG9cbiAgICAgIC8vIGBydW5fY3JlYXRlZGAsIHdob3NlIHRlbmFudCB0aGUgYmFja2VuZCBhbHJlYWR5IGtub3dzKSBzbyB0aGVcbiAgICAgIC8vIGRlcGxveW1lbnQgdGhhdCBjb25zdW1lcyB0aGUgbWVzc2FnZSBjYW4gdGVsbCB3aGV0aGVyIHRoZSBydW4gaXQgaXNcbiAgICAgIC8vIGJlaW5nIGFza2VkIHRvIHJlc2lsaWVudGx5IGNyZWF0ZSB3YXMgY3JlYXRlZCBhZ2FpbnN0IGEgZGlmZmVyZW50XG4gICAgICAvLyBlbnZpcm9ubWVudCB0aGFuIGl0cyBvd24uXG4gICAgICAvL1xuICAgICAgLy8gVGhlIHR3byB3cml0ZXMgYmVsb3cgZ28gdG8gZGlmZmVyZW50IHBsYWNlcyBieSBkaWZmZXJlbnQgcm91dGVzOlxuICAgICAgLy8gYGV2ZW50cy5jcmVhdGVgIGlzIGF0dHJpYnV0ZWQgdG8gVEhJUyBjbGllbnQncyB0ZW5hbnQsIHdoaWxlIHRoZSBxdWV1ZVxuICAgICAgLy8gbWVzc2FnZSBpcyBwaW5uZWQgdG8gYSBkZXBsb3ltZW50SWQuIFdoZW4gdGhvc2UgZGlzYWdyZWUgKGFcbiAgICAgIC8vIHByb2R1Y3Rpb24tY3JlZGVudGlhbGVkIGNsaWVudCBwaW5uaW5nIGEgcHJldmlldyBkZXBsb3ltZW50KSB0aGVcbiAgICAgIC8vIHByZXZpZXcgY29uc3VtZXIgY2FuJ3QgZmluZCB0aGUgcnVuIGluIGl0cyBvd24gdGVuYW50LCBmYWxscyBiYWNrIHRvXG4gICAgICAvLyByZXNpbGllbnQgc3RhcnQsIGFuZCByZS1jcmVhdGVzIGl0OiBvbmUgY2xpZW50LW1pbnRlZCBydW4gaWQsIHR3b1xuICAgICAgLy8gZW52aXJvbm1lbnRzLCB0aGUgcHJvZHVjdGlvbiBjb3B5IHBlbmRpbmcgZm9yZXZlciBhbmQgdGhlIHByZXZpZXcgY29weVxuICAgICAgLy8gZXhlY3V0aW5nLiBXb3JsZHMgd2l0aCBhIHNpbmdsZSB0ZW5hbnQgcmV0dXJuIHVuZGVmaW5lZCBhbmQgdGhlIGZpZWxkXG4gICAgICAvLyBpcyBhYnNlbnQuXG4gICAgICBjb25zdCBjcmVhdG9yRW52aXJvbm1lbnQgPSB3b3JsZC5nZXRFbnZpcm9ubWVudD8uKCk7XG5cbiAgICAgIC8vIElmIFdPUktGTE9XX1ZNIGlzIHNldCBvbiB0aGUgY2xpZW50IHN0YXJ0aW5nIHRoZSBydW4sIHN0YW1wIHRoZVxuICAgICAgLy8gZW5naW5lIGNob2ljZSBpbnRvIHRoZSBydW4ncyBleGVjdXRpb25Db250ZXh0IHNvIHRoZSBydW4ga2VlcHNcbiAgICAgIC8vIGV4ZWN1dGluZyBvbiB0aGUgZW5naW5lIGl0IHN0YXJ0ZWQgb24gKHRoZSBzYW1lIGRlcGxveW1lbnQgY2FuXG4gICAgICAvLyBzZXJ2ZSBib3RoIFZNIGVuZ2luZXMpLiBVbmtub3duIHZhbHVlcyB0aHJvdzsgc2VlXG4gICAgICAvLyBnZXRXb3JrZmxvd1ZtRnJvbUVudigpLlxuICAgICAgY29uc3Qgd29ya2Zsb3dWbSA9IGdldFdvcmtmbG93Vm1Gcm9tRW52KCk7XG5cbiAgICAgIGNvbnN0IGV4ZWN1dGlvbkNvbnRleHQgPSB7XG4gICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgd29ya2Zsb3dDb3JlVmVyc2lvbixcbiAgICAgICAgZmVhdHVyZXM6IHsgZW5jcnlwdGlvbjogISFlbmNyeXB0aW9uS2V5IH0sXG4gICAgICAgIC8vIEF0dGVzdCB0aGF0IHRoZSAqY29uc3VtZXIqIGRlcGxveW1lbnQncyBydW50aW1lIHJlLWVuc3VyZXMgYVxuICAgICAgICAvLyBgaG9va19yZWNlaXZlZGAgZXZlbnQgZnJvbSBhIHF1ZXVlIG1lc3NhZ2UncyBgaG9va0lucHV0YCBvbiByZXBsYXkuXG4gICAgICAgIC8vIEFuIE9MREVSIHByb2R1Y2VyIHJlc3VtaW5nIHRoaXMgcnVuIHJlYWRzIHRoZSBtYXJrZXIgKG1pcnJvcmVkIG9udG9cbiAgICAgICAgLy8gdGhlIGhvb2sncyByZXN1bWVDb250ZXh0IGJ5IHRoZSBzZXJ2ZXIpIHRvIGRlY2lkZSB3aGV0aGVyIGl0cyBsYXp5XG4gICAgICAgIC8vIGZhc3QgcGF0aCBpcyBzYWZlLiBGb3IgYSBjcm9zcy1kZXBsb3ltZW50IHN0YXJ0IHRoZSBjb25zdW1lciBpcyB0aGVcbiAgICAgICAgLy8gdGFyZ2V0IGRlcGxveW1lbnQsIHNvIHdlIHN0YW1wIHRoZSAqdGFyZ2V0J3MqIHZhbHVlIGNhcnJpZWQgYmFjayBvblxuICAgICAgICAvLyB0aGUgaGVhbHRoLWNoZWNrIHByb2JlLCBuZXZlciB0aGUgY2FsbGVyJ3MuIE9taXR0ZWQgd2hlbiB3ZSBjb3VsZFxuICAgICAgICAvLyBub3QgYXR0ZXN0IHRoZSB0YXJnZXQgKG9sZGVyIHRhcmdldCwgdGltZW91dCwgb3Igbm8gcHJvYmUgY2hhbm5lbCksXG4gICAgICAgIC8vIHdoaWNoIGZhaWxzIHRoZSByZXN1bWUgZ2F0ZSBjbG9zZWQgdG8gdGhlIHNlcXVlbnRpYWwgcGF0aC5cbiAgICAgICAgLi4uKHRhcmdldEhvb2tSZXN1bWVJbnB1dFZlcnNpb24gIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8geyBob29rUmVzdW1lSW5wdXRWZXJzaW9uOiB0YXJnZXRIb29rUmVzdW1lSW5wdXRWZXJzaW9uIH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgICAgLi4uKHdvcmtmbG93Vm0gPyB7IHdvcmtmbG93Vm0gfSA6IHt9KSxcbiAgICAgICAgLi4uKG9wdHMucmVwbGF5ZWRGcm9tUnVuSWRcbiAgICAgICAgICA/IHsgcmVwbGF5ZWRGcm9tUnVuSWQ6IG9wdHMucmVwbGF5ZWRGcm9tUnVuSWQgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgfTtcblxuICAgICAgLy8gQ2FsbCBldmVudHMuY3JlYXRlIChydW5fY3JlYXRlZCkgYW5kIHF1ZXVlIGluIHBhcmFsbGVsLlxuICAgICAgLy8gSWYgZXZlbnRzLmNyZWF0ZSBmYWlscyB3aXRoIDQyOS81eHgsIHRoZSBydW4gd2FzIHN0aWxsIGFjY2VwdGVkXG4gICAgICAvLyB2aWEgdGhlIHF1ZXVlIGFuZCBjcmVhdGlvbiB3aWxsIGJlIHJlLXRyaWVkIGFzeW5jIGJ5IHRoZSBydW50aW1lLlxuICAgICAgY29uc3QgW3J1bkNyZWF0ZWRSZXN1bHQsIHF1ZXVlUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAgIHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgcnVuSWQsXG4gICAgICAgICAge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX2NyZWF0ZWQnLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb24sXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgZGVwbG95bWVudElkOiBkZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBpbnB1dDogd29ya2Zsb3dBcmd1bWVudHMsXG4gICAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgIC4uLihlbmNyeXB0aW9uUHVibGljS2V5ID8geyBlbmNyeXB0aW9uUHVibGljS2V5IH0gOiB7fSksXG4gICAgICAgICAgICAgIC4uLmF0dHJpYnV0ZVNlZWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgeyB2MUNvbXBhdCB9XG4gICAgICAgICksXG4gICAgICAgIHdvcmxkLnF1ZXVlKFxuICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgb3B0cy5uYW1lc3BhY2UpLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgLi4uKHNwZWNWZXJzaW9uID49IFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVFxuICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgIHJ1bklucHV0OiB7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0OiB3b3JrZmxvd0FyZ3VtZW50cyxcbiAgICAgICAgICAgICAgICAgICAgZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICBleGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgICAgICAgICAuLi4oZW5jcnlwdGlvblB1YmxpY0tleSA/IHsgZW5jcnlwdGlvblB1YmxpY0tleSB9IDoge30pLFxuICAgICAgICAgICAgICAgICAgICAuLi4oY3JlYXRvckVudmlyb25tZW50ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICA/IHsgZW52aXJvbm1lbnQ6IGNyZWF0b3JFbnZpcm9ubWVudCB9XG4gICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmF0dHJpYnV0ZVNlZWQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgLy8gRm9yd2FyZCBhbnkgY2FsbGVyLXN1cHBsaWVkIHJlZ2lvbiBoaW50IHNvIHdvcmxkcyB3aXRoXG4gICAgICAgICAgICAvLyBwZXItcmVnaW9uIHF1ZXVlIHJvdXRpbmcgKGUuZy4gd29ybGQtdmVyY2VsKSBjYW4gdGFyZ2V0IHRoZVxuICAgICAgICAgICAgLy8gbWF0Y2hpbmcgcXVldWUuIFdvcmxkcyB3aXRob3V0IGEgcmVnaW9uYWwgZGltZW5zaW9uIGlnbm9yZVxuICAgICAgICAgICAgLy8gdGhpcyBmaWVsZC5cbiAgICAgICAgICAgIC4uLihvcHRzLnJlZ2lvbiAhPT0gdW5kZWZpbmVkID8geyByZWdpb246IG9wdHMucmVnaW9uIH0gOiB7fSksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgXSk7XG5cbiAgICAgIC8vIFF1ZXVlIGZhaWx1cmUgaXMgYWx3YXlzIGZhdGFsOiB0aGUgcnVuIHdhcyBub3QgZW5xdWV1ZWRcbiAgICAgIGlmIChxdWV1ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgdGhyb3cgcXVldWVSZXN1bHQucmVhc29uO1xuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgZXZlbnRzLmNyZWF0ZSByZXN1bHRcbiAgICAgIGxldCByZXNpbGllbnRTdGFydCA9IGZhbHNlO1xuICAgICAgaWYgKHJ1bkNyZWF0ZWRSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgIGNvbnN0IGVyciA9IHJ1bkNyZWF0ZWRSZXN1bHQucmVhc29uO1xuICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgLy8gNDA5OiBUaGUgcnVuIGFscmVhZHkgZXhpc3RzLiBUaGlzIGNhbiBoYXBwZW4gaW4gZXh0cmVtZSBjYXNlcyB3aGVyZVxuICAgICAgICAgIC8vIHRoZSBydW4gY3JlYXRpb24gY2FsbCBnZXRzIGEgY29sZCBzdGFydCBvciBvdGhlciBzbG93ZG93biwgYW5kIHRoZSBxdWV1ZVxuICAgICAgICAgIC8vICsgcnVuX3N0YXJ0ZWQgY2FsbCBjb21wbGV0ZXMgZmFzdGVyLiBXZSBleHBlY3QgdGhpcyB0byBiZSA8PTElIG9mIGNhc2VzLlxuICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgd2UgY2FuIHNhZmVseSByZXR1cm4uXG4gICAgICAgIH0gZWxzZSBpZiAoaXNSZXRyeWFibGVXb3JsZEVycm9yKGVycikpIHtcbiAgICAgICAgICAvLyA0MjkgKFRocm90dGxlRXJyb3IpLCA1eHgsIGFuZCB0cmFuc2llbnQgdHJhbnNwb3J0IGZhaWx1cmVzXG4gICAgICAgICAgLy8gKFRSQU5TUE9SVC9USU1FT1VUKSBhcmUgcmV0cnlhYmxlOiB0aGUgcnVuIHdhcyBhY2NlcHRlZCB2aWEgdGhlXG4gICAgICAgICAgLy8gcXVldWUgYW5kIGNyZWF0aW9uIHdpbGwgYmUgcmUtdHJpZWQgYnkgdGhlIHJ1bnRpbWUgd2hlbiBpdCBjYWxsc1xuICAgICAgICAgIC8vIHJ1bl9zdGFydGVkLlxuICAgICAgICAgIHJlc2lsaWVudFN0YXJ0ID0gdHJ1ZTtcbiAgICAgICAgICBydW50aW1lTG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAnUnVuIGNyZWF0aW9uIGV2ZW50IGZhaWxlZCwgYnV0IHRoZSBydW4gd2FzIGFjY2VwdGVkIHZpYSB0aGUgcXVldWUuICcgK1xuICAgICAgICAgICAgICAnVGhlIHJ1bl9jcmVhdGVkIGV2ZW50IHdpbGwgYmUgcmUtdHJpZWQgYXN5bmMgYnkgdGhlIHJ1bnRpbWUuJyxcbiAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQsIGVycm9yOiBlcnIubWVzc2FnZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHJ1bkNyZWF0ZWRSZXN1bHQudmFsdWU7XG4gICAgICAgIC8vIFZlcmlmeSBzZXJ2ZXIgYWNjZXB0ZWQgb3VyIHJ1bklkXG4gICAgICAgIGlmICghdjFDb21wYXQgJiYgcmVzdWx0LnJ1bi5ydW5JZCAhPT0gcnVuSWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICBgU2VydmVyIHJldHVybmVkIGRpZmZlcmVudCBydW5JZCB0aGFuIHJlcXVlc3RlZDogZXhwZWN0ZWQgJHtydW5JZH0sIGdvdCAke3Jlc3VsdC5ydW4ucnVuSWR9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVGhlc2UgYXJndW1lbnQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlIHByb21pc2VcbiAgICAgIC8vIGhhbmRlZCB0byB3YWl0VW50aWwgbXVzdCBuZXZlciByZWplY3QgKGFuIHVuY29uc3VtZWQgd2FpdFVudGlsXG4gICAgICAvLyByZWplY3Rpb24gY3Jhc2hlcyB0aGUgcHJvY2VzcyBhcyB1bmhhbmRsZWRSZWplY3Rpb24pLCBzbyB1bmV4cGVjdGVkXG4gICAgICAvLyBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICBzYWZlV2FpdFVudGlsKFByb21pc2UuYWxsKG9wcyksIChlcnIpID0+IHtcbiAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICdCYWNrZ3JvdW5kIGZsdXNoIG9mIHdvcmtmbG93IGFyZ3VtZW50IHN0cmVhbXMgZmFpbGVkJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5JZChydW5JZCksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5EZXBsb3ltZW50SWQoZGVwbG95bWVudElkKSxcbiAgICAgICAgLi4uKHJ1bkNyZWF0ZWRSZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJ1xuICAgICAgICAgID8gQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKHJ1bkNyZWF0ZWRSZXN1bHQudmFsdWUucnVuLnN0YXR1cylcbiAgICAgICAgICA6IHt9KSxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gbmV3IFJ1bjxUUmVzdWx0PihydW5JZCwgeyByZXNpbGllbnRTdGFydCB9KTtcbiAgICB9KTtcbiAgfSk7XG59XG4iXX0=