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

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 (310) hide show
  1. package/dist/attribute-changes.d.ts +5 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +35 -2
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +74 -5
  7. package/dist/capture-stack.d.ts +1 -1
  8. package/dist/capture-stack.js +2 -2
  9. package/dist/class-serialization.d.ts +32 -0
  10. package/dist/class-serialization.d.ts.map +1 -1
  11. package/dist/class-serialization.js +37 -1
  12. package/dist/classify-error.d.ts +19 -3
  13. package/dist/classify-error.d.ts.map +1 -1
  14. package/dist/classify-error.js +98 -6
  15. package/dist/context-violation-error.d.ts +5 -5
  16. package/dist/context-violation-error.d.ts.map +1 -1
  17. package/dist/context-violation-error.js +8 -6
  18. package/dist/create-hook.d.ts +72 -7
  19. package/dist/create-hook.d.ts.map +1 -1
  20. package/dist/create-hook.js +1 -1
  21. package/dist/define-hook.js +2 -2
  22. package/dist/describe-error.d.ts +7 -7
  23. package/dist/describe-error.d.ts.map +1 -1
  24. package/dist/describe-error.js +97 -12
  25. package/dist/encryption.d.ts +38 -4
  26. package/dist/encryption.d.ts.map +1 -1
  27. package/dist/encryption.js +96 -14
  28. package/dist/events-consumer.d.ts +271 -0
  29. package/dist/events-consumer.d.ts.map +1 -1
  30. package/dist/events-consumer.js +646 -42
  31. package/dist/flushable-stream.d.ts +56 -1
  32. package/dist/flushable-stream.d.ts.map +1 -1
  33. package/dist/flushable-stream.js +123 -11
  34. package/dist/global.d.ts +36 -2
  35. package/dist/global.d.ts.map +1 -1
  36. package/dist/global.js +21 -6
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -2
  40. package/dist/log-format.d.ts +2 -2
  41. package/dist/log-format.js +7 -7
  42. package/dist/logger.d.ts +1 -0
  43. package/dist/logger.d.ts.map +1 -1
  44. package/dist/logger.js +10 -6
  45. package/dist/private.d.ts +226 -9
  46. package/dist/private.d.ts.map +1 -1
  47. package/dist/private.js +626 -7
  48. package/dist/replay-payload-cache.d.ts +64 -0
  49. package/dist/replay-payload-cache.d.ts.map +1 -0
  50. package/dist/replay-payload-cache.js +158 -0
  51. package/dist/runtime/compute-instance.d.ts +13 -0
  52. package/dist/runtime/compute-instance.d.ts.map +1 -0
  53. package/dist/runtime/compute-instance.js +14 -0
  54. package/dist/runtime/constants.d.ts +315 -0
  55. package/dist/runtime/constants.d.ts.map +1 -1
  56. package/dist/runtime/constants.js +502 -16
  57. package/dist/runtime/count-step-started-events.d.ts +52 -0
  58. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  59. package/dist/runtime/count-step-started-events.js +72 -0
  60. package/dist/runtime/deployment-guard.d.ts +99 -0
  61. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  62. package/dist/runtime/deployment-guard.js +154 -0
  63. package/dist/runtime/get-port-lazy.d.ts +15 -0
  64. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  65. package/dist/runtime/get-port-lazy.js +75 -6
  66. package/dist/runtime/get-world-lazy.d.ts +5 -14
  67. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  68. package/dist/runtime/get-world-lazy.js +19 -29
  69. package/dist/runtime/helpers.d.ts +341 -29
  70. package/dist/runtime/helpers.d.ts.map +1 -1
  71. package/dist/runtime/helpers.js +559 -57
  72. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  73. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  74. package/dist/runtime/quickjs-assets.generated.js +30 -0
  75. package/dist/runtime/quickjs-entrypoint.d.ts +136 -0
  76. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  77. package/dist/runtime/quickjs-entrypoint.js +1686 -0
  78. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  79. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-runtime.js +2427 -0
  81. package/dist/runtime/quickjs-serde.d.ts +107 -0
  82. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-serde.js +2159 -0
  84. package/dist/runtime/replay-budget.d.ts +97 -0
  85. package/dist/runtime/replay-budget.d.ts.map +1 -0
  86. package/dist/runtime/replay-budget.js +139 -0
  87. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  88. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  89. package/dist/runtime/replay-recovery-reporter.js +64 -0
  90. package/dist/runtime/resume-hook.d.ts +91 -8
  91. package/dist/runtime/resume-hook.d.ts.map +1 -1
  92. package/dist/runtime/resume-hook.js +512 -89
  93. package/dist/runtime/resume-latency.d.ts +150 -0
  94. package/dist/runtime/resume-latency.d.ts.map +1 -0
  95. package/dist/runtime/resume-latency.js +155 -0
  96. package/dist/runtime/run-id-time.d.ts +19 -0
  97. package/dist/runtime/run-id-time.d.ts.map +1 -0
  98. package/dist/runtime/run-id-time.js +42 -0
  99. package/dist/runtime/run.d.ts +72 -7
  100. package/dist/runtime/run.d.ts.map +1 -1
  101. package/dist/runtime/run.js +280 -53
  102. package/dist/runtime/runs.d.ts +54 -3
  103. package/dist/runtime/runs.d.ts.map +1 -1
  104. package/dist/runtime/runs.js +126 -16
  105. package/dist/runtime/start.d.ts +101 -2
  106. package/dist/runtime/start.d.ts.map +1 -1
  107. package/dist/runtime/start.js +352 -61
  108. package/dist/runtime/step-executor.d.ts +205 -5
  109. package/dist/runtime/step-executor.d.ts.map +1 -1
  110. package/dist/runtime/step-executor.js +760 -127
  111. package/dist/runtime/step-latency.d.ts +220 -0
  112. package/dist/runtime/step-latency.d.ts.map +1 -0
  113. package/dist/runtime/step-latency.js +215 -0
  114. package/dist/runtime/step-ownership.d.ts +72 -0
  115. package/dist/runtime/step-ownership.d.ts.map +1 -0
  116. package/dist/runtime/step-ownership.js +114 -0
  117. package/dist/runtime/step-single-flight.d.ts +12 -0
  118. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  119. package/dist/runtime/step-single-flight.js +75 -0
  120. package/dist/runtime/suspension-handler.d.ts +269 -7
  121. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  122. package/dist/runtime/suspension-handler.js +1253 -125
  123. package/dist/runtime/unserializable-step.d.ts +34 -0
  124. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  125. package/dist/runtime/unserializable-step.js +52 -0
  126. package/dist/runtime/vm-mode.d.ts +44 -0
  127. package/dist/runtime/vm-mode.d.ts.map +1 -0
  128. package/dist/runtime/vm-mode.js +62 -0
  129. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  130. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  131. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  132. package/dist/runtime/wait-continuation.d.ts +106 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +136 -0
  135. package/dist/runtime/wait-until.d.ts +18 -0
  136. package/dist/runtime/wait-until.d.ts.map +1 -0
  137. package/dist/runtime/wait-until.js +42 -0
  138. package/dist/runtime/world-compatibility.d.ts +32 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +44 -0
  141. package/dist/runtime/world-init.d.ts +17 -42
  142. package/dist/runtime/world-init.d.ts.map +1 -1
  143. package/dist/runtime/world-init.js +18 -43
  144. package/dist/runtime/world.d.ts +14 -2
  145. package/dist/runtime/world.d.ts.map +1 -1
  146. package/dist/runtime/world.js +75 -19
  147. package/dist/runtime.d.ts +10 -6
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3741 -490
  150. package/dist/sealed-box.d.ts +167 -0
  151. package/dist/sealed-box.d.ts.map +1 -0
  152. package/dist/sealed-box.js +571 -0
  153. package/dist/serialization/client.d.ts +3 -3
  154. package/dist/serialization/client.d.ts.map +1 -1
  155. package/dist/serialization/client.js +8 -4
  156. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  157. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  158. package/dist/serialization/codec-devalue-vm.js +148 -0
  159. package/dist/serialization/codec-devalue.d.ts +1 -1
  160. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  161. package/dist/serialization/codec-devalue.js +24 -6
  162. package/dist/serialization/codec.d.ts +37 -2
  163. package/dist/serialization/codec.d.ts.map +1 -1
  164. package/dist/serialization/codec.js +2 -2
  165. package/dist/serialization/compression.d.ts +105 -0
  166. package/dist/serialization/compression.d.ts.map +1 -0
  167. package/dist/serialization/compression.js +261 -0
  168. package/dist/serialization/encryption.d.ts +119 -17
  169. package/dist/serialization/encryption.d.ts.map +1 -1
  170. package/dist/serialization/encryption.js +152 -17
  171. package/dist/serialization/errors.d.ts +13 -0
  172. package/dist/serialization/errors.d.ts.map +1 -1
  173. package/dist/serialization/errors.js +20 -2
  174. package/dist/serialization/format.d.ts +6 -6
  175. package/dist/serialization/format.js +7 -7
  176. package/dist/serialization/hardened.d.ts +156 -0
  177. package/dist/serialization/hardened.d.ts.map +1 -0
  178. package/dist/serialization/hardened.js +538 -0
  179. package/dist/serialization/index.d.ts +10 -8
  180. package/dist/serialization/index.d.ts.map +1 -1
  181. package/dist/serialization/index.js +10 -8
  182. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  183. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  184. package/dist/serialization/reducers/class-vm.js +77 -0
  185. package/dist/serialization/reducers/class.d.ts.map +1 -1
  186. package/dist/serialization/reducers/class.js +11 -6
  187. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  188. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  189. package/dist/serialization/reducers/common-vm.js +616 -0
  190. package/dist/serialization/reducers/common.d.ts +1 -1
  191. package/dist/serialization/reducers/common.d.ts.map +1 -1
  192. package/dist/serialization/reducers/common.js +202 -62
  193. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  194. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  195. package/dist/serialization/reducers/step-function-vm.js +97 -0
  196. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  197. package/dist/serialization/reducers/step-function.js +25 -9
  198. package/dist/serialization/step.d.ts +4 -4
  199. package/dist/serialization/step.d.ts.map +1 -1
  200. package/dist/serialization/step.js +9 -5
  201. package/dist/serialization/types.d.ts +80 -1
  202. package/dist/serialization/types.d.ts.map +1 -1
  203. package/dist/serialization/types.js +15 -1
  204. package/dist/serialization/workflow-vm.d.ts +29 -0
  205. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  206. package/dist/serialization/workflow-vm.js +74 -0
  207. package/dist/serialization-format.d.ts +64 -8
  208. package/dist/serialization-format.d.ts.map +1 -1
  209. package/dist/serialization-format.js +225 -73
  210. package/dist/serialization.d.ts +262 -34
  211. package/dist/serialization.d.ts.map +1 -1
  212. package/dist/serialization.js +1879 -274
  213. package/dist/set-attributes.d.ts +13 -0
  214. package/dist/set-attributes.d.ts.map +1 -0
  215. package/dist/set-attributes.js +60 -0
  216. package/dist/source-map.d.ts +25 -0
  217. package/dist/source-map.d.ts.map +1 -1
  218. package/dist/source-map.js +154 -10
  219. package/dist/step/context-storage.d.ts +61 -2
  220. package/dist/step/context-storage.d.ts.map +1 -1
  221. package/dist/step/context-storage.js +7 -5
  222. package/dist/step/writable-stream.d.ts +3 -3
  223. package/dist/step/writable-stream.d.ts.map +1 -1
  224. package/dist/step/writable-stream.js +72 -9
  225. package/dist/step.d.ts.map +1 -1
  226. package/dist/step.js +148 -27
  227. package/dist/symbols.d.ts +50 -0
  228. package/dist/symbols.d.ts.map +1 -1
  229. package/dist/symbols.js +51 -1
  230. package/dist/telemetry/semantic-conventions.d.ts +397 -2
  231. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  232. package/dist/telemetry/semantic-conventions.js +297 -3
  233. package/dist/telemetry.d.ts +91 -0
  234. package/dist/telemetry.d.ts.map +1 -1
  235. package/dist/telemetry.js +244 -17
  236. package/dist/test-support/orchestrator-context.d.ts +25 -0
  237. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  238. package/dist/test-support/orchestrator-context.js +101 -0
  239. package/dist/types.d.ts +6 -0
  240. package/dist/types.d.ts.map +1 -1
  241. package/dist/types.js +23 -1
  242. package/dist/util.d.ts +0 -5
  243. package/dist/util.d.ts.map +1 -1
  244. package/dist/util.js +1 -15
  245. package/dist/version.d.ts +1 -1
  246. package/dist/version.d.ts.map +1 -1
  247. package/dist/version.js +2 -2
  248. package/dist/vm/index.d.ts.map +1 -1
  249. package/dist/vm/index.js +84 -14
  250. package/dist/vm/script-cache.d.ts +26 -0
  251. package/dist/vm/script-cache.d.ts.map +1 -0
  252. package/dist/vm/script-cache.js +131 -0
  253. package/dist/vm/uint8array-base64.js +1 -1
  254. package/dist/workflow/abort-controller.d.ts +2 -2
  255. package/dist/workflow/abort-controller.d.ts.map +1 -1
  256. package/dist/workflow/abort-controller.js +88 -21
  257. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  258. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  259. package/dist/workflow/attribute-dispatcher.js +45 -0
  260. package/dist/workflow/create-hook.d.ts.map +1 -1
  261. package/dist/workflow/create-hook.js +24 -3
  262. package/dist/workflow/get-workflow-metadata.js +2 -2
  263. package/dist/workflow/hook.d.ts.map +1 -1
  264. package/dist/workflow/hook.js +304 -47
  265. package/dist/workflow/index.d.ts +1 -0
  266. package/dist/workflow/index.d.ts.map +1 -1
  267. package/dist/workflow/index.js +2 -1
  268. package/dist/workflow/set-attributes.d.ts +68 -0
  269. package/dist/workflow/set-attributes.d.ts.map +1 -0
  270. package/dist/workflow/set-attributes.js +60 -0
  271. package/dist/workflow/sleep.d.ts.map +1 -1
  272. package/dist/workflow/sleep.js +58 -12
  273. package/dist/workflow/world-init-stub.d.ts +3 -3
  274. package/dist/workflow/world-init-stub.js +4 -4
  275. package/dist/workflow.d.ts +95 -3
  276. package/dist/workflow.d.ts.map +1 -1
  277. package/dist/workflow.js +895 -561
  278. package/docs/api-reference/create-hook.mdx +89 -10
  279. package/docs/api-reference/create-webhook.mdx +16 -15
  280. package/docs/api-reference/define-hook.mdx +35 -33
  281. package/docs/api-reference/fatal-error.mdx +30 -8
  282. package/docs/api-reference/fetch.mdx +14 -10
  283. package/docs/api-reference/get-step-metadata.mdx +2 -2
  284. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  285. package/docs/api-reference/get-writable.mdx +7 -7
  286. package/docs/api-reference/index.mdx +4 -1
  287. package/docs/api-reference/retryable-error.mdx +1 -1
  288. package/docs/api-reference/set-attributes.mdx +61 -0
  289. package/docs/api-reference/sleep.mdx +4 -4
  290. package/docs/foundations/cancellation.mdx +31 -32
  291. package/docs/foundations/errors-and-retries.mdx +42 -11
  292. package/docs/foundations/hooks.mdx +64 -35
  293. package/docs/foundations/idempotency.mdx +244 -12
  294. package/docs/foundations/index.mdx +1 -23
  295. package/docs/foundations/meta.json +2 -1
  296. package/docs/foundations/serialization.mdx +21 -22
  297. package/docs/foundations/starting-workflows.mdx +106 -30
  298. package/docs/foundations/streaming.mdx +107 -59
  299. package/docs/foundations/versioning.mdx +263 -0
  300. package/docs/foundations/workflows-and-steps.mdx +9 -9
  301. package/docs/how-it-works/cancellation.mdx +63 -63
  302. package/docs/how-it-works/code-transform.mdx +83 -67
  303. package/docs/how-it-works/encryption.mdx +30 -26
  304. package/docs/how-it-works/event-sourcing.mdx +98 -34
  305. package/docs/how-it-works/framework-integrations.mdx +96 -337
  306. package/docs/how-it-works/understanding-directives.mdx +22 -22
  307. package/package.json +24 -15
  308. package/dist/runtime/step-handler.d.ts +0 -2
  309. package/dist/runtime/step-handler.d.ts.map +0 -1
  310. package/dist/runtime/step-handler.js +0 -776
@@ -1,35 +1,153 @@
1
+ import assert from 'node:assert/strict';
1
2
  import { types } from 'node:util';
2
- import { waitUntil } from '@vercel/functions';
3
- import { EntityConflictError, FatalError, RetryableError, RunExpiredError, ThrottleError, TooEarlyError, WorkflowRuntimeError, } from '@workflow/errors';
4
- import { pluralize } from '@workflow/utils';
5
- import { SPEC_VERSION_CURRENT } from '@workflow/world';
3
+ import { EntityConflictError, FatalError, RetryableError, RunExpiredError, SerializationError, ThrottleError, TooEarlyError, WorkflowRuntimeError, } from '@workflow/errors';
4
+ import { createWorkflowBaseUrl, pluralize, stepDisplayName, } from '@workflow/utils';
5
+ import { requireEventSlot, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
6
6
  import { runtimeLogger, stepLogger } from '../logger.js';
7
7
  import { getStepFunction } from '../private.js';
8
- import { dehydrateStepError, dehydrateStepReturnValue, hydrateStepArguments, hydrateStepError, } from '../serialization.js';
8
+ import { formatSerializationError } from '../serialization/errors.js';
9
+ import { cancelAbortReaders, dehydrateStepError, dehydrateStepReturnValue, hydrateStepArguments, hydrateStepError, } from '../serialization.js';
9
10
  import { contextStorage } from '../step/context-storage.js';
10
11
  import * as Attribute from '../telemetry/semantic-conventions.js';
11
- import { trace } from '../telemetry.js';
12
- import { getErrorName, getErrorStack, normalizeUnknownError, } from '../types.js';
12
+ import { recordStepExecutionDuration, trace } from '../telemetry.js';
13
+ import { getErrorName, getErrorStack, normalizeUnknownError, promoteAbortErrorToFatal, } from '../types.js';
14
+ import { COMPUTE_INSTANCE_ID } from './compute-instance.js';
15
+ import { isOptimisticInlineStartEnabled, isOptimisticInlineStartExplicitlyDisabled, } from './constants.js';
13
16
  import { getPortLazy } from './get-port-lazy.js';
14
- import { memoizeEncryptionKey } from './helpers.js';
15
- const DEFAULT_STEP_MAX_RETRIES = 3;
17
+ import { maxEventSlot, memoizeEncryptionKey, } from './helpers.js';
18
+ import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
19
+ import { computeResumeTtrAttributes, } from './resume-latency.js';
20
+ import { computeStepLatencyEventData, } from './step-latency.js';
21
+ import { isUnserializableStepInputPlaceholder } from './unserializable-step.js';
22
+ import { safeWaitUntil } from './wait-until.js';
23
+ export const DEFAULT_STEP_MAX_RETRIES = 3;
24
+ /**
25
+ * Extract the inline delta from a step-terminal `events.create` result,
26
+ * if the World populated one. A delta is only meaningful when the caller
27
+ * requested it (`sinceCursor` was passed) and the World returned both
28
+ * `events` and a `cursor`; otherwise we return undefined and the caller
29
+ * falls back to the normal incremental `events.list`. `hasMore` defaults
30
+ * to false (single page) when the World omits it.
31
+ */
32
+ function extractInlineDelta(result, requested) {
33
+ if (!requested)
34
+ return undefined;
35
+ if (!result.events || result.cursor === undefined)
36
+ return undefined;
37
+ return {
38
+ events: result.events,
39
+ cursor: result.cursor,
40
+ hasMore: result.hasMore ?? false,
41
+ };
42
+ }
16
43
  /**
17
44
  * Executes a single step: creates step_started event, hydrates input,
18
45
  * runs the step function, creates step_completed/step_failed/step_retrying events.
19
46
  *
20
- * Does NOT queue workflow continuation messages the caller decides what to do next.
21
- * Used by both the V1 step handler and the V2 combined handler.
47
+ * Does NOT queue workflow continuation messages; the caller decides what to do next.
48
+ * Used by the combined workflow handler for step execution.
22
49
  */
23
50
  export async function executeStep(params) {
24
51
  const { world, workflowRunId, workflowName, workflowStartedAt, stepId, stepName, } = params;
25
- const isVercel = process.env.VERCEL_URL !== undefined;
26
- return trace(`STEP ${stepName}`, {}, async (span) => {
52
+ // Truthiness, not presence: `vercel env pull` writes `VERCEL_URL=""` into
53
+ // `.env.local`, and a framework that loads that file locally would otherwise
54
+ // put us on the Vercel branch with nothing to build a host from, making
55
+ // `https://` the base URL of every step.
56
+ const isVercel = Boolean(process.env.VERCEL_URL);
57
+ // Gate payload compression on the run's specVersion.
58
+ const compression = (params.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
59
+ const replayRecoveryReporter = params.replayRecoveryReporter ?? ReplayRecoveryReporter.inert();
60
+ /**
61
+ * The highest log slot this executor knows about, seeded from the view its
62
+ * caller scheduled the step against and advanced by every event it commits.
63
+ *
64
+ * Advancing is what keeps the snapshot honest across a step's own writes. A
65
+ * step commits `step_started` and then `step_completed`; if the second still
66
+ * named the caller's original position, the World would report the first one
67
+ * back as an event this writer had not seen, on every step, forever.
68
+ *
69
+ * This reads a report for its highest position and then discards it, where
70
+ * the replay loop and the suspension handler merge theirs with
71
+ * `absorbSkippedSlotReport`. That is the difference between the callers, not
72
+ * an oversight: an executor holds no loaded log to merge into. It runs from a
73
+ * queued delivery whose only view of the log is the integer its caller passed
74
+ * in, so the position is the entire value the report has to it. Whoever
75
+ * replays next loads the log and gets the events themselves.
76
+ */
77
+ let knownSlot = params.slotSnapshot?.eventCount;
78
+ const observeSlot = (result) => {
79
+ if (knownSlot === undefined) {
80
+ // The caller scheduled this step without naming a position, so there is
81
+ // no snapshot to advance and the writes below send none. Not the same as
82
+ // a run without positions: every run has them, this executor was not
83
+ // told which one it started from.
84
+ return;
85
+ }
86
+ const observed = [];
87
+ if (result.event) {
88
+ observed.push(requireEventSlot(result.event.eventId));
89
+ }
90
+ const reported = maxEventSlot(result.events ?? []);
91
+ if (reported !== undefined) {
92
+ observed.push(reported);
93
+ }
94
+ for (const slot of observed) {
95
+ if (slot > knownSlot) {
96
+ knownSlot = slot;
97
+ }
98
+ }
99
+ };
100
+ const createEvent = async (data, eventParams) => {
101
+ const result = await replayRecoveryReporter.withEventCreate(knownSlot === undefined
102
+ ? eventParams
103
+ : { eventCount: knownSlot, ...eventParams }, (p) => world.events.create(workflowRunId, data, p));
104
+ observeSlot(result);
105
+ return result;
106
+ };
107
+ // `step_started` identifies the invocation that performed this attempt.
108
+ // Keep request and compute provenance independent: world-vercel serializes
109
+ // requestId as analytics `vercelId`, while computeInstanceId identifies the
110
+ // worker that executed the step.
111
+ const stepStartedEventParams = {
112
+ computeInstanceId: COMPUTE_INSTANCE_ID,
113
+ ...(params.requestId ? { requestId: params.requestId } : {}),
114
+ };
115
+ const spanName = `step.execute ${stepDisplayName(stepName)}`;
116
+ return trace(spanName, {}, async (span) => {
27
117
  span?.setAttributes({
28
118
  ...Attribute.StepName(stepName),
29
119
  ...Attribute.WorkflowName(workflowName),
30
120
  ...Attribute.WorkflowRunId(workflowRunId),
31
121
  ...Attribute.StepId(stepId),
32
122
  });
123
+ // The two lazy start modes are mutually exclusive by construction (the
124
+ // caller sets one or the other), and several branches below read only one
125
+ // of them to decide whether the step is brand-new. Enforced rather than
126
+ // documented so a caller that ever sets both fails here instead of
127
+ // silently taking the pre-claimed path with an unsent input.
128
+ assert(!(params.lazyStepInput !== undefined && params.preclaimedStart), 'executeStep: lazyStepInput and preclaimedStart are mutually exclusive');
129
+ // A pre-claimed start that LOST the batched pair's atomic create-claim: a
130
+ // concurrent writer owns this step. Same outcome as losing the lazy
131
+ // claim (EntityConflictError → skipped), decided before ANY write, the
132
+ // unregistered-step fallback below included, since a step this handler
133
+ // does not own is not its to fail.
134
+ if (params.preclaimedStart && params.preclaimedStart.owned === false) {
135
+ runtimeLogger.debug('Pre-claimed step start lost, skipping', {
136
+ stepName,
137
+ stepId,
138
+ workflowRunId,
139
+ });
140
+ span?.setAttributes({
141
+ ...Attribute.StepSkipped(true),
142
+ // `running`, not `completed`: the pair's 409 says the step already
143
+ // EXISTS, and the writer that won the create-claim is executing it.
144
+ // The other skip site below is a genuine terminal-state conflict;
145
+ // tagging both `completed` would make the attribute read 100%
146
+ // `completed` and lose the only distinction worth querying it for.
147
+ ...Attribute.StepSkipReason('running'),
148
+ });
149
+ return { type: 'skipped' };
150
+ }
33
151
  // Memoized accessor for the per-run encryption key. The first caller
34
152
  // (input hydration on the success path, or one of the early-return
35
153
  // dehydrateStepError paths if step_started fails) triggers the actual
@@ -37,8 +155,8 @@ export async function executeStep(params) {
37
155
  const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
38
156
  const stepFn = getStepFunction(stepName);
39
157
  if (!stepFn || typeof stepFn !== 'function') {
40
- // Step function not registered fail the step immediately (not the run).
41
- // This matches the V1 step handler pattern: create step_failed event so
158
+ // Step function not registered: fail the step immediately (not the run).
159
+ // Create a step_failed event so
42
160
  // the workflow can handle it gracefully via try/catch in user code.
43
161
  const errorMessage = `Step "${stepName}" is not registered in the current deployment. This usually indicates a build or bundling issue that caused the step to not be included in the deployment.`;
44
162
  runtimeLogger.error('Step function not registered, failing step', {
@@ -46,13 +164,61 @@ export async function executeStep(params) {
46
164
  stepName,
47
165
  stepId,
48
166
  });
167
+ // On the lazy inline path the suspension handler deferred this step's
168
+ // `step_created`, expecting executeStep to materialize the step via a
169
+ // lazy `step_started` carrying its input. We never get that far for an
170
+ // unregistered step, so the step entity does not exist yet, and writing
171
+ // `step_failed` straight away would hit the world's "step must exist"
172
+ // ordering guard and wedge the run. Send the lazy `step_started` first
173
+ // (it creates the step + synthetic `step_created` atomically and keeps
174
+ // replay correct), then fail it below. This also preserves the
175
+ // exactly-one-owner guarantee: a concurrent handler that won the create
176
+ // makes our lazy `step_started` reject with EntityConflictError → we
177
+ // return `skipped` and never write the failure twice.
178
+ if (params.lazyStepInput !== undefined) {
179
+ try {
180
+ // Turbo: this lazy `step_started` must not precede the backgrounded
181
+ // `run_started`. Order it after the run-ready barrier (best-effort:
182
+ // a barrier rejection means the run doesn't exist, and the create
183
+ // below surfaces the real error). No-op outside turbo.
184
+ if (params.runReadyBarrier) {
185
+ await params.runReadyBarrier.catch(() => { });
186
+ }
187
+ await createEvent({
188
+ eventType: 'step_started',
189
+ specVersion: SPEC_VERSION_CURRENT,
190
+ correlationId: stepId,
191
+ eventData: {
192
+ stepName,
193
+ workflowName,
194
+ input: params.lazyStepInput,
195
+ // Stamped for consistency even though this step terminal-fails
196
+ // immediately below; the log should never show an unowned
197
+ // lazy start.
198
+ ...(params.ownerMessageId !== undefined
199
+ ? { ownerMessageId: params.ownerMessageId }
200
+ : {}),
201
+ },
202
+ }, stepStartedEventParams);
203
+ }
204
+ catch (startErr) {
205
+ if (EntityConflictError.is(startErr)) {
206
+ return { type: 'skipped' };
207
+ }
208
+ if (RunExpiredError.is(startErr)) {
209
+ return { type: 'gone' };
210
+ }
211
+ throw startErr;
212
+ }
213
+ }
49
214
  try {
50
- await world.events.create(workflowRunId, {
215
+ await createEvent({
51
216
  eventType: 'step_failed',
52
217
  specVersion: SPEC_VERSION_CURRENT,
53
218
  correlationId: stepId,
54
219
  eventData: {
55
- error: await dehydrateStepError(new FatalError(errorMessage), workflowRunId, await getEncryptionKey()),
220
+ stepName,
221
+ error: await dehydrateStepError(new FatalError(errorMessage), workflowRunId, await getEncryptionKey(), [], globalThis, compression),
56
222
  },
57
223
  });
58
224
  }
@@ -72,20 +238,62 @@ export async function executeStep(params) {
72
238
  span?.setAttributes({
73
239
  ...Attribute.StepMaxRetries(maxRetries),
74
240
  });
75
- // step_started validates state and returns the step entity
76
- let step;
77
- try {
78
- const startResult = await world.events.create(workflowRunId, {
79
- eventType: 'step_started',
80
- specVersion: SPEC_VERSION_CURRENT,
81
- correlationId: stepId,
241
+ // maxRetries enforced before starting another attempt. Timeouts can kill
242
+ // a step execution without any way to catch the error, so the post-body/error
243
+ // guards below might miss it. Hence, we use `authoritativeAttempt` count
244
+ // as an additional guard based on step_started count or queue delivery count
245
+ // on backgrounded steps.
246
+ // Thrown-error exhaustion still terminates one attempt earlier via the post-body
247
+ // guard (with the thrown error as cause), and this check does not affect that.
248
+ if (params.authoritativeAttempt !== undefined &&
249
+ params.authoritativeAttempt > maxRetries + 1) {
250
+ const retryCount = maxRetries;
251
+ const errorMessage = `Step "${stepName}" exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
252
+ stepLogger.error('Step exceeded max retries', {
253
+ workflowRunId,
254
+ stepName,
255
+ stepId,
256
+ attempt: params.authoritativeAttempt,
257
+ maxRetries,
82
258
  });
83
- if (!startResult.step) {
84
- throw new WorkflowRuntimeError(`step_started event for "${stepId}" did not return step entity`);
259
+ try {
260
+ await createEvent({
261
+ eventType: 'step_failed',
262
+ specVersion: SPEC_VERSION_CURRENT,
263
+ correlationId: stepId,
264
+ eventData: {
265
+ stepName,
266
+ error: await dehydrateStepError(new FatalError(errorMessage), workflowRunId, await getEncryptionKey(), [], globalThis, compression),
267
+ },
268
+ });
269
+ }
270
+ catch (err) {
271
+ if (EntityConflictError.is(err)) {
272
+ // Step already reached a terminal state (a concurrent handler or an
273
+ // earlier delivery failed/completed it), so nothing to do.
274
+ runtimeLogger.info('Tried failing step for exceeded retries, but step has already finished.', {
275
+ workflowRunId,
276
+ stepId,
277
+ stepName,
278
+ message: err instanceof Error ? err.message : String(err),
279
+ });
280
+ return { type: 'skipped' };
281
+ }
282
+ if (RunExpiredError.is(err)) {
283
+ return { type: 'gone' };
284
+ }
285
+ throw err;
85
286
  }
86
- step = startResult.step;
287
+ span?.setAttributes({
288
+ ...Attribute.StepStatus('failed'),
289
+ ...Attribute.StepRetryExhausted(true),
290
+ });
291
+ return { type: 'failed' };
87
292
  }
88
- catch (err) {
293
+ // Maps a `step_started` rejection to a terminal StepExecutionResult,
294
+ // shared by the await path (below) and the optimistic-start reconciliation.
295
+ // Returns undefined when the error is not one we translate (caller rethrows).
296
+ const startErrorToResult = (err) => {
89
297
  if (ThrottleError.is(err)) {
90
298
  const retryAfter = Math.max(1, typeof err.retryAfter === 'number' ? err.retryAfter : 1);
91
299
  runtimeLogger.info('Throttled on step_started, deferring', {
@@ -102,7 +310,7 @@ export async function executeStep(params) {
102
310
  stepName,
103
311
  stepId,
104
312
  workflowRunId,
105
- error: err.message,
313
+ error: err instanceof Error ? err.message : String(err),
106
314
  });
107
315
  span?.setAttributes({
108
316
  ...Attribute.StepSkipped(true),
@@ -119,7 +327,179 @@ export async function executeStep(params) {
119
327
  });
120
328
  return { type: 'retry', timeoutSeconds };
121
329
  }
122
- throw err;
330
+ return undefined;
331
+ };
332
+ // Optimistic inline start: when we hold the step input locally (lazy inline
333
+ // path) and the optimization is enabled, fire `step_started` WITHOUT
334
+ // awaiting and run the body against locally-synthesized state. A lazy step
335
+ // is always brand-new ⇒ attempt 1, no prior error, started now, so we
336
+ // don't need the server round-trip to begin. We reconcile the in-flight
337
+ // `step_started` before any terminal write (`reconcileOptimisticStart`): if
338
+ // it lost the atomic create-claim (409) or the run is gone/throttled, we
339
+ // discard the body result. Running the body before confirming ownership can
340
+ // execute a step more than once when handlers race, so inline step bodies
341
+ // must be idempotent; disable via WORKFLOW_OPTIMISTIC_INLINE_START=0.
342
+ //
343
+ // Turbo mode passes `forceOptimisticStart` to enable this regardless of the
344
+ // env flag (its single-handler guarantee removes the race). But it still
345
+ // defers to an *explicit* `WORKFLOW_OPTIMISTIC_INLINE_START=0`: forced
346
+ // optimistic start runs the body before `step_started`/`run_started` is
347
+ // confirmed, which is exactly the property an operator opts out of with that
348
+ // flag, so an explicit opt-out wins over turbo's force.
349
+ const optimisticStart =
350
+ // A pre-claimed start already settled its claim in the suspension
351
+ // batch; there is nothing to fire optimistically (lazyStepInput is
352
+ // also absent on that path; this term is documentation).
353
+ params.preclaimedStart === undefined &&
354
+ params.lazyStepInput !== undefined &&
355
+ // Stale-sensitive guarded batches await the claim so the 412 fence
356
+ // covers the body, not just durable writes; see
357
+ // StepExecutorParams.suppressOptimisticStart.
358
+ params.suppressOptimisticStart !== true &&
359
+ (isOptimisticInlineStartEnabled() ||
360
+ (params.forceOptimisticStart === true &&
361
+ !isOptimisticInlineStartExplicitlyDisabled()));
362
+ let step;
363
+ // Params for the `step_started` create on either path below. The slot
364
+ // snapshot is not spread here: `createEvent` attaches it to every write,
365
+ // this one included.
366
+ const startEventParams = stepStartedEventParams;
367
+ // `Date.now()` taken immediately before the `step_started` create is
368
+ // issued (either path below); anchors RSFS's end point. See
369
+ // StepLatencyEventData.rsfs and the call sites below.
370
+ let stepStartPostSentAtMs;
371
+ // `Date.now()` taken once the `step_started` response has returned and the
372
+ // claim succeeded: T6 of the hook-resume TTR window. Only the await path
373
+ // can set it: optimistic inline start deliberately does not wait for the
374
+ // claim before running the body, so at T7 it has no completion instant and
375
+ // the TTR breakdown reports no `step_claim_ms` (see
376
+ // runtime/resume-latency.ts).
377
+ let stepClaimCompletedAtMs;
378
+ // Settled outcome of the in-flight optimistic `step_started`. Handlers are
379
+ // attached synchronously (`.then(ok, err)`) so a fast rejection never
380
+ // surfaces as an unhandledRejection while the body runs.
381
+ let optimisticStartSettled;
382
+ // Await the optimistic `step_started` outcome and translate a lost race /
383
+ // terminal run / throttle into a result that short-circuits the body
384
+ // output. Returns undefined when we own the step and may write its terminal
385
+ // event. A non-translatable rejection is rethrown (so a transient
386
+ // step_started failure propagates to the queue handler for redelivery,
387
+ // exactly as on the await path). Idempotent: safe to call more than once.
388
+ const reconcileOptimisticStart = async () => {
389
+ if (!optimisticStartSettled)
390
+ return undefined;
391
+ const settled = await optimisticStartSettled;
392
+ if (settled.ok)
393
+ return undefined;
394
+ const mapped = startErrorToResult(settled.err);
395
+ if (!mapped)
396
+ throw settled.err;
397
+ return mapped;
398
+ };
399
+ if (params.preclaimedStart?.owned) {
400
+ // Pre-claimed inline start: the suspension handler's batched fan-out
401
+ // already committed this step's `step_created` + `step_started` pair,
402
+ // so this execution owns a started attempt-1 step without sending a
403
+ // start of its own: the body begins straight off the batch commit and
404
+ // the terminal write below has no in-flight claim to reconcile. The
405
+ // batch timestamps stand in for the claim's: the POST instant anchors
406
+ // RSFS, the response instant is TTR's claim completion (T6).
407
+ step = params.preclaimedStart.step;
408
+ stepStartPostSentAtMs = params.preclaimedStart.batchPostSentAtMs;
409
+ stepClaimCompletedAtMs = params.preclaimedStart.claimCompletedAtMs;
410
+ }
411
+ else if (optimisticStart) {
412
+ // Chain the lazy `step_started` on the run-ready barrier (turbo mode):
413
+ // the step can't be created before its run exists, but the body below
414
+ // runs immediately against synthesized state, so the `run_started`
415
+ // round-trip overlaps the body rather than blocking it. Outside turbo the
416
+ // barrier is undefined and this is a plain create.
417
+ const startedPromise = (params.runReadyBarrier ?? Promise.resolve()).then(() => {
418
+ // Taken right before the create fires, not before the barrier:
419
+ // RSFS measures the run_started-to-POST stretch, and the barrier
420
+ // wait IS part of that stretch under turbo.
421
+ stepStartPostSentAtMs = Date.now();
422
+ return createEvent({
423
+ eventType: 'step_started',
424
+ specVersion: SPEC_VERSION_CURRENT,
425
+ correlationId: stepId,
426
+ eventData: {
427
+ stepName,
428
+ workflowName,
429
+ input: params.lazyStepInput,
430
+ // Inline-ownership stamp; see StepExecutorParams.ownerMessageId.
431
+ ...(params.ownerMessageId !== undefined
432
+ ? { ownerMessageId: params.ownerMessageId }
433
+ : {}),
434
+ },
435
+ },
436
+ // Guard the claim; see StepExecutorParams.slotSnapshot. A
437
+ // stale (412) rejection surfaces via reconcileOptimisticStart as a
438
+ // non-translatable error: the body result is discarded and the
439
+ // rejection propagates to the caller.
440
+ startEventParams);
441
+ });
442
+ optimisticStartSettled = startedPromise.then(() => ({ ok: true }), (err) => ({ ok: false, err }));
443
+ const now = new Date();
444
+ step = {
445
+ runId: workflowRunId,
446
+ stepId,
447
+ stepName,
448
+ status: 'running',
449
+ input: params.lazyStepInput,
450
+ attempt: 1,
451
+ startedAt: now,
452
+ createdAt: now,
453
+ updatedAt: now,
454
+ };
455
+ }
456
+ else {
457
+ // step_started validates state and returns the step entity. On the lazy
458
+ // inline path we also carry the step `input` so the world creates the
459
+ // step on the fly (no separate step_created round-trip). The world's
460
+ // atomic create-claim makes this exactly-one-owner: a concurrent loser
461
+ // gets EntityConflictError, mapped to `{ type: 'skipped' }`, so it never
462
+ // runs the body. When `lazyStepInput` is absent this is the legacy
463
+ // step_started (step already created, no payload).
464
+ try {
465
+ // Inline-ownership stamp: present on the lazy paths AND on the
466
+ // owned-recovery payload-less start (a redelivery of the owning
467
+ // message re-executing its step must re-stamp, since ownership derives
468
+ // from the latest start, so an unstamped recovery start would read
469
+ // as "unowned" to a later wake). Only the background-step path
470
+ // passes no ownerMessageId: its start is the bare one, clearing
471
+ // ownership as intended.
472
+ const ownershipStamp = params.ownerMessageId !== undefined
473
+ ? { ownerMessageId: params.ownerMessageId }
474
+ : {};
475
+ stepStartPostSentAtMs = Date.now();
476
+ const startResult = await createEvent({
477
+ eventType: 'step_started',
478
+ specVersion: SPEC_VERSION_CURRENT,
479
+ correlationId: stepId,
480
+ eventData: params.lazyStepInput !== undefined
481
+ ? {
482
+ stepName,
483
+ workflowName,
484
+ input: params.lazyStepInput,
485
+ ...ownershipStamp,
486
+ }
487
+ : { stepName, ...ownershipStamp },
488
+ },
489
+ // Guard the claim; see StepExecutorParams.slotSnapshot. A
490
+ // stale (412) rejection is intentionally NOT translated by
491
+ // startErrorToResult below, so it propagates to the caller for a
492
+ // fresh replay.
493
+ startEventParams);
494
+ stepClaimCompletedAtMs = Date.now();
495
+ step = startResult.step;
496
+ }
497
+ catch (err) {
498
+ const mapped = startErrorToResult(err);
499
+ if (mapped)
500
+ return mapped;
501
+ throw err;
502
+ }
123
503
  }
124
504
  runtimeLogger.debug('Step execution details', {
125
505
  stepName,
@@ -132,8 +512,8 @@ export async function executeStep(params) {
132
512
  });
133
513
  let result;
134
514
  // Check max retries AFTER step_started (attempt was just incremented).
135
- // Only enforce when the step has a previous error this distinguishes
136
- // actual retries (failed → retry) from concurrent starts (V2 inline
515
+ // Only enforce when the step has a previous error; this distinguishes
516
+ // actual retries (failed → retry) from concurrent inline starts
137
517
  // execution loop can cause multiple handlers to step_started the same
138
518
  // step simultaneously, inflating the attempt counter without any failure).
139
519
  if (step.attempt > maxRetries + 1 && step.error) {
@@ -155,16 +535,17 @@ export async function executeStep(params) {
155
535
  wrappedError.cause = await hydrateStepError(step.error, workflowRunId, await getEncryptionKey());
156
536
  }
157
537
  catch {
158
- // Ignore best-effort cause attachment.
538
+ // Ignore: best-effort cause attachment.
159
539
  }
160
540
  }
161
541
  try {
162
- await world.events.create(workflowRunId, {
542
+ await createEvent({
163
543
  eventType: 'step_failed',
164
544
  specVersion: SPEC_VERSION_CURRENT,
165
545
  correlationId: stepId,
166
546
  eventData: {
167
- error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey()),
547
+ stepName,
548
+ error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey(), [], globalThis, compression),
168
549
  },
169
550
  });
170
551
  }
@@ -186,19 +567,53 @@ export async function executeStep(params) {
186
567
  });
187
568
  return { type: 'failed' };
188
569
  }
570
+ // Ops that must be durably committed before step completion (e.g. a
571
+ // step-initiated abort's hook_received event). See StepContext. Declared
572
+ // outside the try so the failure path below can also drain them.
573
+ const preCompletionOps = [];
574
+ const ops = [];
575
+ let opsSettled = true;
576
+ // Latency telemetry to attach to this step's terminal event. Computed
577
+ // right before user code runs; declared here so the failure path (the
578
+ // catch below) can attach it to step_failed too.
579
+ let latencyEventData;
580
+ // Backfill RSFS onto the already-computed telemetry once the optimistic
581
+ // turbo start has settled. On that path the step-start POST fires inside
582
+ // the run-ready barrier's `.then`, so `stepStartPostSentAtMs` (and
583
+ // therefore RSFS) is usually still unset when `latencyEventData` is
584
+ // first computed just before user code (the barrier is still in flight
585
+ // for any non-trivial `run_started` round-trip, which is exactly the
586
+ // slow-run_started case RSFS exists to measure). By the time
587
+ // `reconcileOptimisticStart()` has awaited the barrier the POST timestamp
588
+ // is known, so we patch RSFS in before the terminal event is written.
589
+ // Without this, slow-run_started samples are dropped, biasing RSFS
590
+ // percentiles low (missing-not-at-random). Recomputes only RSFS;
591
+ // TTFS/STSO stay anchored to `executionStartTime` as computed above.
592
+ const backfillOptimisticRsfs = () => {
593
+ if (!latencyEventData || latencyEventData.rsfs !== undefined)
594
+ return;
595
+ const anchorMs = params.latencyTracking?.rsfsAnchorMs;
596
+ if (anchorMs === undefined || stepStartPostSentAtMs === undefined)
597
+ return;
598
+ latencyEventData.rsfs = Math.max(0, stepStartPostSentAtMs - anchorMs);
599
+ if (span) {
600
+ span.setAttributes({
601
+ ...Attribute.StepRsfsMs(latencyEventData.rsfs),
602
+ });
603
+ }
604
+ };
189
605
  try {
190
606
  const attempt = step.attempt;
191
607
  if (!step.startedAt) {
192
608
  throw new WorkflowRuntimeError(`Step "${stepId}" has no "startedAt" timestamp`);
193
609
  }
194
610
  const stepStartedAt = step.startedAt;
195
- const ops = [];
196
611
  // Use the provided encryption key when available, otherwise resolve
197
612
  // through the memoized accessor declared at the top of this trace.
198
613
  const encryptionKey = params.encryptionKey ?? (await getEncryptionKey());
199
614
  const hydratedInput = await trace('step.hydrate', {}, async (hydrateSpan) => {
200
615
  const startTime = Date.now();
201
- const hydrated = await hydrateStepArguments(step.input, workflowRunId, encryptionKey, ops);
616
+ const hydrated = await hydrateStepArguments(step.input, workflowRunId, encryptionKey, ops, globalThis, {}, params.workflowDeploymentId);
202
617
  const durationMs = Date.now() - startTime;
203
618
  hydrateSpan?.setAttributes({
204
619
  ...Attribute.StepArgumentsCount(hydrated.args.length),
@@ -206,39 +621,169 @@ export async function executeStep(params) {
206
621
  });
207
622
  return hydrated;
208
623
  });
624
+ // Finalization of an unserializable-argument step writes step_created
625
+ // (placeholder input) and step_failed as two separate durable writes.
626
+ // A crash or transient failure between them leaves this step pending
627
+ // with the placeholder stored as its input, and normal crash recovery
628
+ // then dispatches it here. NEVER run user code with placeholder
629
+ // arguments; complete the intended failure instead. The
630
+ // SerializationError is fatal (`fatal: true`), so the catch below
631
+ // writes step_failed without retries, exactly what the interrupted
632
+ // finalization was about to do.
633
+ if (isUnserializableStepInputPlaceholder(hydratedInput)) {
634
+ const { message, hint } = formatSerializationError('step arguments', undefined);
635
+ throw new SerializationError(message, { hint });
636
+ }
209
637
  const args = hydratedInput.args;
210
638
  const thisVal = hydratedInput.thisVal ?? null;
211
- const port = isVercel ? undefined : await getPortLazy();
639
+ const workflowBaseUrl = createWorkflowBaseUrl(isVercel
640
+ ? `https://${process.env.VERCEL_URL}`
641
+ : `http://localhost:${(await getPortLazy()) ?? 3000}`);
642
+ // --- User code execution ---
643
+ // Wrap only stepFn.apply() (user step code) so cleanup below runs on
644
+ // BOTH success and failure. A user-code throw is captured here and
645
+ // re-raised after cancelAbortReaders, so it still flows to the outer
646
+ // catch (step_failed/step_retrying), but the abort-stream reader is
647
+ // torn down first. Without this, a throwing/retrying signal-bearing
648
+ // step would leak a real-time abort reader per attempt.
649
+ let userCodeError;
650
+ let userCodeFailed = false;
212
651
  const executionStartTime = Date.now();
213
- result = await trace('step.execute', {}, async () => {
214
- return await contextStorage.run({
215
- stepMetadata: {
216
- stepName,
217
- stepId,
218
- stepStartedAt: new Date(+stepStartedAt),
219
- attempt,
220
- },
221
- workflowMetadata: {
222
- workflowName,
223
- workflowRunId,
224
- workflowStartedAt: new Date(+workflowStartedAt),
225
- url: isVercel
226
- ? `https://${process.env.VERCEL_URL}`
227
- : `http://localhost:${port ?? 3000}`,
228
- features: { encryption: !!encryptionKey },
229
- },
230
- ops,
231
- closureVars: hydratedInput.closureVars,
232
- encryptionKey,
233
- }, () => stepFn.apply(thisVal, args));
652
+ latencyEventData = computeStepLatencyEventData({
653
+ tracking: params.latencyTracking,
654
+ stepCodeStartedAtMs: executionStartTime,
655
+ attempt,
656
+ lazyStepStart: params.lazyStepInput !== undefined,
657
+ optimisticStart,
658
+ preclaimedStart: params.preclaimedStart !== undefined,
659
+ stepStartPostSentAtMs,
234
660
  });
661
+ if (latencyEventData) {
662
+ // Mirror the latency telemetry onto the step span so traces show
663
+ // TTFS/STSO/RSFS alongside the flame graph, not just Datadog metrics.
664
+ span?.setAttributes({
665
+ ...(latencyEventData.ttfs !== undefined
666
+ ? Attribute.StepTtfsMs(latencyEventData.ttfs)
667
+ : {}),
668
+ ...(latencyEventData.stso !== undefined
669
+ ? Attribute.StepStsoMs(latencyEventData.stso)
670
+ : {}),
671
+ ...(latencyEventData.rsfs !== undefined
672
+ ? Attribute.StepRsfsMs(latencyEventData.rsfs)
673
+ : {}),
674
+ ...(latencyEventData.finalSchedulingReplay !== undefined
675
+ ? Attribute.StepFinalSchedulingReplayMs(latencyEventData.finalSchedulingReplay)
676
+ : {}),
677
+ ...Attribute.StepLatencyOptimizations(latencyEventData.optimizations ?? []),
678
+ });
679
+ }
680
+ /**
681
+ * Close the hook-resume TTR measurement (see runtime/resume-latency.ts).
682
+ *
683
+ * Called from INSIDE `contextStorage.run`, immediately before
684
+ * `stepFn.apply()`, deliberately not alongside the step-latency
685
+ * telemetry above. `executionStartTime` is taken before the inner
686
+ * `step.execute` span and the step context are established, and
687
+ * `step_prepare_ms` is documented to include exactly that setup, so
688
+ * anchoring T7 there would under-report both the phase and the total.
689
+ * TTFS/STSO keep their own anchor so this changes nothing about them.
690
+ *
691
+ * The `reported` latch makes one resumption yield one sample even
692
+ * though every step of an inline batch is handed the same tracking
693
+ * object: whichever step first reaches user code takes the
694
+ * measurement. Sharing it (rather than pinning the batch's first step)
695
+ * is what keeps the sample alive when that first step loses its atomic
696
+ * create-claim to a concurrent invocation while a sibling proceeds.
697
+ * The check-and-set is synchronous, so concurrent siblings cannot both
698
+ * pass it.
699
+ */
700
+ const reportResumeTtr = () => {
701
+ const tracking = params.resumeTracking;
702
+ if (!tracking || tracking.reported)
703
+ return;
704
+ const attributes = computeResumeTtrAttributes({
705
+ tracking,
706
+ attempt,
707
+ stepClaimStartedAtMs: stepStartPostSentAtMs,
708
+ stepClaimCompletedAtMs,
709
+ stepCodeStartedAtMs: Date.now(),
710
+ });
711
+ if (!attributes)
712
+ return;
713
+ tracking.reported = true;
714
+ span?.setAttributes(attributes);
715
+ };
716
+ let stepExecutionStatus = 'ok';
717
+ const stepExecutionStartTime = performance.now();
718
+ try {
719
+ result = await trace('step.execute', {}, async () => {
720
+ return await contextStorage.run({
721
+ stepMetadata: {
722
+ stepName,
723
+ stepId,
724
+ stepStartedAt: new Date(+stepStartedAt),
725
+ attempt,
726
+ },
727
+ workflowMetadata: {
728
+ workflowName,
729
+ workflowRunId,
730
+ workflowStartedAt: new Date(+workflowStartedAt),
731
+ url: workflowBaseUrl,
732
+ features: { encryption: !!encryptionKey },
733
+ },
734
+ workflowDeploymentId: params.workflowDeploymentId,
735
+ rootRunId: params.rootRunId,
736
+ ops,
737
+ preCompletionOps,
738
+ closureVars: hydratedInput.closureVars,
739
+ encryptionKey,
740
+ // Turbo optimistic start runs this body before `run_started` is
741
+ // durable. Expose the barrier so a direct step-body world write
742
+ // (e.g. `setAttributes`) can order itself after the
743
+ // run exists. Undefined on the await path (run already durable).
744
+ runReadyBarrier: optimisticStart
745
+ ? params.runReadyBarrier
746
+ : undefined,
747
+ }, () => {
748
+ // The last instant before user code: T7 of the resume window.
749
+ reportResumeTtr();
750
+ return stepFn.apply(thisVal, args);
751
+ });
752
+ });
753
+ }
754
+ catch (err) {
755
+ stepExecutionStatus = 'error';
756
+ userCodeError = err;
757
+ userCodeFailed = true;
758
+ }
759
+ finally {
760
+ void recordStepExecutionDuration(performance.now() - stepExecutionStartTime, stepExecutionStatus);
761
+ }
235
762
  const executionTimeMs = Date.now() - executionStartTime;
763
+ // Tear down any abort-stream readers opened while hydrating the step's
764
+ // arguments (a serialized AbortSignal opens a real-time abort reader for
765
+ // the step's duration). Without this the reader's `read()` promise never
766
+ // settles, so the `ops` flush below always loses the 500ms race and the
767
+ // step reports `hasPendingOps`, forcing the inline loop to queue a
768
+ // continuation and paying a full round-trip per signal-bearing step.
769
+ // Runs unconditionally (success or failure) so a throwing step doesn't
770
+ // leak the reader.
771
+ cancelAbortReaders(...args, thisVal, hydratedInput.closureVars);
772
+ // Re-raise a user-code failure now that cleanup has run; the outer
773
+ // catch maps it to step_failed/step_retrying.
774
+ if (userCodeFailed) {
775
+ throw userCodeError;
776
+ }
236
777
  span?.setAttributes({
237
778
  ...Attribute.QueueExecutionTimeMs(executionTimeMs),
238
779
  });
239
780
  result = await trace('step.dehydrate', {}, async (dehydrateSpan) => {
240
781
  const startTime = Date.now();
241
- const dehydrated = await dehydrateStepReturnValue(result, workflowRunId, encryptionKey, ops);
782
+ const dehydrated = await dehydrateStepReturnValue(result, workflowRunId, encryptionKey, ops, globalThis, false, false, compression,
783
+ // Turbo optimistic start: a returned stream is piped to the server
784
+ // after the body but within this same op flush, so gate its first
785
+ // write on the run-ready barrier. Undefined on the await path.
786
+ optimisticStart ? params.runReadyBarrier : undefined);
242
787
  const durationMs = Date.now() - startTime;
243
788
  dehydrateSpan?.setAttributes({
244
789
  ...Attribute.QueueSerializeTimeMs(durationMs),
@@ -247,79 +792,108 @@ export async function executeStep(params) {
247
792
  return dehydrated;
248
793
  });
249
794
  // Flush pending ops (stream writes, etc.) with a short inline wait.
250
- // Now that WorkflowServerWritableStream flushes synchronously on
251
- // each write (not via setTimeout), the flushablePipe's pendingOps
252
- // accurately reflects whether data has reached the server. Most ops
253
- // settle within ~200ms (100ms lock-release polling + HTTP flush).
795
+ // WorkflowServerWritableStream acks writes on buffer entry
796
+ // (group-commit batching); durability is enforced by its drain
797
+ // barrier, which the flushable state's completion awaits after
798
+ // lock release. Most ops settle within ~200ms (lock-release
799
+ // polling + one batched HTTP flush).
254
800
  // If ops don't settle in 500ms (e.g., WritableStream kept open
255
801
  // across steps), waitUntil handles the rest.
256
- let opsSettled = true;
257
802
  if (ops.length > 0) {
258
- const opsPromise = Promise.all(ops).catch((err) => {
259
- const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
260
- if (!isAbortError)
261
- throw err;
803
+ const opsPromise = Promise.all(ops);
804
+ // The race below surfaces failures inline when ops settle quickly;
805
+ // if the 500ms timeout wins, the failure is only observed here. The
806
+ // promise handed to waitUntil must never reject (an unconsumed
807
+ // waitUntil rejection crashes the process as unhandledRejection),
808
+ // so unexpected failures are logged instead.
809
+ safeWaitUntil(opsPromise, (err) => {
810
+ runtimeLogger.warn('Background flush of step stream ops failed', {
811
+ workflowRunId,
812
+ stepId,
813
+ error: err instanceof Error ? err.message : String(err),
814
+ });
262
815
  });
263
- waitUntil(opsPromise);
264
816
  opsSettled = await Promise.race([
265
- opsPromise.then(() => true),
817
+ opsPromise.then(() => true, (err) => {
818
+ // Ignore expected client disconnect errors (e.g., browser
819
+ // refresh during streaming)
820
+ const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
821
+ if (isAbortError)
822
+ return true;
823
+ throw err;
824
+ }),
266
825
  new Promise((r) => setTimeout(() => r(false), 500)),
267
826
  ]);
268
827
  }
269
- // Create step_completed event
270
- let stepCompleted409 = false;
271
- await world.events
272
- .create(workflowRunId, {
273
- eventType: 'step_completed',
274
- specVersion: SPEC_VERSION_CURRENT,
275
- correlationId: stepId,
276
- eventData: {
277
- result: result,
278
- },
279
- })
280
- .catch((err) => {
281
- if (EntityConflictError.is(err)) {
282
- runtimeLogger.info('Tried completing step, but step has already finished.', {
283
- workflowRunId,
284
- stepId,
285
- stepName,
286
- message: err.message,
287
- });
288
- stepCompleted409 = true;
289
- return;
290
- }
291
- throw err;
292
- });
293
- if (stepCompleted409) {
294
- return { type: 'skipped' };
828
+ // Optimistic start: the body ran before `step_started` was confirmed.
829
+ // Reconcile it now: if we lost the create-claim (or the run is
830
+ // gone/throttled) discard this result and don't write step_completed.
831
+ // Reconcile before draining preCompletionOps: a discarded result means
832
+ // the winning handler owns the outcome (and re-fires any abort
833
+ // idempotently), so there's no point paying the abort-commit latency.
834
+ if (optimisticStart) {
835
+ const reconcile = await reconcileOptimisticStart();
836
+ if (reconcile)
837
+ return reconcile;
838
+ // Barrier resolved: the step-start POST timestamp is now known, so
839
+ // RSFS can be attached to the step_completed event below.
840
+ backfillOptimisticRsfs();
295
841
  }
296
- span?.setAttributes({
297
- ...Attribute.StepStatus('completed'),
298
- ...Attribute.StepResultType(typeof result),
299
- });
300
- if (ops.length > 0) {
301
- stepLogger.debug('Step has pending ops', {
302
- workflowRunId,
303
- stepName,
304
- opsCount: ops.length,
305
- });
842
+ // Commit must-be-durable ops (e.g. a step-initiated abort's
843
+ // hook_received event) before writing step_completed, so any workflow
844
+ // continuation triggered by that event observes the abort rather than
845
+ // racing it. These ops swallow their own errors, so awaiting only
846
+ // enforces ordering (the `.catch()` defends the no-reject contract on
847
+ // StepContext.preCompletionOps).
848
+ //
849
+ // Tradeoff: correctness requires the hook be durable before completion,
850
+ // so, unlike the background `ops` flush above, this cannot be capped
851
+ // with a resolve-on-timeout race. A slow resume therefore adds its
852
+ // latency to a step that aborts a controller, and a true hang holds
853
+ // completion until the platform/queue execution timeout fires; the queue
854
+ // then redelivers and the step retries, re-firing the abort idempotently.
855
+ if (preCompletionOps.length > 0) {
856
+ await Promise.all(preCompletionOps).catch(() => { });
306
857
  }
307
- // hasPendingOps signals the V2 handler to break the loop
308
- // and queue a continuation so waitUntil can flush them.
309
- return { type: 'completed', hasPendingOps: !opsSettled };
310
858
  }
311
859
  catch (err) {
312
- const normalizedError = await normalizeUnknownError(err);
313
- const normalizedStack = normalizedError.stack || getErrorStack(err) || '';
314
- if (err instanceof Error) {
315
- span?.recordException?.(err);
860
+ // Optimistic start: the body threw before `step_started` was confirmed.
861
+ // Reconcile first: if we lost the create-claim (or the run is
862
+ // gone/throttled) the body error is moot; discard it and don't write a
863
+ // terminal event (the winning handler owns the outcome). Reconcile
864
+ // before draining preCompletionOps for the same reason as the success
865
+ // path: a discarded outcome doesn't need the abort committed here.
866
+ if (optimisticStart) {
867
+ const reconcile = await reconcileOptimisticStart();
868
+ if (reconcile)
869
+ return reconcile;
870
+ // Barrier resolved: attach RSFS to the step_failed event(s) below.
871
+ backfillOptimisticRsfs();
316
872
  }
317
- const isFatal = FatalError.is(err);
873
+ // Order any must-be-durable ops (e.g. a step-initiated abort's
874
+ // hook_received event) ahead of step_failed too: a step that aborts and
875
+ // then throws must still have the abort recorded before the failure
876
+ // continuation observes it. Same latency tradeoff and no-reject contract
877
+ // as the success path above. See StepContext.preCompletionOps.
878
+ if (preCompletionOps.length > 0) {
879
+ await Promise.all(preCompletionOps).catch(() => { });
880
+ }
881
+ const effectiveErr = promoteAbortErrorToFatal(err);
882
+ const normalizedError = await normalizeUnknownError(effectiveErr);
883
+ const normalizedStack = normalizedError.stack || getErrorStack(effectiveErr) || '';
884
+ if (effectiveErr instanceof Error) {
885
+ span?.recordException?.(effectiveErr);
886
+ }
887
+ const isFatal = FatalError.is(effectiveErr);
318
888
  span?.setAttributes({
319
- ...Attribute.StepErrorName(getErrorName(err)),
889
+ ...Attribute.StepErrorName(getErrorName(effectiveErr)),
320
890
  ...Attribute.StepErrorMessage(normalizedError.message),
321
- ...Attribute.ErrorType(getErrorName(err)),
322
- ...Attribute.ErrorCategory(isFatal ? 'fatal' : RetryableError.is(err) ? 'retryable' : 'transient'),
891
+ ...Attribute.ErrorType(getErrorName(effectiveErr)),
892
+ ...Attribute.ErrorCategory(isFatal
893
+ ? 'fatal'
894
+ : RetryableError.is(effectiveErr)
895
+ ? 'retryable'
896
+ : 'transient'),
323
897
  ...Attribute.ErrorRetryable(!isFatal),
324
898
  });
325
899
  if (RunExpiredError.is(err)) {
@@ -336,16 +910,18 @@ export async function executeStep(params) {
336
910
  // error preserves it for consumers. `types.isNativeError()` works
337
911
  // across VM realms (a workflow-thrown error is an instance of the
338
912
  // VM's Error class, not the host's).
339
- if (types.isNativeError(err) && normalizedStack) {
340
- err.stack = normalizedStack;
913
+ if (types.isNativeError(effectiveErr) && normalizedStack) {
914
+ effectiveErr.stack = normalizedStack;
341
915
  }
342
916
  try {
343
- await world.events.create(workflowRunId, {
917
+ await createEvent({
344
918
  eventType: 'step_failed',
345
919
  specVersion: SPEC_VERSION_CURRENT,
346
920
  correlationId: stepId,
347
921
  eventData: {
348
- error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
922
+ stepName,
923
+ error: await dehydrateStepError(effectiveErr, workflowRunId, await getEncryptionKey(), [], globalThis, compression),
924
+ ...latencyEventData,
349
925
  },
350
926
  });
351
927
  }
@@ -393,12 +969,14 @@ export async function executeStep(params) {
393
969
  if (normalizedStack)
394
970
  wrappedError.stack = normalizedStack;
395
971
  try {
396
- await world.events.create(workflowRunId, {
972
+ await createEvent({
397
973
  eventType: 'step_failed',
398
974
  specVersion: SPEC_VERSION_CURRENT,
399
975
  correlationId: stepId,
400
976
  eventData: {
401
- error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey()),
977
+ stepName,
978
+ error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey(), [], globalThis, compression),
979
+ ...latencyEventData,
402
980
  },
403
981
  });
404
982
  }
@@ -444,12 +1022,13 @@ export async function executeStep(params) {
444
1022
  err.stack = normalizedStack;
445
1023
  }
446
1024
  try {
447
- await world.events.create(workflowRunId, {
1025
+ await createEvent({
448
1026
  eventType: 'step_retrying',
449
1027
  specVersion: SPEC_VERSION_CURRENT,
450
1028
  correlationId: stepId,
451
1029
  eventData: {
452
- error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
1030
+ stepName,
1031
+ error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey(), [], globalThis, compression),
453
1032
  ...(RetryableError.is(err) && { retryAfter: err.retryAfter }),
454
1033
  },
455
1034
  });
@@ -475,6 +1054,60 @@ export async function executeStep(params) {
475
1054
  });
476
1055
  return { type: 'retry', timeoutSeconds };
477
1056
  }
1057
+ // Create step_completed event outside the step execution failure path:
1058
+ // persistence failures are infrastructure errors and should redeliver the
1059
+ // queue message, not become user step_retrying/step_failed events.
1060
+ let completedResult;
1061
+ try {
1062
+ completedResult = await createEvent({
1063
+ eventType: 'step_completed',
1064
+ specVersion: SPEC_VERSION_CURRENT,
1065
+ correlationId: stepId,
1066
+ eventData: {
1067
+ stepName,
1068
+ workflowName,
1069
+ result: result,
1070
+ ...latencyEventData,
1071
+ },
1072
+ }, params.inlineDeltaSinceCursor !== undefined
1073
+ ? { sinceCursor: params.inlineDeltaSinceCursor }
1074
+ : undefined);
1075
+ }
1076
+ catch (err) {
1077
+ if (EntityConflictError.is(err)) {
1078
+ runtimeLogger.info('Tried completing step, but step has already finished.', {
1079
+ workflowRunId,
1080
+ stepId,
1081
+ stepName,
1082
+ message: err.message,
1083
+ });
1084
+ return { type: 'skipped' };
1085
+ }
1086
+ if (RunExpiredError.is(err)) {
1087
+ stepLogger.info('Workflow run already completed, skipping step', {
1088
+ workflowRunId,
1089
+ stepId,
1090
+ message: err.message,
1091
+ });
1092
+ return { type: 'gone' };
1093
+ }
1094
+ throw err;
1095
+ }
1096
+ const inlineDelta = extractInlineDelta(completedResult, params.inlineDeltaSinceCursor !== undefined);
1097
+ span?.setAttributes({
1098
+ ...Attribute.StepStatus('completed'),
1099
+ ...Attribute.StepResultType(typeof result),
1100
+ });
1101
+ if (ops.length > 0) {
1102
+ stepLogger.debug('Step has pending ops', {
1103
+ workflowRunId,
1104
+ stepName,
1105
+ opsCount: ops.length,
1106
+ });
1107
+ }
1108
+ // hasPendingOps signals the combined handler to break the loop
1109
+ // and queue a continuation so waitUntil can flush them.
1110
+ return { type: 'completed', hasPendingOps: !opsSettled, inlineDelta };
478
1111
  });
479
1112
  }
480
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1leGVjdXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL3N0ZXAtZXhlY3V0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixVQUFVLEVBQ1YsY0FBYyxFQUNkLGVBQWUsRUFDZixhQUFhLEVBQ2IsYUFBYSxFQUNiLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU1QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hELE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNwQixnQkFBZ0IsR0FDakIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEMsT0FBTyxFQUNMLFlBQVksRUFDWixhQUFhLEVBQ2IscUJBQXFCLEdBQ3RCLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFcEQsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLENBQUM7QUF3Qm5DOzs7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QUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO2dCQUM1RCxDQUFDLENBQUMsQ0FBQyxDQUNOLENBQUM7WUFFRixJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLENBQUM7Z0JBQ3BELEdBQUcsU0FBUyxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQzthQUN0QyxDQUFDLENBQUM7WUFFSCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsQ0FBQztRQUMzQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdHlwZXMgfSBmcm9tICdub2RlOnV0aWwnO1xuaW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRmF0YWxFcnJvcixcbiAgUmV0cnlhYmxlRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgVGhyb3R0bGVFcnJvcixcbiAgVG9vRWFybHlFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgcGx1cmFsaXplIH0gZnJvbSAnQHdvcmtmbG93L3V0aWxzJztcbmltcG9ydCB0eXBlIHsgV29ybGQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgU1BFQ19WRVJTSU9OX0NVUlJFTlQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHR5cGUgeyBDcnlwdG9LZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIsIHN0ZXBMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZ2V0U3RlcEZ1bmN0aW9uIH0gZnJvbSAnLi4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQge1xuICBkZWh5ZHJhdGVTdGVwRXJyb3IsXG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIGh5ZHJhdGVTdGVwRXJyb3IsXG59IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgY29udGV4dFN0b3JhZ2UgfSBmcm9tICcuLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IHRyYWNlIH0gZnJvbSAnLi4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7XG4gIGdldEVycm9yTmFtZSxcbiAgZ2V0RXJyb3JTdGFjayxcbiAgbm9ybWFsaXplVW5rbm93bkVycm9yLFxufSBmcm9tICcuLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBnZXRQb3J0TGF6eSB9IGZyb20gJy4vZ2V0LXBvcnQtbGF6eS5qcyc7XG5pbXBvcnQgeyBtZW1vaXplRW5jcnlwdGlvbktleSB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5cbmNvbnN0IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUyA9IDM7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RlcEV4ZWN1dG9yUGFyYW1zIHtcbiAgd29ybGQ6IFdvcmxkO1xuICB3b3JrZmxvd1J1bklkOiBzdHJpbmc7XG4gIHdvcmtmbG93TmFtZTogc3RyaW5nO1xuICB3b3JrZmxvd1N0YXJ0ZWRBdDogbnVtYmVyO1xuICBzdGVwSWQ6IHN0cmluZztcbiAgc3RlcE5hbWU6IHN0cmluZztcbiAgZW5jcnlwdGlvbktleT86IENyeXB0b0tleTtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgYSBzdGVwIGV4ZWN1dGlvbiBhdHRlbXB0LiBUaGUgY2FsbGVyIGRlY2lkZXMgd2hhdCB0byBkb1xuICogYmFzZWQgb24gdGhlIHJlc3VsdCB0eXBlIChlLmcuLCBxdWV1ZSB3b3JrZmxvdyBjb250aW51YXRpb24sIHJlcGxheSBpbmxpbmUsIGV0Yy4pLlxuICovXG5leHBvcnQgdHlwZSBTdGVwRXhlY3V0aW9uUmVzdWx0ID1cbiAgfCB7IHR5cGU6ICdjb21wbGV0ZWQnOyBoYXNQZW5kaW5nT3BzPzogYm9vbGVhbiB9XG4gIHwgeyB0eXBlOiAnZmFpbGVkJyB9XG4gIHwgeyB0eXBlOiAncmV0cnknOyB0aW1lb3V0U2Vjb25kczogbnVtYmVyIH1cbiAgfCB7IHR5cGU6ICdza2lwcGVkJyB9XG4gIHwgeyB0eXBlOiAnZ29uZScgfVxuICB8IHsgdHlwZTogJ3Rocm90dGxlZCc7IHRpbWVvdXRTZWNvbmRzOiBudW1iZXIgfTtcblxuLyoqXG4gKiBFeGVjdXRlcyBhIHNpbmdsZSBzdGVwOiBjcmVhdGVzIHN0ZXBfc3RhcnRlZCBldmVudCwgaHlkcmF0ZXMgaW5wdXQsXG4gKiBydW5zIHRoZSBzdGVwIGZ1bmN0aW9uLCBjcmVhdGVzIHN0ZXBfY29tcGxldGVkL3N0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcgZXZlbnRzLlxuICpcbiAqIERvZXMgTk9UIHF1ZXVlIHdvcmtmbG93IGNvbnRpbnVhdGlvbiBtZXNzYWdlcyDigJQgdGhlIGNhbGxlciBkZWNpZGVzIHdoYXQgdG8gZG8gbmV4dC5cbiAqIFVzZWQgYnkgYm90aCB0aGUgVjEgc3RlcCBoYW5kbGVyIGFuZCB0aGUgVjIgY29tYmluZWQgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVTdGVwKFxuICBwYXJhbXM6IFN0ZXBFeGVjdXRvclBhcmFtc1xuKTogUHJvbWlzZTxTdGVwRXhlY3V0aW9uUmVzdWx0PiB7XG4gIGNvbnN0IHtcbiAgICB3b3JsZCxcbiAgICB3b3JrZmxvd1J1bklkLFxuICAgIHdvcmtmbG93TmFtZSxcbiAgICB3b3JrZmxvd1N0YXJ0ZWRBdCxcbiAgICBzdGVwSWQsXG4gICAgc3RlcE5hbWUsXG4gIH0gPSBwYXJhbXM7XG4gIGNvbnN0IGlzVmVyY2VsID0gcHJvY2Vzcy5lbnYuVkVSQ0VMX1VSTCAhPT0gdW5kZWZpbmVkO1xuXG4gIHJldHVybiB0cmFjZShgU1RFUCAke3N0ZXBOYW1lfWAsIHt9LCBhc3luYyAoc3BhbikgPT4ge1xuICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBOYW1lKHN0ZXBOYW1lKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKHdvcmtmbG93UnVuSWQpLFxuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBJZChzdGVwSWQpLFxuICAgIH0pO1xuXG4gICAgLy8gTWVtb2l6ZWQgYWNjZXNzb3IgZm9yIHRoZSBwZXItcnVuIGVuY3J5cHRpb24ga2V5LiBUaGUgZmlyc3QgY2FsbGVyXG4gICAgLy8gKGlucHV0IGh5ZHJhdGlvbiBvbiB0aGUgc3VjY2VzcyBwYXRoLCBvciBvbmUgb2YgdGhlIGVhcmx5LXJldHVyblxuICAgIC8vIGRlaHlkcmF0ZVN0ZXBFcnJvciBwYXRocyBpZiBzdGVwX3N0YXJ0ZWQgZmFpbHMpIHRyaWdnZXJzIHRoZSBhY3R1YWxcbiAgICAvLyBmZXRjaCAvIEhLREYgZGVyaXZhdGlvbjsgc3Vic2VxdWVudCBjYWxsZXJzIGF3YWl0IHRoZSBjYWNoZWQgcHJvbWlzZS5cbiAgICBjb25zdCBnZXRFbmNyeXB0aW9uS2V5ID0gbWVtb2l6ZUVuY3J5cHRpb25LZXkod29ybGQsIHdvcmtmbG93UnVuSWQpO1xuXG4gICAgY29uc3Qgc3RlcEZuID0gZ2V0U3RlcEZ1bmN0aW9uKHN0ZXBOYW1lKTtcbiAgICBpZiAoIXN0ZXBGbiB8fCB0eXBlb2Ygc3RlcEZuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBTdGVwIGZ1bmN0aW9uIG5vdCByZWdpc3RlcmVkIOKAlCBmYWlsIHRoZSBzdGVwIGltbWVkaWF0ZWx5IChub3QgdGhlIHJ1bikuXG4gICAgICAvLyBUaGlzIG1hdGNoZXMgdGhlIFYxIHN0ZXAgaGFuZGxlciBwYXR0ZXJuOiBjcmVhdGUgc3RlcF9mYWlsZWQgZXZlbnQgc29cbiAgICAgIC8vIHRoZSB3b3JrZmxvdyBjYW4gaGFuZGxlIGl0IGdyYWNlZnVsbHkgdmlhIHRyeS9jYXRjaCBpbiB1c2VyIGNvZGUuXG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBcIiR7c3RlcE5hbWV9XCIgaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGN1cnJlbnQgZGVwbG95bWVudC4gVGhpcyB1c3VhbGx5IGluZGljYXRlcyBhIGJ1aWxkIG9yIGJ1bmRsaW5nIGlzc3VlIHRoYXQgY2F1c2VkIHRoZSBzdGVwIHRvIG5vdCBiZSBpbmNsdWRlZCBpbiB0aGUgZGVwbG95bWVudC5gO1xuICAgICAgcnVudGltZUxvZ2dlci5lcnJvcignU3RlcCBmdW5jdGlvbiBub3QgcmVnaXN0ZXJlZCwgZmFpbGluZyBzdGVwJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgc3RlcElkLFxuICAgICAgfSk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHdvcmtmbG93UnVuSWQsIHtcbiAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgIG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSksXG4gICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKHN0ZXBGYWlsRXJyKSB7XG4gICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IHN0ZXBGYWlsRXJyO1xuICAgICAgfVxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBGYXRhbEVycm9yKHRydWUpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4geyB0eXBlOiAnZmFpbGVkJyB9O1xuICAgIH1cblxuICAgIGNvbnN0IG1heFJldHJpZXMgPSBzdGVwRm4ubWF4UmV0cmllcyA/PyBERUZBVUxUX1NURVBfTUFYX1JFVFJJRVM7XG5cbiAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTWF4UmV0cmllcyhtYXhSZXRyaWVzKSxcbiAgICB9KTtcblxuICAgIC8vIHN0ZXBfc3RhcnRlZCB2YWxpZGF0ZXMgc3RhdGUgYW5kIHJldHVybnMgdGhlIHN0ZXAgZW50aXR5XG4gICAgbGV0IHN0ZXA7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXJ0UmVzdWx0ID0gYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZSh3b3JrZmxvd1J1bklkLCB7XG4gICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfc3RhcnRlZCcsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghc3RhcnRSZXN1bHQuc3RlcCkge1xuICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgYHN0ZXBfc3RhcnRlZCBldmVudCBmb3IgXCIke3N0ZXBJZH1cIiBkaWQgbm90IHJldHVybiBzdGVwIGVudGl0eWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHN0ZXAgPSBzdGFydFJlc3VsdC5zdGVwO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKFRocm90dGxlRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBjb25zdCByZXRyeUFmdGVyID0gTWF0aC5tYXgoXG4gICAgICAgICAgMSxcbiAgICAgICAgICB0eXBlb2YgZXJyLnJldHJ5QWZ0ZXIgPT09ICdudW1iZXInID8gZXJyLnJldHJ5QWZ0ZXIgOiAxXG4gICAgICAgICk7XG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnVGhyb3R0bGVkIG9uIHN0ZXBfc3RhcnRlZCwgZGVmZXJyaW5nJywge1xuICAgICAgICAgIHJldHJ5QWZ0ZXJTZWNvbmRzOiByZXRyeUFmdGVyLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3Rocm90dGxlZCcsIHRpbWVvdXRTZWNvbmRzOiByZXRyeUFmdGVyIH07XG4gICAgICB9XG4gICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgIGBXb3JrZmxvdyBydW4gXCIke3dvcmtmbG93UnVuSWR9XCIgaGFzIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBzdGVwIFwiJHtzdGVwSWR9XCI6ICR7ZXJyLm1lc3NhZ2V9YFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAnZ29uZScgfTtcbiAgICAgIH1cbiAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3RlcCBpbiB0ZXJtaW5hbCBzdGF0ZSwgc2tpcHBpbmcnLCB7XG4gICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgc3RlcElkLFxuICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgZXJyb3I6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTa2lwcGVkKHRydWUpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU2tpcFJlYXNvbignY29tcGxldGVkJyksXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAnc2tpcHBlZCcgfTtcbiAgICAgIH1cbiAgICAgIGlmIChUb29FYXJseUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBNYXRoLm1heCgxLCBlcnIucmV0cnlBZnRlciA/PyAxKTtcbiAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3RlcCByZXRyeUFmdGVyIHRpbWVzdGFtcCBub3QgeWV0IHJlYWNoZWQnLCB7XG4gICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgc3RlcElkLFxuICAgICAgICAgIHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3JldHJ5JywgdGltZW91dFNlY29uZHMgfTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG5cbiAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdGVwIGV4ZWN1dGlvbiBkZXRhaWxzJywge1xuICAgICAgc3RlcE5hbWUsXG4gICAgICBzdGVwSWQ6IHN0ZXAuc3RlcElkLFxuICAgICAgc3RhdHVzOiBzdGVwLnN0YXR1cyxcbiAgICAgIGF0dGVtcHQ6IHN0ZXAuYXR0ZW1wdCxcbiAgICB9KTtcblxuICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoc3RlcC5zdGF0dXMpLFxuICAgIH0pO1xuXG4gICAgbGV0IHJlc3VsdDogdW5rbm93bjtcblxuICAgIC8vIENoZWNrIG1heCByZXRyaWVzIEFGVEVSIHN0ZXBfc3RhcnRlZCAoYXR0ZW1wdCB3YXMganVzdCBpbmNyZW1lbnRlZCkuXG4gICAgLy8gT25seSBlbmZvcmNlIHdoZW4gdGhlIHN0ZXAgaGFzIGEgcHJldmlvdXMgZXJyb3Ig4oCUIHRoaXMgZGlzdGluZ3Vpc2hlc1xuICAgIC8vIGFjdHVhbCByZXRyaWVzIChmYWlsZWQg4oaSIHJldHJ5KSBmcm9tIGNvbmN1cnJlbnQgc3RhcnRzIChWMiBpbmxpbmVcbiAgICAvLyBleGVjdXRpb24gbG9vcCBjYW4gY2F1c2UgbXVsdGlwbGUgaGFuZGxlcnMgdG8gc3RlcF9zdGFydGVkIHRoZSBzYW1lXG4gICAgLy8gc3RlcCBzaW11bHRhbmVvdXNseSwgaW5mbGF0aW5nIHRoZSBhdHRlbXB0IGNvdW50ZXIgd2l0aG91dCBhbnkgZmFpbHVyZSkuXG4gICAgaWYgKHN0ZXAuYXR0ZW1wdCA+IG1heFJldHJpZXMgKyAxICYmIHN0ZXAuZXJyb3IpIHtcbiAgICAgIGNvbnN0IHJldHJ5Q291bnQgPSBzdGVwLmF0dGVtcHQgLSAxO1xuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFN0ZXAgXCIke3N0ZXBOYW1lfVwiIGV4Y2VlZGVkIG1heCByZXRyaWVzICgke3JldHJ5Q291bnR9ICR7cGx1cmFsaXplKCdyZXRyeScsICdyZXRyaWVzJywgcmV0cnlDb3VudCl9KWA7XG4gICAgICBzdGVwTG9nZ2VyLmVycm9yKCdTdGVwIGV4Y2VlZGVkIG1heCByZXRyaWVzJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgIH0pO1xuICAgICAgLy8gUHJlc2VydmUgdGhlIHByaW9yIGF0dGVtcHQncyBzZXJpYWxpemVkIGVycm9yIGFzIHRoZSBjYXVzZSBzbyB0aGVcbiAgICAgIC8vIHVuZGVybHlpbmcgZmFpbHVyZSBpcyByZWNvdmVyYWJsZSBmcm9tIGBzdGVwLmVycm9yLmNhdXNlYCBhZnRlclxuICAgICAgLy8gaHlkcmF0aW9uLCB3aXRob3V0IGZvcmNpbmcgY29uc3VtZXJzIHRvIHdhbGsgdGhlIHN0ZXBfcmV0cnlpbmdcbiAgICAgIC8vIGV2ZW50IGhpc3RvcnkuIEJlc3QtZWZmb3J0OiBpZiBoeWRyYXRpb24gb2YgdGhlIHByaW9yIGBzdGVwLmVycm9yYFxuICAgICAgLy8gdGhyb3dzLCBmYWxsIGJhY2sgdG8gYSBGYXRhbEVycm9yIHdpdGhvdXQgY2F1c2UuXG4gICAgICBjb25zdCB3cmFwcGVkRXJyb3IgPSBuZXcgRmF0YWxFcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgICAgaWYgKHN0ZXAuZXJyb3IgIT0gbnVsbCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICh3cmFwcGVkRXJyb3IgYXMgRXJyb3IpLmNhdXNlID0gYXdhaXQgaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgIHN0ZXAuZXJyb3IsXG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gSWdub3JlIOKAlCBiZXN0LWVmZm9ydCBjYXVzZSBhdHRhY2htZW50LlxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHdvcmtmbG93UnVuSWQsIHtcbiAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgIHdyYXBwZWRFcnJvcixcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICApLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7IHR5cGU6ICdmYWlsZWQnIH07XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGF0dGVtcHQgPSBzdGVwLmF0dGVtcHQ7XG5cbiAgICAgIGlmICghc3RlcC5zdGFydGVkQXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgIGBTdGVwIFwiJHtzdGVwSWR9XCIgaGFzIG5vIFwic3RhcnRlZEF0XCIgdGltZXN0YW1wYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3Qgc3RlcFN0YXJ0ZWRBdCA9IHN0ZXAuc3RhcnRlZEF0O1xuICAgICAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgICAgIC8vIFVzZSB0aGUgcHJvdmlkZWQgZW5jcnlwdGlvbiBrZXkgd2hlbiBhdmFpbGFibGUsIG90aGVyd2lzZSByZXNvbHZlXG4gICAgICAvLyB0aHJvdWdoIHRoZSBtZW1vaXplZCBhY2Nlc3NvciBkZWNsYXJlZCBhdCB0aGUgdG9wIG9mIHRoaXMgdHJhY2UuXG4gICAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcGFyYW1zLmVuY3J5cHRpb25LZXkgPz8gKGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKSk7XG4gICAgICBjb25zdCBoeWRyYXRlZElucHV0ID0gYXdhaXQgdHJhY2UoXG4gICAgICAgICdzdGVwLmh5ZHJhdGUnLFxuICAgICAgICB7fSxcbiAgICAgICAgYXN5bmMgKGh5ZHJhdGVTcGFuKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBjb25zdCBoeWRyYXRlZCA9IGF3YWl0IGh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgc3RlcC5pbnB1dCxcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgb3BzXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgICAgICBoeWRyYXRlU3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEFyZ3VtZW50c0NvdW50KGh5ZHJhdGVkLmFyZ3MubGVuZ3RoKSxcbiAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZURlc2VyaWFsaXplVGltZU1zKGR1cmF0aW9uTXMpLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBoeWRyYXRlZDtcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgY29uc3QgYXJncyA9IGh5ZHJhdGVkSW5wdXQuYXJncztcbiAgICAgIGNvbnN0IHRoaXNWYWwgPSBoeWRyYXRlZElucHV0LnRoaXNWYWwgPz8gbnVsbDtcbiAgICAgIGNvbnN0IHBvcnQgPSBpc1ZlcmNlbCA/IHVuZGVmaW5lZCA6IGF3YWl0IGdldFBvcnRMYXp5KCk7XG5cbiAgICAgIGNvbnN0IGV4ZWN1dGlvblN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0cmFjZSgnc3RlcC5leGVjdXRlJywge30sIGFzeW5jICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGNvbnRleHRTdG9yYWdlLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzdGVwTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgc3RlcFN0YXJ0ZWRBdDogbmV3IERhdGUoK3N0ZXBTdGFydGVkQXQpLFxuICAgICAgICAgICAgICBhdHRlbXB0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdvcmtmbG93TWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogbmV3IERhdGUoK3dvcmtmbG93U3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgdXJsOiBpc1ZlcmNlbFxuICAgICAgICAgICAgICAgID8gYGh0dHBzOi8vJHtwcm9jZXNzLmVudi5WRVJDRUxfVVJMfWBcbiAgICAgICAgICAgICAgICA6IGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydCA/PyAzMDAwfWAsXG4gICAgICAgICAgICAgIGZlYXR1cmVzOiB7IGVuY3J5cHRpb246ICEhZW5jcnlwdGlvbktleSB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wcyxcbiAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBoeWRyYXRlZElucHV0LmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICB9LFxuICAgICAgICAgICgpID0+IHN0ZXBGbi5hcHBseSh0aGlzVmFsLCBhcmdzKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgICBjb25zdCBleGVjdXRpb25UaW1lTXMgPSBEYXRlLm5vdygpIC0gZXhlY3V0aW9uU3RhcnRUaW1lO1xuXG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlRXhlY3V0aW9uVGltZU1zKGV4ZWN1dGlvblRpbWVNcyksXG4gICAgICB9KTtcblxuICAgICAgcmVzdWx0ID0gYXdhaXQgdHJhY2UoJ3N0ZXAuZGVoeWRyYXRlJywge30sIGFzeW5jIChkZWh5ZHJhdGVTcGFuKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IGRlaHlkcmF0ZWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICBvcHNcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZHVyYXRpb25NcyA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgIGRlaHlkcmF0ZVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZVNlcmlhbGl6ZVRpbWVNcyhkdXJhdGlvbk1zKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJlc3VsdFR5cGUodHlwZW9mIGRlaHlkcmF0ZWQpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGRlaHlkcmF0ZWQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gRmx1c2ggcGVuZGluZyBvcHMgKHN0cmVhbSB3cml0ZXMsIGV0Yy4pIHdpdGggYSBzaG9ydCBpbmxpbmUgd2FpdC5cbiAgICAgIC8vIE5vdyB0aGF0IFdvcmtmbG93U2VydmVyV3JpdGFibGVTdHJlYW0gZmx1c2hlcyBzeW5jaHJvbm91c2x5IG9uXG4gICAgICAvLyBlYWNoIHdyaXRlIChub3QgdmlhIHNldFRpbWVvdXQpLCB0aGUgZmx1c2hhYmxlUGlwZSdzIHBlbmRpbmdPcHNcbiAgICAgIC8vIGFjY3VyYXRlbHkgcmVmbGVjdHMgd2hldGhlciBkYXRhIGhhcyByZWFjaGVkIHRoZSBzZXJ2ZXIuIE1vc3Qgb3BzXG4gICAgICAvLyBzZXR0bGUgd2l0aGluIH4yMDBtcyAoMTAwbXMgbG9jay1yZWxlYXNlIHBvbGxpbmcgKyBIVFRQIGZsdXNoKS5cbiAgICAgIC8vIElmIG9wcyBkb24ndCBzZXR0bGUgaW4gNTAwbXMgKGUuZy4sIFdyaXRhYmxlU3RyZWFtIGtlcHQgb3BlblxuICAgICAgLy8gYWNyb3NzIHN0ZXBzKSwgd2FpdFVudGlsIGhhbmRsZXMgdGhlIHJlc3QuXG4gICAgICBsZXQgb3BzU2V0dGxlZCA9IHRydWU7XG4gICAgICBpZiAob3BzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3Qgb3BzUHJvbWlzZSA9IFByb21pc2UuYWxsKG9wcykuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIGNvbnN0IGlzQWJvcnRFcnJvciA9XG4gICAgICAgICAgICBlcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBlcnI/Lm5hbWUgPT09ICdSZXNwb25zZUFib3J0ZWQnO1xuICAgICAgICAgIGlmICghaXNBYm9ydEVycm9yKSB0aHJvdyBlcnI7XG4gICAgICAgIH0pO1xuICAgICAgICB3YWl0VW50aWwob3BzUHJvbWlzZSk7XG4gICAgICAgIG9wc1NldHRsZWQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgIG9wc1Byb21pc2UudGhlbigoKSA9PiB0cnVlIGFzIGNvbnN0KSxcbiAgICAgICAgICBuZXcgUHJvbWlzZTxmYWxzZT4oKHIpID0+IHNldFRpbWVvdXQoKCkgPT4gcihmYWxzZSksIDUwMCkpLFxuICAgICAgICBdKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIHN0ZXBfY29tcGxldGVkIGV2ZW50XG4gICAgICBsZXQgc3RlcENvbXBsZXRlZDQwOSA9IGZhbHNlO1xuICAgICAgYXdhaXQgd29ybGQuZXZlbnRzXG4gICAgICAgIC5jcmVhdGUod29ya2Zsb3dSdW5JZCwge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY29tcGxldGVkJyxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHQgYXMgVWludDhBcnJheSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1RyaWVkIGNvbXBsZXRpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgc3RlcENvbXBsZXRlZDQwOSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSk7XG5cbiAgICAgIGlmIChzdGVwQ29tcGxldGVkNDA5KSB7XG4gICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgfVxuXG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2NvbXBsZXRlZCcpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJlc3VsdFR5cGUodHlwZW9mIHJlc3VsdCksXG4gICAgICB9KTtcblxuICAgICAgaWYgKG9wcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHN0ZXBMb2dnZXIuZGVidWcoJ1N0ZXAgaGFzIHBlbmRpbmcgb3BzJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgb3BzQ291bnQ6IG9wcy5sZW5ndGgsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gaGFzUGVuZGluZ09wcyBzaWduYWxzIHRoZSBWMiBoYW5kbGVyIHRvIGJyZWFrIHRoZSBsb29wXG4gICAgICAvLyBhbmQgcXVldWUgYSBjb250aW51YXRpb24gc28gd2FpdFVudGlsIGNhbiBmbHVzaCB0aGVtLlxuICAgICAgcmV0dXJuIHsgdHlwZTogJ2NvbXBsZXRlZCcsIGhhc1BlbmRpbmdPcHM6ICFvcHNTZXR0bGVkIH07XG4gICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRXJyb3IgPSBhd2FpdCBub3JtYWxpemVVbmtub3duRXJyb3IoZXJyKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRTdGFjayA9IG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVycikgfHwgJyc7XG5cbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlcnIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpc0ZhdGFsID0gRmF0YWxFcnJvci5pcyhlcnIpO1xuXG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBFcnJvck5hbWUoZ2V0RXJyb3JOYW1lKGVycikpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEVycm9yTWVzc2FnZShub3JtYWxpemVkRXJyb3IubWVzc2FnZSksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclR5cGUoZ2V0RXJyb3JOYW1lKGVycikpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JDYXRlZ29yeShcbiAgICAgICAgICBpc0ZhdGFsID8gJ2ZhdGFsJyA6IFJldHJ5YWJsZUVycm9yLmlzKGVycikgPyAncmV0cnlhYmxlJyA6ICd0cmFuc2llbnQnXG4gICAgICAgICksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclJldHJ5YWJsZSghaXNGYXRhbCksXG4gICAgICB9KTtcblxuICAgICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIHN0ZXBMb2dnZXIuaW5mbygnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBzdGVwJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgc3RlcElkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2dvbmUnIH07XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0ZhdGFsKSB7XG4gICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgJ0VuY291bnRlcmVkIEZhdGFsRXJyb3Igd2hpbGUgZXhlY3V0aW5nIHN0ZXAsIGJ1YmJsaW5nIHVwIHRvIHBhcmVudCB3b3JrZmxvdycsXG4gICAgICAgICAgeyB3b3JrZmxvd1J1bklkLCBzdGVwTmFtZSwgZXJyb3JTdGFjazogbm9ybWFsaXplZFN0YWNrIH1cbiAgICAgICAgKTtcbiAgICAgICAgLy8gQXBwbHkgdGhlIG5vcm1hbGl6ZWQgc3RhY2sgdG8gdGhlIHRocm93biB2YWx1ZSBzbyB0aGUgc2VyaWFsaXplZFxuICAgICAgICAvLyBlcnJvciBwcmVzZXJ2ZXMgaXQgZm9yIGNvbnN1bWVycy4gYHR5cGVzLmlzTmF0aXZlRXJyb3IoKWAgd29ya3NcbiAgICAgICAgLy8gYWNyb3NzIFZNIHJlYWxtcyAoYSB3b3JrZmxvdy10aHJvd24gZXJyb3IgaXMgYW4gaW5zdGFuY2Ugb2YgdGhlXG4gICAgICAgIC8vIFZNJ3MgRXJyb3IgY2xhc3MsIG5vdCB0aGUgaG9zdCdzKS5cbiAgICAgICAgaWYgKHR5cGVzLmlzTmF0aXZlRXJyb3IoZXJyKSAmJiBub3JtYWxpemVkU3RhY2spIHtcbiAgICAgICAgICAoZXJyIGFzIEVycm9yKS5zdGFjayA9IG5vcm1hbGl6ZWRTdGFjaztcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUod29ya2Zsb3dSdW5JZCwge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogc3RlcEZhaWxFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgfVxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBGYXRhbEVycm9yKHRydWUpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2ZhaWxlZCcgfTtcbiAgICAgIH1cblxuICAgICAgLy8gTm9uLWZhdGFsIGVycm9yOiBjaGVjayBpZiByZXRyaWVzIHJlbWFpbmluZ1xuICAgICAgY29uc3QgY3VycmVudEF0dGVtcHQgPSBzdGVwLmF0dGVtcHQ7XG5cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEF0dGVtcHQoY3VycmVudEF0dGVtcHQpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcE1heFJldHJpZXMobWF4UmV0cmllcyksXG4gICAgICB9KTtcblxuICAgICAgaWYgKGN1cnJlbnRBdHRlbXB0ID49IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgIC8vIE1heCByZXRyaWVzIHJlYWNoZWRcbiAgICAgICAgY29uc3QgcmV0cnlDb3VudCA9IHN0ZXAuYXR0ZW1wdCAtIDE7XG4gICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgJ01heCByZXRyaWVzIHJlYWNoZWQsIGJ1YmJsaW5nIGVycm9yIHRvIHBhcmVudCB3b3JrZmxvdycsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgYXR0ZW1wdDogc3RlcC5hdHRlbXB0LFxuICAgICAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgICAgICAgIGVycm9yU3RhY2s6IG5vcm1hbGl6ZWRTdGFjayxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBTdGVwIFwiJHtzdGVwTmFtZX1cIiBmYWlsZWQgYWZ0ZXIgJHttYXhSZXRyaWVzfSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIG1heFJldHJpZXMpfTogJHtub3JtYWxpemVkRXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAvLyBXcmFwIHRoZSBvcmlnaW5hbCB0aHJvd24gdmFsdWUgYXMgYGNhdXNlYCBvbiBhIGZyZXNoIEZhdGFsRXJyb3JcbiAgICAgICAgLy8gc28gdGhlIHdyYXBwaW5nIG1lc3NhZ2UgKyByZXRyeS1jb3VudCBmcmFtaW5nIGlzIHRoZSB1c2VyLWZhY2luZ1xuICAgICAgICAvLyBlcnJvciB3aGlsZSB0aGUgb3JpZ2luYWwgZmFpbHVyZSByZW1haW5zIHJlY292ZXJhYmxlIGZyb21cbiAgICAgICAgLy8gYGVyci5jYXVzZWAgYWZ0ZXIgaHlkcmF0aW9uLlxuICAgICAgICBjb25zdCB3cmFwcGVkRXJyb3IgPSBuZXcgRmF0YWxFcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGVycjtcbiAgICAgICAgaWYgKG5vcm1hbGl6ZWRTdGFjaykgd3JhcHBlZEVycm9yLnN0YWNrID0gbm9ybWFsaXplZFN0YWNrO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUod29ya2Zsb3dSdW5JZCwge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgd3JhcHBlZEVycm9yLFxuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogc3RlcEZhaWxFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgfVxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeUV4aGF1c3RlZCh0cnVlKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IHR5cGU6ICdmYWlsZWQnIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJldHJpZXMgcmVtYWluaW5nXG4gICAgICBpZiAoUmV0cnlhYmxlRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBzdGVwTG9nZ2VyLmluZm8oJ0VuY291bnRlcmVkIFJldHJ5YWJsZUVycm9yLCBzdGVwIHdpbGwgYmUgcmV0cmllZCcsIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ZXBMb2dnZXIuaW5mbygnRW5jb3VudGVyZWQgRXJyb3IsIHN0ZXAgd2lsbCBiZSByZXRyaWVkJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgYXR0ZW1wdDogY3VycmVudEF0dGVtcHQsXG4gICAgICAgICAgZXJyb3JTdGFjazogbm9ybWFsaXplZFN0YWNrLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gQXBwbHkgdGhlIG5vcm1hbGl6ZWQgc3RhY2sgdG8gdGhlIHRocm93biB2YWx1ZSBzbyBpdCBzdXJ2aXZlc1xuICAgICAgLy8gc2VyaWFsaXphdGlvbi4gU2VlIHRoZSBGYXRhbEVycm9yIHNpdGUgYWJvdmUgZm9yIHdoeSB3ZSB1c2VcbiAgICAgIC8vIGB0eXBlcy5pc05hdGl2ZUVycm9yYCBpbnN0ZWFkIG9mIGBlcnIgaW5zdGFuY2VvZiBFcnJvcmAuXG4gICAgICBpZiAodHlwZXMuaXNOYXRpdmVFcnJvcihlcnIpICYmIG5vcm1hbGl6ZWRTdGFjaykge1xuICAgICAgICAoZXJyIGFzIEVycm9yKS5zdGFjayA9IG5vcm1hbGl6ZWRTdGFjaztcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUod29ya2Zsb3dSdW5JZCwge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfcmV0cnlpbmcnLFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIC4uLihSZXRyeWFibGVFcnJvci5pcyhlcnIpICYmIHsgcmV0cnlBZnRlcjogZXJyLnJldHJ5QWZ0ZXIgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChzdGVwUmV0cnlFcnIpIHtcbiAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoc3RlcFJldHJ5RXJyKSkge1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICdUcmllZCByZXRyeWluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBzdGVwUmV0cnlFcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IHN0ZXBSZXRyeUVycjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBNYXRoLm1heChcbiAgICAgICAgMSxcbiAgICAgICAgUmV0cnlhYmxlRXJyb3IuaXMoZXJyKVxuICAgICAgICAgID8gTWF0aC5jZWlsKCgrZXJyLnJldHJ5QWZ0ZXIuZ2V0VGltZSgpIC0gRGF0ZS5ub3coKSkgLyAxMDAwKVxuICAgICAgICAgIDogMVxuICAgICAgKTtcblxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlUaW1lb3V0U2Vjb25kcyh0aW1lb3V0U2Vjb25kcyksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlXaWxsUmV0cnkodHJ1ZSksXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHsgdHlwZTogJ3JldHJ5JywgdGltZW91dFNlY29uZHMgfTtcbiAgICB9XG4gIH0pO1xufVxuIl19
1113
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1leGVjdXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL3N0ZXAtZXhlY3V0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxNQUFNLE1BQU0sb0JBQW9CLENBQUM7QUFDeEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFVBQVUsRUFDVixjQUFjLEVBQ2QsZUFBZSxFQUNmLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsYUFBYSxFQUNiLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsU0FBUyxFQUNULGVBQWUsR0FDaEIsTUFBTSxpQkFBaUIsQ0FBQztBQVV6QixPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLG9CQUFvQixFQUNwQixpQ0FBaUMsR0FDbEMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWhELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RFLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLHdCQUF3QixFQUN4QixvQkFBb0IsRUFDcEIsZ0JBQWdCLEdBQ2pCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzVELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JFLE9BQU8sRUFDTCxZQUFZLEVBQ1osYUFBYSxFQUNiLHFCQUFxQixFQUNyQix3QkFBd0IsR0FDekIsTUFBTSxh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QUM7UUFDRCwrREFBK0Q7UUFDL0Qsd0RBQXdEO1FBQ3hELE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUN4RSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ25vZGU6YXNzZXJ0L3N0cmljdCc7XG5pbXBvcnQgeyB0eXBlcyB9IGZyb20gJ25vZGU6dXRpbCc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBSZXRyeWFibGVFcnJvcixcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBTZXJpYWxpemF0aW9uRXJyb3IsXG4gIFRocm90dGxlRXJyb3IsXG4gIFRvb0Vhcmx5RXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVdvcmtmbG93QmFzZVVybCxcbiAgcGx1cmFsaXplLFxuICBzdGVwRGlzcGxheU5hbWUsXG59IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgdHlwZSB7XG4gIENyZWF0ZUV2ZW50UGFyYW1zLFxuICBDcmVhdGVFdmVudFJlcXVlc3QsXG4gIEV2ZW50LFxuICBFdmVudFJlc3VsdCxcbiAgU2VyaWFsaXplZERhdGEsXG4gIFN0YXJ0ZWRTdGVwLFxuICBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7XG4gIHJlcXVpcmVFdmVudFNsb3QsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04sXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyLCBzdGVwTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGdldFN0ZXBGdW5jdGlvbiB9IGZyb20gJy4uL3ByaXZhdGUuanMnO1xuaW1wb3J0IHR5cGUgeyBQYXlsb2FkS2V5IH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7IGZvcm1hdFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24vZXJyb3JzLmpzJztcbmltcG9ydCB7XG4gIGNhbmNlbEFib3J0UmVhZGVycyxcbiAgZGVoeWRyYXRlU3RlcEVycm9yLFxuICBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUsXG4gIGh5ZHJhdGVTdGVwQXJndW1lbnRzLFxuICBoeWRyYXRlU3RlcEVycm9yLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IGNvbnRleHRTdG9yYWdlIH0gZnJvbSAnLi4vc3RlcC9jb250ZXh0LXN0b3JhZ2UuanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5pbXBvcnQgeyByZWNvcmRTdGVwRXhlY3V0aW9uRHVyYXRpb24sIHRyYWNlIH0gZnJvbSAnLi4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7XG4gIGdldEVycm9yTmFtZSxcbiAgZ2V0RXJyb3JTdGFjayxcbiAgbm9ybWFsaXplVW5rbm93bkVycm9yLFxuICBwcm9tb3RlQWJvcnRFcnJvclRvRmF0YWwsXG59IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7IENPTVBVVEVfSU5TVEFOQ0VfSUQgfSBmcm9tICcuL2NvbXB1dGUtaW5zdGFuY2UuanMnO1xuaW1wb3J0IHtcbiAgaXNPcHRpbWlzdGljSW5saW5lU3RhcnRFbmFibGVkLFxuICBpc09wdGltaXN0aWNJbmxpbmVTdGFydEV4cGxpY2l0bHlEaXNhYmxlZCxcbn0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgZ2V0UG9ydExhenkgfSBmcm9tICcuL2dldC1wb3J0LWxhenkuanMnO1xuaW1wb3J0IHtcbiAgbWF4RXZlbnRTbG90LFxuICBtZW1vaXplRW5jcnlwdGlvbktleSxcbiAgdHlwZSBTbG90U25hcHNob3RQYXJhbXMsXG59IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyIH0gZnJvbSAnLi9yZXBsYXktcmVjb3ZlcnktcmVwb3J0ZXIuanMnO1xuaW1wb3J0IHtcbiAgY29tcHV0ZVJlc3VtZVR0ckF0dHJpYnV0ZXMsXG4gIHR5cGUgUmVzdW1lVHRyVHJhY2tpbmcsXG59IGZyb20gJy4vcmVzdW1lLWxhdGVuY3kuanMnO1xuaW1wb3J0IHtcbiAgY29tcHV0ZVN0ZXBMYXRlbmN5RXZlbnREYXRhLFxuICB0eXBlIFN0ZXBMYXRlbmN5RXZlbnREYXRhLFxuICB0eXBlIFN0ZXBMYXRlbmN5VHJhY2tpbmcsXG59IGZyb20gJy4vc3RlcC1sYXRlbmN5LmpzJztcbmltcG9ydCB7IGlzVW5zZXJpYWxpemFibGVTdGVwSW5wdXRQbGFjZWhvbGRlciB9IGZyb20gJy4vdW5zZXJpYWxpemFibGUtc3RlcC5qcyc7XG5pbXBvcnQgeyBzYWZlV2FpdFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUyA9IDM7XG5cbi8qKlxuICogRXh0cmFjdCB0aGUgaW5saW5lIGRlbHRhIGZyb20gYSBzdGVwLXRlcm1pbmFsIGBldmVudHMuY3JlYXRlYCByZXN1bHQsXG4gKiBpZiB0aGUgV29ybGQgcG9wdWxhdGVkIG9uZS4gQSBkZWx0YSBpcyBvbmx5IG1lYW5pbmdmdWwgd2hlbiB0aGUgY2FsbGVyXG4gKiByZXF1ZXN0ZWQgaXQgKGBzaW5jZUN1cnNvcmAgd2FzIHBhc3NlZCkgYW5kIHRoZSBXb3JsZCByZXR1cm5lZCBib3RoXG4gKiBgZXZlbnRzYCBhbmQgYSBgY3Vyc29yYDsgb3RoZXJ3aXNlIHdlIHJldHVybiB1bmRlZmluZWQgYW5kIHRoZSBjYWxsZXJcbiAqIGZhbGxzIGJhY2sgdG8gdGhlIG5vcm1hbCBpbmNyZW1lbnRhbCBgZXZlbnRzLmxpc3RgLiBgaGFzTW9yZWAgZGVmYXVsdHNcbiAqIHRvIGZhbHNlIChzaW5nbGUgcGFnZSkgd2hlbiB0aGUgV29ybGQgb21pdHMgaXQuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RJbmxpbmVEZWx0YShcbiAgcmVzdWx0OiB7IGV2ZW50cz86IEV2ZW50W107IGN1cnNvcj86IHN0cmluZyB8IG51bGw7IGhhc01vcmU/OiBib29sZWFuIH0sXG4gIHJlcXVlc3RlZDogYm9vbGVhblxuKTogSW5saW5lRXZlbnREZWx0YSB8IHVuZGVmaW5lZCB7XG4gIGlmICghcmVxdWVzdGVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoIXJlc3VsdC5ldmVudHMgfHwgcmVzdWx0LmN1cnNvciA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4ge1xuICAgIGV2ZW50czogcmVzdWx0LmV2ZW50cyxcbiAgICBjdXJzb3I6IHJlc3VsdC5jdXJzb3IsXG4gICAgaGFzTW9yZTogcmVzdWx0Lmhhc01vcmUgPz8gZmFsc2UsXG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RlcEV4ZWN1dG9yUGFyYW1zIHtcbiAgd29ybGQ6IFdvcmxkO1xuICB3b3JrZmxvd1J1bklkOiBzdHJpbmc7XG4gIC8qKiBEZXBsb3ltZW50IHRoYXQgb3ducyB0aGUgd29ya2Zsb3cgcnVuLCBmb3IgZm9yd2FyZGVkIHdyaXRhYmxlIHN0cmVhbXMuICovXG4gIHdvcmtmbG93RGVwbG95bWVudElkPzogc3RyaW5nO1xuICB3b3JrZmxvd05hbWU6IHN0cmluZztcbiAgd29ya2Zsb3dTdGFydGVkQXQ6IG51bWJlcjtcbiAgLyoqIFJlcXVlc3QgSUQgb2YgdGhlIGludm9jYXRpb24gZXhlY3V0aW5nIHRoaXMgc3RlcCwgd2hlbiBwcm92aWRlZCBieSBpdHMgcXVldWUuICovXG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqIFJvb3QgcnVuIGlkIG9mIHRoaXMgcnVuJ3MgbGluZWFnZSwgY2FycmllZCBpbnRvIHRoZSBzdGVwIGNvbnRleHQuICovXG4gIHJvb3RSdW5JZD86IHN0cmluZztcbiAgc3RlcElkOiBzdHJpbmc7XG4gIHN0ZXBOYW1lOiBzdHJpbmc7XG4gIGVuY3J5cHRpb25LZXk/OiBQYXlsb2FkS2V5O1xuICAvKipcbiAgICogVGhlIHdvcmtmbG93IHJ1bidzIHNwZWNWZXJzaW9uLCB1c2VkIHRvIGdhdGUgcGF5bG9hZCBjb21wcmVzc2lvbi5cbiAgICogU3RlcCBvdXRwdXRzL2Vycm9ycyBhcmUgb25seSBjb21wcmVzc2VkIHdoZW4gdGhlIHJ1biBpcyBtYXJrZWQgYXNcbiAgICogY29tcHJlc3Npb24tY2FwYWJsZSAoc3BlY1ZlcnNpb24gPj0gNSkuXG4gICAqL1xuICBydW5TcGVjVmVyc2lvbj86IG51bWJlcjtcbiAgLyoqXG4gICAqIExhenkgc3RlcCBzdGFydDogdGhlIGFscmVhZHktZGVoeWRyYXRlZCBzdGVwIGlucHV0LiBXaGVuIHByb3ZpZGVkLCB0aGVcbiAgICogYHN0ZXBfc3RhcnRlZGAgZXZlbnQgY2FycmllcyB0aGlzIGlucHV0IHNvIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIG9uXG4gICAqIHRoZSBmbHkgKG5vIHNlcGFyYXRlIGBzdGVwX2NyZWF0ZWRgIHJvdW5kLXRyaXApLiBTZXQgYnkgdGhlIG93bmVkLWlubGluZVxuICAgKiBwYXRoIGZvciB0aGUgc3RlcCB3aG9zZSBgc3RlcF9jcmVhdGVkYCB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyIGRlZmVycmVkLlxuICAgKiBUaGUgd29ybGQncyBhdG9taWMgY3JlYXRlLWNsYWltIGlzIHRoZSBleGFjdGx5LW9uZS1vd25lciBnYXRlOiBsb3NpbmcgaXRcbiAgICogc3VyZmFjZXMgYXMgYEVudGl0eUNvbmZsaWN0RXJyb3JgIOKGkiBgeyB0eXBlOiAnc2tpcHBlZCcgfWAsIHNvIGEgaGFuZGxlclxuICAgKiB0aGF0IGRpZCBub3Qgd2luIHRoZSBjcmVhdGUgbmV2ZXIgcnVucyB0aGUgYm9keS4gT21pdHRlZCBvbiBldmVyeSBvdGhlclxuICAgKiBwYXRoLCB3aGVyZSB0aGUgc3RlcCBhbHJlYWR5IGhhcyBhIGBzdGVwX2NyZWF0ZWRgIGFuZCBgc3RlcF9zdGFydGVkYFxuICAgKiBjYXJyaWVzIG5vIHBheWxvYWQgKHRoZSBsZWdhY3kgY29udHJhY3QpLlxuICAgKi9cbiAgbGF6eVN0ZXBJbnB1dD86IFNlcmlhbGl6ZWREYXRhO1xuICAvKipcbiAgICogUHJlLWNsYWltZWQgaW5saW5lIHN0YXJ0OiB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyIGNvbW1pdHRlZCAob3IgbG9zdCkgdGhpc1xuICAgKiBzdGVwJ3MgYHN0ZXBfY3JlYXRlZGAgKyBgc3RlcF9zdGFydGVkYCBwYWlyIGluc2lkZSBpdHMgYmF0Y2hlZCBmYW4tb3V0XG4gICAqIHdyaXRlLCBzbyB0aGUgc3RhcnQgdGhpcyBleGVjdXRvciB3b3VsZCBvdGhlcndpc2Ugc2VuZCBoYXMgYWxyZWFkeSBiZWVuXG4gICAqIGRlY2lkZWQuIGBvd25lZDogZmFsc2VgIHJldHVybnMgYHsgdHlwZTogJ3NraXBwZWQnIH1gIGJlZm9yZSBhbnkgd3JpdGUsXG4gICAqIHRoZSBzYW1lIG91dGNvbWUgYXMgbG9zaW5nIHRoZSBsYXp5IGNsYWltJ3MgYXRvbWljIGNyZWF0ZS4gYG93bmVkOiB0cnVlYFxuICAgKiBza2lwcyBib3RoIHN0YXJ0IHBhdGhzIChubyBzdGFydCB3cml0ZSBhdCBhbGwpIGFuZCBydW5zIHRoZSBib2R5IGFnYWluc3RcbiAgICogdGhlIGNsYWltZWQgc3RlcC4gTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGxhenlTdGVwSW5wdXRgOiB0aGUgaW5wdXRcbiAgICogYWxyZWFkeSByb2RlIHRoZSBwYWlyJ3MgYHN0ZXBfY3JlYXRlZGAsIGFuZCB0aGUgY2xhaW1lZCBzdGVwIGNhcnJpZXMgaXQuXG4gICAqL1xuICBwcmVjbGFpbWVkU3RhcnQ/OiBQcmVjbGFpbWVkSW5saW5lU3RhcnQ7XG4gIC8qKlxuICAgKiBJbmxpbmUgc3RlcCBvd25lcnNoaXA6IHRoZSBxdWV1ZSBtZXNzYWdlIElEIG9mIHRoZSBpbnZvY2F0aW9uIHRoaXNcbiAgICogZXhlY3V0ZVN0ZXAgY2FsbCBydW5zIGluIChmcm9tIHRoZSBxdWV1ZSBoYW5kbGVyJ3MgbWV0YSkuIFdoZW4gc2V0LCB0aGVcbiAgICogYHN0ZXBfc3RhcnRlZGAgdGhpcyBjYWxsIHNlbmRzIGlzIHN0YW1wZWQgd2l0aCBpdDogb24gdGhlIGxhenkgcGF0aHNcbiAgICogKHdoZXJlIGBsYXp5U3RlcElucHV0YCBpcyBwcmVzZW50KSBhbmQgb24gdGhlIG93bmVkLXJlY292ZXJ5XG4gICAqIHBheWxvYWQtbGVzcyBzdGFydCAod2hlcmUgaXQgaXMgbm90OyB0aGUgcmUtc3RhbXAga2VlcHMgYSByZWNvdmVyZWRcbiAgICogc3RlcCByZWFkYWJsZSBhcyBvd25lZCBieSB0aGlzIG1lc3NhZ2UsIHNpbmNlIG93bmVyc2hpcCBkZXJpdmVzIGZyb21cbiAgICogdGhlIExBVEVTVCBzdGFydCwgc28gYSByZWNvdmVyeSBzdGFydCBpcyBuZXZlciBiYXJlKS4gV2FrZVxuICAgKiByZXBsYXlzIHRoYXQgb2JzZXJ2ZSBhbiBhY3RpdmVseS1vd25lZCBzdGVwIHN1cHByZXNzIHRoZSBpbW1lZGlhdGVcbiAgICogcmVxdWV1ZSBhbmQgZW5xdWV1ZSBhIGRlbGF5ZWQgYmFja3N0b3AgaW5zdGVhZC4gT21pdHRlZCBvbiB0aGVcbiAgICogYmFja2dyb3VuZC1zdGVwIHBhdGgsIHdob3NlIGJhcmUgc3RhcnQgaW50ZW50aW9uYWxseSBjbGVhcnMgb3duZXJzaGlwXG4gICAqICh0aGUgc3RlcCBpcyBxdWV1ZS1vd25lZCBmcm9tIHRoYXQgcG9pbnQpLlxuICAgKi9cbiAgb3duZXJNZXNzYWdlSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBJbmxpbmUtZGVsdGEgb3B0aW1pemF0aW9uIChvcHQtaW4pLiBXaGVuIHByb3ZpZGVkLCB0aGUgY3Vyc29yIG9mIHRoZVxuICAgKiBldmVudCBsb2cgYXMgb2JzZXJ2ZWQgYnkgdGhlIGNhbGxlciAqYmVmb3JlKiB0aGlzIHN0ZXAncyBldmVudHMgd2VyZVxuICAgKiB3cml0dGVuLiBJdCBpcyB0aHJlYWRlZCBpbnRvIHRoZSBzdGVwLXRlcm1pbmFsIGBldmVudHMuY3JlYXRlYCBzbyBhXG4gICAqIHN1cHBvcnRpbmcgV29ybGQgY2FuIHJldHVybiB0aGUgZGVsdGEgb2YgZXZlbnRzIHdyaXR0ZW4gc2luY2UgKHNlZVxuICAgKiB7QGxpbmsgaW1wb3J0KCdAd29ya2Zsb3cvd29ybGQnKS5DcmVhdGVFdmVudFBhcmFtcy5zaW5jZUN1cnNvcn0pLlxuICAgKiBPbmx5IHNldCB0aGlzIHdoZW4gYGNvcnJlbGF0aW9uSWRgLWJhc2VkIG93bmVyc2hpcCBndWFyYW50ZWVzIHRoaXNcbiAgICogaGFuZGxlciBpcyB0aGUgc29sZSBpbmxpbmUgd3JpdGVyIGZvciB0aGUgcnVuIG9uIHRoaXMgaXRlcmF0aW9uLlxuICAgKi9cbiAgaW5saW5lRGVsdGFTaW5jZUN1cnNvcj86IHN0cmluZztcbiAgLyoqXG4gICAqIEhvdyBtdWNoIG9mIHRoZSBydW4ncyBsb2cgdGhlIGNhbGxlcidzIHJlcGxheSBoYWQgbG9hZGVkIHdoZW4gaXQgc2NoZWR1bGVkXG4gICAqIHRoaXMgc3RlcCwgYXMgdGhlIGhpZ2hlc3Qgc2xvdCB0aGF0IGxvZyBvY2N1cGllcy4gU2VlZHMgdGhlIHNuYXBzaG90IGV2ZXJ5XG4gICAqIHdyaXRlIHRoaXMgZXhlY3V0b3IgbWFrZXMgY2FycmllczsgZWFjaCBjb21taXR0ZWQgZXZlbnQgYWR2YW5jZXMgaXQgdG8gaXRzXG4gICAqIG93biBzbG90LCBzbyBhIGxhdGVyIHdyaXRlIG5ldmVyIG5hbWVzIGEgcG9zaXRpb24gdGhhdCBwcmVkYXRlcyBhbiBlYXJsaWVyXG4gICAqIG9uZSBmcm9tIHRoZSBzYW1lIHN0ZXAuXG4gICAqXG4gICAqIEl0IG1hdHRlcnMgbW9zdCBvbiB0aGUgbGF6eSBpbmxpbmUgcGF0aCwgd2hlcmUgdGhlIGBzdGVwX3N0YXJ0ZWRgIGNsYWltIGlzXG4gICAqIHRoZSBzdGVwJ3MgRklSU1QgZHVyYWJsZSB3cml0ZSAoaXRzIGBzdGVwX2NyZWF0ZWRgIGlzIGRlZmVycmVkKTogd2l0aG91dCBhXG4gICAqIHNlZWQgdGhlIGNsYWltIHdvdWxkIG5hbWUgbm8gcG9zaXRpb24gYXQgYWxsLCBhbmQgYSByZXBsYXkgd29ya2luZyBmcm9tIGFcbiAgICogc3RhbGUgdmlldyBjb3VsZCBjbGFpbSAoYW5kIHRoZW4gY29tbWl0KSBhIHN0ZXAgc2NoZWR1bGVkIHdpdGhvdXRcbiAgICogb2JzZXJ2aW5nIGFuIGV2ZW50IGl0IG5ldmVyIGxvYWRlZC5cbiAgICpcbiAgICogQSBXb3JsZCB0aGF0IGZlbmNlcyByZWplY3RzIGEgc3RhbGUgY2xhaW0gd2l0aCBgUHJlY29uZGl0aW9uRmFpbGVkRXJyb3JgXG4gICAqICg0MTIpOyBleGVjdXRlU3RlcCBkb2VzIE5PVCB0cmFuc2xhdGUgdGhhdCByZWplY3Rpb24gKHJlLWNsYWltaW5nIGluIHBsYWNlXG4gICAqIHdvdWxkIHN0aWxsIGNvbW1pdCB0aGUgc3RhbGUgc2NoZWR1bGUpLCBzbyBpdCBwcm9wYWdhdGVzIGZvciB0aGUgY2FsbGVyIHRvXG4gICAqIGFiYW5kb24gdGhlIGJhdGNoIGFuZCByZXN0YXJ0IGl0cyByZXBsYXkuIFVuZGVmaW5lZCBmb3IgYSBjYWxsZXIgd2l0aFxuICAgKiBub3RoaW5nIGxvYWRlZC5cbiAgICovXG4gIHNsb3RTbmFwc2hvdD86IFNsb3RTbmFwc2hvdFBhcmFtcztcbiAgLyoqXG4gICAqIFN1cHByZXNzIG9wdGltaXN0aWMgaW5saW5lIHN0YXJ0IGZvciB0aGlzIHN0ZXAgcmVnYXJkbGVzcyBvZlxuICAgKiBgV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlRgIC8gYGZvcmNlT3B0aW1pc3RpY1N0YXJ0YDogdGFrZSB0aGVcbiAgICogYXdhaXQtdGhlbi1ydW4gcGF0aCBzbyB0aGUgYm9keSBvbmx5IHJ1bnMgYWZ0ZXIgdGhlIGBzdGVwX3N0YXJ0ZWRgIGNsYWltXG4gICAqIHN1Y2NlZWRzLiBTZXQgYnkgdGhlIHJ1bnRpbWUgZm9yIGd1YXJkLWVuZm9yY2VkIGJhdGNoZXMgdGhhdCBhcmVcbiAgICogc3RhbGUtc2Vuc2l0aXZlIChhbiBvcGVuIGhvb2sgbWVhbnMgYW4gb3V0LW9mLWJhbmQgZXZlbnQgY2FuIG1ha2UgdGhlXG4gICAqIHNjaGVkdWxpbmcgdmlldyBzdGFsZSk6IHRoZSBndWFyZCdzIDQxMiBmZW5jZSBjYW4gcmVqZWN0IGEgc3RhbGUgY2xhaW0nc1xuICAgKiBkdXJhYmxlIHdyaXRlcywgYnV0IGl0IGNhbm5vdCB1bi1ydW4gYSBib2R5IHRoYXQgb3B0aW1pc3RpYyBzdGFydCBiZWdhblxuICAgKiBiZWZvcmUgdGhlIGNsYWltIHNldHRsZWQ7IGF3YWl0aW5nIHRoZSBjbGFpbSBleHRlbmRzIHRoZSBmZW5jZSB0byB1c2VyXG4gICAqIGNvZGUuIFdpbnMgb3ZlciBgZm9yY2VPcHRpbWlzdGljU3RhcnRgIGFuZCB0aGUgZW52IGZsYWcuXG4gICAqL1xuICBzdXBwcmVzc09wdGltaXN0aWNTdGFydD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBGb3JjZSBvcHRpbWlzdGljIGlubGluZSBzdGFydCByZWdhcmRsZXNzIG9mXG4gICAqIGBXT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVGAuIFNldCBieSB0dXJibyBtb2RlIG9uIHRoZSBmaXJzdCBkZWxpdmVyeVxuICAgKiBvZiB0aGUgZmlyc3QgaW52b2NhdGlvbiwgd2hlcmUgZm9yY2luZyBpdCBpcyBzYWZlOiB0aGVyZSBpcyBubyBjb25jdXJyZW50XG4gICAqIHBlZXIgaGFuZGxlciB0byByYWNlIHRoZSBjcmVhdGUtY2xhaW0sIHNvIHRoZSBib2R5IHJ1bnMgZXhhY3RseSBvbmNlLiBPbmx5XG4gICAqIG1lYW5pbmdmdWwgdG9nZXRoZXIgd2l0aCBgbGF6eVN0ZXBJbnB1dGAgKGEgYnJhbmQtbmV3IGxhenkgc3RlcCkuXG4gICAqL1xuICBmb3JjZU9wdGltaXN0aWNTdGFydD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUdXJibyBtb2RlIG9ubHk6IGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIG9uY2UgdGhlIGJhY2tncm91bmRlZFxuICAgKiBgcnVuX3N0YXJ0ZWRgIGhhcyBsYW5kZWQuIFdoZW4gc2V0LCB0aGUgbGF6eS9vcHRpbWlzdGljIGBzdGVwX3N0YXJ0ZWRgIGlzXG4gICAqIGNoYWluZWQgb24gaXQgc28gdGhlIHN0ZXAgaXMgbmV2ZXIgY3JlYXRlZCBiZWZvcmUgaXRzIHJ1biBleGlzdHMuIFRoZSBib2R5XG4gICAqIHN0aWxsIHJ1bnMgaW1tZWRpYXRlbHkgYWdhaW5zdCBsb2NhbGx5LXN5bnRoZXNpemVkIHN0YXRlIChvbmx5IHRoZSBuZXR3b3JrXG4gICAqIHdyaXRlIHdhaXRzKSwgc28gdGhlIGBydW5fc3RhcnRlZGAgcm91bmQtdHJpcCBvdmVybGFwcyB0aGUgYm9keS4gYHVuZGVmaW5lZGBcbiAgICogb3V0c2lkZSB0dXJibywgd2hlcmUgYHJ1bl9zdGFydGVkYCB3YXMgYWxyZWFkeSBhd2FpdGVkIHVwIGZyb250LlxuICAgKi9cbiAgcnVuUmVhZHlCYXJyaWVyPzogUHJvbWlzZTx1bmtub3duPjtcbiAgLyoqXG4gICAqIExhdGVuY3kgdGVsZW1ldHJ5IChUVEZTIC8gU1RTTyk6IGVsaWdpYmlsaXR5IGFuZCBhbmNob3IgdGltZXN0YW1wcyBkZWNpZGVkXG4gICAqIGJ5IHRoZSBvcmNoZXN0cmF0b3IuIFdoZW4gc2V0LCB0aGlzIGV4ZWN1dG9yIGNvbXB1dGVzIHRoZSBmaW5hbCB2YWx1ZXNcbiAgICogYWdhaW5zdCB0aGUgd2FsbCBjbG9jayB0YWtlbiBpbW1lZGlhdGVseSBiZWZvcmUgdXNlciBjb2RlIHJ1bnMgYW5kXG4gICAqIGF0dGFjaGVzIHRoZW0gdG8gdGhlIHN0ZXAncyB0ZXJtaW5hbCBldmVudC4gU2V0IG9ubHkgZm9yIHRoZSBmaXJzdCBzdGVwIG9mXG4gICAqIGFuIGlubGluZSBiYXRjaCwgYW5kIG9ubHkgb24gZmlyc3QtYXR0ZW1wdCBleGVjdXRpb25zIHRoYXQgcXVhbGlmeTsgc2VlXG4gICAqIHJ1bnRpbWUvc3RlcC1sYXRlbmN5LnRzLlxuICAgKi9cbiAgbGF0ZW5jeVRyYWNraW5nPzogU3RlcExhdGVuY3lUcmFja2luZztcbiAgLyoqXG4gICAqIEhvb2stcmVzdW1lIFRUUiB0ZWxlbWV0cnk6IHRoZSBib3VuZGFyaWVzIG9mIGEgaG9vayByZXN1bXB0aW9uIHdob3NlIG5leHRcbiAgICogZHVyYWJsZSBzdGVwIGlzIHRoZSBvbmUgdGhpcyBjYWxsIGlzIGFib3V0IHRvIGV4ZWN1dGUuIFdoZW4gc2V0LCB0aGVcbiAgICogZXhlY3V0b3IgY2xvc2VzIHRoZSBtZWFzdXJlbWVudCBhZ2FpbnN0IHRoZSBgc3RlcF9zdGFydGVkYCBjbGFpbSBhbmQgdGhlXG4gICAqIHdhbGwgY2xvY2sgdGFrZW4gaW1tZWRpYXRlbHkgYmVmb3JlIHVzZXIgY29kZSwgYW5kIGF0dGFjaGVzIHRoZSB0b3RhbCBwbHVzXG4gICAqIGl0cyBwaGFzZSBicmVha2Rvd24gdG8gdGhpcyBzdGVwJ3MgYHN0ZXAuZXhlY3V0ZWAgc3Bhbi4gU2V0IGJ5IHRoZSBydW50aW1lXG4gICAqIGZvciBleGFjdGx5IG9uZSBzdGVwIHBlciByZXN1bXB0aW9uOyBzZWUgcnVudGltZS9yZXN1bWUtbGF0ZW5jeS50cy5cbiAgICovXG4gIHJlc3VtZVRyYWNraW5nPzogUmVzdW1lVHRyVHJhY2tpbmc7XG4gIC8qKlxuICAgKiBBdXRob3JpdGF0aXZlIGF0dGVtcHQgbnVtYmVyIGZvciB0aGlzIGV4ZWN1dGlvbiwgdXNlZCB0byBib3VuZCByZXRyaWVzXG4gICAqIGFnYWluc3QgYG1heFJldHJpZXNgIEJFRk9SRSB0aGUgYm9keSBydW5zLiBUbyBhbHNvIGNhdGNoXG4gICAqIHN0ZXAgdGltZW91dHMgKHdoaWNoIHdlIGNhbid0IGhhdmUgY2F0Y2ggaGFuZGxlcnMgZm9yKSwgd2UgZGV0ZXJtaW5lXG4gICAqIHRoZSBhdHRlbXB0IGNvdW50IGJhc2VkIGFzIGZvbGxvd3M6XG4gICAqIC0gSW5saW5lIChjb21iaW5lZCBoYW5kbGVyKTogdGhlIG51bWJlciBvZiBgc3RlcF9zdGFydGVkYCBldmVudHMgYWxyZWFkeVxuICAgKiAgIGluIHRoZSBldmVudCBsb2cgZm9yIHRoaXMgc3RlcCwgcGx1cyBvbmUgZm9yIHRoZSBhdHRlbXB0IGFib3V0IHRvIHJ1bi5cbiAgICogLSBCYWNrZ3JvdW5kIChxdWV1ZS1kaXNwYXRjaGVkKTogdGhlIHF1ZXVlIGRlbGl2ZXJ5IGNvdW50XG4gICAqICAgKGBtZXRhZGF0YS5hdHRlbXB0YCksIHdoaWNoIGluY3JlbWVudHMgb24gZXZlcnkgcmVkZWxpdmVyeS5cbiAgICovXG4gIGF1dGhvcml0YXRpdmVBdHRlbXB0PzogbnVtYmVyO1xuICAvKiogT25lLXNob3QgcmVjb3ZlcnkgdGVsZW1ldHJ5IGFjdGl2YXRlZCBieSB0aGUgb3JjaGVzdHJhdG9yIHJlcGxheS4gKi9cbiAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcj86IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXI7XG59XG5cbi8qKlxuICogVGhlIHNldHRsZWQgb3V0Y29tZSBvZiBhIGBzdGVwX2NyZWF0ZWRgICsgYHN0ZXBfc3RhcnRlZGAgcGFpciB0aGVcbiAqIHN1c3BlbnNpb24gaGFuZGxlciBmb2xkZWQgaW50byBpdHMgYmF0Y2hlZCBmYW4tb3V0IHdyaXRlIChzZWVcbiAqIGBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdC5pbmxpbmVDbGFpbXNgKS4gSGFuZGVkIHRvIGV4ZWN1dGVTdGVwIGFzXG4gKiB7QGxpbmsgU3RlcEV4ZWN1dG9yUGFyYW1zLnByZWNsYWltZWRTdGFydH0gc28gdGhlIGV4ZWN1dG9yIHJ1bnMgKG9yIHNraXBzKVxuICogdGhlIGJvZHkgb2ZmIHRoZSBiYXRjaCdzIHZlcmRpY3QgaW5zdGVhZCBvZiBzZW5kaW5nIGEgc3RhcnQgb2YgaXRzIG93bi5cbiAqL1xuZXhwb3J0IHR5cGUgUHJlY2xhaW1lZElubGluZVN0YXJ0ID1cbiAgfCB7XG4gICAgICAvKiogVGhlIHBhaXIgY29tbWl0dGVkOiB0aGlzIGV4ZWN1dGlvbiBvd25zIHRoZSBzdGVwIGFuZCBydW5zIHRoZSBib2R5LiAqL1xuICAgICAgb3duZWQ6IHRydWU7XG4gICAgICAvKipcbiAgICAgICAqIFRoZSBzdGFydGVkIHN0ZXAgZW50aXR5IGZyb20gdGhlIGJhdGNoIHJlc3VsdCwgd2l0aCB0aGUgbG9jYWxseVxuICAgICAgICogZGVoeWRyYXRlZCBpbnB1dCBhdHRhY2hlZCBieSB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyIChiYXRjaCByZXNwb25zZXNcbiAgICAgICAqIHJldHVybiByZWZzIGxhemlseTsgdGhlIGJvZHkncyBoeWRyYXRpb24gd2FudHMgdGhlIHNhbWUgYnl0ZXMgdGhlXG4gICAgICAgKiBwYWlyJ3MgYHN0ZXBfY3JlYXRlZGAgY2FycmllZCkuXG4gICAgICAgKi9cbiAgICAgIHN0ZXA6IFN0YXJ0ZWRTdGVwO1xuICAgICAgLyoqXG4gICAgICAgKiBgRGF0ZS5ub3coKWAgdGFrZW4gcmlnaHQgYmVmb3JlIHRoZSBiYXRjaCBQT1NUIHRoYXQgY2FycmllZCB0aGUgcGFpcjpcbiAgICAgICAqIHRoZSBjbGFpbSdzIFwic3RhcnQgUE9TVCBzZW50XCIgaW5zdGFudCwgYW5jaG9yaW5nIFJTRlMgZXhhY3RseSBsaWtlXG4gICAgICAgKiB0aGUgbGF6eSBjbGFpbSdzIG93biBQT1NUIHdvdWxkLlxuICAgICAgICovXG4gICAgICBiYXRjaFBvc3RTZW50QXRNcz86IG51bWJlcjtcbiAgICAgIC8qKlxuICAgICAgICogYERhdGUubm93KClgIHRha2VuIHJpZ2h0IGFmdGVyIHRoYXQgYmF0Y2ggUE9TVCByZXR1cm5lZDogdGhlXG4gICAgICAgKiBjbGFpbSdzIGNvbXBsZXRpb24gaW5zdGFudCAoVDYgb2YgdGhlIGhvb2stcmVzdW1lIFRUUiB3aW5kb3cpLlxuICAgICAgICovXG4gICAgICBjbGFpbUNvbXBsZXRlZEF0TXM/OiBudW1iZXI7XG4gICAgfVxuICB8IHtcbiAgICAgIC8qKlxuICAgICAgICogVGhlIHBhaXIgbG9zdCBpdHMgYXRvbWljIGNyZWF0ZS1jbGFpbSAocGVyLWV2ZW50IDQwOSk6IGEgY29uY3VycmVudFxuICAgICAgICogd3JpdGVyIG93bnMgdGhlIHN0ZXAsIHNvIHRoZSBib2R5IG11c3Qgbm90IHJ1biBoZXJlLlxuICAgICAgICovXG4gICAgICBvd25lZDogZmFsc2U7XG4gICAgfTtcblxuLyoqXG4gKiBJbmxpbmUtZGVsdGEgcmV0dXJuZWQgYnkgYSBzdGVwLXRlcm1pbmFsIHdyaXRlIHdoZW4gdGhlIGNhbGxlciBwYXNzZWRcbiAqIHtAbGluayBTdGVwRXhlY3V0b3JQYXJhbXMuaW5saW5lRGVsdGFTaW5jZUN1cnNvcn0gYW5kIHRoZSBXb3JsZCBzdXBwb3J0c1xuICogdGhlIG9wdGltaXphdGlvbi4gYGV2ZW50c2AgYXJlIHRoZSBldmVudHMgd3JpdHRlbiBzdHJpY3RseSBhZnRlciB0aGF0XG4gKiBjdXJzb3IgKHRoaXMgc3RlcCdzIGV2ZW50cyBwbHVzIGFueXRoaW5nIGludGVybGVhdmVkIGluLWJhbmQpLCBgY3Vyc29yYFxuICogaXMgdGhlIHBvc2l0aW9uIHBhc3QgdGhlIGxhc3Qgb25lLCBhbmQgYGhhc01vcmVgIHNpZ25hbHMgYSBmdXJ0aGVyIHBhZ2VcbiAqICh0aGUgY2FsbGVyIHRoZW4gZmFsbHMgYmFjayB0byBhIGZ1bGwgaW5jcmVtZW50YWwgZmV0Y2gpLiBBYnNlbnQgd2hlblxuICogdGhlIFdvcmxkIGRpZCBub3QgcmV0dXJuIGEgZGVsdGEuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5saW5lRXZlbnREZWx0YSB7XG4gIGV2ZW50czogRXZlbnRbXTtcbiAgY3Vyc29yOiBzdHJpbmcgfCBudWxsO1xuICBoYXNNb3JlOiBib29sZWFuO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBhIHN0ZXAgZXhlY3V0aW9uIGF0dGVtcHQuIFRoZSBjYWxsZXIgZGVjaWRlcyB3aGF0IHRvIGRvXG4gKiBiYXNlZCBvbiB0aGUgcmVzdWx0IHR5cGUgKGUuZy4sIHF1ZXVlIHdvcmtmbG93IGNvbnRpbnVhdGlvbiwgcmVwbGF5IGlubGluZSwgZXRjLikuXG4gKlxuICogYGlubGluZURlbHRhYCBpcyBhdHRhY2hlZCB0byBhIGBjb21wbGV0ZWRgIHJlc3VsdCB3aGVuIHRoZSBjYWxsZXJcbiAqIHJlcXVlc3RlZCBpdCB2aWEge0BsaW5rIFN0ZXBFeGVjdXRvclBhcmFtcy5pbmxpbmVEZWx0YVNpbmNlQ3Vyc29yfSBhbmRcbiAqIHRoZSBXb3JsZCByZXR1cm5lZCBvbmUuIFN0ZXAgZmFpbHVyZXMgYXJlIHJhcmUgYW5kIG5vdCB0aGUgaW5saW5lXG4gKiBvcHRpbWl6YXRpb24ncyB0YXJnZXQsIHNvIHRoZSBgZmFpbGVkYCBwYXRoIGxlYXZlcyBpdCB0byB0aGUgbm9ybWFsXG4gKiBpbmNyZW1lbnRhbCBmZXRjaC5cbiAqL1xuZXhwb3J0IHR5cGUgU3RlcEV4ZWN1dGlvblJlc3VsdCA9XG4gIHwge1xuICAgICAgdHlwZTogJ2NvbXBsZXRlZCc7XG4gICAgICBoYXNQZW5kaW5nT3BzPzogYm9vbGVhbjtcbiAgICAgIGlubGluZURlbHRhPzogSW5saW5lRXZlbnREZWx0YTtcbiAgICB9XG4gIHwgeyB0eXBlOiAnZmFpbGVkJyB9XG4gIHwgeyB0eXBlOiAncmV0cnknOyB0aW1lb3V0U2Vjb25kczogbnVtYmVyIH1cbiAgfCB7IHR5cGU6ICdza2lwcGVkJyB9XG4gIHwgeyB0eXBlOiAnZ29uZScgfVxuICB8IHsgdHlwZTogJ3Rocm90dGxlZCc7IHRpbWVvdXRTZWNvbmRzOiBudW1iZXIgfTtcblxuLyoqXG4gKiBFeGVjdXRlcyBhIHNpbmdsZSBzdGVwOiBjcmVhdGVzIHN0ZXBfc3RhcnRlZCBldmVudCwgaHlkcmF0ZXMgaW5wdXQsXG4gKiBydW5zIHRoZSBzdGVwIGZ1bmN0aW9uLCBjcmVhdGVzIHN0ZXBfY29tcGxldGVkL3N0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcgZXZlbnRzLlxuICpcbiAqIERvZXMgTk9UIHF1ZXVlIHdvcmtmbG93IGNvbnRpbnVhdGlvbiBtZXNzYWdlczsgdGhlIGNhbGxlciBkZWNpZGVzIHdoYXQgdG8gZG8gbmV4dC5cbiAqIFVzZWQgYnkgdGhlIGNvbWJpbmVkIHdvcmtmbG93IGhhbmRsZXIgZm9yIHN0ZXAgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZVN0ZXAoXG4gIHBhcmFtczogU3RlcEV4ZWN1dG9yUGFyYW1zXG4pOiBQcm9taXNlPFN0ZXBFeGVjdXRpb25SZXN1bHQ+IHtcbiAgY29uc3Qge1xuICAgIHdvcmxkLFxuICAgIHdvcmtmbG93UnVuSWQsXG4gICAgd29ya2Zsb3dOYW1lLFxuICAgIHdvcmtmbG93U3RhcnRlZEF0LFxuICAgIHN0ZXBJZCxcbiAgICBzdGVwTmFtZSxcbiAgfSA9IHBhcmFtcztcbiAgLy8gVHJ1dGhpbmVzcywgbm90IHByZXNlbmNlOiBgdmVyY2VsIGVudiBwdWxsYCB3cml0ZXMgYFZFUkNFTF9VUkw9XCJcImAgaW50b1xuICAvLyBgLmVudi5sb2NhbGAsIGFuZCBhIGZyYW1ld29yayB0aGF0IGxvYWRzIHRoYXQgZmlsZSBsb2NhbGx5IHdvdWxkIG90aGVyd2lzZVxuICAvLyBwdXQgdXMgb24gdGhlIFZlcmNlbCBicmFuY2ggd2l0aCBub3RoaW5nIHRvIGJ1aWxkIGEgaG9zdCBmcm9tLCBtYWtpbmdcbiAgLy8gYGh0dHBzOi8vYCB0aGUgYmFzZSBVUkwgb2YgZXZlcnkgc3RlcC5cbiAgY29uc3QgaXNWZXJjZWwgPSBCb29sZWFuKHByb2Nlc3MuZW52LlZFUkNFTF9VUkwpO1xuICAvLyBHYXRlIHBheWxvYWQgY29tcHJlc3Npb24gb24gdGhlIHJ1bidzIHNwZWNWZXJzaW9uLlxuICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgKHBhcmFtcy5ydW5TcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT047XG4gIGNvbnN0IHJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgPVxuICAgIHBhcmFtcy5yZXBsYXlSZWNvdmVyeVJlcG9ydGVyID8/IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXIuaW5lcnQoKTtcbiAgLyoqXG4gICAqIFRoZSBoaWdoZXN0IGxvZyBzbG90IHRoaXMgZXhlY3V0b3Iga25vd3MgYWJvdXQsIHNlZWRlZCBmcm9tIHRoZSB2aWV3IGl0c1xuICAgKiBjYWxsZXIgc2NoZWR1bGVkIHRoZSBzdGVwIGFnYWluc3QgYW5kIGFkdmFuY2VkIGJ5IGV2ZXJ5IGV2ZW50IGl0IGNvbW1pdHMuXG4gICAqXG4gICAqIEFkdmFuY2luZyBpcyB3aGF0IGtlZXBzIHRoZSBzbmFwc2hvdCBob25lc3QgYWNyb3NzIGEgc3RlcCdzIG93biB3cml0ZXMuIEFcbiAgICogc3RlcCBjb21taXRzIGBzdGVwX3N0YXJ0ZWRgIGFuZCB0aGVuIGBzdGVwX2NvbXBsZXRlZGA7IGlmIHRoZSBzZWNvbmQgc3RpbGxcbiAgICogbmFtZWQgdGhlIGNhbGxlcidzIG9yaWdpbmFsIHBvc2l0aW9uLCB0aGUgV29ybGQgd291bGQgcmVwb3J0IHRoZSBmaXJzdCBvbmVcbiAgICogYmFjayBhcyBhbiBldmVudCB0aGlzIHdyaXRlciBoYWQgbm90IHNlZW4sIG9uIGV2ZXJ5IHN0ZXAsIGZvcmV2ZXIuXG4gICAqXG4gICAqIFRoaXMgcmVhZHMgYSByZXBvcnQgZm9yIGl0cyBoaWdoZXN0IHBvc2l0aW9uIGFuZCB0aGVuIGRpc2NhcmRzIGl0LCB3aGVyZVxuICAgKiB0aGUgcmVwbGF5IGxvb3AgYW5kIHRoZSBzdXNwZW5zaW9uIGhhbmRsZXIgbWVyZ2UgdGhlaXJzIHdpdGhcbiAgICogYGFic29yYlNraXBwZWRTbG90UmVwb3J0YC4gVGhhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjYWxsZXJzLCBub3RcbiAgICogYW4gb3ZlcnNpZ2h0OiBhbiBleGVjdXRvciBob2xkcyBubyBsb2FkZWQgbG9nIHRvIG1lcmdlIGludG8uIEl0IHJ1bnMgZnJvbSBhXG4gICAqIHF1ZXVlZCBkZWxpdmVyeSB3aG9zZSBvbmx5IHZpZXcgb2YgdGhlIGxvZyBpcyB0aGUgaW50ZWdlciBpdHMgY2FsbGVyIHBhc3NlZFxuICAgKiBpbiwgc28gdGhlIHBvc2l0aW9uIGlzIHRoZSBlbnRpcmUgdmFsdWUgdGhlIHJlcG9ydCBoYXMgdG8gaXQuIFdob2V2ZXJcbiAgICogcmVwbGF5cyBuZXh0IGxvYWRzIHRoZSBsb2cgYW5kIGdldHMgdGhlIGV2ZW50cyB0aGVtc2VsdmVzLlxuICAgKi9cbiAgbGV0IGtub3duU2xvdCA9IHBhcmFtcy5zbG90U25hcHNob3Q/LmV2ZW50Q291bnQ7XG4gIGNvbnN0IG9ic2VydmVTbG90ID0gKHJlc3VsdDogeyBldmVudD86IEV2ZW50OyBldmVudHM/OiBFdmVudFtdIH0pOiB2b2lkID0+IHtcbiAgICBpZiAoa25vd25TbG90ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIFRoZSBjYWxsZXIgc2NoZWR1bGVkIHRoaXMgc3RlcCB3aXRob3V0IG5hbWluZyBhIHBvc2l0aW9uLCBzbyB0aGVyZSBpc1xuICAgICAgLy8gbm8gc25hcHNob3QgdG8gYWR2YW5jZSBhbmQgdGhlIHdyaXRlcyBiZWxvdyBzZW5kIG5vbmUuIE5vdCB0aGUgc2FtZSBhc1xuICAgICAgLy8gYSBydW4gd2l0aG91dCBwb3NpdGlvbnM6IGV2ZXJ5IHJ1biBoYXMgdGhlbSwgdGhpcyBleGVjdXRvciB3YXMgbm90XG4gICAgICAvLyB0b2xkIHdoaWNoIG9uZSBpdCBzdGFydGVkIGZyb20uXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG9ic2VydmVkOiBudW1iZXJbXSA9IFtdO1xuICAgIGlmIChyZXN1bHQuZXZlbnQpIHtcbiAgICAgIG9ic2VydmVkLnB1c2gocmVxdWlyZUV2ZW50U2xvdChyZXN1bHQuZXZlbnQuZXZlbnRJZCkpO1xuICAgIH1cbiAgICBjb25zdCByZXBvcnRlZCA9IG1heEV2ZW50U2xvdChyZXN1bHQuZXZlbnRzID8/IFtdKTtcbiAgICBpZiAocmVwb3J0ZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgb2JzZXJ2ZWQucHVzaChyZXBvcnRlZCk7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc2xvdCBvZiBvYnNlcnZlZCkge1xuICAgICAgaWYgKHNsb3QgPiBrbm93blNsb3QpIHtcbiAgICAgICAga25vd25TbG90ID0gc2xvdDtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIGNvbnN0IGNyZWF0ZUV2ZW50ID0gYXN5bmMgPFQgZXh0ZW5kcyBDcmVhdGVFdmVudFJlcXVlc3Q+KFxuICAgIGRhdGE6IFQsXG4gICAgZXZlbnRQYXJhbXM/OiBDcmVhdGVFdmVudFBhcmFtc1xuICApID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXBsYXlSZWNvdmVyeVJlcG9ydGVyLndpdGhFdmVudENyZWF0ZShcbiAgICAgIGtub3duU2xvdCA9PT0gdW5kZWZpbmVkXG4gICAgICAgID8gZXZlbnRQYXJhbXNcbiAgICAgICAgOiB7IGV2ZW50Q291bnQ6IGtub3duU2xvdCwgLi4uZXZlbnRQYXJhbXMgfSxcbiAgICAgIChwKSA9PiB3b3JsZC5ldmVudHMuY3JlYXRlKHdvcmtmbG93UnVuSWQsIGRhdGEsIHApXG4gICAgKTtcbiAgICBvYnNlcnZlU2xvdChyZXN1bHQpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gYHN0ZXBfc3RhcnRlZGAgaWRlbnRpZmllcyB0aGUgaW52b2NhdGlvbiB0aGF0IHBlcmZvcm1lZCB0aGlzIGF0dGVtcHQuXG4gIC8vIEtlZXAgcmVxdWVzdCBhbmQgY29tcHV0ZSBwcm92ZW5hbmNlIGluZGVwZW5kZW50OiB3b3JsZC12ZXJjZWwgc2VyaWFsaXplc1xuICAvLyByZXF1ZXN0SWQgYXMgYW5hbHl0aWNzIGB2ZXJjZWxJZGAsIHdoaWxlIGNvbXB1dGVJbnN0YW5jZUlkIGlkZW50aWZpZXMgdGhlXG4gIC8vIHdvcmtlciB0aGF0IGV4ZWN1dGVkIHRoZSBzdGVwLlxuICBjb25zdCBzdGVwU3RhcnRlZEV2ZW50UGFyYW1zOiBDcmVhdGVFdmVudFBhcmFtcyA9IHtcbiAgICBjb21wdXRlSW5zdGFuY2VJZDogQ09NUFVURV9JTlNUQU5DRV9JRCxcbiAgICAuLi4ocGFyYW1zLnJlcXVlc3RJZCA/IHsgcmVxdWVzdElkOiBwYXJhbXMucmVxdWVzdElkIH0gOiB7fSksXG4gIH07XG5cbiAgY29uc3Qgc3Bhbk5hbWUgPSBgc3RlcC5leGVjdXRlICR7c3RlcERpc3BsYXlOYW1lKHN0ZXBOYW1lKX1gO1xuICByZXR1cm4gdHJhY2Uoc3Bhbk5hbWUsIHt9LCBhc3luYyAoc3BhbikgPT4ge1xuICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBOYW1lKHN0ZXBOYW1lKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKHdvcmtmbG93UnVuSWQpLFxuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBJZChzdGVwSWQpLFxuICAgIH0pO1xuXG4gICAgLy8gVGhlIHR3byBsYXp5IHN0YXJ0IG1vZGVzIGFyZSBtdXR1YWxseSBleGNsdXNpdmUgYnkgY29uc3RydWN0aW9uICh0aGVcbiAgICAvLyBjYWxsZXIgc2V0cyBvbmUgb3IgdGhlIG90aGVyKSwgYW5kIHNldmVyYWwgYnJhbmNoZXMgYmVsb3cgcmVhZCBvbmx5IG9uZVxuICAgIC8vIG9mIHRoZW0gdG8gZGVjaWRlIHdoZXRoZXIgdGhlIHN0ZXAgaXMgYnJhbmQtbmV3LiBFbmZvcmNlZCByYXRoZXIgdGhhblxuICAgIC8vIGRvY3VtZW50ZWQgc28gYSBjYWxsZXIgdGhhdCBldmVyIHNldHMgYm90aCBmYWlscyBoZXJlIGluc3RlYWQgb2ZcbiAgICAvLyBzaWxlbnRseSB0YWtpbmcgdGhlIHByZS1jbGFpbWVkIHBhdGggd2l0aCBhbiB1bnNlbnQgaW5wdXQuXG4gICAgYXNzZXJ0KFxuICAgICAgIShwYXJhbXMubGF6eVN0ZXBJbnB1dCAhPT0gdW5kZWZpbmVkICYmIHBhcmFtcy5wcmVjbGFpbWVkU3RhcnQpLFxuICAgICAgJ2V4ZWN1dGVTdGVwOiBsYXp5U3RlcElucHV0IGFuZCBwcmVjbGFpbWVkU3RhcnQgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZSdcbiAgICApO1xuXG4gICAgLy8gQSBwcmUtY2xhaW1lZCBzdGFydCB0aGF0IExPU1QgdGhlIGJhdGNoZWQgcGFpcidzIGF0b21pYyBjcmVhdGUtY2xhaW06IGFcbiAgICAvLyBjb25jdXJyZW50IHdyaXRlciBvd25zIHRoaXMgc3RlcC4gU2FtZSBvdXRjb21lIGFzIGxvc2luZyB0aGUgbGF6eVxuICAgIC8vIGNsYWltIChFbnRpdHlDb25mbGljdEVycm9yIOKGkiBza2lwcGVkKSwgZGVjaWRlZCBiZWZvcmUgQU5ZIHdyaXRlLCB0aGVcbiAgICAvLyB1bnJlZ2lzdGVyZWQtc3RlcCBmYWxsYmFjayBiZWxvdyBpbmNsdWRlZCwgc2luY2UgYSBzdGVwIHRoaXMgaGFuZGxlclxuICAgIC8vIGRvZXMgbm90IG93biBpcyBub3QgaXRzIHRvIGZhaWwuXG4gICAgaWYgKHBhcmFtcy5wcmVjbGFpbWVkU3RhcnQgJiYgcGFyYW1zLnByZWNsYWltZWRTdGFydC5vd25lZCA9PT0gZmFsc2UpIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1ByZS1jbGFpbWVkIHN0ZXAgc3RhcnQgbG9zdCwgc2tpcHBpbmcnLCB7XG4gICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICBzdGVwSWQsXG4gICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICB9KTtcbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBwZWQodHJ1ZSksXG4gICAgICAgIC8vIGBydW5uaW5nYCwgbm90IGBjb21wbGV0ZWRgOiB0aGUgcGFpcidzIDQwOSBzYXlzIHRoZSBzdGVwIGFscmVhZHlcbiAgICAgICAgLy8gRVhJU1RTLCBhbmQgdGhlIHdyaXRlciB0aGF0IHdvbiB0aGUgY3JlYXRlLWNsYWltIGlzIGV4ZWN1dGluZyBpdC5cbiAgICAgICAgLy8gVGhlIG90aGVyIHNraXAgc2l0ZSBiZWxvdyBpcyBhIGdlbnVpbmUgdGVybWluYWwtc3RhdGUgY29uZmxpY3Q7XG4gICAgICAgIC8vIHRhZ2dpbmcgYm90aCBgY29tcGxldGVkYCB3b3VsZCBtYWtlIHRoZSBhdHRyaWJ1dGUgcmVhZCAxMDAlXG4gICAgICAgIC8vIGBjb21wbGV0ZWRgIGFuZCBsb3NlIHRoZSBvbmx5IGRpc3RpbmN0aW9uIHdvcnRoIHF1ZXJ5aW5nIGl0IGZvci5cbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTa2lwUmVhc29uKCdydW5uaW5nJyksXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgIH1cblxuICAgIC8vIE1lbW9pemVkIGFjY2Vzc29yIGZvciB0aGUgcGVyLXJ1biBlbmNyeXB0aW9uIGtleS4gVGhlIGZpcnN0IGNhbGxlclxuICAgIC8vIChpbnB1dCBoeWRyYXRpb24gb24gdGhlIHN1Y2Nlc3MgcGF0aCwgb3Igb25lIG9mIHRoZSBlYXJseS1yZXR1cm5cbiAgICAvLyBkZWh5ZHJhdGVTdGVwRXJyb3IgcGF0aHMgaWYgc3RlcF9zdGFydGVkIGZhaWxzKSB0cmlnZ2VycyB0aGUgYWN0dWFsXG4gICAgLy8gZmV0Y2ggLyBIS0RGIGRlcml2YXRpb247IHN1YnNlcXVlbnQgY2FsbGVycyBhd2FpdCB0aGUgY2FjaGVkIHByb21pc2UuXG4gICAgY29uc3QgZ2V0RW5jcnlwdGlvbktleSA9IG1lbW9pemVFbmNyeXB0aW9uS2V5KHdvcmxkLCB3b3JrZmxvd1J1bklkKTtcblxuICAgIGNvbnN0IHN0ZXBGbiA9IGdldFN0ZXBGdW5jdGlvbihzdGVwTmFtZSk7XG4gICAgaWYgKCFzdGVwRm4gfHwgdHlwZW9mIHN0ZXBGbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gU3RlcCBmdW5jdGlvbiBub3QgcmVnaXN0ZXJlZDogZmFpbCB0aGUgc3RlcCBpbW1lZGlhdGVseSAobm90IHRoZSBydW4pLlxuICAgICAgLy8gQ3JlYXRlIGEgc3RlcF9mYWlsZWQgZXZlbnQgc29cbiAgICAgIC8vIHRoZSB3b3JrZmxvdyBjYW4gaGFuZGxlIGl0IGdyYWNlZnVsbHkgdmlhIHRyeS9jYXRjaCBpbiB1c2VyIGNvZGUuXG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBcIiR7c3RlcE5hbWV9XCIgaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGN1cnJlbnQgZGVwbG95bWVudC4gVGhpcyB1c3VhbGx5IGluZGljYXRlcyBhIGJ1aWxkIG9yIGJ1bmRsaW5nIGlzc3VlIHRoYXQgY2F1c2VkIHRoZSBzdGVwIHRvIG5vdCBiZSBpbmNsdWRlZCBpbiB0aGUgZGVwbG95bWVudC5gO1xuICAgICAgcnVudGltZUxvZ2dlci5lcnJvcignU3RlcCBmdW5jdGlvbiBub3QgcmVnaXN0ZXJlZCwgZmFpbGluZyBzdGVwJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgc3RlcElkLFxuICAgICAgfSk7XG4gICAgICAvLyBPbiB0aGUgbGF6eSBpbmxpbmUgcGF0aCB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyIGRlZmVycmVkIHRoaXMgc3RlcCdzXG4gICAgICAvLyBgc3RlcF9jcmVhdGVkYCwgZXhwZWN0aW5nIGV4ZWN1dGVTdGVwIHRvIG1hdGVyaWFsaXplIHRoZSBzdGVwIHZpYSBhXG4gICAgICAvLyBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGNhcnJ5aW5nIGl0cyBpbnB1dC4gV2UgbmV2ZXIgZ2V0IHRoYXQgZmFyIGZvciBhblxuICAgICAgLy8gdW5yZWdpc3RlcmVkIHN0ZXAsIHNvIHRoZSBzdGVwIGVudGl0eSBkb2VzIG5vdCBleGlzdCB5ZXQsIGFuZCB3cml0aW5nXG4gICAgICAvLyBgc3RlcF9mYWlsZWRgIHN0cmFpZ2h0IGF3YXkgd291bGQgaGl0IHRoZSB3b3JsZCdzIFwic3RlcCBtdXN0IGV4aXN0XCJcbiAgICAgIC8vIG9yZGVyaW5nIGd1YXJkIGFuZCB3ZWRnZSB0aGUgcnVuLiBTZW5kIHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGZpcnN0XG4gICAgICAvLyAoaXQgY3JlYXRlcyB0aGUgc3RlcCArIHN5bnRoZXRpYyBgc3RlcF9jcmVhdGVkYCBhdG9taWNhbGx5IGFuZCBrZWVwc1xuICAgICAgLy8gcmVwbGF5IGNvcnJlY3QpLCB0aGVuIGZhaWwgaXQgYmVsb3cuIFRoaXMgYWxzbyBwcmVzZXJ2ZXMgdGhlXG4gICAgICAvLyBleGFjdGx5LW9uZS1vd25lciBndWFyYW50ZWU6IGEgY29uY3VycmVudCBoYW5kbGVyIHRoYXQgd29uIHRoZSBjcmVhdGVcbiAgICAgIC8vIG1ha2VzIG91ciBsYXp5IGBzdGVwX3N0YXJ0ZWRgIHJlamVjdCB3aXRoIEVudGl0eUNvbmZsaWN0RXJyb3Ig4oaSIHdlXG4gICAgICAvLyByZXR1cm4gYHNraXBwZWRgIGFuZCBuZXZlciB3cml0ZSB0aGUgZmFpbHVyZSB0d2ljZS5cbiAgICAgIGlmIChwYXJhbXMubGF6eVN0ZXBJbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gVHVyYm86IHRoaXMgbGF6eSBgc3RlcF9zdGFydGVkYCBtdXN0IG5vdCBwcmVjZWRlIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICAgICAgICAvLyBgcnVuX3N0YXJ0ZWRgLiBPcmRlciBpdCBhZnRlciB0aGUgcnVuLXJlYWR5IGJhcnJpZXIgKGJlc3QtZWZmb3J0OlxuICAgICAgICAgIC8vIGEgYmFycmllciByZWplY3Rpb24gbWVhbnMgdGhlIHJ1biBkb2Vzbid0IGV4aXN0LCBhbmQgdGhlIGNyZWF0ZVxuICAgICAgICAgIC8vIGJlbG93IHN1cmZhY2VzIHRoZSByZWFsIGVycm9yKS4gTm8tb3Agb3V0c2lkZSB0dXJiby5cbiAgICAgICAgICBpZiAocGFyYW1zLnJ1blJlYWR5QmFycmllcikge1xuICAgICAgICAgICAgYXdhaXQgcGFyYW1zLnJ1blJlYWR5QmFycmllci5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX3N0YXJ0ZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgIGlucHV0OiBwYXJhbXMubGF6eVN0ZXBJbnB1dCxcbiAgICAgICAgICAgICAgICAvLyBTdGFtcGVkIGZvciBjb25zaXN0ZW5jeSBldmVuIHRob3VnaCB0aGlzIHN0ZXAgdGVybWluYWwtZmFpbHNcbiAgICAgICAgICAgICAgICAvLyBpbW1lZGlhdGVseSBiZWxvdzsgdGhlIGxvZyBzaG91bGQgbmV2ZXIgc2hvdyBhbiB1bm93bmVkXG4gICAgICAgICAgICAgICAgLy8gbGF6eSBzdGFydC5cbiAgICAgICAgICAgICAgICAuLi4ocGFyYW1zLm93bmVyTWVzc2FnZUlkICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgID8geyBvd25lck1lc3NhZ2VJZDogcGFyYW1zLm93bmVyTWVzc2FnZUlkIH1cbiAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN0ZXBTdGFydGVkRXZlbnRQYXJhbXNcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChzdGFydEVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0YXJ0RXJyKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3NraXBwZWQnIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoc3RhcnRFcnIpKSB7XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnZ29uZScgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgc3RhcnRFcnI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KHtcbiAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgbmV3IEZhdGFsRXJyb3IoZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpLFxuICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhzdGVwRmFpbEVycikpIHtcbiAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc2tpcHBlZCcgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgIH1cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHsgdHlwZTogJ2ZhaWxlZCcgfTtcbiAgICB9XG5cbiAgICBjb25zdCBtYXhSZXRyaWVzID0gc3RlcEZuLm1heFJldHJpZXMgPz8gREVGQVVMVF9TVEVQX01BWF9SRVRSSUVTO1xuXG4gICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAuLi5BdHRyaWJ1dGUuU3RlcE1heFJldHJpZXMobWF4UmV0cmllcyksXG4gICAgfSk7XG5cbiAgICAvLyBtYXhSZXRyaWVzIGVuZm9yY2VkIGJlZm9yZSBzdGFydGluZyBhbm90aGVyIGF0dGVtcHQuIFRpbWVvdXRzIGNhbiBraWxsXG4gICAgLy8gYSBzdGVwIGV4ZWN1dGlvbiB3aXRob3V0IGFueSB3YXkgdG8gY2F0Y2ggdGhlIGVycm9yLCBzbyB0aGUgcG9zdC1ib2R5L2Vycm9yXG4gICAgLy8gZ3VhcmRzIGJlbG93IG1pZ2h0IG1pc3MgaXQuIEhlbmNlLCB3ZSB1c2UgYGF1dGhvcml0YXRpdmVBdHRlbXB0YCBjb3VudFxuICAgIC8vIGFzIGFuIGFkZGl0aW9uYWwgZ3VhcmQgYmFzZWQgb24gc3RlcF9zdGFydGVkIGNvdW50IG9yIHF1ZXVlIGRlbGl2ZXJ5IGNvdW50XG4gICAgLy8gb24gYmFja2dyb3VuZGVkIHN0ZXBzLlxuICAgIC8vIFRocm93bi1lcnJvciBleGhhdXN0aW9uIHN0aWxsIHRlcm1pbmF0ZXMgb25lIGF0dGVtcHQgZWFybGllciB2aWEgdGhlIHBvc3QtYm9keVxuICAgIC8vIGd1YXJkICh3aXRoIHRoZSB0aHJvd24gZXJyb3IgYXMgY2F1c2UpLCBhbmQgdGhpcyBjaGVjayBkb2VzIG5vdCBhZmZlY3QgdGhhdC5cbiAgICBpZiAoXG4gICAgICBwYXJhbXMuYXV0aG9yaXRhdGl2ZUF0dGVtcHQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcGFyYW1zLmF1dGhvcml0YXRpdmVBdHRlbXB0ID4gbWF4UmV0cmllcyArIDFcbiAgICApIHtcbiAgICAgIGNvbnN0IHJldHJ5Q291bnQgPSBtYXhSZXRyaWVzO1xuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFN0ZXAgXCIke3N0ZXBOYW1lfVwiIGV4Y2VlZGVkIG1heCByZXRyaWVzICgke3JldHJ5Q291bnR9ICR7cGx1cmFsaXplKCdyZXRyeScsICdyZXRyaWVzJywgcmV0cnlDb3VudCl9KWA7XG4gICAgICBzdGVwTG9nZ2VyLmVycm9yKCdTdGVwIGV4Y2VlZGVkIG1heCByZXRyaWVzJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgc3RlcElkLFxuICAgICAgICBhdHRlbXB0OiBwYXJhbXMuYXV0aG9yaXRhdGl2ZUF0dGVtcHQsXG4gICAgICAgIG1heFJldHJpZXMsXG4gICAgICB9KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KHtcbiAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgbmV3IEZhdGFsRXJyb3IoZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpLFxuICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgIC8vIFN0ZXAgYWxyZWFkeSByZWFjaGVkIGEgdGVybWluYWwgc3RhdGUgKGEgY29uY3VycmVudCBoYW5kbGVyIG9yIGFuXG4gICAgICAgICAgLy8gZWFybGllciBkZWxpdmVyeSBmYWlsZWQvY29tcGxldGVkIGl0KSwgc28gbm90aGluZyB0byBkby5cbiAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwIGZvciBleGNlZWRlZCByZXRyaWVzLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc2tpcHBlZCcgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICByZXR1cm4geyB0eXBlOiAnZ29uZScgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5RXhoYXVzdGVkKHRydWUpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4geyB0eXBlOiAnZmFpbGVkJyB9O1xuICAgIH1cblxuICAgIC8vIE1hcHMgYSBgc3RlcF9zdGFydGVkYCByZWplY3Rpb24gdG8gYSB0ZXJtaW5hbCBTdGVwRXhlY3V0aW9uUmVzdWx0LFxuICAgIC8vIHNoYXJlZCBieSB0aGUgYXdhaXQgcGF0aCAoYmVsb3cpIGFuZCB0aGUgb3B0aW1pc3RpYy1zdGFydCByZWNvbmNpbGlhdGlvbi5cbiAgICAvLyBSZXR1cm5zIHVuZGVmaW5lZCB3aGVuIHRoZSBlcnJvciBpcyBub3Qgb25lIHdlIHRyYW5zbGF0ZSAoY2FsbGVyIHJldGhyb3dzKS5cbiAgICBjb25zdCBzdGFydEVycm9yVG9SZXN1bHQgPSAoXG4gICAgICBlcnI6IHVua25vd25cbiAgICApOiBTdGVwRXhlY3V0aW9uUmVzdWx0IHwgdW5kZWZpbmVkID0+IHtcbiAgICAgIGlmIChUaHJvdHRsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgY29uc3QgcmV0cnlBZnRlciA9IE1hdGgubWF4KFxuICAgICAgICAgIDEsXG4gICAgICAgICAgdHlwZW9mIGVyci5yZXRyeUFmdGVyID09PSAnbnVtYmVyJyA/IGVyci5yZXRyeUFmdGVyIDogMVxuICAgICAgICApO1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1Rocm90dGxlZCBvbiBzdGVwX3N0YXJ0ZWQsIGRlZmVycmluZycsIHtcbiAgICAgICAgICByZXRyeUFmdGVyU2Vjb25kczogcmV0cnlBZnRlcixcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IHR5cGU6ICd0aHJvdHRsZWQnLCB0aW1lb3V0U2Vjb25kczogcmV0cnlBZnRlciB9O1xuICAgICAgfVxuICAgICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICBgV29ya2Zsb3cgcnVuIFwiJHt3b3JrZmxvd1J1bklkfVwiIGhhcyBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgc3RlcCBcIiR7c3RlcElkfVwiOiAke2Vyci5tZXNzYWdlfWBcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2dvbmUnIH07XG4gICAgICB9XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1N0ZXAgaW4gdGVybWluYWwgc3RhdGUsIHNraXBwaW5nJywge1xuICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgIH0pO1xuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBwZWQodHJ1ZSksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTa2lwUmVhc29uKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgfVxuICAgICAgaWYgKFRvb0Vhcmx5RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGgubWF4KDEsIGVyci5yZXRyeUFmdGVyID8/IDEpO1xuICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdGVwIHJldHJ5QWZ0ZXIgdGltZXN0YW1wIG5vdCB5ZXQgcmVhY2hlZCcsIHtcbiAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgdGltZW91dFNlY29uZHMsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAncmV0cnknLCB0aW1lb3V0U2Vjb25kcyB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgLy8gT3B0aW1pc3RpYyBpbmxpbmUgc3RhcnQ6IHdoZW4gd2UgaG9sZCB0aGUgc3RlcCBpbnB1dCBsb2NhbGx5IChsYXp5IGlubGluZVxuICAgIC8vIHBhdGgpIGFuZCB0aGUgb3B0aW1pemF0aW9uIGlzIGVuYWJsZWQsIGZpcmUgYHN0ZXBfc3RhcnRlZGAgV0lUSE9VVFxuICAgIC8vIGF3YWl0aW5nIGFuZCBydW4gdGhlIGJvZHkgYWdhaW5zdCBsb2NhbGx5LXN5bnRoZXNpemVkIHN0YXRlLiBBIGxhenkgc3RlcFxuICAgIC8vIGlzIGFsd2F5cyBicmFuZC1uZXcg4oeSIGF0dGVtcHQgMSwgbm8gcHJpb3IgZXJyb3IsIHN0YXJ0ZWQgbm93LCBzbyB3ZVxuICAgIC8vIGRvbid0IG5lZWQgdGhlIHNlcnZlciByb3VuZC10cmlwIHRvIGJlZ2luLiBXZSByZWNvbmNpbGUgdGhlIGluLWZsaWdodFxuICAgIC8vIGBzdGVwX3N0YXJ0ZWRgIGJlZm9yZSBhbnkgdGVybWluYWwgd3JpdGUgKGByZWNvbmNpbGVPcHRpbWlzdGljU3RhcnRgKTogaWZcbiAgICAvLyBpdCBsb3N0IHRoZSBhdG9taWMgY3JlYXRlLWNsYWltICg0MDkpIG9yIHRoZSBydW4gaXMgZ29uZS90aHJvdHRsZWQsIHdlXG4gICAgLy8gZGlzY2FyZCB0aGUgYm9keSByZXN1bHQuIFJ1bm5pbmcgdGhlIGJvZHkgYmVmb3JlIGNvbmZpcm1pbmcgb3duZXJzaGlwIGNhblxuICAgIC8vIGV4ZWN1dGUgYSBzdGVwIG1vcmUgdGhhbiBvbmNlIHdoZW4gaGFuZGxlcnMgcmFjZSwgc28gaW5saW5lIHN0ZXAgYm9kaWVzXG4gICAgLy8gbXVzdCBiZSBpZGVtcG90ZW50OyBkaXNhYmxlIHZpYSBXT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVD0wLlxuICAgIC8vXG4gICAgLy8gVHVyYm8gbW9kZSBwYXNzZXMgYGZvcmNlT3B0aW1pc3RpY1N0YXJ0YCB0byBlbmFibGUgdGhpcyByZWdhcmRsZXNzIG9mIHRoZVxuICAgIC8vIGVudiBmbGFnIChpdHMgc2luZ2xlLWhhbmRsZXIgZ3VhcmFudGVlIHJlbW92ZXMgdGhlIHJhY2UpLiBCdXQgaXQgc3RpbGxcbiAgICAvLyBkZWZlcnMgdG8gYW4gKmV4cGxpY2l0KiBgV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlQ9MGA6IGZvcmNlZFxuICAgIC8vIG9wdGltaXN0aWMgc3RhcnQgcnVucyB0aGUgYm9keSBiZWZvcmUgYHN0ZXBfc3RhcnRlZGAvYHJ1bl9zdGFydGVkYCBpc1xuICAgIC8vIGNvbmZpcm1lZCwgd2hpY2ggaXMgZXhhY3RseSB0aGUgcHJvcGVydHkgYW4gb3BlcmF0b3Igb3B0cyBvdXQgb2Ygd2l0aCB0aGF0XG4gICAgLy8gZmxhZywgc28gYW4gZXhwbGljaXQgb3B0LW91dCB3aW5zIG92ZXIgdHVyYm8ncyBmb3JjZS5cbiAgICBjb25zdCBvcHRpbWlzdGljU3RhcnQgPVxuICAgICAgLy8gQSBwcmUtY2xhaW1lZCBzdGFydCBhbHJlYWR5IHNldHRsZWQgaXRzIGNsYWltIGluIHRoZSBzdXNwZW5zaW9uXG4gICAgICAvLyBiYXRjaDsgdGhlcmUgaXMgbm90aGluZyB0byBmaXJlIG9wdGltaXN0aWNhbGx5IChsYXp5U3RlcElucHV0IGlzXG4gICAgICAvLyBhbHNvIGFic2VudCBvbiB0aGF0IHBhdGg7IHRoaXMgdGVybSBpcyBkb2N1bWVudGF0aW9uKS5cbiAgICAgIHBhcmFtcy5wcmVjbGFpbWVkU3RhcnQgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgcGFyYW1zLmxhenlTdGVwSW5wdXQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgLy8gU3RhbGUtc2Vuc2l0aXZlIGd1YXJkZWQgYmF0Y2hlcyBhd2FpdCB0aGUgY2xhaW0gc28gdGhlIDQxMiBmZW5jZVxuICAgICAgLy8gY292ZXJzIHRoZSBib2R5LCBub3QganVzdCBkdXJhYmxlIHdyaXRlczsgc2VlXG4gICAgICAvLyBTdGVwRXhlY3V0b3JQYXJhbXMuc3VwcHJlc3NPcHRpbWlzdGljU3RhcnQuXG4gICAgICBwYXJhbXMuc3VwcHJlc3NPcHRpbWlzdGljU3RhcnQgIT09IHRydWUgJiZcbiAgICAgIChpc09wdGltaXN0aWNJbmxpbmVTdGFydEVuYWJsZWQoKSB8fFxuICAgICAgICAocGFyYW1zLmZvcmNlT3B0aW1pc3RpY1N0YXJ0ID09PSB0cnVlICYmXG4gICAgICAgICAgIWlzT3B0aW1pc3RpY0lubGluZVN0YXJ0RXhwbGljaXRseURpc2FibGVkKCkpKTtcblxuICAgIGxldCBzdGVwOiBTdGFydGVkU3RlcDtcbiAgICAvLyBQYXJhbXMgZm9yIHRoZSBgc3RlcF9zdGFydGVkYCBjcmVhdGUgb24gZWl0aGVyIHBhdGggYmVsb3cuIFRoZSBzbG90XG4gICAgLy8gc25hcHNob3QgaXMgbm90IHNwcmVhZCBoZXJlOiBgY3JlYXRlRXZlbnRgIGF0dGFjaGVzIGl0IHRvIGV2ZXJ5IHdyaXRlLFxuICAgIC8vIHRoaXMgb25lIGluY2x1ZGVkLlxuICAgIGNvbnN0IHN0YXJ0RXZlbnRQYXJhbXMgPSBzdGVwU3RhcnRlZEV2ZW50UGFyYW1zO1xuICAgIC8vIGBEYXRlLm5vdygpYCB0YWtlbiBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGBzdGVwX3N0YXJ0ZWRgIGNyZWF0ZSBpc1xuICAgIC8vIGlzc3VlZCAoZWl0aGVyIHBhdGggYmVsb3cpOyBhbmNob3JzIFJTRlMncyBlbmQgcG9pbnQuIFNlZVxuICAgIC8vIFN0ZXBMYXRlbmN5RXZlbnREYXRhLnJzZnMgYW5kIHRoZSBjYWxsIHNpdGVzIGJlbG93LlxuICAgIGxldCBzdGVwU3RhcnRQb3N0U2VudEF0TXM6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAvLyBgRGF0ZS5ub3coKWAgdGFrZW4gb25jZSB0aGUgYHN0ZXBfc3RhcnRlZGAgcmVzcG9uc2UgaGFzIHJldHVybmVkIGFuZCB0aGVcbiAgICAvLyBjbGFpbSBzdWNjZWVkZWQ6IFQ2IG9mIHRoZSBob29rLXJlc3VtZSBUVFIgd2luZG93LiBPbmx5IHRoZSBhd2FpdCBwYXRoXG4gICAgLy8gY2FuIHNldCBpdDogb3B0aW1pc3RpYyBpbmxpbmUgc3RhcnQgZGVsaWJlcmF0ZWx5IGRvZXMgbm90IHdhaXQgZm9yIHRoZVxuICAgIC8vIGNsYWltIGJlZm9yZSBydW5uaW5nIHRoZSBib2R5LCBzbyBhdCBUNyBpdCBoYXMgbm8gY29tcGxldGlvbiBpbnN0YW50IGFuZFxuICAgIC8vIHRoZSBUVFIgYnJlYWtkb3duIHJlcG9ydHMgbm8gYHN0ZXBfY2xhaW1fbXNgIChzZWVcbiAgICAvLyBydW50aW1lL3Jlc3VtZS1sYXRlbmN5LnRzKS5cbiAgICBsZXQgc3RlcENsYWltQ29tcGxldGVkQXRNczogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIC8vIFNldHRsZWQgb3V0Y29tZSBvZiB0aGUgaW4tZmxpZ2h0IG9wdGltaXN0aWMgYHN0ZXBfc3RhcnRlZGAuIEhhbmRsZXJzIGFyZVxuICAgIC8vIGF0dGFjaGVkIHN5bmNocm9ub3VzbHkgKGAudGhlbihvaywgZXJyKWApIHNvIGEgZmFzdCByZWplY3Rpb24gbmV2ZXJcbiAgICAvLyBzdXJmYWNlcyBhcyBhbiB1bmhhbmRsZWRSZWplY3Rpb24gd2hpbGUgdGhlIGJvZHkgcnVucy5cbiAgICBsZXQgb3B0aW1pc3RpY1N0YXJ0U2V0dGxlZDpcbiAgICAgIHwgUHJvbWlzZTx7IG9rOiB0cnVlIH0gfCB7IG9rOiBmYWxzZTsgZXJyOiB1bmtub3duIH0+XG4gICAgICB8IHVuZGVmaW5lZDtcbiAgICAvLyBBd2FpdCB0aGUgb3B0aW1pc3RpYyBgc3RlcF9zdGFydGVkYCBvdXRjb21lIGFuZCB0cmFuc2xhdGUgYSBsb3N0IHJhY2UgL1xuICAgIC8vIHRlcm1pbmFsIHJ1biAvIHRocm90dGxlIGludG8gYSByZXN1bHQgdGhhdCBzaG9ydC1jaXJjdWl0cyB0aGUgYm9keVxuICAgIC8vIG91dHB1dC4gUmV0dXJucyB1bmRlZmluZWQgd2hlbiB3ZSBvd24gdGhlIHN0ZXAgYW5kIG1heSB3cml0ZSBpdHMgdGVybWluYWxcbiAgICAvLyBldmVudC4gQSBub24tdHJhbnNsYXRhYmxlIHJlamVjdGlvbiBpcyByZXRocm93biAoc28gYSB0cmFuc2llbnRcbiAgICAvLyBzdGVwX3N0YXJ0ZWQgZmFpbHVyZSBwcm9wYWdhdGVzIHRvIHRoZSBxdWV1ZSBoYW5kbGVyIGZvciByZWRlbGl2ZXJ5LFxuICAgIC8vIGV4YWN0bHkgYXMgb24gdGhlIGF3YWl0IHBhdGgpLiBJZGVtcG90ZW50OiBzYWZlIHRvIGNhbGwgbW9yZSB0aGFuIG9uY2UuXG4gICAgY29uc3QgcmVjb25jaWxlT3B0aW1pc3RpY1N0YXJ0ID0gYXN5bmMgKCk6IFByb21pc2U8XG4gICAgICBTdGVwRXhlY3V0aW9uUmVzdWx0IHwgdW5kZWZpbmVkXG4gICAgPiA9PiB7XG4gICAgICBpZiAoIW9wdGltaXN0aWNTdGFydFNldHRsZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBzZXR0bGVkID0gYXdhaXQgb3B0aW1pc3RpY1N0YXJ0U2V0dGxlZDtcbiAgICAgIGlmIChzZXR0bGVkLm9rKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgbWFwcGVkID0gc3RhcnRFcnJvclRvUmVzdWx0KHNldHRsZWQuZXJyKTtcbiAgICAgIGlmICghbWFwcGVkKSB0aHJvdyBzZXR0bGVkLmVycjtcbiAgICAgIHJldHVybiBtYXBwZWQ7XG4gICAgfTtcblxuICAgIGlmIChwYXJhbXMucHJlY2xhaW1lZFN0YXJ0Py5vd25lZCkge1xuICAgICAgLy8gUHJlLWNsYWltZWQgaW5saW5lIHN0YXJ0OiB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyJ3MgYmF0Y2hlZCBmYW4tb3V0XG4gICAgICAvLyBhbHJlYWR5IGNvbW1pdHRlZCB0aGlzIHN0ZXAncyBgc3RlcF9jcmVhdGVkYCArIGBzdGVwX3N0YXJ0ZWRgIHBhaXIsXG4gICAgICAvLyBzbyB0aGlzIGV4ZWN1dGlvbiBvd25zIGEgc3RhcnRlZCBhdHRlbXB0LTEgc3RlcCB3aXRob3V0IHNlbmRpbmcgYVxuICAgICAgLy8gc3RhcnQgb2YgaXRzIG93bjogdGhlIGJvZHkgYmVnaW5zIHN0cmFpZ2h0IG9mZiB0aGUgYmF0Y2ggY29tbWl0IGFuZFxuICAgICAgLy8gdGhlIHRlcm1pbmFsIHdyaXRlIGJlbG93IGhhcyBubyBpbi1mbGlnaHQgY2xhaW0gdG8gcmVjb25jaWxlLiBUaGVcbiAgICAgIC8vIGJhdGNoIHRpbWVzdGFtcHMgc3RhbmQgaW4gZm9yIHRoZSBjbGFpbSdzOiB0aGUgUE9TVCBpbnN0YW50IGFuY2hvcnNcbiAgICAgIC8vIFJTRlMsIHRoZSByZXNwb25zZSBpbnN0YW50IGlzIFRUUidzIGNsYWltIGNvbXBsZXRpb24gKFQ2KS5cbiAgICAgIHN0ZXAgPSBwYXJhbXMucHJlY2xhaW1lZFN0YXJ0LnN0ZXA7XG4gICAgICBzdGVwU3RhcnRQb3N0U2VudEF0TXMgPSBwYXJhbXMucHJlY2xhaW1lZFN0YXJ0LmJhdGNoUG9zdFNlbnRBdE1zO1xuICAgICAgc3RlcENsYWltQ29tcGxldGVkQXRNcyA9IHBhcmFtcy5wcmVjbGFpbWVkU3RhcnQuY2xhaW1Db21wbGV0ZWRBdE1zO1xuICAgIH0gZWxzZSBpZiAob3B0aW1pc3RpY1N0YXJ0KSB7XG4gICAgICAvLyBDaGFpbiB0aGUgbGF6eSBgc3RlcF9zdGFydGVkYCBvbiB0aGUgcnVuLXJlYWR5IGJhcnJpZXIgKHR1cmJvIG1vZGUpOlxuICAgICAgLy8gdGhlIHN0ZXAgY2FuJ3QgYmUgY3JlYXRlZCBiZWZvcmUgaXRzIHJ1biBleGlzdHMsIGJ1dCB0aGUgYm9keSBiZWxvd1xuICAgICAgLy8gcnVucyBpbW1lZGlhdGVseSBhZ2FpbnN0IHN5bnRoZXNpemVkIHN0YXRlLCBzbyB0aGUgYHJ1bl9zdGFydGVkYFxuICAgICAgLy8gcm91bmQtdHJpcCBvdmVybGFwcyB0aGUgYm9keSByYXRoZXIgdGhhbiBibG9ja2luZyBpdC4gT3V0c2lkZSB0dXJibyB0aGVcbiAgICAgIC8vIGJhcnJpZXIgaXMgdW5kZWZpbmVkIGFuZCB0aGlzIGlzIGEgcGxhaW4gY3JlYXRlLlxuICAgICAgY29uc3Qgc3RhcnRlZFByb21pc2UgPSAocGFyYW1zLnJ1blJlYWR5QmFycmllciA/PyBQcm9taXNlLnJlc29sdmUoKSkudGhlbihcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIC8vIFRha2VuIHJpZ2h0IGJlZm9yZSB0aGUgY3JlYXRlIGZpcmVzLCBub3QgYmVmb3JlIHRoZSBiYXJyaWVyOlxuICAgICAgICAgIC8vIFJTRlMgbWVhc3VyZXMgdGhlIHJ1bl9zdGFydGVkLXRvLVBPU1Qgc3RyZXRjaCwgYW5kIHRoZSBiYXJyaWVyXG4gICAgICAgICAgLy8gd2FpdCBJUyBwYXJ0IG9mIHRoYXQgc3RyZXRjaCB1bmRlciB0dXJiby5cbiAgICAgICAgICBzdGVwU3RhcnRQb3N0U2VudEF0TXMgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVFdmVudChcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9zdGFydGVkJyxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICBpbnB1dDogcGFyYW1zLmxhenlTdGVwSW5wdXQsXG4gICAgICAgICAgICAgICAgLy8gSW5saW5lLW93bmVyc2hpcCBzdGFtcDsgc2VlIFN0ZXBFeGVjdXRvclBhcmFtcy5vd25lck1lc3NhZ2VJZC5cbiAgICAgICAgICAgICAgICAuLi4ocGFyYW1zLm93bmVyTWVzc2FnZUlkICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgID8geyBvd25lck1lc3NhZ2VJZDogcGFyYW1zLm93bmVyTWVzc2FnZUlkIH1cbiAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8vIEd1YXJkIHRoZSBjbGFpbTsgc2VlIFN0ZXBFeGVjdXRvclBhcmFtcy5zbG90U25hcHNob3QuIEFcbiAgICAgICAgICAgIC8vIHN0YWxlICg0MTIpIHJlamVjdGlvbiBzdXJmYWNlcyB2aWEgcmVjb25jaWxlT3B0aW1pc3RpY1N0YXJ0IGFzIGFcbiAgICAgICAgICAgIC8vIG5vbi10cmFuc2xhdGFibGUgZXJyb3I6IHRoZSBib2R5IHJlc3VsdCBpcyBkaXNjYXJkZWQgYW5kIHRoZVxuICAgICAgICAgICAgLy8gcmVqZWN0aW9uIHByb3BhZ2F0ZXMgdG8gdGhlIGNhbGxlci5cbiAgICAgICAgICAgIHN0YXJ0RXZlbnRQYXJhbXNcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICApO1xuICAgICAgb3B0aW1pc3RpY1N0YXJ0U2V0dGxlZCA9IHN0YXJ0ZWRQcm9taXNlLnRoZW4oXG4gICAgICAgICgpID0+ICh7IG9rOiB0cnVlIGFzIGNvbnN0IH0pLFxuICAgICAgICAoZXJyKSA9PiAoeyBvazogZmFsc2UgYXMgY29uc3QsIGVyciB9KVxuICAgICAgKTtcbiAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgICBzdGVwID0ge1xuICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgc3RlcElkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgc3RhdHVzOiAncnVubmluZycsXG4gICAgICAgIGlucHV0OiBwYXJhbXMubGF6eVN0ZXBJbnB1dCxcbiAgICAgICAgYXR0ZW1wdDogMSxcbiAgICAgICAgc3RhcnRlZEF0OiBub3csXG4gICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHN0ZXBfc3RhcnRlZCB2YWxpZGF0ZXMgc3RhdGUgYW5kIHJldHVybnMgdGhlIHN0ZXAgZW50aXR5LiBPbiB0aGUgbGF6eVxuICAgICAgLy8gaW5saW5lIHBhdGggd2UgYWxzbyBjYXJyeSB0aGUgc3RlcCBgaW5wdXRgIHNvIHRoZSB3b3JsZCBjcmVhdGVzIHRoZVxuICAgICAgLy8gc3RlcCBvbiB0aGUgZmx5IChubyBzZXBhcmF0ZSBzdGVwX2NyZWF0ZWQgcm91bmQtdHJpcCkuIFRoZSB3b3JsZCdzXG4gICAgICAvLyBhdG9taWMgY3JlYXRlLWNsYWltIG1ha2VzIHRoaXMgZXhhY3RseS1vbmUtb3duZXI6IGEgY29uY3VycmVudCBsb3NlclxuICAgICAgLy8gZ2V0cyBFbnRpdHlDb25mbGljdEVycm9yLCBtYXBwZWQgdG8gYHsgdHlwZTogJ3NraXBwZWQnIH1gLCBzbyBpdCBuZXZlclxuICAgICAgLy8gcnVucyB0aGUgYm9keS4gV2hlbiBgbGF6eVN0ZXBJbnB1dGAgaXMgYWJzZW50IHRoaXMgaXMgdGhlIGxlZ2FjeVxuICAgICAgLy8gc3RlcF9zdGFydGVkIChzdGVwIGFscmVhZHkgY3JlYXRlZCwgbm8gcGF5bG9hZCkuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBJbmxpbmUtb3duZXJzaGlwIHN0YW1wOiBwcmVzZW50IG9uIHRoZSBsYXp5IHBhdGhzIEFORCBvbiB0aGVcbiAgICAgICAgLy8gb3duZWQtcmVjb3ZlcnkgcGF5bG9hZC1sZXNzIHN0YXJ0IChhIHJlZGVsaXZlcnkgb2YgdGhlIG93bmluZ1xuICAgICAgICAvLyBtZXNzYWdlIHJlLWV4ZWN1dGluZyBpdHMgc3RlcCBtdXN0IHJlLXN0YW1wLCBzaW5jZSBvd25lcnNoaXAgZGVyaXZlc1xuICAgICAgICAvLyBmcm9tIHRoZSBsYXRlc3Qgc3RhcnQsIHNvIGFuIHVuc3RhbXBlZCByZWNvdmVyeSBzdGFydCB3b3VsZCByZWFkXG4gICAgICAgIC8vIGFzIFwidW5vd25lZFwiIHRvIGEgbGF0ZXIgd2FrZSkuIE9ubHkgdGhlIGJhY2tncm91bmQtc3RlcCBwYXRoXG4gICAgICAgIC8vIHBhc3NlcyBubyBvd25lck1lc3NhZ2VJZDogaXRzIHN0YXJ0IGlzIHRoZSBiYXJlIG9uZSwgY2xlYXJpbmdcbiAgICAgICAgLy8gb3duZXJzaGlwIGFzIGludGVuZGVkLlxuICAgICAgICBjb25zdCBvd25lcnNoaXBTdGFtcCA9XG4gICAgICAgICAgcGFyYW1zLm93bmVyTWVzc2FnZUlkICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8geyBvd25lck1lc3NhZ2VJZDogcGFyYW1zLm93bmVyTWVzc2FnZUlkIH1cbiAgICAgICAgICAgIDoge307XG4gICAgICAgIHN0ZXBTdGFydFBvc3RTZW50QXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHN0YXJ0UmVzdWx0ID0gYXdhaXQgY3JlYXRlRXZlbnQoXG4gICAgICAgICAge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9zdGFydGVkJyxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YTpcbiAgICAgICAgICAgICAgcGFyYW1zLmxhenlTdGVwSW5wdXQgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICBpbnB1dDogcGFyYW1zLmxhenlTdGVwSW5wdXQsXG4gICAgICAgICAgICAgICAgICAgIC4uLm93bmVyc2hpcFN0YW1wLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDogeyBzdGVwTmFtZSwgLi4ub3duZXJzaGlwU3RhbXAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIC8vIEd1YXJkIHRoZSBjbGFpbTsgc2VlIFN0ZXBFeGVjdXRvclBhcmFtcy5zbG90U25hcHNob3QuIEFcbiAgICAgICAgICAvLyBzdGFsZSAoNDEyKSByZWplY3Rpb24gaXMgaW50ZW50aW9uYWxseSBOT1QgdHJhbnNsYXRlZCBieVxuICAgICAgICAgIC8vIHN0YXJ0RXJyb3JUb1Jlc3VsdCBiZWxvdywgc28gaXQgcHJvcGFnYXRlcyB0byB0aGUgY2FsbGVyIGZvciBhXG4gICAgICAgICAgLy8gZnJlc2ggcmVwbGF5LlxuICAgICAgICAgIHN0YXJ0RXZlbnRQYXJhbXNcbiAgICAgICAgKTtcbiAgICAgICAgc3RlcENsYWltQ29tcGxldGVkQXRNcyA9IERhdGUubm93KCk7XG5cbiAgICAgICAgc3RlcCA9IHN0YXJ0UmVzdWx0LnN0ZXA7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc3QgbWFwcGVkID0gc3RhcnRFcnJvclRvUmVzdWx0KGVycik7XG4gICAgICAgIGlmIChtYXBwZWQpIHJldHVybiBtYXBwZWQ7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdGVwIGV4ZWN1dGlvbiBkZXRhaWxzJywge1xuICAgICAgc3RlcE5hbWUsXG4gICAgICBzdGVwSWQ6IHN0ZXAuc3RlcElkLFxuICAgICAgc3RhdHVzOiBzdGVwLnN0YXR1cyxcbiAgICAgIGF0dGVtcHQ6IHN0ZXAuYXR0ZW1wdCxcbiAgICB9KTtcblxuICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoc3RlcC5zdGF0dXMpLFxuICAgIH0pO1xuXG4gICAgbGV0IHJlc3VsdDogdW5rbm93bjtcblxuICAgIC8vIENoZWNrIG1heCByZXRyaWVzIEFGVEVSIHN0ZXBfc3RhcnRlZCAoYXR0ZW1wdCB3YXMganVzdCBpbmNyZW1lbnRlZCkuXG4gICAgLy8gT25seSBlbmZvcmNlIHdoZW4gdGhlIHN0ZXAgaGFzIGEgcHJldmlvdXMgZXJyb3I7IHRoaXMgZGlzdGluZ3Vpc2hlc1xuICAgIC8vIGFjdHVhbCByZXRyaWVzIChmYWlsZWQg4oaSIHJldHJ5KSBmcm9tIGNvbmN1cnJlbnQgaW5saW5lIHN0YXJ0c1xuICAgIC8vIGV4ZWN1dGlvbiBsb29wIGNhbiBjYXVzZSBtdWx0aXBsZSBoYW5kbGVycyB0byBzdGVwX3N0YXJ0ZWQgdGhlIHNhbWVcbiAgICAvLyBzdGVwIHNpbXVsdGFuZW91c2x5LCBpbmZsYXRpbmcgdGhlIGF0dGVtcHQgY291bnRlciB3aXRob3V0IGFueSBmYWlsdXJlKS5cbiAgICBpZiAoc3RlcC5hdHRlbXB0ID4gbWF4UmV0cmllcyArIDEgJiYgc3RlcC5lcnJvcikge1xuICAgICAgY29uc3QgcmV0cnlDb3VudCA9IHN0ZXAuYXR0ZW1wdCAtIDE7XG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBcIiR7c3RlcE5hbWV9XCIgZXhjZWVkZWQgbWF4IHJldHJpZXMgKCR7cmV0cnlDb3VudH0gJHtwbHVyYWxpemUoJ3JldHJ5JywgJ3JldHJpZXMnLCByZXRyeUNvdW50KX0pYDtcbiAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoJ1N0ZXAgZXhjZWVkZWQgbWF4IHJldHJpZXMnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICByZXRyeUNvdW50LFxuICAgICAgfSk7XG4gICAgICAvLyBQcmVzZXJ2ZSB0aGUgcHJpb3IgYXR0ZW1wdCdzIHNlcmlhbGl6ZWQgZXJyb3IgYXMgdGhlIGNhdXNlIHNvIHRoZVxuICAgICAgLy8gdW5kZXJseWluZyBmYWlsdXJlIGlzIHJlY292ZXJhYmxlIGZyb20gYHN0ZXAuZXJyb3IuY2F1c2VgIGFmdGVyXG4gICAgICAvLyBoeWRyYXRpb24sIHdpdGhvdXQgZm9yY2luZyBjb25zdW1lcnMgdG8gd2FsayB0aGUgc3RlcF9yZXRyeWluZ1xuICAgICAgLy8gZXZlbnQgaGlzdG9yeS4gQmVzdC1lZmZvcnQ6IGlmIGh5ZHJhdGlvbiBvZiB0aGUgcHJpb3IgYHN0ZXAuZXJyb3JgXG4gICAgICAvLyB0aHJvd3MsIGZhbGwgYmFjayB0byBhIEZhdGFsRXJyb3Igd2l0aG91dCBjYXVzZS5cbiAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICBpZiAoc3RlcC5lcnJvciAhPSBudWxsKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgKHdyYXBwZWRFcnJvciBhcyBFcnJvcikuY2F1c2UgPSBhd2FpdCBoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgc3RlcC5lcnJvcixcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBJZ25vcmU6IGJlc3QtZWZmb3J0IGNhdXNlIGF0dGFjaG1lbnQuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KHtcbiAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgd3JhcHBlZEVycm9yLFxuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCksXG4gICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc2tpcHBlZCcgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5RXhoYXVzdGVkKHRydWUpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4geyB0eXBlOiAnZmFpbGVkJyB9O1xuICAgIH1cblxuICAgIC8vIE9wcyB0aGF0IG11c3QgYmUgZHVyYWJseSBjb21taXR0ZWQgYmVmb3JlIHN0ZXAgY29tcGxldGlvbiAoZS5nLiBhXG4gICAgLy8gc3RlcC1pbml0aWF0ZWQgYWJvcnQncyBob29rX3JlY2VpdmVkIGV2ZW50KS4gU2VlIFN0ZXBDb250ZXh0LiBEZWNsYXJlZFxuICAgIC8vIG91dHNpZGUgdGhlIHRyeSBzbyB0aGUgZmFpbHVyZSBwYXRoIGJlbG93IGNhbiBhbHNvIGRyYWluIHRoZW0uXG4gICAgY29uc3QgcHJlQ29tcGxldGlvbk9wczogUHJvbWlzZTx2b2lkPltdID0gW107XG4gICAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgICBsZXQgb3BzU2V0dGxlZCA9IHRydWU7XG5cbiAgICAvLyBMYXRlbmN5IHRlbGVtZXRyeSB0byBhdHRhY2ggdG8gdGhpcyBzdGVwJ3MgdGVybWluYWwgZXZlbnQuIENvbXB1dGVkXG4gICAgLy8gcmlnaHQgYmVmb3JlIHVzZXIgY29kZSBydW5zOyBkZWNsYXJlZCBoZXJlIHNvIHRoZSBmYWlsdXJlIHBhdGggKHRoZVxuICAgIC8vIGNhdGNoIGJlbG93KSBjYW4gYXR0YWNoIGl0IHRvIHN0ZXBfZmFpbGVkIHRvby5cbiAgICBsZXQgbGF0ZW5jeUV2ZW50RGF0YTogU3RlcExhdGVuY3lFdmVudERhdGEgfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBCYWNrZmlsbCBSU0ZTIG9udG8gdGhlIGFscmVhZHktY29tcHV0ZWQgdGVsZW1ldHJ5IG9uY2UgdGhlIG9wdGltaXN0aWNcbiAgICAvLyB0dXJibyBzdGFydCBoYXMgc2V0dGxlZC4gT24gdGhhdCBwYXRoIHRoZSBzdGVwLXN0YXJ0IFBPU1QgZmlyZXMgaW5zaWRlXG4gICAgLy8gdGhlIHJ1bi1yZWFkeSBiYXJyaWVyJ3MgYC50aGVuYCwgc28gYHN0ZXBTdGFydFBvc3RTZW50QXRNc2AgKGFuZFxuICAgIC8vIHRoZXJlZm9yZSBSU0ZTKSBpcyB1c3VhbGx5IHN0aWxsIHVuc2V0IHdoZW4gYGxhdGVuY3lFdmVudERhdGFgIGlzXG4gICAgLy8gZmlyc3QgY29tcHV0ZWQganVzdCBiZWZvcmUgdXNlciBjb2RlICh0aGUgYmFycmllciBpcyBzdGlsbCBpbiBmbGlnaHRcbiAgICAvLyBmb3IgYW55IG5vbi10cml2aWFsIGBydW5fc3RhcnRlZGAgcm91bmQtdHJpcCwgd2hpY2ggaXMgZXhhY3RseSB0aGVcbiAgICAvLyBzbG93LXJ1bl9zdGFydGVkIGNhc2UgUlNGUyBleGlzdHMgdG8gbWVhc3VyZSkuIEJ5IHRoZSB0aW1lXG4gICAgLy8gYHJlY29uY2lsZU9wdGltaXN0aWNTdGFydCgpYCBoYXMgYXdhaXRlZCB0aGUgYmFycmllciB0aGUgUE9TVCB0aW1lc3RhbXBcbiAgICAvLyBpcyBrbm93biwgc28gd2UgcGF0Y2ggUlNGUyBpbiBiZWZvcmUgdGhlIHRlcm1pbmFsIGV2ZW50IGlzIHdyaXR0ZW4uXG4gICAgLy8gV2l0aG91dCB0aGlzLCBzbG93LXJ1bl9zdGFydGVkIHNhbXBsZXMgYXJlIGRyb3BwZWQsIGJpYXNpbmcgUlNGU1xuICAgIC8vIHBlcmNlbnRpbGVzIGxvdyAobWlzc2luZy1ub3QtYXQtcmFuZG9tKS4gUmVjb21wdXRlcyBvbmx5IFJTRlM7XG4gICAgLy8gVFRGUy9TVFNPIHN0YXkgYW5jaG9yZWQgdG8gYGV4ZWN1dGlvblN0YXJ0VGltZWAgYXMgY29tcHV0ZWQgYWJvdmUuXG4gICAgY29uc3QgYmFja2ZpbGxPcHRpbWlzdGljUnNmcyA9ICgpOiB2b2lkID0+IHtcbiAgICAgIGlmICghbGF0ZW5jeUV2ZW50RGF0YSB8fCBsYXRlbmN5RXZlbnREYXRhLnJzZnMgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgICAgY29uc3QgYW5jaG9yTXMgPSBwYXJhbXMubGF0ZW5jeVRyYWNraW5nPy5yc2ZzQW5jaG9yTXM7XG4gICAgICBpZiAoYW5jaG9yTXMgPT09IHVuZGVmaW5lZCB8fCBzdGVwU3RhcnRQb3N0U2VudEF0TXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgICAgbGF0ZW5jeUV2ZW50RGF0YS5yc2ZzID0gTWF0aC5tYXgoMCwgc3RlcFN0YXJ0UG9zdFNlbnRBdE1zIC0gYW5jaG9yTXMpO1xuICAgICAgaWYgKHNwYW4pIHtcbiAgICAgICAgc3Bhbi5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJzZnNNcyhsYXRlbmN5RXZlbnREYXRhLnJzZnMpLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGF0dGVtcHQgPSBzdGVwLmF0dGVtcHQ7XG5cbiAgICAgIGlmICghc3RlcC5zdGFydGVkQXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgIGBTdGVwIFwiJHtzdGVwSWR9XCIgaGFzIG5vIFwic3RhcnRlZEF0XCIgdGltZXN0YW1wYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3Qgc3RlcFN0YXJ0ZWRBdCA9IHN0ZXAuc3RhcnRlZEF0O1xuICAgICAgLy8gVXNlIHRoZSBwcm92aWRlZCBlbmNyeXB0aW9uIGtleSB3aGVuIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIHJlc29sdmVcbiAgICAgIC8vIHRocm91Z2ggdGhlIG1lbW9pemVkIGFjY2Vzc29yIGRlY2xhcmVkIGF0IHRoZSB0b3Agb2YgdGhpcyB0cmFjZS5cbiAgICAgIGNvbnN0IGVuY3J5cHRpb25LZXkgPSBwYXJhbXMuZW5jcnlwdGlvbktleSA/PyAoYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpKTtcbiAgICAgIGNvbnN0IGh5ZHJhdGVkSW5wdXQgPSBhd2FpdCB0cmFjZShcbiAgICAgICAgJ3N0ZXAuaHlkcmF0ZScsXG4gICAgICAgIHt9LFxuICAgICAgICBhc3luYyAoaHlkcmF0ZVNwYW4pID0+IHtcbiAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIGNvbnN0IGh5ZHJhdGVkID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICBzdGVwLmlucHV0LFxuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAge30sXG4gICAgICAgICAgICBwYXJhbXMud29ya2Zsb3dEZXBsb3ltZW50SWRcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xuICAgICAgICAgIGh5ZHJhdGVTcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwQXJndW1lbnRzQ291bnQoaHlkcmF0ZWQuYXJncy5sZW5ndGgpLFxuICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlRGVzZXJpYWxpemVUaW1lTXMoZHVyYXRpb25NcyksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIGh5ZHJhdGVkO1xuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyBGaW5hbGl6YXRpb24gb2YgYW4gdW5zZXJpYWxpemFibGUtYXJndW1lbnQgc3RlcCB3cml0ZXMgc3RlcF9jcmVhdGVkXG4gICAgICAvLyAocGxhY2Vob2xkZXIgaW5wdXQpIGFuZCBzdGVwX2ZhaWxlZCBhcyB0d28gc2VwYXJhdGUgZHVyYWJsZSB3cml0ZXMuXG4gICAgICAvLyBBIGNyYXNoIG9yIHRyYW5zaWVudCBmYWlsdXJlIGJldHdlZW4gdGhlbSBsZWF2ZXMgdGhpcyBzdGVwIHBlbmRpbmdcbiAgICAgIC8vIHdpdGggdGhlIHBsYWNlaG9sZGVyIHN0b3JlZCBhcyBpdHMgaW5wdXQsIGFuZCBub3JtYWwgY3Jhc2ggcmVjb3ZlcnlcbiAgICAgIC8vIHRoZW4gZGlzcGF0Y2hlcyBpdCBoZXJlLiBORVZFUiBydW4gdXNlciBjb2RlIHdpdGggcGxhY2Vob2xkZXJcbiAgICAgIC8vIGFyZ3VtZW50czsgY29tcGxldGUgdGhlIGludGVuZGVkIGZhaWx1cmUgaW5zdGVhZC4gVGhlXG4gICAgICAvLyBTZXJpYWxpemF0aW9uRXJyb3IgaXMgZmF0YWwgKGBmYXRhbDogdHJ1ZWApLCBzbyB0aGUgY2F0Y2ggYmVsb3dcbiAgICAgIC8vIHdyaXRlcyBzdGVwX2ZhaWxlZCB3aXRob3V0IHJldHJpZXMsIGV4YWN0bHkgd2hhdCB0aGUgaW50ZXJydXB0ZWRcbiAgICAgIC8vIGZpbmFsaXphdGlvbiB3YXMgYWJvdXQgdG8gZG8uXG4gICAgICBpZiAoaXNVbnNlcmlhbGl6YWJsZVN0ZXBJbnB1dFBsYWNlaG9sZGVyKGh5ZHJhdGVkSW5wdXQpKSB7XG4gICAgICAgIGNvbnN0IHsgbWVzc2FnZSwgaGludCB9ID0gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgICAgICdzdGVwIGFyZ3VtZW50cycsXG4gICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICk7XG4gICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IobWVzc2FnZSwgeyBoaW50IH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhcmdzID0gaHlkcmF0ZWRJbnB1dC5hcmdzO1xuICAgICAgY29uc3QgdGhpc1ZhbCA9IGh5ZHJhdGVkSW5wdXQudGhpc1ZhbCA/PyBudWxsO1xuICAgICAgY29uc3Qgd29ya2Zsb3dCYXNlVXJsID0gY3JlYXRlV29ya2Zsb3dCYXNlVXJsKFxuICAgICAgICBpc1ZlcmNlbFxuICAgICAgICAgID8gYGh0dHBzOi8vJHtwcm9jZXNzLmVudi5WRVJDRUxfVVJMfWBcbiAgICAgICAgICA6IGBodHRwOi8vbG9jYWxob3N0OiR7KGF3YWl0IGdldFBvcnRMYXp5KCkpID8/IDMwMDB9YFxuICAgICAgKTtcblxuICAgICAgLy8gLS0tIFVzZXIgY29kZSBleGVjdXRpb24gLS0tXG4gICAgICAvLyBXcmFwIG9ubHkgc3RlcEZuLmFwcGx5KCkgKHVzZXIgc3RlcCBjb2RlKSBzbyBjbGVhbnVwIGJlbG93IHJ1bnMgb25cbiAgICAgIC8vIEJPVEggc3VjY2VzcyBhbmQgZmFpbHVyZS4gQSB1c2VyLWNvZGUgdGhyb3cgaXMgY2FwdHVyZWQgaGVyZSBhbmRcbiAgICAgIC8vIHJlLXJhaXNlZCBhZnRlciBjYW5jZWxBYm9ydFJlYWRlcnMsIHNvIGl0IHN0aWxsIGZsb3dzIHRvIHRoZSBvdXRlclxuICAgICAgLy8gY2F0Y2ggKHN0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcpLCBidXQgdGhlIGFib3J0LXN0cmVhbSByZWFkZXIgaXNcbiAgICAgIC8vIHRvcm4gZG93biBmaXJzdC4gV2l0aG91dCB0aGlzLCBhIHRocm93aW5nL3JldHJ5aW5nIHNpZ25hbC1iZWFyaW5nXG4gICAgICAvLyBzdGVwIHdvdWxkIGxlYWsgYSByZWFsLXRpbWUgYWJvcnQgcmVhZGVyIHBlciBhdHRlbXB0LlxuICAgICAgbGV0IHVzZXJDb2RlRXJyb3I6IHVua25vd247XG4gICAgICBsZXQgdXNlckNvZGVGYWlsZWQgPSBmYWxzZTtcblxuICAgICAgY29uc3QgZXhlY3V0aW9uU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIGxhdGVuY3lFdmVudERhdGEgPSBjb21wdXRlU3RlcExhdGVuY3lFdmVudERhdGEoe1xuICAgICAgICB0cmFja2luZzogcGFyYW1zLmxhdGVuY3lUcmFja2luZyxcbiAgICAgICAgc3RlcENvZGVTdGFydGVkQXRNczogZXhlY3V0aW9uU3RhcnRUaW1lLFxuICAgICAgICBhdHRlbXB0LFxuICAgICAgICBsYXp5U3RlcFN0YXJ0OiBwYXJhbXMubGF6eVN0ZXBJbnB1dCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICBvcHRpbWlzdGljU3RhcnQsXG4gICAgICAgIHByZWNsYWltZWRTdGFydDogcGFyYW1zLnByZWNsYWltZWRTdGFydCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICBzdGVwU3RhcnRQb3N0U2VudEF0TXMsXG4gICAgICB9KTtcbiAgICAgIGlmIChsYXRlbmN5RXZlbnREYXRhKSB7XG4gICAgICAgIC8vIE1pcnJvciB0aGUgbGF0ZW5jeSB0ZWxlbWV0cnkgb250byB0aGUgc3RlcCBzcGFuIHNvIHRyYWNlcyBzaG93XG4gICAgICAgIC8vIFRURlMvU1RTTy9SU0ZTIGFsb25nc2lkZSB0aGUgZmxhbWUgZ3JhcGgsIG5vdCBqdXN0IERhdGFkb2cgbWV0cmljcy5cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uKGxhdGVuY3lFdmVudERhdGEudHRmcyAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IEF0dHJpYnV0ZS5TdGVwVHRmc01zKGxhdGVuY3lFdmVudERhdGEudHRmcylcbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgIC4uLihsYXRlbmN5RXZlbnREYXRhLnN0c28gIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgPyBBdHRyaWJ1dGUuU3RlcFN0c29NcyhsYXRlbmN5RXZlbnREYXRhLnN0c28pXG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAuLi4obGF0ZW5jeUV2ZW50RGF0YS5yc2ZzICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gQXR0cmlidXRlLlN0ZXBSc2ZzTXMobGF0ZW5jeUV2ZW50RGF0YS5yc2ZzKVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgLi4uKGxhdGVuY3lFdmVudERhdGEuZmluYWxTY2hlZHVsaW5nUmVwbGF5ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gQXR0cmlidXRlLlN0ZXBGaW5hbFNjaGVkdWxpbmdSZXBsYXlNcyhcbiAgICAgICAgICAgICAgICBsYXRlbmN5RXZlbnREYXRhLmZpbmFsU2NoZWR1bGluZ1JlcGxheVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcExhdGVuY3lPcHRpbWl6YXRpb25zKFxuICAgICAgICAgICAgbGF0ZW5jeUV2ZW50RGF0YS5vcHRpbWl6YXRpb25zID8/IFtdXG4gICAgICAgICAgKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICAvKipcbiAgICAgICAqIENsb3NlIHRoZSBob29rLXJlc3VtZSBUVFIgbWVhc3VyZW1lbnQgKHNlZSBydW50aW1lL3Jlc3VtZS1sYXRlbmN5LnRzKS5cbiAgICAgICAqXG4gICAgICAgKiBDYWxsZWQgZnJvbSBJTlNJREUgYGNvbnRleHRTdG9yYWdlLnJ1bmAsIGltbWVkaWF0ZWx5IGJlZm9yZVxuICAgICAgICogYHN0ZXBGbi5hcHBseSgpYCwgZGVsaWJlcmF0ZWx5IG5vdCBhbG9uZ3NpZGUgdGhlIHN0ZXAtbGF0ZW5jeVxuICAgICAgICogdGVsZW1ldHJ5IGFib3ZlLiBgZXhlY3V0aW9uU3RhcnRUaW1lYCBpcyB0YWtlbiBiZWZvcmUgdGhlIGlubmVyXG4gICAgICAgKiBgc3RlcC5leGVjdXRlYCBzcGFuIGFuZCB0aGUgc3RlcCBjb250ZXh0IGFyZSBlc3RhYmxpc2hlZCwgYW5kXG4gICAgICAgKiBgc3RlcF9wcmVwYXJlX21zYCBpcyBkb2N1bWVudGVkIHRvIGluY2x1ZGUgZXhhY3RseSB0aGF0IHNldHVwLCBzb1xuICAgICAgICogYW5jaG9yaW5nIFQ3IHRoZXJlIHdvdWxkIHVuZGVyLXJlcG9ydCBib3RoIHRoZSBwaGFzZSBhbmQgdGhlIHRvdGFsLlxuICAgICAgICogVFRGUy9TVFNPIGtlZXAgdGhlaXIgb3duIGFuY2hvciBzbyB0aGlzIGNoYW5nZXMgbm90aGluZyBhYm91dCB0aGVtLlxuICAgICAgICpcbiAgICAgICAqIFRoZSBgcmVwb3J0ZWRgIGxhdGNoIG1ha2VzIG9uZSByZXN1bXB0aW9uIHlpZWxkIG9uZSBzYW1wbGUgZXZlblxuICAgICAgICogdGhvdWdoIGV2ZXJ5IHN0ZXAgb2YgYW4gaW5saW5lIGJhdGNoIGlzIGhhbmRlZCB0aGUgc2FtZSB0cmFja2luZ1xuICAgICAgICogb2JqZWN0OiB3aGljaGV2ZXIgc3RlcCBmaXJzdCByZWFjaGVzIHVzZXIgY29kZSB0YWtlcyB0aGVcbiAgICAgICAqIG1lYXN1cmVtZW50LiBTaGFyaW5nIGl0IChyYXRoZXIgdGhhbiBwaW5uaW5nIHRoZSBiYXRjaCdzIGZpcnN0IHN0ZXApXG4gICAgICAgKiBpcyB3aGF0IGtlZXBzIHRoZSBzYW1wbGUgYWxpdmUgd2hlbiB0aGF0IGZpcnN0IHN0ZXAgbG9zZXMgaXRzIGF0b21pY1xuICAgICAgICogY3JlYXRlLWNsYWltIHRvIGEgY29uY3VycmVudCBpbnZvY2F0aW9uIHdoaWxlIGEgc2libGluZyBwcm9jZWVkcy5cbiAgICAgICAqIFRoZSBjaGVjay1hbmQtc2V0IGlzIHN5bmNocm9ub3VzLCBzbyBjb25jdXJyZW50IHNpYmxpbmdzIGNhbm5vdCBib3RoXG4gICAgICAgKiBwYXNzIGl0LlxuICAgICAgICovXG4gICAgICBjb25zdCByZXBvcnRSZXN1bWVUdHIgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIGNvbnN0IHRyYWNraW5nID0gcGFyYW1zLnJlc3VtZVRyYWNraW5nO1xuICAgICAgICBpZiAoIXRyYWNraW5nIHx8IHRyYWNraW5nLnJlcG9ydGVkKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBjb21wdXRlUmVzdW1lVHRyQXR0cmlidXRlcyh7XG4gICAgICAgICAgdHJhY2tpbmcsXG4gICAgICAgICAgYXR0ZW1wdCxcbiAgICAgICAgICBzdGVwQ2xhaW1TdGFydGVkQXRNczogc3RlcFN0YXJ0UG9zdFNlbnRBdE1zLFxuICAgICAgICAgIHN0ZXBDbGFpbUNvbXBsZXRlZEF0TXMsXG4gICAgICAgICAgc3RlcENvZGVTdGFydGVkQXRNczogRGF0ZS5ub3coKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghYXR0cmlidXRlcykgcmV0dXJuO1xuICAgICAgICB0cmFja2luZy5yZXBvcnRlZCA9IHRydWU7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gICAgICB9O1xuXG4gICAgICBsZXQgc3RlcEV4ZWN1dGlvblN0YXR1czogJ29rJyB8ICdlcnJvcicgPSAnb2snO1xuICAgICAgY29uc3Qgc3RlcEV4ZWN1dGlvblN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gYXdhaXQgdHJhY2UoJ3N0ZXAuZXhlY3V0ZScsIHt9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGNvbnRleHRTdG9yYWdlLnJ1bihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc3RlcE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgIHN0ZXBTdGFydGVkQXQ6IG5ldyBEYXRlKCtzdGVwU3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgICBhdHRlbXB0LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB3b3JrZmxvd01ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQ6IG5ldyBEYXRlKCt3b3JrZmxvd1N0YXJ0ZWRBdCksXG4gICAgICAgICAgICAgICAgdXJsOiB3b3JrZmxvd0Jhc2VVcmwsXG4gICAgICAgICAgICAgICAgZmVhdHVyZXM6IHsgZW5jcnlwdGlvbjogISFlbmNyeXB0aW9uS2V5IH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHdvcmtmbG93RGVwbG95bWVudElkOiBwYXJhbXMud29ya2Zsb3dEZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIHJvb3RSdW5JZDogcGFyYW1zLnJvb3RSdW5JZCxcbiAgICAgICAgICAgICAgb3BzLFxuICAgICAgICAgICAgICBwcmVDb21wbGV0aW9uT3BzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogaHlkcmF0ZWRJbnB1dC5jbG9zdXJlVmFycyxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgLy8gVHVyYm8gb3B0aW1pc3RpYyBzdGFydCBydW5zIHRoaXMgYm9keSBiZWZvcmUgYHJ1bl9zdGFydGVkYCBpc1xuICAgICAgICAgICAgICAvLyBkdXJhYmxlLiBFeHBvc2UgdGhlIGJhcnJpZXIgc28gYSBkaXJlY3Qgc3RlcC1ib2R5IHdvcmxkIHdyaXRlXG4gICAgICAgICAgICAgIC8vIChlLmcuIGBzZXRBdHRyaWJ1dGVzYCkgY2FuIG9yZGVyIGl0c2VsZiBhZnRlciB0aGVcbiAgICAgICAgICAgICAgLy8gcnVuIGV4aXN0cy4gVW5kZWZpbmVkIG9uIHRoZSBhd2FpdCBwYXRoIChydW4gYWxyZWFkeSBkdXJhYmxlKS5cbiAgICAgICAgICAgICAgcnVuUmVhZHlCYXJyaWVyOiBvcHRpbWlzdGljU3RhcnRcbiAgICAgICAgICAgICAgICA/IHBhcmFtcy5ydW5SZWFkeUJhcnJpZXJcbiAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgIC8vIFRoZSBsYXN0IGluc3RhbnQgYmVmb3JlIHVzZXIgY29kZTogVDcgb2YgdGhlIHJlc3VtZSB3aW5kb3cuXG4gICAgICAgICAgICAgIHJlcG9ydFJlc3VtZVR0cigpO1xuICAgICAgICAgICAgICByZXR1cm4gc3RlcEZuLmFwcGx5KHRoaXNWYWwsIGFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHN0ZXBFeGVjdXRpb25TdGF0dXMgPSAnZXJyb3InO1xuICAgICAgICB1c2VyQ29kZUVycm9yID0gZXJyO1xuICAgICAgICB1c2VyQ29kZUZhaWxlZCA9IHRydWU7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB2b2lkIHJlY29yZFN0ZXBFeGVjdXRpb25EdXJhdGlvbihcbiAgICAgICAgICBwZXJmb3JtYW5jZS5ub3coKSAtIHN0ZXBFeGVjdXRpb25TdGFydFRpbWUsXG4gICAgICAgICAgc3RlcEV4ZWN1dGlvblN0YXR1c1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhlY3V0aW9uVGltZU1zID0gRGF0ZS5ub3coKSAtIGV4ZWN1dGlvblN0YXJ0VGltZTtcblxuICAgICAgLy8gVGVhciBkb3duIGFueSBhYm9ydC1zdHJlYW0gcmVhZGVycyBvcGVuZWQgd2hpbGUgaHlkcmF0aW5nIHRoZSBzdGVwJ3NcbiAgICAgIC8vIGFyZ3VtZW50cyAoYSBzZXJpYWxpemVkIEFib3J0U2lnbmFsIG9wZW5zIGEgcmVhbC10aW1lIGFib3J0IHJlYWRlciBmb3JcbiAgICAgIC8vIHRoZSBzdGVwJ3MgZHVyYXRpb24pLiBXaXRob3V0IHRoaXMgdGhlIHJlYWRlcidzIGByZWFkKClgIHByb21pc2UgbmV2ZXJcbiAgICAgIC8vIHNldHRsZXMsIHNvIHRoZSBgb3BzYCBmbHVzaCBiZWxvdyBhbHdheXMgbG9zZXMgdGhlIDUwMG1zIHJhY2UgYW5kIHRoZVxuICAgICAgLy8gc3RlcCByZXBvcnRzIGBoYXNQZW5kaW5nT3BzYCwgZm9yY2luZyB0aGUgaW5saW5lIGxvb3AgdG8gcXVldWUgYVxuICAgICAgLy8gY29udGludWF0aW9uIGFuZCBwYXlpbmcgYSBmdWxsIHJvdW5kLXRyaXAgcGVyIHNpZ25hbC1iZWFyaW5nIHN0ZXAuXG4gICAgICAvLyBSdW5zIHVuY29uZGl0aW9uYWxseSAoc3VjY2VzcyBvciBmYWlsdXJlKSBzbyBhIHRocm93aW5nIHN0ZXAgZG9lc24ndFxuICAgICAgLy8gbGVhayB0aGUgcmVhZGVyLlxuICAgICAgY2FuY2VsQWJvcnRSZWFkZXJzKC4uLmFyZ3MsIHRoaXNWYWwsIGh5ZHJhdGVkSW5wdXQuY2xvc3VyZVZhcnMpO1xuXG4gICAgICAvLyBSZS1yYWlzZSBhIHVzZXItY29kZSBmYWlsdXJlIG5vdyB0aGF0IGNsZWFudXAgaGFzIHJ1bjsgdGhlIG91dGVyXG4gICAgICAvLyBjYXRjaCBtYXBzIGl0IHRvIHN0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcuXG4gICAgICBpZiAodXNlckNvZGVGYWlsZWQpIHtcbiAgICAgICAgdGhyb3cgdXNlckNvZGVFcnJvcjtcbiAgICAgIH1cblxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZUV4ZWN1dGlvblRpbWVNcyhleGVjdXRpb25UaW1lTXMpLFxuICAgICAgfSk7XG5cbiAgICAgIHJlc3VsdCA9IGF3YWl0IHRyYWNlKCdzdGVwLmRlaHlkcmF0ZScsIHt9LCBhc3luYyAoZGVoeWRyYXRlU3BhbikgPT4ge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCBkZWh5ZHJhdGVkID0gYXdhaXQgZGVoeWRyYXRlU3RlcFJldHVyblZhbHVlKFxuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgY29tcHJlc3Npb24sXG4gICAgICAgICAgLy8gVHVyYm8gb3B0aW1pc3RpYyBzdGFydDogYSByZXR1cm5lZCBzdHJlYW0gaXMgcGlwZWQgdG8gdGhlIHNlcnZlclxuICAgICAgICAgIC8vIGFmdGVyIHRoZSBib2R5IGJ1dCB3aXRoaW4gdGhpcyBzYW1lIG9wIGZsdXNoLCBzbyBnYXRlIGl0cyBmaXJzdFxuICAgICAgICAgIC8vIHdyaXRlIG9uIHRoZSBydW4tcmVhZHkgYmFycmllci4gVW5kZWZpbmVkIG9uIHRoZSBhd2FpdCBwYXRoLlxuICAgICAgICAgIG9wdGltaXN0aWNTdGFydCA/IHBhcmFtcy5ydW5SZWFkeUJhcnJpZXIgOiB1bmRlZmluZWRcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZHVyYXRpb25NcyA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgIGRlaHlkcmF0ZVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZVNlcmlhbGl6ZVRpbWVNcyhkdXJhdGlvbk1zKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJlc3VsdFR5cGUodHlwZW9mIGRlaHlkcmF0ZWQpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGRlaHlkcmF0ZWQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gRmx1c2ggcGVuZGluZyBvcHMgKHN0cmVhbSB3cml0ZXMsIGV0Yy4pIHdpdGggYSBzaG9ydCBpbmxpbmUgd2FpdC5cbiAgICAgIC8vIFdvcmtmbG93U2VydmVyV3JpdGFibGVTdHJlYW0gYWNrcyB3cml0ZXMgb24gYnVmZmVyIGVudHJ5XG4gICAgICAvLyAoZ3JvdXAtY29tbWl0IGJhdGNoaW5nKTsgZHVyYWJpbGl0eSBpcyBlbmZvcmNlZCBieSBpdHMgZHJhaW5cbiAgICAgIC8vIGJhcnJpZXIsIHdoaWNoIHRoZSBmbHVzaGFibGUgc3RhdGUncyBjb21wbGV0aW9uIGF3YWl0cyBhZnRlclxuICAgICAgLy8gbG9jayByZWxlYXNlLiBNb3N0IG9wcyBzZXR0bGUgd2l0aGluIH4yMDBtcyAobG9jay1yZWxlYXNlXG4gICAgICAvLyBwb2xsaW5nICsgb25lIGJhdGNoZWQgSFRUUCBmbHVzaCkuXG4gICAgICAvLyBJZiBvcHMgZG9uJ3Qgc2V0dGxlIGluIDUwMG1zIChlLmcuLCBXcml0YWJsZVN0cmVhbSBrZXB0IG9wZW5cbiAgICAgIC8vIGFjcm9zcyBzdGVwcyksIHdhaXRVbnRpbCBoYW5kbGVzIHRoZSByZXN0LlxuICAgICAgaWYgKG9wcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IG9wc1Byb21pc2UgPSBQcm9taXNlLmFsbChvcHMpO1xuICAgICAgICAvLyBUaGUgcmFjZSBiZWxvdyBzdXJmYWNlcyBmYWlsdXJlcyBpbmxpbmUgd2hlbiBvcHMgc2V0dGxlIHF1aWNrbHk7XG4gICAgICAgIC8vIGlmIHRoZSA1MDBtcyB0aW1lb3V0IHdpbnMsIHRoZSBmYWlsdXJlIGlzIG9ubHkgb2JzZXJ2ZWQgaGVyZS4gVGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIHNhZmVXYWl0VW50aWwob3BzUHJvbWlzZSwgKGVycikgPT4ge1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybignQmFja2dyb3VuZCBmbHVzaCBvZiBzdGVwIHN0cmVhbSBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBvcHNTZXR0bGVkID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICBvcHNQcm9taXNlLnRoZW4oXG4gICAgICAgICAgICAoKSA9PiB0cnVlIGFzIGNvbnN0LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICAvLyBJZ25vcmUgZXhwZWN0ZWQgY2xpZW50IGRpc2Nvbm5lY3QgZXJyb3JzIChlLmcuLCBicm93c2VyXG4gICAgICAgICAgICAgIC8vIHJlZnJlc2ggZHVyaW5nIHN0cmVhbWluZylcbiAgICAgICAgICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgICAgICAgICBlcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBlcnI/Lm5hbWUgPT09ICdSZXNwb25zZUFib3J0ZWQnO1xuICAgICAgICAgICAgICBpZiAoaXNBYm9ydEVycm9yKSByZXR1cm4gdHJ1ZSBhcyBjb25zdDtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICksXG4gICAgICAgICAgbmV3IFByb21pc2U8ZmFsc2U+KChyKSA9PiBzZXRUaW1lb3V0KCgpID0+IHIoZmFsc2UpLCA1MDApKSxcbiAgICAgICAgXSk7XG4gICAgICB9XG5cbiAgICAgIC8vIE9wdGltaXN0aWMgc3RhcnQ6IHRoZSBib2R5IHJhbiBiZWZvcmUgYHN0ZXBfc3RhcnRlZGAgd2FzIGNvbmZpcm1lZC5cbiAgICAgIC8vIFJlY29uY2lsZSBpdCBub3c6IGlmIHdlIGxvc3QgdGhlIGNyZWF0ZS1jbGFpbSAob3IgdGhlIHJ1biBpc1xuICAgICAgLy8gZ29uZS90aHJvdHRsZWQpIGRpc2NhcmQgdGhpcyByZXN1bHQgYW5kIGRvbid0IHdyaXRlIHN0ZXBfY29tcGxldGVkLlxuICAgICAgLy8gUmVjb25jaWxlIGJlZm9yZSBkcmFpbmluZyBwcmVDb21wbGV0aW9uT3BzOiBhIGRpc2NhcmRlZCByZXN1bHQgbWVhbnNcbiAgICAgIC8vIHRoZSB3aW5uaW5nIGhhbmRsZXIgb3ducyB0aGUgb3V0Y29tZSAoYW5kIHJlLWZpcmVzIGFueSBhYm9ydFxuICAgICAgLy8gaWRlbXBvdGVudGx5KSwgc28gdGhlcmUncyBubyBwb2ludCBwYXlpbmcgdGhlIGFib3J0LWNvbW1pdCBsYXRlbmN5LlxuICAgICAgaWYgKG9wdGltaXN0aWNTdGFydCkge1xuICAgICAgICBjb25zdCByZWNvbmNpbGUgPSBhd2FpdCByZWNvbmNpbGVPcHRpbWlzdGljU3RhcnQoKTtcbiAgICAgICAgaWYgKHJlY29uY2lsZSkgcmV0dXJuIHJlY29uY2lsZTtcbiAgICAgICAgLy8gQmFycmllciByZXNvbHZlZDogdGhlIHN0ZXAtc3RhcnQgUE9TVCB0aW1lc3RhbXAgaXMgbm93IGtub3duLCBzb1xuICAgICAgICAvLyBSU0ZTIGNhbiBiZSBhdHRhY2hlZCB0byB0aGUgc3RlcF9jb21wbGV0ZWQgZXZlbnQgYmVsb3cuXG4gICAgICAgIGJhY2tmaWxsT3B0aW1pc3RpY1JzZnMoKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ29tbWl0IG11c3QtYmUtZHVyYWJsZSBvcHMgKGUuZy4gYSBzdGVwLWluaXRpYXRlZCBhYm9ydCdzXG4gICAgICAvLyBob29rX3JlY2VpdmVkIGV2ZW50KSBiZWZvcmUgd3JpdGluZyBzdGVwX2NvbXBsZXRlZCwgc28gYW55IHdvcmtmbG93XG4gICAgICAvLyBjb250aW51YXRpb24gdHJpZ2dlcmVkIGJ5IHRoYXQgZXZlbnQgb2JzZXJ2ZXMgdGhlIGFib3J0IHJhdGhlciB0aGFuXG4gICAgICAvLyByYWNpbmcgaXQuIFRoZXNlIG9wcyBzd2FsbG93IHRoZWlyIG93biBlcnJvcnMsIHNvIGF3YWl0aW5nIG9ubHlcbiAgICAgIC8vIGVuZm9yY2VzIG9yZGVyaW5nICh0aGUgYC5jYXRjaCgpYCBkZWZlbmRzIHRoZSBuby1yZWplY3QgY29udHJhY3Qgb25cbiAgICAgIC8vIFN0ZXBDb250ZXh0LnByZUNvbXBsZXRpb25PcHMpLlxuICAgICAgLy9cbiAgICAgIC8vIFRyYWRlb2ZmOiBjb3JyZWN0bmVzcyByZXF1aXJlcyB0aGUgaG9vayBiZSBkdXJhYmxlIGJlZm9yZSBjb21wbGV0aW9uLFxuICAgICAgLy8gc28sIHVubGlrZSB0aGUgYmFja2dyb3VuZCBgb3BzYCBmbHVzaCBhYm92ZSwgdGhpcyBjYW5ub3QgYmUgY2FwcGVkXG4gICAgICAvLyB3aXRoIGEgcmVzb2x2ZS1vbi10aW1lb3V0IHJhY2UuIEEgc2xvdyByZXN1bWUgdGhlcmVmb3JlIGFkZHMgaXRzXG4gICAgICAvLyBsYXRlbmN5IHRvIGEgc3RlcCB0aGF0IGFib3J0cyBhIGNvbnRyb2xsZXIsIGFuZCBhIHRydWUgaGFuZyBob2xkc1xuICAgICAgLy8gY29tcGxldGlvbiB1bnRpbCB0aGUgcGxhdGZvcm0vcXVldWUgZXhlY3V0aW9uIHRpbWVvdXQgZmlyZXM7IHRoZSBxdWV1ZVxuICAgICAgLy8gdGhlbiByZWRlbGl2ZXJzIGFuZCB0aGUgc3RlcCByZXRyaWVzLCByZS1maXJpbmcgdGhlIGFib3J0IGlkZW1wb3RlbnRseS5cbiAgICAgIGlmIChwcmVDb21wbGV0aW9uT3BzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJlQ29tcGxldGlvbk9wcykuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgLy8gT3B0aW1pc3RpYyBzdGFydDogdGhlIGJvZHkgdGhyZXcgYmVmb3JlIGBzdGVwX3N0YXJ0ZWRgIHdhcyBjb25maXJtZWQuXG4gICAgICAvLyBSZWNvbmNpbGUgZmlyc3Q6IGlmIHdlIGxvc3QgdGhlIGNyZWF0ZS1jbGFpbSAob3IgdGhlIHJ1biBpc1xuICAgICAgLy8gZ29uZS90aHJvdHRsZWQpIHRoZSBib2R5IGVycm9yIGlzIG1vb3Q7IGRpc2NhcmQgaXQgYW5kIGRvbid0IHdyaXRlIGFcbiAgICAgIC8vIHRlcm1pbmFsIGV2ZW50ICh0aGUgd2lubmluZyBoYW5kbGVyIG93bnMgdGhlIG91dGNvbWUpLiBSZWNvbmNpbGVcbiAgICAgIC8vIGJlZm9yZSBkcmFpbmluZyBwcmVDb21wbGV0aW9uT3BzIGZvciB0aGUgc2FtZSByZWFzb24gYXMgdGhlIHN1Y2Nlc3NcbiAgICAgIC8vIHBhdGg6IGEgZGlzY2FyZGVkIG91dGNvbWUgZG9lc24ndCBuZWVkIHRoZSBhYm9ydCBjb21taXR0ZWQgaGVyZS5cbiAgICAgIGlmIChvcHRpbWlzdGljU3RhcnQpIHtcbiAgICAgICAgY29uc3QgcmVjb25jaWxlID0gYXdhaXQgcmVjb25jaWxlT3B0aW1pc3RpY1N0YXJ0KCk7XG4gICAgICAgIGlmIChyZWNvbmNpbGUpIHJldHVybiByZWNvbmNpbGU7XG4gICAgICAgIC8vIEJhcnJpZXIgcmVzb2x2ZWQ6IGF0dGFjaCBSU0ZTIHRvIHRoZSBzdGVwX2ZhaWxlZCBldmVudChzKSBiZWxvdy5cbiAgICAgICAgYmFja2ZpbGxPcHRpbWlzdGljUnNmcygpO1xuICAgICAgfVxuXG4gICAgICAvLyBPcmRlciBhbnkgbXVzdC1iZS1kdXJhYmxlIG9wcyAoZS5nLiBhIHN0ZXAtaW5pdGlhdGVkIGFib3J0J3NcbiAgICAgIC8vIGhvb2tfcmVjZWl2ZWQgZXZlbnQpIGFoZWFkIG9mIHN0ZXBfZmFpbGVkIHRvbzogYSBzdGVwIHRoYXQgYWJvcnRzIGFuZFxuICAgICAgLy8gdGhlbiB0aHJvd3MgbXVzdCBzdGlsbCBoYXZlIHRoZSBhYm9ydCByZWNvcmRlZCBiZWZvcmUgdGhlIGZhaWx1cmVcbiAgICAgIC8vIGNvbnRpbnVhdGlvbiBvYnNlcnZlcyBpdC4gU2FtZSBsYXRlbmN5IHRyYWRlb2ZmIGFuZCBuby1yZWplY3QgY29udHJhY3RcbiAgICAgIC8vIGFzIHRoZSBzdWNjZXNzIHBhdGggYWJvdmUuIFNlZSBTdGVwQ29udGV4dC5wcmVDb21wbGV0aW9uT3BzLlxuICAgICAgaWYgKHByZUNvbXBsZXRpb25PcHMubGVuZ3RoID4gMCkge1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcmVDb21wbGV0aW9uT3BzKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVmZmVjdGl2ZUVyciA9IHByb21vdGVBYm9ydEVycm9yVG9GYXRhbChlcnIpO1xuXG4gICAgICBjb25zdCBub3JtYWxpemVkRXJyb3IgPSBhd2FpdCBub3JtYWxpemVVbmtub3duRXJyb3IoZWZmZWN0aXZlRXJyKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRTdGFjayA9XG4gICAgICAgIG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVmZmVjdGl2ZUVycikgfHwgJyc7XG5cbiAgICAgIGlmIChlZmZlY3RpdmVFcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlZmZlY3RpdmVFcnIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpc0ZhdGFsID0gRmF0YWxFcnJvci5pcyhlZmZlY3RpdmVFcnIpO1xuXG4gICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBFcnJvck5hbWUoZ2V0RXJyb3JOYW1lKGVmZmVjdGl2ZUVycikpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEVycm9yTWVzc2FnZShub3JtYWxpemVkRXJyb3IubWVzc2FnZSksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclR5cGUoZ2V0RXJyb3JOYW1lKGVmZmVjdGl2ZUVycikpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JDYXRlZ29yeShcbiAgICAgICAgICBpc0ZhdGFsXG4gICAgICAgICAgICA/ICdmYXRhbCdcbiAgICAgICAgICAgIDogUmV0cnlhYmxlRXJyb3IuaXMoZWZmZWN0aXZlRXJyKVxuICAgICAgICAgICAgICA/ICdyZXRyeWFibGUnXG4gICAgICAgICAgICAgIDogJ3RyYW5zaWVudCdcbiAgICAgICAgKSxcbiAgICAgICAgLi4uQXR0cmlidXRlLkVycm9yUmV0cnlhYmxlKCFpc0ZhdGFsKSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgc3RlcExvZ2dlci5pbmZvKCdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIHN0ZXAnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAnZ29uZScgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRmF0YWwpIHtcbiAgICAgICAgc3RlcExvZ2dlci5lcnJvcihcbiAgICAgICAgICAnRW5jb3VudGVyZWQgRmF0YWxFcnJvciB3aGlsZSBleGVjdXRpbmcgc3RlcCwgYnViYmxpbmcgdXAgdG8gcGFyZW50IHdvcmtmbG93JyxcbiAgICAgICAgICB7IHdvcmtmbG93UnVuSWQsIHN0ZXBOYW1lLCBlcnJvclN0YWNrOiBub3JtYWxpemVkU3RhY2sgfVxuICAgICAgICApO1xuICAgICAgICAvLyBBcHBseSB0aGUgbm9ybWFsaXplZCBzdGFjayB0byB0aGUgdGhyb3duIHZhbHVlIHNvIHRoZSBzZXJpYWxpemVkXG4gICAgICAgIC8vIGVycm9yIHByZXNlcnZlcyBpdCBmb3IgY29uc3VtZXJzLiBgdHlwZXMuaXNOYXRpdmVFcnJvcigpYCB3b3Jrc1xuICAgICAgICAvLyBhY3Jvc3MgVk0gcmVhbG1zIChhIHdvcmtmbG93LXRocm93biBlcnJvciBpcyBhbiBpbnN0YW5jZSBvZiB0aGVcbiAgICAgICAgLy8gVk0ncyBFcnJvciBjbGFzcywgbm90IHRoZSBob3N0J3MpLlxuICAgICAgICBpZiAodHlwZXMuaXNOYXRpdmVFcnJvcihlZmZlY3RpdmVFcnIpICYmIG5vcm1hbGl6ZWRTdGFjaykge1xuICAgICAgICAgIChlZmZlY3RpdmVFcnIgYXMgRXJyb3IpLnN0YWNrID0gbm9ybWFsaXplZFN0YWNrO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgY3JlYXRlRXZlbnQoe1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICAgIGVmZmVjdGl2ZUVycixcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKSxcbiAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIC4uLmxhdGVuY3lFdmVudERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogc3RlcEZhaWxFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgfVxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBGYXRhbEVycm9yKHRydWUpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2ZhaWxlZCcgfTtcbiAgICAgIH1cblxuICAgICAgLy8gTm9uLWZhdGFsIGVycm9yOiBjaGVjayBpZiByZXRyaWVzIHJlbWFpbmluZ1xuICAgICAgY29uc3QgY3VycmVudEF0dGVtcHQgPSBzdGVwLmF0dGVtcHQ7XG5cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEF0dGVtcHQoY3VycmVudEF0dGVtcHQpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcE1heFJldHJpZXMobWF4UmV0cmllcyksXG4gICAgICB9KTtcblxuICAgICAgaWYgKGN1cnJlbnRBdHRlbXB0ID49IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgIC8vIE1heCByZXRyaWVzIHJlYWNoZWRcbiAgICAgICAgY29uc3QgcmV0cnlDb3VudCA9IHN0ZXAuYXR0ZW1wdCAtIDE7XG4gICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgJ01heCByZXRyaWVzIHJlYWNoZWQsIGJ1YmJsaW5nIGVycm9yIHRvIHBhcmVudCB3b3JrZmxvdycsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgYXR0ZW1wdDogc3RlcC5hdHRlbXB0LFxuICAgICAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgICAgICAgIGVycm9yU3RhY2s6IG5vcm1hbGl6ZWRTdGFjayxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBTdGVwIFwiJHtzdGVwTmFtZX1cIiBmYWlsZWQgYWZ0ZXIgJHttYXhSZXRyaWVzfSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIG1heFJldHJpZXMpfTogJHtub3JtYWxpemVkRXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAvLyBXcmFwIHRoZSBvcmlnaW5hbCB0aHJvd24gdmFsdWUgYXMgYGNhdXNlYCBvbiBhIGZyZXNoIEZhdGFsRXJyb3JcbiAgICAgICAgLy8gc28gdGhlIHdyYXBwaW5nIG1lc3NhZ2UgKyByZXRyeS1jb3VudCBmcmFtaW5nIGlzIHRoZSB1c2VyLWZhY2luZ1xuICAgICAgICAvLyBlcnJvciB3aGlsZSB0aGUgb3JpZ2luYWwgZmFpbHVyZSByZW1haW5zIHJlY292ZXJhYmxlIGZyb21cbiAgICAgICAgLy8gYGVyci5jYXVzZWAgYWZ0ZXIgaHlkcmF0aW9uLlxuICAgICAgICBjb25zdCB3cmFwcGVkRXJyb3IgPSBuZXcgRmF0YWxFcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGVycjtcbiAgICAgICAgaWYgKG5vcm1hbGl6ZWRTdGFjaykgd3JhcHBlZEVycm9yLnN0YWNrID0gbm9ybWFsaXplZFN0YWNrO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGNyZWF0ZUV2ZW50KHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICB3cmFwcGVkRXJyb3IsXG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCksXG4gICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAuLi5sYXRlbmN5RXZlbnREYXRhLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoc3RlcEZhaWxFcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhzdGVwRmFpbEVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc2tpcHBlZCcgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgc3RlcEZhaWxFcnI7XG4gICAgICAgIH1cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAnZmFpbGVkJyB9O1xuICAgICAgfVxuXG4gICAgICAvLyBSZXRyaWVzIHJlbWFpbmluZ1xuICAgICAgaWYgKFJldHJ5YWJsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgc3RlcExvZ2dlci5pbmZvKCdFbmNvdW50ZXJlZCBSZXRyeWFibGVFcnJvciwgc3RlcCB3aWxsIGJlIHJldHJpZWQnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICBhdHRlbXB0OiBjdXJyZW50QXR0ZW1wdCxcbiAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGVwTG9nZ2VyLmluZm8oJ0VuY291bnRlcmVkIEVycm9yLCBzdGVwIHdpbGwgYmUgcmV0cmllZCcsIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgIGVycm9yU3RhY2s6IG5vcm1hbGl6ZWRTdGFjayxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFwcGx5IHRoZSBub3JtYWxpemVkIHN0YWNrIHRvIHRoZSB0aHJvd24gdmFsdWUgc28gaXQgc3Vydml2ZXNcbiAgICAgIC8vIHNlcmlhbGl6YXRpb24uIFNlZSB0aGUgRmF0YWxFcnJvciBzaXRlIGFib3ZlIGZvciB3aHkgd2UgdXNlXG4gICAgICAvLyBgdHlwZXMuaXNOYXRpdmVFcnJvcmAgaW5zdGVhZCBvZiBgZXJyIGluc3RhbmNlb2YgRXJyb3JgLlxuICAgICAgaWYgKHR5cGVzLmlzTmF0aXZlRXJyb3IoZXJyKSAmJiBub3JtYWxpemVkU3RhY2spIHtcbiAgICAgICAgKGVyciBhcyBFcnJvcikuc3RhY2sgPSBub3JtYWxpemVkU3RhY2s7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBjcmVhdGVFdmVudCh7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9yZXRyeWluZycsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCksXG4gICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIC4uLihSZXRyeWFibGVFcnJvci5pcyhlcnIpICYmIHsgcmV0cnlBZnRlcjogZXJyLnJldHJ5QWZ0ZXIgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChzdGVwUmV0cnlFcnIpIHtcbiAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoc3RlcFJldHJ5RXJyKSkge1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICdUcmllZCByZXRyeWluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBzdGVwUmV0cnlFcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdza2lwcGVkJyB9O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IHN0ZXBSZXRyeUVycjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBNYXRoLm1heChcbiAgICAgICAgMSxcbiAgICAgICAgUmV0cnlhYmxlRXJyb3IuaXMoZXJyKVxuICAgICAgICAgID8gTWF0aC5jZWlsKCgrZXJyLnJldHJ5QWZ0ZXIuZ2V0VGltZSgpIC0gRGF0ZS5ub3coKSkgLyAxMDAwKVxuICAgICAgICAgIDogMVxuICAgICAgKTtcblxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlUaW1lb3V0U2Vjb25kcyh0aW1lb3V0U2Vjb25kcyksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlXaWxsUmV0cnkodHJ1ZSksXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHsgdHlwZTogJ3JldHJ5JywgdGltZW91dFNlY29uZHMgfTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgc3RlcF9jb21wbGV0ZWQgZXZlbnQgb3V0c2lkZSB0aGUgc3RlcCBleGVjdXRpb24gZmFpbHVyZSBwYXRoOlxuICAgIC8vIHBlcnNpc3RlbmNlIGZhaWx1cmVzIGFyZSBpbmZyYXN0cnVjdHVyZSBlcnJvcnMgYW5kIHNob3VsZCByZWRlbGl2ZXIgdGhlXG4gICAgLy8gcXVldWUgbWVzc2FnZSwgbm90IGJlY29tZSB1c2VyIHN0ZXBfcmV0cnlpbmcvc3RlcF9mYWlsZWQgZXZlbnRzLlxuICAgIGxldCBjb21wbGV0ZWRSZXN1bHQ6IEV2ZW50UmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICBjb21wbGV0ZWRSZXN1bHQgPSBhd2FpdCBjcmVhdGVFdmVudChcbiAgICAgICAge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY29tcGxldGVkJyxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICByZXN1bHQ6IHJlc3VsdCBhcyBVaW50OEFycmF5LFxuICAgICAgICAgICAgLi4ubGF0ZW5jeUV2ZW50RGF0YSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBwYXJhbXMuaW5saW5lRGVsdGFTaW5jZUN1cnNvciAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyB7IHNpbmNlQ3Vyc29yOiBwYXJhbXMuaW5saW5lRGVsdGFTaW5jZUN1cnNvciB9XG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAnVHJpZWQgY29tcGxldGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3NraXBwZWQnIH07XG4gICAgICB9XG4gICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgc3RlcExvZ2dlci5pbmZvKCdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIHN0ZXAnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyB0eXBlOiAnZ29uZScgfTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG5cbiAgICBjb25zdCBpbmxpbmVEZWx0YSA9IGV4dHJhY3RJbmxpbmVEZWx0YShcbiAgICAgIGNvbXBsZXRlZFJlc3VsdCxcbiAgICAgIHBhcmFtcy5pbmxpbmVEZWx0YVNpbmNlQ3Vyc29yICE9PSB1bmRlZmluZWRcbiAgICApO1xuXG4gICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnY29tcGxldGVkJyksXG4gICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJlc3VsdFR5cGUodHlwZW9mIHJlc3VsdCksXG4gICAgfSk7XG5cbiAgICBpZiAob3BzLmxlbmd0aCA+IDApIHtcbiAgICAgIHN0ZXBMb2dnZXIuZGVidWcoJ1N0ZXAgaGFzIHBlbmRpbmcgb3BzJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgb3BzQ291bnQ6IG9wcy5sZW5ndGgsXG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gaGFzUGVuZGluZ09wcyBzaWduYWxzIHRoZSBjb21iaW5lZCBoYW5kbGVyIHRvIGJyZWFrIHRoZSBsb29wXG4gICAgLy8gYW5kIHF1ZXVlIGEgY29udGludWF0aW9uIHNvIHdhaXRVbnRpbCBjYW4gZmx1c2ggdGhlbS5cbiAgICByZXR1cm4geyB0eXBlOiAnY29tcGxldGVkJywgaGFzUGVuZGluZ09wczogIW9wc1NldHRsZWQsIGlubGluZURlbHRhIH07XG4gIH0pO1xufVxuIl19