@workflow/core 5.0.0-beta.36 → 5.0.0-beta.37

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 (112) hide show
  1. package/dist/capabilities.d.ts +6 -0
  2. package/dist/capabilities.d.ts.map +1 -1
  3. package/dist/capabilities.js +13 -1
  4. package/dist/encryption.d.ts +15 -2
  5. package/dist/encryption.d.ts.map +1 -1
  6. package/dist/encryption.js +28 -7
  7. package/dist/flushable-stream.d.ts +26 -0
  8. package/dist/flushable-stream.d.ts.map +1 -1
  9. package/dist/flushable-stream.js +63 -187
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/log-format.js +3 -3
  14. package/dist/private.d.ts +76 -33
  15. package/dist/private.d.ts.map +1 -1
  16. package/dist/private.js +149 -22
  17. package/dist/replay-payload-cache.d.ts +3 -2
  18. package/dist/replay-payload-cache.d.ts.map +1 -1
  19. package/dist/replay-payload-cache.js +8 -2
  20. package/dist/runtime/count-step-started-events.d.ts +52 -0
  21. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  22. package/dist/runtime/count-step-started-events.js +72 -0
  23. package/dist/runtime/helpers.d.ts +41 -12
  24. package/dist/runtime/helpers.d.ts.map +1 -1
  25. package/dist/runtime/helpers.js +75 -22
  26. package/dist/runtime/resume-hook.d.ts +2 -2
  27. package/dist/runtime/resume-hook.d.ts.map +1 -1
  28. package/dist/runtime/resume-hook.js +174 -55
  29. package/dist/runtime/run.d.ts.map +1 -1
  30. package/dist/runtime/run.js +3 -3
  31. package/dist/runtime/runs.d.ts.map +1 -1
  32. package/dist/runtime/runs.js +5 -3
  33. package/dist/runtime/start.d.ts.map +1 -1
  34. package/dist/runtime/start.js +65 -18
  35. package/dist/runtime/step-executor.d.ts +9 -8
  36. package/dist/runtime/step-executor.d.ts.map +1 -1
  37. package/dist/runtime/step-executor.js +17 -17
  38. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  39. package/dist/runtime/suspension-handler.js +2 -3
  40. package/dist/runtime/world.d.ts +2 -7
  41. package/dist/runtime/world.d.ts.map +1 -1
  42. package/dist/runtime/world.js +3 -10
  43. package/dist/runtime.d.ts +1 -1
  44. package/dist/runtime.d.ts.map +1 -1
  45. package/dist/runtime.js +74 -122
  46. package/dist/sealed-box.d.ts +167 -0
  47. package/dist/sealed-box.d.ts.map +1 -0
  48. package/dist/sealed-box.js +571 -0
  49. package/dist/serialization/client.d.ts +3 -3
  50. package/dist/serialization/client.d.ts.map +1 -1
  51. package/dist/serialization/client.js +1 -1
  52. package/dist/serialization/codec.d.ts +6 -4
  53. package/dist/serialization/codec.d.ts.map +1 -1
  54. package/dist/serialization/codec.js +1 -1
  55. package/dist/serialization/encryption.d.ts +118 -17
  56. package/dist/serialization/encryption.d.ts.map +1 -1
  57. package/dist/serialization/encryption.js +131 -15
  58. package/dist/serialization/step.d.ts +4 -4
  59. package/dist/serialization/step.d.ts.map +1 -1
  60. package/dist/serialization/step.js +2 -2
  61. package/dist/serialization/types.d.ts +20 -0
  62. package/dist/serialization/types.d.ts.map +1 -1
  63. package/dist/serialization/types.js +11 -1
  64. package/dist/serialization-format.d.ts +44 -4
  65. package/dist/serialization-format.d.ts.map +1 -1
  66. package/dist/serialization-format.js +66 -9
  67. package/dist/serialization.d.ts +21 -21
  68. package/dist/serialization.d.ts.map +1 -1
  69. package/dist/serialization.js +496 -174
  70. package/dist/set-attributes.d.ts +2 -7
  71. package/dist/set-attributes.d.ts.map +1 -1
  72. package/dist/set-attributes.js +1 -6
  73. package/dist/step/context-storage.d.ts +2 -2
  74. package/dist/step/context-storage.d.ts.map +1 -1
  75. package/dist/step/context-storage.js +2 -2
  76. package/dist/step/writable-stream.d.ts.map +1 -1
  77. package/dist/step/writable-stream.js +14 -3
  78. package/dist/step.d.ts.map +1 -1
  79. package/dist/step.js +79 -8
  80. package/dist/symbols.d.ts +23 -10
  81. package/dist/symbols.d.ts.map +1 -1
  82. package/dist/symbols.js +24 -11
  83. package/dist/telemetry/semantic-conventions.d.ts +4 -4
  84. package/dist/telemetry/semantic-conventions.js +2 -2
  85. package/dist/version.d.ts +1 -1
  86. package/dist/version.js +2 -2
  87. package/dist/vm/index.d.ts.map +1 -1
  88. package/dist/vm/index.js +76 -9
  89. package/dist/workflow/abort-controller.d.ts +1 -1
  90. package/dist/workflow/abort-controller.d.ts.map +1 -1
  91. package/dist/workflow/abort-controller.js +36 -2
  92. package/dist/workflow/hook.d.ts.map +1 -1
  93. package/dist/workflow/hook.js +64 -24
  94. package/dist/workflow/index.d.ts +1 -1
  95. package/dist/workflow/index.d.ts.map +1 -1
  96. package/dist/workflow/index.js +2 -2
  97. package/dist/workflow/set-attributes.d.ts +0 -9
  98. package/dist/workflow/set-attributes.d.ts.map +1 -1
  99. package/dist/workflow/set-attributes.js +1 -6
  100. package/dist/workflow/sleep.d.ts.map +1 -1
  101. package/dist/workflow/sleep.js +21 -9
  102. package/dist/workflow.d.ts +2 -2
  103. package/dist/workflow.d.ts.map +1 -1
  104. package/dist/workflow.js +22 -83
  105. package/docs/api-reference/set-attributes.mdx +0 -4
  106. package/docs/how-it-works/cancellation.mdx +2 -2
  107. package/docs/how-it-works/code-transform.mdx +19 -15
  108. package/docs/how-it-works/framework-integrations.mdx +95 -341
  109. package/package.json +6 -6
  110. package/dist/runtime/step-handler.d.ts +0 -2
  111. package/dist/runtime/step-handler.d.ts.map +0 -1
  112. package/dist/runtime/step-handler.js +0 -839
@@ -1,839 +0,0 @@
1
- import { EntityConflictError, FatalError, RetryableError, RunExpiredError, StepNotRegisteredError, ThrottleError, TooEarlyError, WorkflowRuntimeError, WorkflowWorldError, } from '@workflow/errors';
2
- import { createWorkflowBaseUrl, formatStepName, pluralize, stepDisplayName, } from '@workflow/utils';
3
- import { getQueueTopicPrefix, resolveQueueNamespace, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, StepInvokePayloadSchema, } from '@workflow/world';
4
- import { describeError } from '../describe-error.js';
5
- import { runtimeLogger, stepLogger } from '../logger.js';
6
- import { getStepFunction } from '../private.js';
7
- import { cancelAbortReaders, dehydrateStepError, dehydrateStepReturnValue, hydrateStepArguments, hydrateStepError, } from '../serialization.js';
8
- import { contextStorage } from '../step/context-storage.js';
9
- import * as Attribute from '../telemetry/semantic-conventions.js';
10
- import { buildInvocationSpanLinks, getNextTraceCarrier, getSpanKind, getWorkflowTraceMode, isUsableTraceCarrier, trace, withTraceContext, } from '../telemetry.js';
11
- import { getErrorName, getErrorStack, normalizeUnknownError, promoteAbortErrorToFatal, } from '../types.js';
12
- import { getMaxQueueDeliveries } from './constants.js';
13
- import { getPortLazy } from './get-port-lazy.js';
14
- import { getQueueOverhead, getWorkflowQueueName, handleHealthCheckMessage, memoizeEncryptionKey, parseHealthCheckPayload, queueMessage, withHealthCheck, } from './helpers.js';
15
- import { safeWaitUntil } from './wait-until.js';
16
- import { getWorld, getWorldHandlers } from './world.js';
17
- const DEFAULT_STEP_MAX_RETRIES = 3;
18
- function createStepHandler(namespace) {
19
- const resolvedNamespace = resolveQueueNamespace(namespace);
20
- const stepPrefix = getQueueTopicPrefix('step', resolvedNamespace);
21
- return (worldHandlers) => worldHandlers.createQueueHandler(stepPrefix, async (message_, metadata) => {
22
- // Check if this is a health check message
23
- // NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
24
- // They only write a simple status response to a stream and do not expose sensitive data.
25
- // The stream name includes a unique correlationId that must be known by the caller.
26
- const healthCheck = parseHealthCheckPayload(message_);
27
- if (healthCheck) {
28
- await handleHealthCheckMessage(healthCheck, 'step', worldHandlers.specVersion);
29
- return;
30
- }
31
- const { workflowName, workflowRunId, workflowStartedAt, stepId, traceCarrier: incomingTraceCarrier, requestedAt, } = StepInvokePayloadSchema.parse(message_);
32
- const { requestId } = metadata;
33
- // serializeTraceCarrier() returns `{}` when no OTEL SDK is registered
34
- // or no span is active — treat an empty carrier the same as an absent
35
- // one so linked mode falls back to a fresh origin instead of
36
- // forwarding a useless `{}` forever.
37
- const traceContext = isUsableTraceCarrier(incomingTraceCarrier)
38
- ? incomingTraceCarrier
39
- : undefined;
40
- // --- Trace correlation mode ---
41
- // 'linked' (default): the STEP span below starts a NEW root trace with
42
- // span links to the delivery context and the run-origin context from
43
- // the message's trace carrier. 'continuous': legacy behavior — the
44
- // restored run-origin context parents this invocation's spans.
45
- const traceMode = getWorkflowTraceMode();
46
- // Trace carrier to attach to messages this invocation enqueues — see
47
- // getNextTraceCarrier for the linked/continuous semantics.
48
- const nextTraceCarrier = () => getNextTraceCarrier(traceMode, traceContext);
49
- // --- Max delivery check ---
50
- // Enforce max delivery limit before any infrastructure calls.
51
- // This prevents runaway steps from consuming infinite queue deliveries.
52
- // At this point, we want to do the minimal amount of work (no fetching
53
- // of the step details, etc. We simply attempt to mark the step as failed
54
- // and enqueue the workflow once, and if either of those fails, the message
55
- // is still consumed but with adequate logging that an error occurred.
56
- // Scoped logger for this step invocation — attaches run/step context to
57
- // every log line below so callers don't repeat it.
58
- const stepNameFromQueue = metadata.queueName.slice(stepPrefix.length);
59
- const stepRuntimeLogger = runtimeLogger.forRun(workflowRunId, workflowName, { stepId, stepName: stepNameFromQueue });
60
- const maxQueueDeliveries = getMaxQueueDeliveries();
61
- if (metadata.attempt > maxQueueDeliveries) {
62
- stepRuntimeLogger.error(`Step handler exceeded max deliveries (${metadata.attempt}/${maxQueueDeliveries})`, {
63
- attempt: metadata.attempt,
64
- });
65
- try {
66
- const world = await getWorld();
67
- const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
68
- const err = new FatalError(`Step exceeded maximum queue deliveries (${metadata.attempt}/${maxQueueDeliveries})`);
69
- await world.events.create(workflowRunId, {
70
- eventType: 'step_failed',
71
- specVersion: SPEC_VERSION_CURRENT,
72
- correlationId: stepId,
73
- eventData: {
74
- stepName: stepNameFromQueue,
75
- error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
76
- },
77
- }, { requestId });
78
- // Re-queue the workflow to handle the failed step
79
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
80
- runId: workflowRunId,
81
- traceCarrier: await nextTraceCarrier(),
82
- requestedAt: new Date(),
83
- });
84
- }
85
- catch (err) {
86
- if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
87
- return;
88
- }
89
- // Can't even mark the step as failed. Consume the message to stop
90
- // further retries. The run will remain in its current state.
91
- stepRuntimeLogger.error(`Failed to mark step as failed after ${metadata.attempt} delivery attempts. ` +
92
- `A persistent error is preventing the step from being terminated. ` +
93
- `The run will remain in its current state until manually resolved. ` +
94
- `This is most likely due to a persistent outage of the workflow backend ` +
95
- `or a bug in the workflow runtime and should be reported to the Workflow team.`, {
96
- attempt: metadata.attempt,
97
- errorName: err instanceof Error ? err.name : 'UnknownError',
98
- errorMessage: err instanceof Error ? err.message : String(err),
99
- errorStack: err instanceof Error ? err.stack : undefined,
100
- });
101
- }
102
- return;
103
- }
104
- // In linked mode the only span link is to the run-origin context; the
105
- // step.execute span stays a child of the local delivery (flow-route)
106
- // context. In continuous mode the link points at the delivery context.
107
- const spanLinks = await buildInvocationSpanLinks(traceMode, traceContext);
108
- // Execute step within the propagated trace context (continuous mode
109
- // only — in linked mode the run-origin is NOT restored as the parent,
110
- // so withTraceContext is a passthrough and the step.execute span stays
111
- // a child of the local delivery context, linked to the run origin).
112
- const parentTraceCarrier = traceMode === 'continuous' ? traceContext : undefined;
113
- return await withTraceContext(parentTraceCarrier, async () => {
114
- // Extract the step name from the topic name
115
- const stepName = metadata.queueName.slice(stepPrefix.length);
116
- const world = await getWorld();
117
- const isVercel = process.env.VERCEL_URL !== undefined;
118
- // Memoized accessor for the per-run AES-256 encryption key. The first
119
- // caller (typically `hydrateStepArguments` for input deserialization,
120
- // or one of the early-return dehydrateStepError paths if step_started
121
- // fails) triggers the actual fetch / HKDF derivation; subsequent
122
- // callers await the cached promise. Steps that fail before any
123
- // encryption-aware work happens (e.g. an immediate step_started
124
- // conflict) skip the fetch entirely.
125
- const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
126
- // Resolve local async values concurrently before entering the trace span
127
- const [port, spanKind] = await Promise.all([
128
- isVercel ? undefined : getPortLazy(),
129
- getSpanKind('CONSUMER'),
130
- ]);
131
- // TODO: resolve the workflow base URL through the World interface.
132
- // This fallback cannot see local/Postgres baseUrl overrides or custom-world routing.
133
- const workflowBaseUrl = createWorkflowBaseUrl(isVercel
134
- ? `https://${process.env.VERCEL_URL}`
135
- : `http://localhost:${port ?? 3000}`);
136
- return trace(`step.execute ${stepDisplayName(stepName)}`, { kind: spanKind, links: spanLinks }, async (span) => {
137
- span?.setAttributes({
138
- ...Attribute.StepName(stepName),
139
- ...Attribute.StepAttempt(metadata.attempt),
140
- // Standard OTEL messaging conventions
141
- ...Attribute.MessagingSystem('vercel-queue'),
142
- ...Attribute.MessagingDestinationName(metadata.queueName),
143
- ...Attribute.MessagingMessageId(metadata.messageId),
144
- ...Attribute.MessagingOperationType('process'),
145
- ...getQueueOverhead({ requestedAt }),
146
- });
147
- // Note: Step function validation happens after step_started so we can
148
- // properly fail the step (not the run) if the function is not registered.
149
- // This allows the workflow to handle the step failure gracefully.
150
- const stepFn = getStepFunction(stepName);
151
- span?.setAttributes({
152
- ...Attribute.WorkflowName(workflowName),
153
- ...Attribute.WorkflowRunId(workflowRunId),
154
- ...Attribute.StepId(stepId),
155
- ...Attribute.StepTracePropagated(!!traceContext),
156
- ...Attribute.WorkflowTraceMode(traceMode),
157
- });
158
- // step_started validates state and returns the step entity, so no separate
159
- // world.steps.get() call is needed. The server checks:
160
- // - Step not in terminal state (returns 409)
161
- // - retryAfter timestamp reached (returns 425 with Retry-After header)
162
- // - Workflow still active (returns 410 if completed)
163
- let step;
164
- // Gate payload compression on the step entity's specVersion
165
- // (stamped by the same-deployment orchestrator that created the
166
- // step, so spec >= 5 implies every reader of this run's payloads
167
- // understands the 'gzip' format). Returns false on the early
168
- // failure paths where step_started didn't return an entity.
169
- const compressionForStep = () => (step?.specVersion ?? 0) >=
170
- SPEC_VERSION_SUPPORTS_COMPRESSION;
171
- try {
172
- const startResult = await world.events.create(workflowRunId, {
173
- eventType: 'step_started',
174
- specVersion: SPEC_VERSION_CURRENT,
175
- correlationId: stepId,
176
- eventData: { stepName },
177
- }, { requestId });
178
- if (!startResult.step) {
179
- throw new WorkflowRuntimeError(`step_started event for "${stepId}" did not return step entity`);
180
- }
181
- step = startResult.step;
182
- }
183
- catch (err) {
184
- if (ThrottleError.is(err)) {
185
- const retryRetryAfter = Math.max(1, typeof err.retryAfter === 'number' ? err.retryAfter : 1);
186
- stepRuntimeLogger.info('Throttled again on retry, deferring to queue', {
187
- retryAfterSeconds: retryRetryAfter,
188
- });
189
- return { timeoutSeconds: retryRetryAfter };
190
- }
191
- if (RunExpiredError.is(err)) {
192
- // Expected when a run is cancelled while a step is in-flight.
193
- stepRuntimeLogger.info('Workflow run has already completed, skipping step', { errorName: err.name, errorMessage: err.message });
194
- return;
195
- }
196
- if (EntityConflictError.is(err)) {
197
- // Step already in a terminal state — another worker finished
198
- // it or it was retried to completion. Re-enqueue the parent
199
- // workflow so it can observe the outcome.
200
- stepRuntimeLogger.debug('Step in terminal state, re-enqueuing workflow', {
201
- errorName: err.name,
202
- errorMessage: err.message,
203
- });
204
- span?.setAttributes({
205
- ...Attribute.StepSkipped(true),
206
- ...Attribute.StepSkipReason('completed'),
207
- });
208
- span?.addEvent?.('step.skipped', {
209
- 'skip.reason': 'terminal_state',
210
- 'step.name': stepName,
211
- 'step.id': stepId,
212
- });
213
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
214
- runId: workflowRunId,
215
- traceCarrier: await nextTraceCarrier(),
216
- requestedAt: new Date(),
217
- });
218
- return;
219
- }
220
- // Too early: retryAfter timestamp not reached yet
221
- // Return timeout to queue so it retries later
222
- if (TooEarlyError.is(err)) {
223
- const timeoutSeconds = Math.max(1, err.retryAfter ?? 1);
224
- span?.setAttributes({
225
- ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
226
- });
227
- // Add span event for delayed retry
228
- span?.addEvent?.('step.delayed', {
229
- 'delay.reason': 'retry_after_not_reached',
230
- 'delay.timeout_seconds': timeoutSeconds,
231
- });
232
- stepRuntimeLogger.debug('Step retryAfter timestamp not yet reached', {
233
- retryAfterSeconds: err.retryAfter,
234
- timeoutSeconds,
235
- });
236
- return { timeoutSeconds };
237
- }
238
- // Re-throw other errors
239
- throw err;
240
- }
241
- stepRuntimeLogger.debug('Step execution details', {
242
- status: step.status,
243
- attempt: step.attempt,
244
- });
245
- span?.setAttributes({
246
- ...Attribute.StepStatus(step.status),
247
- });
248
- // Validate step function exists AFTER step_started so we can
249
- // properly fail the step (not the run) if the function is missing.
250
- // This allows the workflow to handle the step failure gracefully,
251
- // similar to how FatalError is handled.
252
- if (!stepFn || typeof stepFn !== 'function') {
253
- const err = new StepNotRegisteredError(stepName);
254
- stepRuntimeLogger.error('Step function not registered, failing step (not run)', {
255
- errorName: err.name,
256
- errorMessage: err.message,
257
- errorStack: err.stack,
258
- });
259
- // Fail the step via event (event-sourced architecture)
260
- // This matches the FatalError pattern - fail the step and re-queue workflow
261
- try {
262
- await world.events.create(workflowRunId, {
263
- eventType: 'step_failed',
264
- specVersion: SPEC_VERSION_CURRENT,
265
- correlationId: stepId,
266
- eventData: {
267
- stepName,
268
- error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey(), [], globalThis, compressionForStep()),
269
- },
270
- }, { requestId });
271
- }
272
- catch (stepFailErr) {
273
- if (EntityConflictError.is(stepFailErr)) {
274
- // Step already transitioned to a terminal state — duplicate
275
- // delivery or concurrent cancellation. Drop silently.
276
- stepRuntimeLogger.info('Tried failing step for missing function, but step has already finished.', {
277
- errorName: stepFailErr.name,
278
- errorMessage: stepFailErr.message,
279
- });
280
- return;
281
- }
282
- throw stepFailErr;
283
- }
284
- span?.setAttributes({
285
- ...Attribute.StepStatus('failed'),
286
- ...Attribute.StepFatalError(true),
287
- });
288
- // Re-invoke the workflow to handle the failed step
289
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
290
- runId: workflowRunId,
291
- traceCarrier: await nextTraceCarrier(),
292
- requestedAt: new Date(),
293
- });
294
- return;
295
- }
296
- const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
297
- span?.setAttributes({
298
- ...Attribute.StepMaxRetries(maxRetries),
299
- });
300
- let result;
301
- // Check max retries AFTER step_started (attempt was just incremented)
302
- // step.attempt tracks how many times step_started has been called.
303
- // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
304
- // Use > here (not >=) because this guards against re-invocation AFTER all attempts are used.
305
- // The post-failure check uses >= to decide whether to retry after a failure.
306
- if (step.attempt > maxRetries + 1) {
307
- const retryCount = step.attempt - 1;
308
- // Persisted message — kept short, no machine `stepName`,
309
- // since observability already attributes the event to a
310
- // specific step.
311
- const errorMessage = `Step exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
312
- stepLogger.error(`Step ${formatStepName(stepName)} exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`, {
313
- workflowRunId,
314
- workflowName,
315
- stepId,
316
- stepName,
317
- retryCount,
318
- });
319
- // Fail the step via event (event-sourced architecture).
320
- // Preserve the prior attempt's serialized error as the cause so
321
- // the underlying failure is recoverable from `step.error.cause`
322
- // after hydration, without forcing consumers to walk the
323
- // step_retrying event history. Mirrors the post-failure path
324
- // below that wraps the live `err` as cause.
325
- const wrappedError = new FatalError(errorMessage);
326
- if (step.error != null) {
327
- try {
328
- wrappedError.cause = await hydrateStepError(step.error, workflowRunId, await getEncryptionKey());
329
- }
330
- catch {
331
- // Ignore: best-effort cause attachment, the wrapping
332
- // FatalError stack/message still surface the failure.
333
- }
334
- }
335
- try {
336
- await world.events.create(workflowRunId, {
337
- eventType: 'step_failed',
338
- specVersion: SPEC_VERSION_CURRENT,
339
- correlationId: stepId,
340
- eventData: {
341
- stepName,
342
- error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey(), [], globalThis, compressionForStep()),
343
- },
344
- }, { requestId });
345
- }
346
- catch (err) {
347
- if (EntityConflictError.is(err)) {
348
- // Step already transitioned to a terminal state — duplicate
349
- // delivery or concurrent completion. Drop silently.
350
- stepRuntimeLogger.info('Tried failing step, but step has already finished.', {
351
- errorName: err.name,
352
- errorMessage: err.message,
353
- });
354
- return;
355
- }
356
- throw err;
357
- }
358
- span?.setAttributes({
359
- ...Attribute.StepStatus('failed'),
360
- ...Attribute.StepRetryExhausted(true),
361
- });
362
- // Re-invoke the workflow to handle the failed step
363
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
364
- runId: workflowRunId,
365
- traceCarrier: await nextTraceCarrier(),
366
- requestedAt: new Date(),
367
- });
368
- return;
369
- }
370
- // --- Infrastructure: prepare step input ---
371
- // Network/server errors propagate to the queue handler for retry.
372
- // WorkflowRuntimeError (data integrity issues) are fatal — retrying
373
- // won't fix them, so we re-queue the workflow to surface the error.
374
- // step_started already validated the step is in valid state (pending/running)
375
- // and returned the updated step entity with incremented attempt
376
- // step.attempt is now the current attempt number (after increment)
377
- const attempt = step.attempt;
378
- if (!step.startedAt) {
379
- const errorMessage = `Step "${stepId}" has no "startedAt" timestamp`;
380
- stepRuntimeLogger.error('Fatal runtime error during step setup', {
381
- errorMessage,
382
- });
383
- try {
384
- await world.events.create(workflowRunId, {
385
- eventType: 'step_failed',
386
- specVersion: SPEC_VERSION_CURRENT,
387
- correlationId: stepId,
388
- eventData: {
389
- stepName,
390
- error: await dehydrateStepError(new FatalError(errorMessage), workflowRunId, await getEncryptionKey(), [], globalThis, compressionForStep()),
391
- },
392
- }, { requestId });
393
- }
394
- catch (failErr) {
395
- if (EntityConflictError.is(failErr)) {
396
- return;
397
- }
398
- throw failErr;
399
- }
400
- // Re-queue the workflow so it can process the step failure
401
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
402
- runId: workflowRunId,
403
- traceCarrier: await nextTraceCarrier(),
404
- requestedAt: new Date(),
405
- });
406
- return;
407
- }
408
- // Capture startedAt for use in async callback (TypeScript narrowing doesn't persist)
409
- const stepStartedAt = step.startedAt;
410
- // Resolve the encryption key now that we're committed to running
411
- // user code: input hydration needs it, and `contextStorage` (and
412
- // any user-code paths that run inside it) capture the resolved
413
- // value. Triggers the underlying world / KMS fetch once, with
414
- // subsequent dehydrate paths reusing the memoized result.
415
- const encryptionKey = await getEncryptionKey();
416
- // Hydrate the step input arguments, closure variables, and thisVal
417
- // NOTE: This captures only the synchronous portion of hydration. Any async
418
- // operations (e.g., stream loading) are added to `ops` and executed later
419
- // via Promise.all(ops) - their timing is not included in this measurement.
420
- const ops = [];
421
- // Ops that must be durably committed before step completion (e.g. a
422
- // step-initiated abort's hook_received event). See StepContext.
423
- const preCompletionOps = [];
424
- const hydratedInput = await trace('step.hydrate', {}, async (hydrateSpan) => {
425
- const startTime = Date.now();
426
- const result = await hydrateStepArguments(step.input, workflowRunId, encryptionKey, ops, globalThis, {}, process.env.VERCEL_DEPLOYMENT_ID);
427
- const durationMs = Date.now() - startTime;
428
- hydrateSpan?.setAttributes({
429
- ...Attribute.StepArgumentsCount(result.args.length),
430
- ...Attribute.QueueDeserializeTimeMs(durationMs),
431
- });
432
- return result;
433
- });
434
- const args = hydratedInput.args;
435
- const thisVal = hydratedInput.thisVal ?? null;
436
- // --- User code execution ---
437
- // Only errors from stepFn.apply() (user step code) should produce
438
- // step_failed/step_retrying. Infrastructure errors (network, server)
439
- // must propagate to the queue handler for automatic retry.
440
- let userCodeError;
441
- let userCodeFailed = false;
442
- const executionStartTime = Date.now();
443
- try {
444
- result = await trace('step.execute', {}, async () => {
445
- return await contextStorage.run({
446
- stepMetadata: {
447
- stepName,
448
- stepId,
449
- stepStartedAt: new Date(+stepStartedAt),
450
- attempt,
451
- },
452
- workflowMetadata: {
453
- workflowName,
454
- workflowRunId,
455
- workflowStartedAt: new Date(+workflowStartedAt),
456
- url: workflowBaseUrl,
457
- features: { encryption: !!encryptionKey },
458
- },
459
- workflowDeploymentId: process.env.VERCEL_DEPLOYMENT_ID,
460
- ops,
461
- preCompletionOps,
462
- closureVars: hydratedInput.closureVars,
463
- encryptionKey,
464
- }, () => stepFn.apply(thisVal, args));
465
- });
466
- }
467
- catch (err) {
468
- userCodeError = err;
469
- userCodeFailed = true;
470
- }
471
- const executionTimeMs = Date.now() - executionStartTime;
472
- cancelAbortReaders(...args, thisVal, hydratedInput.closureVars);
473
- // Commit must-be-durable ops (e.g. a step-initiated abort's
474
- // hook_received event) before writing step_completed/step_failed,
475
- // so any workflow continuation triggered by that event observes the
476
- // abort rather than racing it. Producers swallow their own errors
477
- // per the no-reject contract on StepContext.preCompletionOps; the
478
- // `.catch()` defends it, since this await sits outside the
479
- // user-code try/catch (a stray rejection here would otherwise
480
- // surface as an infra error → queue re-delivery, not a step
481
- // failure). The await only enforces ordering.
482
- if (preCompletionOps.length > 0) {
483
- await Promise.all(preCompletionOps).catch(() => { });
484
- }
485
- span?.setAttributes({
486
- ...Attribute.QueueExecutionTimeMs(executionTimeMs),
487
- });
488
- // --- Dehydrate (serialize) the step's return value ---
489
- // A non-serializable return value is a user-code bug, not an
490
- // infrastructure failure. Route it through the same step-failure
491
- // path as a thrown error so SerializationError (which is marked
492
- // `fatal: true`) short-circuits the retry loop instead of
493
- // bubbling as an HTTP 500 and burning through all 4 queue
494
- // deliveries on a guaranteed-to-fail message.
495
- if (!userCodeFailed) {
496
- try {
497
- result = await trace('step.dehydrate', {}, async (dehydrateSpan) => {
498
- const startTime = Date.now();
499
- // Step return values are consumed by the workflow VM
500
- // running on this same deployment (version skew
501
- // protection ensures it). Byte-stream framing is
502
- // therefore always safe here.
503
- const dehydrated = await dehydrateStepReturnValue(result, workflowRunId, encryptionKey, ops, globalThis, false, true, compressionForStep());
504
- const durationMs = Date.now() - startTime;
505
- dehydrateSpan?.setAttributes({
506
- ...Attribute.QueueSerializeTimeMs(durationMs),
507
- ...Attribute.StepResultType(typeof dehydrated),
508
- });
509
- return dehydrated;
510
- });
511
- }
512
- catch (err) {
513
- userCodeError = err;
514
- userCodeFailed = true;
515
- }
516
- }
517
- // --- Handle user code errors ---
518
- if (userCodeFailed) {
519
- const err = userCodeError;
520
- // Infrastructure errors that somehow surfaced through user code
521
- // should propagate to the queue handler for retry, not consume
522
- // step attempts.
523
- if (RunExpiredError.is(err)) {
524
- // Workflow has already completed, so no-op
525
- stepLogger.info('Workflow run already completed, skipping step', {
526
- workflowRunId,
527
- stepId,
528
- message: err.message,
529
- });
530
- return;
531
- }
532
- if (WorkflowWorldError.is(err)) {
533
- if (err.status !== undefined && err.status >= 500) {
534
- throw err;
535
- }
536
- }
537
- // Abort failures can cross VM/serialization realms, where
538
- // `instanceof Error` is not reliable.
539
- const effectiveErr = promoteAbortErrorToFatal(err);
540
- const normalizedError = await normalizeUnknownError(effectiveErr);
541
- const normalizedStack = normalizedError.stack || getErrorStack(effectiveErr) || '';
542
- // Record exception for OTEL error tracking
543
- if (effectiveErr instanceof Error) {
544
- span?.recordException?.(effectiveErr);
545
- }
546
- // Determine error category and retryability
547
- const isFatal = FatalError.is(effectiveErr);
548
- const isRetryable = RetryableError.is(effectiveErr);
549
- const errorCategory = isFatal
550
- ? 'fatal'
551
- : isRetryable
552
- ? 'retryable'
553
- : 'transient';
554
- span?.setAttributes({
555
- ...Attribute.StepErrorName(getErrorName(effectiveErr)),
556
- ...Attribute.StepErrorMessage(normalizedError.message),
557
- ...Attribute.ErrorType(getErrorName(effectiveErr)),
558
- ...Attribute.ErrorCategory(errorCategory),
559
- ...Attribute.ErrorRetryable(!isFatal),
560
- });
561
- if (isFatal) {
562
- const description = describeError(err);
563
- const friendlyStep = formatStepName(stepName);
564
- const framing = description.attribution === 'sdk'
565
- ? `Step ${friendlyStep} failed with a FatalError from the SDK runtime — bubbling up to parent workflow`
566
- : `Step ${friendlyStep} threw a FatalError — bubbling up to parent workflow`;
567
- // Mirror the workflow-level log formatting: put the framing +
568
- // stack into the message so console.error renders the stack
569
- // inline, and keep the metadata object small with only the
570
- // structured fields that log drains want to index.
571
- // No `hint` field here — actionable hint text lives on the
572
- // error message itself (so it survives serialization →
573
- // event log → observability rehydrate), and adding it
574
- // again here just duplicates it on stderr.
575
- stepLogger.error(`${framing}\n${normalizedStack || normalizedError.message}`, {
576
- workflowRunId,
577
- stepId,
578
- stepName,
579
- errorAttribution: description.attribution,
580
- errorName: normalizedError.name,
581
- errorMessage: normalizedError.message,
582
- });
583
- // Fail the step via event (event-sourced architecture).
584
- // Persist the promoted FatalError for aborts so the parent
585
- // workflow can distinguish cancellation from retry exhaustion.
586
- try {
587
- await world.events.create(workflowRunId, {
588
- eventType: 'step_failed',
589
- specVersion: SPEC_VERSION_CURRENT,
590
- correlationId: stepId,
591
- eventData: {
592
- stepName,
593
- error: await dehydrateStepError(effectiveErr, workflowRunId, encryptionKey, [], globalThis, compressionForStep()),
594
- },
595
- }, { requestId });
596
- }
597
- catch (stepFailErr) {
598
- if (EntityConflictError.is(stepFailErr)) {
599
- // Step already in terminal state — idempotent.
600
- stepRuntimeLogger.info('Tried failing step, but step has already finished.', {
601
- errorName: stepFailErr.name,
602
- errorMessage: stepFailErr.message,
603
- });
604
- return;
605
- }
606
- throw stepFailErr;
607
- }
608
- span?.setAttributes({
609
- ...Attribute.StepStatus('failed'),
610
- ...Attribute.StepFatalError(true),
611
- });
612
- }
613
- else {
614
- const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
615
- // step.attempt was incremented by step_started, use it here
616
- const currentAttempt = step.attempt;
617
- span?.setAttributes({
618
- ...Attribute.StepAttempt(currentAttempt),
619
- ...Attribute.StepMaxRetries(maxRetries),
620
- });
621
- // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
622
- if (currentAttempt >= maxRetries + 1) {
623
- // Max retries reached
624
- const retryCount = step.attempt - 1;
625
- const description = describeError(err);
626
- const friendlyStep = formatStepName(stepName);
627
- const framing = description.attribution === 'sdk'
628
- ? `Step ${friendlyStep} hit max retries on an SDK runtime error — bubbling to parent workflow`
629
- : `Step ${friendlyStep} hit max retries — bubbling error thrown by your step to the parent workflow`;
630
- stepLogger.error(`${framing}\n${normalizedStack || normalizedError.message}`, {
631
- workflowRunId,
632
- workflowName,
633
- stepId,
634
- stepName,
635
- attempt: step.attempt,
636
- retryCount,
637
- errorAttribution: description.attribution,
638
- errorName: normalizedError.name,
639
- errorMessage: normalizedError.message,
640
- });
641
- // Don't include the machine step name in the persisted
642
- // error message — observability already shows which step
643
- // produced the event, and `stepName: 'step//./.../foo'`
644
- // in the title is just noise. The CLI logger renders
645
- // `Step foo (./...) hit max retries` separately.
646
- const errorMessage = `Step failed after ${maxRetries} ${pluralize('retry', 'retries', maxRetries)}: ${normalizedError.message}`;
647
- // Fail the step via event (event-sourced architecture).
648
- // Wrap the original error with a FatalError that preserves
649
- // the wrapped message plus the original thrown value as
650
- // `cause` so it's recoverable after hydration.
651
- const wrappedError = new FatalError(errorMessage);
652
- wrappedError.cause = err;
653
- if (normalizedStack)
654
- wrappedError.stack = normalizedStack;
655
- try {
656
- await world.events.create(workflowRunId, {
657
- eventType: 'step_failed',
658
- specVersion: SPEC_VERSION_CURRENT,
659
- correlationId: stepId,
660
- eventData: {
661
- stepName,
662
- error: await dehydrateStepError(wrappedError, workflowRunId, encryptionKey, [], globalThis, compressionForStep()),
663
- },
664
- }, { requestId });
665
- }
666
- catch (stepFailErr) {
667
- if (EntityConflictError.is(stepFailErr)) {
668
- // Step already in terminal state — idempotent.
669
- stepRuntimeLogger.info('Tried failing step, but step has already finished.', {
670
- errorName: stepFailErr.name,
671
- errorMessage: stepFailErr.message,
672
- });
673
- return;
674
- }
675
- throw stepFailErr;
676
- }
677
- span?.setAttributes({
678
- ...Attribute.StepStatus('failed'),
679
- ...Attribute.StepRetryExhausted(true),
680
- });
681
- }
682
- else {
683
- // Not at max retries yet - log as a retryable error
684
- if (RetryableError.is(err)) {
685
- stepLogger.info('Encountered RetryableError, step will be retried', {
686
- workflowRunId,
687
- workflowName,
688
- stepId,
689
- stepName,
690
- attempt: currentAttempt,
691
- errorName: err.name,
692
- errorMessage: err.message,
693
- errorStack: normalizedStack,
694
- });
695
- }
696
- else {
697
- stepLogger.info('Encountered Error, step will be retried', {
698
- workflowRunId,
699
- workflowName,
700
- stepId,
701
- stepName,
702
- attempt: currentAttempt,
703
- errorName: normalizedError.name,
704
- errorMessage: normalizedError.message,
705
- errorStack: normalizedStack,
706
- });
707
- }
708
- // Set step to pending for retry via event (event-sourced architecture)
709
- // step_retrying records the error and sets status to pending.
710
- // Serialize the original thrown value so its full type identity
711
- // and custom properties round-trip through the event log.
712
- try {
713
- await world.events.create(workflowRunId, {
714
- eventType: 'step_retrying',
715
- specVersion: SPEC_VERSION_CURRENT,
716
- correlationId: stepId,
717
- eventData: {
718
- stepName,
719
- error: await dehydrateStepError(err, workflowRunId, encryptionKey, [], globalThis, compressionForStep()),
720
- ...(RetryableError.is(err) && {
721
- retryAfter: err.retryAfter,
722
- }),
723
- },
724
- }, { requestId });
725
- }
726
- catch (stepRetryErr) {
727
- if (EntityConflictError.is(stepRetryErr)) {
728
- // Step already in terminal state — idempotent.
729
- stepRuntimeLogger.info('Tried retrying step, but step has already finished.', {
730
- errorName: stepRetryErr.name,
731
- errorMessage: stepRetryErr.message,
732
- });
733
- return;
734
- }
735
- throw stepRetryErr;
736
- }
737
- const timeoutSeconds = Math.max(1, RetryableError.is(err)
738
- ? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1000)
739
- : 1);
740
- span?.setAttributes({
741
- ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
742
- ...Attribute.StepRetryWillRetry(true),
743
- });
744
- // Add span event for retry scheduling
745
- span?.addEvent?.('retry.scheduled', {
746
- 'retry.timeout_seconds': timeoutSeconds,
747
- 'retry.attempt': currentAttempt,
748
- 'retry.max_retries': maxRetries,
749
- });
750
- // It's a retryable error - so have the queue keep the message visible
751
- // so that it gets retried.
752
- return { timeoutSeconds };
753
- }
754
- }
755
- // Re-invoke the workflow to handle the failed/retrying step
756
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
757
- runId: workflowRunId,
758
- traceCarrier: await nextTraceCarrier(),
759
- requestedAt: new Date(),
760
- });
761
- return;
762
- }
763
- // --- Infrastructure: complete the step ---
764
- // Errors here (network failures, server errors) propagate to the
765
- // queue handler for automatic retry.
766
- //
767
- // NOTE: None of the code from this point is guaranteed to run.
768
- // Since the step might fail or cause a function timeout and the
769
- // process might be SIGKILL'd, the workflow runtime must be
770
- // resilient to the below code not executing on a failed step.
771
- // (Dehydration already happened above and is accounted for in the
772
- // userCodeFailed path.)
773
- // These stream ops are flushed in the background; the promise
774
- // handed to waitUntil must never reject (an unconsumed waitUntil
775
- // rejection crashes the process as unhandledRejection), so
776
- // unexpected failures are logged instead.
777
- safeWaitUntil(Promise.all(ops), (err) => {
778
- stepRuntimeLogger.warn('Background flush of step stream ops failed', { error: err instanceof Error ? err.message : String(err) });
779
- });
780
- // Run step_completed and trace serialization concurrently;
781
- // the trace carrier is used in the final queueMessage call below
782
- let stepCompleted409 = false;
783
- const [, traceCarrier] = await Promise.all([
784
- world.events
785
- .create(workflowRunId, {
786
- eventType: 'step_completed',
787
- specVersion: SPEC_VERSION_CURRENT,
788
- correlationId: stepId,
789
- eventData: {
790
- stepName,
791
- result: result,
792
- },
793
- }, { requestId })
794
- .catch((err) => {
795
- if (EntityConflictError.is(err)) {
796
- // Step already in terminal state — idempotent.
797
- stepRuntimeLogger.info('Tried completing step, but step has already finished.', {
798
- errorName: err.name,
799
- errorMessage: err.message,
800
- });
801
- stepCompleted409 = true;
802
- return;
803
- }
804
- throw err;
805
- }),
806
- nextTraceCarrier(),
807
- ]);
808
- if (stepCompleted409) {
809
- return;
810
- }
811
- span?.setAttributes({
812
- ...Attribute.StepStatus('completed'),
813
- ...Attribute.StepResultType(typeof result),
814
- });
815
- // Queue the workflow continuation with the concurrently-resolved trace carrier
816
- await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
817
- runId: workflowRunId,
818
- traceCarrier,
819
- requestedAt: new Date(),
820
- });
821
- });
822
- });
823
- });
824
- }
825
- const stepHandler = createStepHandler();
826
- /**
827
- * A single route that handles any step execution request and routes to the
828
- * appropriate step function. We may eventually want to create different bundles
829
- * for each step, this is temporary.
830
- */
831
- let cachedStepHandler;
832
- export const stepEntrypoint =
833
- /* @__PURE__ */ withHealthCheck(async (req) => {
834
- if (!cachedStepHandler) {
835
- cachedStepHandler = stepHandler(await getWorldHandlers());
836
- }
837
- return cachedStepHandler(req);
838
- });
839
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGNBQWMsRUFDZCxlQUFlLEVBQ2Ysc0JBQXNCLEVBQ3RCLGFBQWEsRUFDYixhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsY0FBYyxFQUNkLFNBQVMsRUFDVCxlQUFlLEdBQ2hCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixxQkFBcUIsRUFDckIsb0JBQW9CLEVBQ3BCLGlDQUFpQyxFQUVqQyx1QkFBdUIsR0FDeEIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQix3QkFBd0IsRUFDeEIsb0JBQW9CLEVBQ3BCLGdCQUFnQixHQUNqQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLEtBQUssRUFDTCxnQkFBZ0IsR0FDakIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQ0wsWUFBWSxFQUNaLGFBQWEsRUFD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QkFBaUIsRUFBRSxDQUFDO0FBRXhDOzs7O0dBSUc7QUFDSCxJQUFJLGlCQUFvRSxDQUFDO0FBQ3pFLE1BQU0sQ0FBQyxNQUFNLGNBQWM7QUFDekIsZUFBZSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7SUFDNUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDdkIsaUJBQWlCLEdBQUcsV0FBVyxDQUFDLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFDRCxPQUFPLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2hDLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRmF0YWxFcnJvcixcbiAgUmV0cnlhYmxlRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgU3RlcE5vdFJlZ2lzdGVyZWRFcnJvcixcbiAgVGhyb3R0bGVFcnJvcixcbiAgVG9vRWFybHlFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG4gIFdvcmtmbG93V29ybGRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICBjcmVhdGVXb3JrZmxvd0Jhc2VVcmwsXG4gIGZvcm1hdFN0ZXBOYW1lLFxuICBwbHVyYWxpemUsXG4gIHN0ZXBEaXNwbGF5TmFtZSxcbn0gZnJvbSAnQHdvcmtmbG93L3V0aWxzJztcbmltcG9ydCB7XG4gIGdldFF1ZXVlVG9waWNQcmVmaXgsXG4gIHJlc29sdmVRdWV1ZU5hbWVzcGFjZSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBTdGVwLFxuICBTdGVwSW52b2tlUGF5bG9hZFNjaGVtYSxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGRlc2NyaWJlRXJyb3IgfSBmcm9tICcuLi9kZXNjcmliZS1lcnJvci5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyLCBzdGVwTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGdldFN0ZXBGdW5jdGlvbiB9IGZyb20gJy4uL3ByaXZhdGUuanMnO1xuaW1wb3J0IHtcbiAgY2FuY2VsQWJvcnRSZWFkZXJzLFxuICBkZWh5ZHJhdGVTdGVwRXJyb3IsXG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIGh5ZHJhdGVTdGVwRXJyb3IsXG59IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgY29udGV4dFN0b3JhZ2UgfSBmcm9tICcuLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7XG4gIGJ1aWxkSW52b2NhdGlvblNwYW5MaW5rcyxcbiAgZ2V0TmV4dFRyYWNlQ2FycmllcixcbiAgZ2V0U3BhbktpbmQsXG4gIGdldFdvcmtmbG93VHJhY2VNb2RlLFxuICBpc1VzYWJsZVRyYWNlQ2FycmllcixcbiAgdHJhY2UsXG4gIHdpdGhUcmFjZUNvbnRleHQsXG59IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQge1xuICBnZXRFcnJvck5hbWUsXG4gIGdldEVycm9yU3RhY2ssXG4gIG5vcm1hbGl6ZVVua25vd25FcnJvcixcbiAgcHJvbW90ZUFib3J0RXJyb3JUb0ZhdGFsLFxufSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbmltcG9ydCB7IGdldE1heFF1ZXVlRGVsaXZlcmllcyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGdldFBvcnRMYXp5IH0gZnJvbSAnLi9nZXQtcG9ydC1sYXp5LmpzJztcbmltcG9ydCB7XG4gIGdldFF1ZXVlT3ZlcmhlYWQsXG4gIGdldFdvcmtmbG93UXVldWVOYW1lLFxuICBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UsXG4gIG1lbW9pemVFbmNyeXB0aW9uS2V5LFxuICBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZCxcbiAgcXVldWVNZXNzYWdlLFxuICB3aXRoSGVhbHRoQ2hlY2ssXG59IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBzYWZlV2FpdFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcbmltcG9ydCB7IGdldFdvcmxkLCBnZXRXb3JsZEhhbmRsZXJzLCB0eXBlIFdvcmxkSGFuZGxlcnMgfSBmcm9tICcuL3dvcmxkLmpzJztcblxuY29uc3QgREVGQVVMVF9TVEVQX01BWF9SRVRSSUVTID0gMztcblxuZnVuY3Rpb24gY3JlYXRlU3RlcEhhbmRsZXIobmFtZXNwYWNlPzogc3RyaW5nKSB7XG4gIGNvbnN0IHJlc29sdmVkTmFtZXNwYWNlID0gcmVzb2x2ZVF1ZXVlTmFtZXNwYWNlKG5hbWVzcGFjZSk7XG4gIGNvbnN0IHN0ZXBQcmVmaXggPSBnZXRRdWV1ZVRvcGljUHJlZml4KCdzdGVwJywgcmVzb2x2ZWROYW1lc3BhY2UpO1xuXG4gIHJldHVybiAod29ybGRIYW5kbGVyczogV29ybGRIYW5kbGVycykgPT5cbiAgICB3b3JsZEhhbmRsZXJzLmNyZWF0ZVF1ZXVlSGFuZGxlcihzdGVwUHJlZml4LCBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgaGVhbHRoIGNoZWNrIG1lc3NhZ2VcbiAgICAgIC8vIE5PVEU6IEhlYWx0aCBjaGVjayBtZXNzYWdlcyBhcmUgaW50ZW50aW9uYWxseSB1bmF1dGhlbnRpY2F0ZWQgZm9yIG1vbml0b3JpbmcgcHVycG9zZXMuXG4gICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgLy8gVGhlIHN0cmVhbSBuYW1lIGluY2x1ZGVzIGEgdW5pcXVlIGNvcnJlbGF0aW9uSWQgdGhhdCBtdXN0IGJlIGtub3duIGJ5IHRoZSBjYWxsZXIuXG4gICAgICBjb25zdCBoZWFsdGhDaGVjayA9IHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkKG1lc3NhZ2VfKTtcbiAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICBhd2FpdCBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UoXG4gICAgICAgICAgaGVhbHRoQ2hlY2ssXG4gICAgICAgICAgJ3N0ZXAnLFxuICAgICAgICAgIHdvcmxkSGFuZGxlcnMuc3BlY1ZlcnNpb25cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgIHN0ZXBJZCxcbiAgICAgICAgdHJhY2VDYXJyaWVyOiBpbmNvbWluZ1RyYWNlQ2FycmllcixcbiAgICAgICAgcmVxdWVzdGVkQXQsXG4gICAgICB9ID0gU3RlcEludm9rZVBheWxvYWRTY2hlbWEucGFyc2UobWVzc2FnZV8pO1xuICAgICAgY29uc3QgeyByZXF1ZXN0SWQgfSA9IG1ldGFkYXRhO1xuICAgICAgLy8gc2VyaWFsaXplVHJhY2VDYXJyaWVyKCkgcmV0dXJucyBge31gIHdoZW4gbm8gT1RFTCBTREsgaXMgcmVnaXN0ZXJlZFxuICAgICAgLy8gb3Igbm8gc3BhbiBpcyBhY3RpdmUg4oCUIHRyZWF0IGFuIGVtcHR5IGNhcnJpZXIgdGhlIHNhbWUgYXMgYW4gYWJzZW50XG4gICAgICAvLyBvbmUgc28gbGlua2VkIG1vZGUgZmFsbHMgYmFjayB0byBhIGZyZXNoIG9yaWdpbiBpbnN0ZWFkIG9mXG4gICAgICAvLyBmb3J3YXJkaW5nIGEgdXNlbGVzcyBge31gIGZvcmV2ZXIuXG4gICAgICBjb25zdCB0cmFjZUNvbnRleHQgPSBpc1VzYWJsZVRyYWNlQ2FycmllcihpbmNvbWluZ1RyYWNlQ2FycmllcilcbiAgICAgICAgPyBpbmNvbWluZ1RyYWNlQ2FycmllclxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgLy8gLS0tIFRyYWNlIGNvcnJlbGF0aW9uIG1vZGUgLS0tXG4gICAgICAvLyAnbGlua2VkJyAoZGVmYXVsdCk6IHRoZSBTVEVQIHNwYW4gYmVsb3cgc3RhcnRzIGEgTkVXIHJvb3QgdHJhY2Ugd2l0aFxuICAgICAgLy8gc3BhbiBsaW5rcyB0byB0aGUgZGVsaXZlcnkgY29udGV4dCBhbmQgdGhlIHJ1bi1vcmlnaW4gY29udGV4dCBmcm9tXG4gICAgICAvLyB0aGUgbWVzc2FnZSdzIHRyYWNlIGNhcnJpZXIuICdjb250aW51b3VzJzogbGVnYWN5IGJlaGF2aW9yIOKAlCB0aGVcbiAgICAgIC8vIHJlc3RvcmVkIHJ1bi1vcmlnaW4gY29udGV4dCBwYXJlbnRzIHRoaXMgaW52b2NhdGlvbidzIHNwYW5zLlxuICAgICAgY29uc3QgdHJhY2VNb2RlID0gZ2V0V29ya2Zsb3dUcmFjZU1vZGUoKTtcblxuICAgICAgLy8gVHJhY2UgY2FycmllciB0byBhdHRhY2ggdG8gbWVzc2FnZXMgdGhpcyBpbnZvY2F0aW9uIGVucXVldWVzIOKAlCBzZWVcbiAgICAgIC8vIGdldE5leHRUcmFjZUNhcnJpZXIgZm9yIHRoZSBsaW5rZWQvY29udGludW91cyBzZW1hbnRpY3MuXG4gICAgICBjb25zdCBuZXh0VHJhY2VDYXJyaWVyID0gKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4gPT5cbiAgICAgICAgZ2V0TmV4dFRyYWNlQ2Fycmllcih0cmFjZU1vZGUsIHRyYWNlQ29udGV4dCk7XG5cbiAgICAgIC8vIC0tLSBNYXggZGVsaXZlcnkgY2hlY2sgLS0tXG4gICAgICAvLyBFbmZvcmNlIG1heCBkZWxpdmVyeSBsaW1pdCBiZWZvcmUgYW55IGluZnJhc3RydWN0dXJlIGNhbGxzLlxuICAgICAgLy8gVGhpcyBwcmV2ZW50cyBydW5hd2F5IHN0ZXBzIGZyb20gY29uc3VtaW5nIGluZmluaXRlIHF1ZXVlIGRlbGl2ZXJpZXMuXG4gICAgICAvLyBBdCB0aGlzIHBvaW50LCB3ZSB3YW50IHRvIGRvIHRoZSBtaW5pbWFsIGFtb3VudCBvZiB3b3JrIChubyBmZXRjaGluZ1xuICAgICAgLy8gb2YgdGhlIHN0ZXAgZGV0YWlscywgZXRjLiBXZSBzaW1wbHkgYXR0ZW1wdCB0byBtYXJrIHRoZSBzdGVwIGFzIGZhaWxlZFxuICAgICAgLy8gYW5kIGVucXVldWUgdGhlIHdvcmtmbG93IG9uY2UsIGFuZCBpZiBlaXRoZXIgb2YgdGhvc2UgZmFpbHMsIHRoZSBtZXNzYWdlXG4gICAgICAvLyBpcyBzdGlsbCBjb25zdW1lZCBidXQgd2l0aCBhZGVxdWF0ZSBsb2dnaW5nIHRoYXQgYW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgICAvLyBTY29wZWQgbG9nZ2VyIGZvciB0aGlzIHN0ZXAgaW52b2NhdGlvbiDigJQgYXR0YWNoZXMgcnVuL3N0ZXAgY29udGV4dCB0b1xuICAgICAgLy8gZXZlcnkgbG9nIGxpbmUgYmVsb3cgc28gY2FsbGVycyBkb24ndCByZXBlYXQgaXQuXG4gICAgICBjb25zdCBzdGVwTmFtZUZyb21RdWV1ZSA9IG1ldGFkYXRhLnF1ZXVlTmFtZS5zbGljZShzdGVwUHJlZml4Lmxlbmd0aCk7XG4gICAgICBjb25zdCBzdGVwUnVudGltZUxvZ2dlciA9IHJ1bnRpbWVMb2dnZXIuZm9yUnVuKFxuICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgIHsgc3RlcElkLCBzdGVwTmFtZTogc3RlcE5hbWVGcm9tUXVldWUgfVxuICAgICAgKTtcblxuICAgICAgY29uc3QgbWF4UXVldWVEZWxpdmVyaWVzID0gZ2V0TWF4UXVldWVEZWxpdmVyaWVzKCk7XG4gICAgICBpZiAobWV0YWRhdGEuYXR0ZW1wdCA+IG1heFF1ZXVlRGVsaXZlcmllcykge1xuICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgICBgU3RlcCBoYW5kbGVyIGV4Y2VlZGVkIG1heCBkZWxpdmVyaWVzICgke21ldGFkYXRhLmF0dGVtcHR9LyR7bWF4UXVldWVEZWxpdmVyaWVzfSlgLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGF0dGVtcHQ6IG1ldGFkYXRhLmF0dGVtcHQsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGQoKTtcbiAgICAgICAgICBjb25zdCBnZXRFbmNyeXB0aW9uS2V5ID0gbWVtb2l6ZUVuY3J5cHRpb25LZXkod29ybGQsIHdvcmtmbG93UnVuSWQpO1xuICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICAgICAgYFN0ZXAgZXhjZWVkZWQgbWF4aW11bSBxdWV1ZSBkZWxpdmVyaWVzICgke21ldGFkYXRhLmF0dGVtcHR9LyR7bWF4UXVldWVEZWxpdmVyaWVzfSlgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgc3RlcE5hbWU6IHN0ZXBOYW1lRnJvbVF1ZXVlLFxuICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBSZS1xdWV1ZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQgc3RlcFxuICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDYW4ndCBldmVuIG1hcmsgdGhlIHN0ZXAgYXMgZmFpbGVkLiBDb25zdW1lIHRoZSBtZXNzYWdlIHRvIHN0b3BcbiAgICAgICAgICAvLyBmdXJ0aGVyIHJldHJpZXMuIFRoZSBydW4gd2lsbCByZW1haW4gaW4gaXRzIGN1cnJlbnQgc3RhdGUuXG4gICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICBgRmFpbGVkIHRvIG1hcmsgc3RlcCBhcyBmYWlsZWQgYWZ0ZXIgJHttZXRhZGF0YS5hdHRlbXB0fSBkZWxpdmVyeSBhdHRlbXB0cy4gYCArXG4gICAgICAgICAgICAgIGBBIHBlcnNpc3RlbnQgZXJyb3IgaXMgcHJldmVudGluZyB0aGUgc3RlcCBmcm9tIGJlaW5nIHRlcm1pbmF0ZWQuIGAgK1xuICAgICAgICAgICAgICBgVGhlIHJ1biB3aWxsIHJlbWFpbiBpbiBpdHMgY3VycmVudCBzdGF0ZSB1bnRpbCBtYW51YWxseSByZXNvbHZlZC4gYCArXG4gICAgICAgICAgICAgIGBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhIHBlcnNpc3RlbnQgb3V0YWdlIG9mIHRoZSB3b3JrZmxvdyBiYWNrZW5kIGAgK1xuICAgICAgICAgICAgICBgb3IgYSBidWcgaW4gdGhlIHdvcmtmbG93IHJ1bnRpbWUgYW5kIHNob3VsZCBiZSByZXBvcnRlZCB0byB0aGUgV29ya2Zsb3cgdGVhbS5gLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm5hbWUgOiAnVW5rbm93bkVycm9yJyxcbiAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgIGVycm9yU3RhY2s6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLnN0YWNrIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBJbiBsaW5rZWQgbW9kZSB0aGUgb25seSBzcGFuIGxpbmsgaXMgdG8gdGhlIHJ1bi1vcmlnaW4gY29udGV4dDsgdGhlXG4gICAgICAvLyBzdGVwLmV4ZWN1dGUgc3BhbiBzdGF5cyBhIGNoaWxkIG9mIHRoZSBsb2NhbCBkZWxpdmVyeSAoZmxvdy1yb3V0ZSlcbiAgICAgIC8vIGNvbnRleHQuIEluIGNvbnRpbnVvdXMgbW9kZSB0aGUgbGluayBwb2ludHMgYXQgdGhlIGRlbGl2ZXJ5IGNvbnRleHQuXG4gICAgICBjb25zdCBzcGFuTGlua3MgPSBhd2FpdCBidWlsZEludm9jYXRpb25TcGFuTGlua3ModHJhY2VNb2RlLCB0cmFjZUNvbnRleHQpO1xuXG4gICAgICAvLyBFeGVjdXRlIHN0ZXAgd2l0aGluIHRoZSBwcm9wYWdhdGVkIHRyYWNlIGNvbnRleHQgKGNvbnRpbnVvdXMgbW9kZVxuICAgICAgLy8gb25seSDigJQgaW4gbGlua2VkIG1vZGUgdGhlIHJ1bi1vcmlnaW4gaXMgTk9UIHJlc3RvcmVkIGFzIHRoZSBwYXJlbnQsXG4gICAgICAvLyBzbyB3aXRoVHJhY2VDb250ZXh0IGlzIGEgcGFzc3Rocm91Z2ggYW5kIHRoZSBzdGVwLmV4ZWN1dGUgc3BhbiBzdGF5c1xuICAgICAgLy8gYSBjaGlsZCBvZiB0aGUgbG9jYWwgZGVsaXZlcnkgY29udGV4dCwgbGlua2VkIHRvIHRoZSBydW4gb3JpZ2luKS5cbiAgICAgIGNvbnN0IHBhcmVudFRyYWNlQ2FycmllciA9XG4gICAgICAgIHRyYWNlTW9kZSA9PT0gJ2NvbnRpbnVvdXMnID8gdHJhY2VDb250ZXh0IDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGF3YWl0IHdpdGhUcmFjZUNvbnRleHQocGFyZW50VHJhY2VDYXJyaWVyLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIEV4dHJhY3QgdGhlIHN0ZXAgbmFtZSBmcm9tIHRoZSB0b3BpYyBuYW1lXG4gICAgICAgIGNvbnN0IHN0ZXBOYW1lID0gbWV0YWRhdGEucXVldWVOYW1lLnNsaWNlKHN0ZXBQcmVmaXgubGVuZ3RoKTtcbiAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICBjb25zdCBpc1ZlcmNlbCA9IHByb2Nlc3MuZW52LlZFUkNFTF9VUkwgIT09IHVuZGVmaW5lZDtcblxuICAgICAgICAvLyBNZW1vaXplZCBhY2Nlc3NvciBmb3IgdGhlIHBlci1ydW4gQUVTLTI1NiBlbmNyeXB0aW9uIGtleS4gVGhlIGZpcnN0XG4gICAgICAgIC8vIGNhbGxlciAodHlwaWNhbGx5IGBoeWRyYXRlU3RlcEFyZ3VtZW50c2AgZm9yIGlucHV0IGRlc2VyaWFsaXphdGlvbixcbiAgICAgICAgLy8gb3Igb25lIG9mIHRoZSBlYXJseS1yZXR1cm4gZGVoeWRyYXRlU3RlcEVycm9yIHBhdGhzIGlmIHN0ZXBfc3RhcnRlZFxuICAgICAgICAvLyBmYWlscykgdHJpZ2dlcnMgdGhlIGFjdHVhbCBmZXRjaCAvIEhLREYgZGVyaXZhdGlvbjsgc3Vic2VxdWVudFxuICAgICAgICAvLyBjYWxsZXJzIGF3YWl0IHRoZSBjYWNoZWQgcHJvbWlzZS4gU3RlcHMgdGhhdCBmYWlsIGJlZm9yZSBhbnlcbiAgICAgICAgLy8gZW5jcnlwdGlvbi1hd2FyZSB3b3JrIGhhcHBlbnMgKGUuZy4gYW4gaW1tZWRpYXRlIHN0ZXBfc3RhcnRlZFxuICAgICAgICAvLyBjb25mbGljdCkgc2tpcCB0aGUgZmV0Y2ggZW50aXJlbHkuXG4gICAgICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleSh3b3JsZCwgd29ya2Zsb3dSdW5JZCk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsb2NhbCBhc3luYyB2YWx1ZXMgY29uY3VycmVudGx5IGJlZm9yZSBlbnRlcmluZyB0aGUgdHJhY2Ugc3BhblxuICAgICAgICBjb25zdCBbcG9ydCwgc3BhbktpbmRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIGlzVmVyY2VsID8gdW5kZWZpbmVkIDogZ2V0UG9ydExhenkoKSxcbiAgICAgICAgICBnZXRTcGFuS2luZCgnQ09OU1VNRVInKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgLy8gVE9ETzogcmVzb2x2ZSB0aGUgd29ya2Zsb3cgYmFzZSBVUkwgdGhyb3VnaCB0aGUgV29ybGQgaW50ZXJmYWNlLlxuICAgICAgICAvLyBUaGlzIGZhbGxiYWNrIGNhbm5vdCBzZWUgbG9jYWwvUG9zdGdyZXMgYmFzZVVybCBvdmVycmlkZXMgb3IgY3VzdG9tLXdvcmxkIHJvdXRpbmcuXG4gICAgICAgIGNvbnN0IHdvcmtmbG93QmFzZVVybCA9IGNyZWF0ZVdvcmtmbG93QmFzZVVybChcbiAgICAgICAgICBpc1ZlcmNlbFxuICAgICAgICAgICAgPyBgaHR0cHM6Ly8ke3Byb2Nlc3MuZW52LlZFUkNFTF9VUkx9YFxuICAgICAgICAgICAgOiBgaHR0cDovL2xvY2FsaG9zdDoke3BvcnQgPz8gMzAwMH1gXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHRyYWNlKFxuICAgICAgICAgIGBzdGVwLmV4ZWN1dGUgJHtzdGVwRGlzcGxheU5hbWUoc3RlcE5hbWUpfWAsXG4gICAgICAgICAgeyBraW5kOiBzcGFuS2luZCwgbGlua3M6IHNwYW5MaW5rcyB9LFxuICAgICAgICAgIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBOYW1lKHN0ZXBOYW1lKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBdHRlbXB0KG1ldGFkYXRhLmF0dGVtcHQpLFxuICAgICAgICAgICAgICAvLyBTdGFuZGFyZCBPVEVMIG1lc3NhZ2luZyBjb252ZW50aW9uc1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nU3lzdGVtKCd2ZXJjZWwtcXVldWUnKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ0Rlc3RpbmF0aW9uTmFtZShtZXRhZGF0YS5xdWV1ZU5hbWUpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nTWVzc2FnZUlkKG1ldGFkYXRhLm1lc3NhZ2VJZCksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdPcGVyYXRpb25UeXBlKCdwcm9jZXNzJyksXG4gICAgICAgICAgICAgIC4uLmdldFF1ZXVlT3ZlcmhlYWQoeyByZXF1ZXN0ZWRBdCB9KSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBOb3RlOiBTdGVwIGZ1bmN0aW9uIHZhbGlkYXRpb24gaGFwcGVucyBhZnRlciBzdGVwX3N0YXJ0ZWQgc28gd2UgY2FuXG4gICAgICAgICAgICAvLyBwcm9wZXJseSBmYWlsIHRoZSBzdGVwIChub3QgdGhlIHJ1bikgaWYgdGhlIGZ1bmN0aW9uIGlzIG5vdCByZWdpc3RlcmVkLlxuICAgICAgICAgICAgLy8gVGhpcyBhbGxvd3MgdGhlIHdvcmtmbG93IHRvIGhhbmRsZSB0aGUgc3RlcCBmYWlsdXJlIGdyYWNlZnVsbHkuXG4gICAgICAgICAgICBjb25zdCBzdGVwRm4gPSBnZXRTdGVwRnVuY3Rpb24oc3RlcE5hbWUpO1xuXG4gICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93TmFtZSh3b3JrZmxvd05hbWUpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5JZCh3b3JrZmxvd1J1bklkKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBJZChzdGVwSWQpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFRyYWNlUHJvcGFnYXRlZCghIXRyYWNlQ29udGV4dCksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1RyYWNlTW9kZSh0cmFjZU1vZGUpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIHN0ZXBfc3RhcnRlZCB2YWxpZGF0ZXMgc3RhdGUgYW5kIHJldHVybnMgdGhlIHN0ZXAgZW50aXR5LCBzbyBubyBzZXBhcmF0ZVxuICAgICAgICAgICAgLy8gd29ybGQuc3RlcHMuZ2V0KCkgY2FsbCBpcyBuZWVkZWQuIFRoZSBzZXJ2ZXIgY2hlY2tzOlxuICAgICAgICAgICAgLy8gLSBTdGVwIG5vdCBpbiB0ZXJtaW5hbCBzdGF0ZSAocmV0dXJucyA0MDkpXG4gICAgICAgICAgICAvLyAtIHJldHJ5QWZ0ZXIgdGltZXN0YW1wIHJlYWNoZWQgKHJldHVybnMgNDI1IHdpdGggUmV0cnktQWZ0ZXIgaGVhZGVyKVxuICAgICAgICAgICAgLy8gLSBXb3JrZmxvdyBzdGlsbCBhY3RpdmUgKHJldHVybnMgNDEwIGlmIGNvbXBsZXRlZClcbiAgICAgICAgICAgIGxldCBzdGVwITogU3RlcDtcbiAgICAgICAgICAgIC8vIEdhdGUgcGF5bG9hZCBjb21wcmVzc2lvbiBvbiB0aGUgc3RlcCBlbnRpdHkncyBzcGVjVmVyc2lvblxuICAgICAgICAgICAgLy8gKHN0YW1wZWQgYnkgdGhlIHNhbWUtZGVwbG95bWVudCBvcmNoZXN0cmF0b3IgdGhhdCBjcmVhdGVkIHRoZVxuICAgICAgICAgICAgLy8gc3RlcCwgc28gc3BlYyA+PSA1IGltcGxpZXMgZXZlcnkgcmVhZGVyIG9mIHRoaXMgcnVuJ3MgcGF5bG9hZHNcbiAgICAgICAgICAgIC8vIHVuZGVyc3RhbmRzIHRoZSAnZ3ppcCcgZm9ybWF0KS4gUmV0dXJucyBmYWxzZSBvbiB0aGUgZWFybHlcbiAgICAgICAgICAgIC8vIGZhaWx1cmUgcGF0aHMgd2hlcmUgc3RlcF9zdGFydGVkIGRpZG4ndCByZXR1cm4gYW4gZW50aXR5LlxuICAgICAgICAgICAgY29uc3QgY29tcHJlc3Npb25Gb3JTdGVwID0gKCkgPT5cbiAgICAgICAgICAgICAgKChzdGVwIGFzIFN0ZXAgfCB1bmRlZmluZWQpPy5zcGVjVmVyc2lvbiA/PyAwKSA+PVxuICAgICAgICAgICAgICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT047XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBzdGFydFJlc3VsdCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX3N0YXJ0ZWQnLFxuICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7IHN0ZXBOYW1lIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgaWYgKCFzdGFydFJlc3VsdC5zdGVwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAgICAgYHN0ZXBfc3RhcnRlZCBldmVudCBmb3IgXCIke3N0ZXBJZH1cIiBkaWQgbm90IHJldHVybiBzdGVwIGVudGl0eWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHN0ZXAgPSBzdGFydFJlc3VsdC5zdGVwO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIGlmIChUaHJvdHRsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXRyeVJldHJ5QWZ0ZXIgPSBNYXRoLm1heChcbiAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICB0eXBlb2YgZXJyLnJldHJ5QWZ0ZXIgPT09ICdudW1iZXInID8gZXJyLnJldHJ5QWZ0ZXIgOiAxXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ1Rocm90dGxlZCBhZ2FpbiBvbiByZXRyeSwgZGVmZXJyaW5nIHRvIHF1ZXVlJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlclNlY29uZHM6IHJldHJ5UmV0cnlBZnRlcixcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiByZXRyeVJldHJ5QWZ0ZXIgfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBFeHBlY3RlZCB3aGVuIGEgcnVuIGlzIGNhbmNlbGxlZCB3aGlsZSBhIHN0ZXAgaXMgaW4tZmxpZ2h0LlxuICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGhhcyBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgc3RlcCcsXG4gICAgICAgICAgICAgICAgICB7IGVycm9yTmFtZTogZXJyLm5hbWUsIGVycm9yTWVzc2FnZTogZXJyLm1lc3NhZ2UgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gYSB0ZXJtaW5hbCBzdGF0ZSDigJQgYW5vdGhlciB3b3JrZXIgZmluaXNoZWRcbiAgICAgICAgICAgICAgICAvLyBpdCBvciBpdCB3YXMgcmV0cmllZCB0byBjb21wbGV0aW9uLiBSZS1lbnF1ZXVlIHRoZSBwYXJlbnRcbiAgICAgICAgICAgICAgICAvLyB3b3JrZmxvdyBzbyBpdCBjYW4gb2JzZXJ2ZSB0aGUgb3V0Y29tZS5cbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICdTdGVwIGluIHRlcm1pbmFsIHN0YXRlLCByZS1lbnF1ZXVpbmcgd29ya2Zsb3cnLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBwZWQodHJ1ZSksXG4gICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBSZWFzb24oJ2NvbXBsZXRlZCcpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNwYW4/LmFkZEV2ZW50Py4oJ3N0ZXAuc2tpcHBlZCcsIHtcbiAgICAgICAgICAgICAgICAgICdza2lwLnJlYXNvbic6ICd0ZXJtaW5hbF9zdGF0ZScsXG4gICAgICAgICAgICAgICAgICAnc3RlcC5uYW1lJzogc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAnc3RlcC5pZCc6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgcmVzb2x2ZWROYW1lc3BhY2UpLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBuZXh0VHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gVG9vIGVhcmx5OiByZXRyeUFmdGVyIHRpbWVzdGFtcCBub3QgcmVhY2hlZCB5ZXRcbiAgICAgICAgICAgICAgLy8gUmV0dXJuIHRpbWVvdXQgdG8gcXVldWUgc28gaXQgcmV0cmllcyBsYXRlclxuICAgICAgICAgICAgICBpZiAoVG9vRWFybHlFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBNYXRoLm1heCgxLCBlcnIucmV0cnlBZnRlciA/PyAxKTtcbiAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlUaW1lb3V0U2Vjb25kcyh0aW1lb3V0U2Vjb25kcyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gQWRkIHNwYW4gZXZlbnQgZm9yIGRlbGF5ZWQgcmV0cnlcbiAgICAgICAgICAgICAgICBzcGFuPy5hZGRFdmVudD8uKCdzdGVwLmRlbGF5ZWQnLCB7XG4gICAgICAgICAgICAgICAgICAnZGVsYXkucmVhc29uJzogJ3JldHJ5X2FmdGVyX25vdF9yZWFjaGVkJyxcbiAgICAgICAgICAgICAgICAgICdkZWxheS50aW1lb3V0X3NlY29uZHMnOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICdTdGVwIHJldHJ5QWZ0ZXIgdGltZXN0YW1wIG5vdCB5ZXQgcmVhY2hlZCcsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHJldHJ5QWZ0ZXJTZWNvbmRzOiBlcnIucmV0cnlBZnRlcixcbiAgICAgICAgICAgICAgICAgICAgdGltZW91dFNlY29uZHMsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kcyB9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFJlLXRocm93IG90aGVyIGVycm9yc1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmRlYnVnKCdTdGVwIGV4ZWN1dGlvbiBkZXRhaWxzJywge1xuICAgICAgICAgICAgICBzdGF0dXM6IHN0ZXAuc3RhdHVzLFxuICAgICAgICAgICAgICBhdHRlbXB0OiBzdGVwLmF0dGVtcHQsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKHN0ZXAuc3RhdHVzKSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBWYWxpZGF0ZSBzdGVwIGZ1bmN0aW9uIGV4aXN0cyBBRlRFUiBzdGVwX3N0YXJ0ZWQgc28gd2UgY2FuXG4gICAgICAgICAgICAvLyBwcm9wZXJseSBmYWlsIHRoZSBzdGVwIChub3QgdGhlIHJ1bikgaWYgdGhlIGZ1bmN0aW9uIGlzIG1pc3NpbmcuXG4gICAgICAgICAgICAvLyBUaGlzIGFsbG93cyB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBzdGVwIGZhaWx1cmUgZ3JhY2VmdWxseSxcbiAgICAgICAgICAgIC8vIHNpbWlsYXIgdG8gaG93IEZhdGFsRXJyb3IgaXMgaGFuZGxlZC5cbiAgICAgICAgICAgIGlmICghc3RlcEZuIHx8IHR5cGVvZiBzdGVwRm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyID0gbmV3IFN0ZXBOb3RSZWdpc3RlcmVkRXJyb3Ioc3RlcE5hbWUpO1xuXG4gICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICdTdGVwIGZ1bmN0aW9uIG5vdCByZWdpc3RlcmVkLCBmYWlsaW5nIHN0ZXAgKG5vdCBydW4pJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgIGVycm9yU3RhY2s6IGVyci5zdGFjayxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKVxuICAgICAgICAgICAgICAvLyBUaGlzIG1hdGNoZXMgdGhlIEZhdGFsRXJyb3IgcGF0dGVybiAtIGZhaWwgdGhlIHN0ZXAgYW5kIHJlLXF1ZXVlIHdvcmtmbG93XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25Gb3JTdGVwKClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRyYW5zaXRpb25lZCB0byBhIHRlcm1pbmFsIHN0YXRlIOKAlCBkdXBsaWNhdGVcbiAgICAgICAgICAgICAgICAgIC8vIGRlbGl2ZXJ5IG9yIGNvbmN1cnJlbnQgY2FuY2VsbGF0aW9uLiBEcm9wIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCBmb3IgbWlzc2luZyBmdW5jdGlvbiwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogc3RlcEZhaWxFcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IHN0ZXBGYWlsRXJyO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgLy8gUmUtaW52b2tlIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIGZhaWxlZCBzdGVwXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUsIHJlc29sdmVkTmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgbmV4dFRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG1heFJldHJpZXMgPSBzdGVwRm4ubWF4UmV0cmllcyA/PyBERUZBVUxUX1NURVBfTUFYX1JFVFJJRVM7XG5cbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcE1heFJldHJpZXMobWF4UmV0cmllcyksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbGV0IHJlc3VsdDogdW5rbm93bjtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgbWF4IHJldHJpZXMgQUZURVIgc3RlcF9zdGFydGVkIChhdHRlbXB0IHdhcyBqdXN0IGluY3JlbWVudGVkKVxuICAgICAgICAgICAgLy8gc3RlcC5hdHRlbXB0IHRyYWNrcyBob3cgbWFueSB0aW1lcyBzdGVwX3N0YXJ0ZWQgaGFzIGJlZW4gY2FsbGVkLlxuICAgICAgICAgICAgLy8gTm90ZTogbWF4UmV0cmllcyBpcyB0aGUgbnVtYmVyIG9mIFJFVFJJRVMgYWZ0ZXIgdGhlIGZpcnN0IGF0dGVtcHQsIHNvIHRvdGFsIGF0dGVtcHRzID0gbWF4UmV0cmllcyArIDFcbiAgICAgICAgICAgIC8vIFVzZSA+IGhlcmUgKG5vdCA+PSkgYmVjYXVzZSB0aGlzIGd1YXJkcyBhZ2FpbnN0IHJlLWludm9jYXRpb24gQUZURVIgYWxsIGF0dGVtcHRzIGFyZSB1c2VkLlxuICAgICAgICAgICAgLy8gVGhlIHBvc3QtZmFpbHVyZSBjaGVjayB1c2VzID49IHRvIGRlY2lkZSB3aGV0aGVyIHRvIHJldHJ5IGFmdGVyIGEgZmFpbHVyZS5cbiAgICAgICAgICAgIGlmIChzdGVwLmF0dGVtcHQgPiBtYXhSZXRyaWVzICsgMSkge1xuICAgICAgICAgICAgICBjb25zdCByZXRyeUNvdW50ID0gc3RlcC5hdHRlbXB0IC0gMTtcbiAgICAgICAgICAgICAgLy8gUGVyc2lzdGVkIG1lc3NhZ2Ug4oCUIGtlcHQgc2hvcnQsIG5vIG1hY2hpbmUgYHN0ZXBOYW1lYCxcbiAgICAgICAgICAgICAgLy8gc2luY2Ugb2JzZXJ2YWJpbGl0eSBhbHJlYWR5IGF0dHJpYnV0ZXMgdGhlIGV2ZW50IHRvIGFcbiAgICAgICAgICAgICAgLy8gc3BlY2lmaWMgc3RlcC5cbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFN0ZXAgZXhjZWVkZWQgbWF4IHJldHJpZXMgKCR7cmV0cnlDb3VudH0gJHtwbHVyYWxpemUoJ3JldHJ5JywgJ3JldHJpZXMnLCByZXRyeUNvdW50KX0pYDtcbiAgICAgICAgICAgICAgc3RlcExvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICBgU3RlcCAke2Zvcm1hdFN0ZXBOYW1lKHN0ZXBOYW1lKX0gZXhjZWVkZWQgbWF4IHJldHJpZXMgKCR7cmV0cnlDb3VudH0gJHtwbHVyYWxpemUoJ3JldHJ5JywgJ3JldHJpZXMnLCByZXRyeUNvdW50KX0pYCxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICByZXRyeUNvdW50LFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgLy8gUHJlc2VydmUgdGhlIHByaW9yIGF0dGVtcHQncyBzZXJpYWxpemVkIGVycm9yIGFzIHRoZSBjYXVzZSBzb1xuICAgICAgICAgICAgICAvLyB0aGUgdW5kZXJseWluZyBmYWlsdXJlIGlzIHJlY292ZXJhYmxlIGZyb20gYHN0ZXAuZXJyb3IuY2F1c2VgXG4gICAgICAgICAgICAgIC8vIGFmdGVyIGh5ZHJhdGlvbiwgd2l0aG91dCBmb3JjaW5nIGNvbnN1bWVycyB0byB3YWxrIHRoZVxuICAgICAgICAgICAgICAvLyBzdGVwX3JldHJ5aW5nIGV2ZW50IGhpc3RvcnkuIE1pcnJvcnMgdGhlIHBvc3QtZmFpbHVyZSBwYXRoXG4gICAgICAgICAgICAgIC8vIGJlbG93IHRoYXQgd3JhcHMgdGhlIGxpdmUgYGVycmAgYXMgY2F1c2UuXG4gICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgIGlmIChzdGVwLmVycm9yICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgKHdyYXBwZWRFcnJvciBhcyBFcnJvcikuY2F1c2UgPSBhd2FpdCBoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBzdGVwLmVycm9yLFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAvLyBJZ25vcmU6IGJlc3QtZWZmb3J0IGNhdXNlIGF0dGFjaG1lbnQsIHRoZSB3cmFwcGluZ1xuICAgICAgICAgICAgICAgICAgLy8gRmF0YWxFcnJvciBzdGFjay9tZXNzYWdlIHN0aWxsIHN1cmZhY2UgdGhlIGZhaWx1cmUuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkRXJyb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25Gb3JTdGVwKClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgdHJhbnNpdGlvbmVkIHRvIGEgdGVybWluYWwgc3RhdGUg4oCUIGR1cGxpY2F0ZVxuICAgICAgICAgICAgICAgICAgLy8gZGVsaXZlcnkgb3IgY29uY3VycmVudCBjb21wbGV0aW9uLiBEcm9wIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIC8vIFJlLWludm9rZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQgc3RlcFxuICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAtLS0gSW5mcmFzdHJ1Y3R1cmU6IHByZXBhcmUgc3RlcCBpbnB1dCAtLS1cbiAgICAgICAgICAgIC8vIE5ldHdvcmsvc2VydmVyIGVycm9ycyBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIHJldHJ5LlxuICAgICAgICAgICAgLy8gV29ya2Zsb3dSdW50aW1lRXJyb3IgKGRhdGEgaW50ZWdyaXR5IGlzc3VlcykgYXJlIGZhdGFsIOKAlCByZXRyeWluZ1xuICAgICAgICAgICAgLy8gd29uJ3QgZml4IHRoZW0sIHNvIHdlIHJlLXF1ZXVlIHRoZSB3b3JrZmxvdyB0byBzdXJmYWNlIHRoZSBlcnJvci5cbiAgICAgICAgICAgIC8vIHN0ZXBfc3RhcnRlZCBhbHJlYWR5IHZhbGlkYXRlZCB0aGUgc3RlcCBpcyBpbiB2YWxpZCBzdGF0ZSAocGVuZGluZy9ydW5uaW5nKVxuICAgICAgICAgICAgLy8gYW5kIHJldHVybmVkIHRoZSB1cGRhdGVkIHN0ZXAgZW50aXR5IHdpdGggaW5jcmVtZW50ZWQgYXR0ZW1wdFxuXG4gICAgICAgICAgICAvLyBzdGVwLmF0dGVtcHQgaXMgbm93IHRoZSBjdXJyZW50IGF0dGVtcHQgbnVtYmVyIChhZnRlciBpbmNyZW1lbnQpXG4gICAgICAgICAgICBjb25zdCBhdHRlbXB0ID0gc3RlcC5hdHRlbXB0O1xuXG4gICAgICAgICAgICBpZiAoIXN0ZXAuc3RhcnRlZEF0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBTdGVwIFwiJHtzdGVwSWR9XCIgaGFzIG5vIFwic3RhcnRlZEF0XCIgdGltZXN0YW1wYDtcbiAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZXJyb3IoJ0ZhdGFsIHJ1bnRpbWUgZXJyb3IgZHVyaW5nIHN0ZXAgc2V0dXAnLCB7XG4gICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSksXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25Gb3JTdGVwKClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChmYWlsRXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyBSZS1xdWV1ZSB0aGUgd29ya2Zsb3cgc28gaXQgY2FuIHByb2Nlc3MgdGhlIHN0ZXAgZmFpbHVyZVxuICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2FwdHVyZSBzdGFydGVkQXQgZm9yIHVzZSBpbiBhc3luYyBjYWxsYmFjayAoVHlwZVNjcmlwdCBuYXJyb3dpbmcgZG9lc24ndCBwZXJzaXN0KVxuICAgICAgICAgICAgY29uc3Qgc3RlcFN0YXJ0ZWRBdCA9IHN0ZXAuc3RhcnRlZEF0O1xuXG4gICAgICAgICAgICAvLyBSZXNvbHZlIHRoZSBlbmNyeXB0aW9uIGtleSBub3cgdGhhdCB3ZSdyZSBjb21taXR0ZWQgdG8gcnVubmluZ1xuICAgICAgICAgICAgLy8gdXNlciBjb2RlOiBpbnB1dCBoeWRyYXRpb24gbmVlZHMgaXQsIGFuZCBgY29udGV4dFN0b3JhZ2VgIChhbmRcbiAgICAgICAgICAgIC8vIGFueSB1c2VyLWNvZGUgcGF0aHMgdGhhdCBydW4gaW5zaWRlIGl0KSBjYXB0dXJlIHRoZSByZXNvbHZlZFxuICAgICAgICAgICAgLy8gdmFsdWUuIFRyaWdnZXJzIHRoZSB1bmRlcmx5aW5nIHdvcmxkIC8gS01TIGZldGNoIG9uY2UsIHdpdGhcbiAgICAgICAgICAgIC8vIHN1YnNlcXVlbnQgZGVoeWRyYXRlIHBhdGhzIHJldXNpbmcgdGhlIG1lbW9pemVkIHJlc3VsdC5cbiAgICAgICAgICAgIGNvbnN0IGVuY3J5cHRpb25LZXkgPSBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCk7XG5cbiAgICAgICAgICAgIC8vIEh5ZHJhdGUgdGhlIHN0ZXAgaW5wdXQgYXJndW1lbnRzLCBjbG9zdXJlIHZhcmlhYmxlcywgYW5kIHRoaXNWYWxcbiAgICAgICAgICAgIC8vIE5PVEU6IFRoaXMgY2FwdHVyZXMgb25seSB0aGUgc3luY2hyb25vdXMgcG9ydGlvbiBvZiBoeWRyYXRpb24uIEFueSBhc3luY1xuICAgICAgICAgICAgLy8gb3BlcmF0aW9ucyAoZS5nLiwgc3RyZWFtIGxvYWRpbmcpIGFyZSBhZGRlZCB0byBgb3BzYCBhbmQgZXhlY3V0ZWQgbGF0ZXJcbiAgICAgICAgICAgIC8vIHZpYSBQcm9taXNlLmFsbChvcHMpIC0gdGhlaXIgdGltaW5nIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGlzIG1lYXN1cmVtZW50LlxuICAgICAgICAgICAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgICAgICAgICAgIC8vIE9wcyB0aGF0IG11c3QgYmUgZHVyYWJseSBjb21taXR0ZWQgYmVmb3JlIHN0ZXAgY29tcGxldGlvbiAoZS5nLiBhXG4gICAgICAgICAgICAvLyBzdGVwLWluaXRpYXRlZCBhYm9ydCdzIGhvb2tfcmVjZWl2ZWQgZXZlbnQpLiBTZWUgU3RlcENvbnRleHQuXG4gICAgICAgICAgICBjb25zdCBwcmVDb21wbGV0aW9uT3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgICAgICAgICAgIGNvbnN0IGh5ZHJhdGVkSW5wdXQgPSBhd2FpdCB0cmFjZShcbiAgICAgICAgICAgICAgJ3N0ZXAuaHlkcmF0ZScsXG4gICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICBhc3luYyAoaHlkcmF0ZVNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICAgICAgc3RlcC5pbnB1dCxcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgb3BzLFxuICAgICAgICAgICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgcHJvY2Vzcy5lbnYuVkVSQ0VMX0RFUExPWU1FTlRfSURcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xuICAgICAgICAgICAgICAgIGh5ZHJhdGVTcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwQXJndW1lbnRzQ291bnQocmVzdWx0LmFyZ3MubGVuZ3RoKSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZURlc2VyaWFsaXplVGltZU1zKGR1cmF0aW9uTXMpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBoeWRyYXRlZElucHV0LmFyZ3M7XG4gICAgICAgICAgICBjb25zdCB0aGlzVmFsID0gaHlkcmF0ZWRJbnB1dC50aGlzVmFsID8/IG51bGw7XG5cbiAgICAgICAgICAgIC8vIC0tLSBVc2VyIGNvZGUgZXhlY3V0aW9uIC0tLVxuICAgICAgICAgICAgLy8gT25seSBlcnJvcnMgZnJvbSBzdGVwRm4uYXBwbHkoKSAodXNlciBzdGVwIGNvZGUpIHNob3VsZCBwcm9kdWNlXG4gICAgICAgICAgICAvLyBzdGVwX2ZhaWxlZC9zdGVwX3JldHJ5aW5nLiBJbmZyYXN0cnVjdHVyZSBlcnJvcnMgKG5ldHdvcmssIHNlcnZlcilcbiAgICAgICAgICAgIC8vIG11c3QgcHJvcGFnYXRlIHRvIHRoZSBxdWV1ZSBoYW5kbGVyIGZvciBhdXRvbWF0aWMgcmV0cnkuXG4gICAgICAgICAgICBsZXQgdXNlckNvZGVFcnJvcjogdW5rbm93bjtcbiAgICAgICAgICAgIGxldCB1c2VyQ29kZUZhaWxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBjb25zdCBleGVjdXRpb25TdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgdHJhY2UoJ3N0ZXAuZXhlY3V0ZScsIHt9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGNvbnRleHRTdG9yYWdlLnJ1bihcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc3RlcE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBTdGFydGVkQXQ6IG5ldyBEYXRlKCtzdGVwU3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd01ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQ6IG5ldyBEYXRlKCt3b3JrZmxvd1N0YXJ0ZWRBdCksXG4gICAgICAgICAgICAgICAgICAgICAgdXJsOiB3b3JrZmxvd0Jhc2VVcmwsXG4gICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXM6IHsgZW5jcnlwdGlvbjogISFlbmNyeXB0aW9uS2V5IH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93RGVwbG95bWVudElkOiBwcm9jZXNzLmVudi5WRVJDRUxfREVQTE9ZTUVOVF9JRCxcbiAgICAgICAgICAgICAgICAgICAgb3BzLFxuICAgICAgICAgICAgICAgICAgICBwcmVDb21wbGV0aW9uT3BzLFxuICAgICAgICAgICAgICAgICAgICBjbG9zdXJlVmFyczogaHlkcmF0ZWRJbnB1dC5jbG9zdXJlVmFycyxcbiAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAoKSA9PiBzdGVwRm4uYXBwbHkodGhpc1ZhbCwgYXJncylcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICB1c2VyQ29kZUVycm9yID0gZXJyO1xuICAgICAgICAgICAgICB1c2VyQ29kZUZhaWxlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBleGVjdXRpb25UaW1lTXMgPSBEYXRlLm5vdygpIC0gZXhlY3V0aW9uU3RhcnRUaW1lO1xuXG4gICAgICAgICAgICBjYW5jZWxBYm9ydFJlYWRlcnMoLi4uYXJncywgdGhpc1ZhbCwgaHlkcmF0ZWRJbnB1dC5jbG9zdXJlVmFycyk7XG5cbiAgICAgICAgICAgIC8vIENvbW1pdCBtdXN0LWJlLWR1cmFibGUgb3BzIChlLmcuIGEgc3RlcC1pbml0aWF0ZWQgYWJvcnQnc1xuICAgICAgICAgICAgLy8gaG9va19yZWNlaXZlZCBldmVudCkgYmVmb3JlIHdyaXRpbmcgc3RlcF9jb21wbGV0ZWQvc3RlcF9mYWlsZWQsXG4gICAgICAgICAgICAvLyBzbyBhbnkgd29ya2Zsb3cgY29udGludWF0aW9uIHRyaWdnZXJlZCBieSB0aGF0IGV2ZW50IG9ic2VydmVzIHRoZVxuICAgICAgICAgICAgLy8gYWJvcnQgcmF0aGVyIHRoYW4gcmFjaW5nIGl0LiBQcm9kdWNlcnMgc3dhbGxvdyB0aGVpciBvd24gZXJyb3JzXG4gICAgICAgICAgICAvLyBwZXIgdGhlIG5vLXJlamVjdCBjb250cmFjdCBvbiBTdGVwQ29udGV4dC5wcmVDb21wbGV0aW9uT3BzOyB0aGVcbiAgICAgICAgICAgIC8vIGAuY2F0Y2goKWAgZGVmZW5kcyBpdCwgc2luY2UgdGhpcyBhd2FpdCBzaXRzIG91dHNpZGUgdGhlXG4gICAgICAgICAgICAvLyB1c2VyLWNvZGUgdHJ5L2NhdGNoIChhIHN0cmF5IHJlamVjdGlvbiBoZXJlIHdvdWxkIG90aGVyd2lzZVxuICAgICAgICAgICAgLy8gc3VyZmFjZSBhcyBhbiBpbmZyYSBlcnJvciDihpIgcXVldWUgcmUtZGVsaXZlcnksIG5vdCBhIHN0ZXBcbiAgICAgICAgICAgIC8vIGZhaWx1cmUpLiBUaGUgYXdhaXQgb25seSBlbmZvcmNlcyBvcmRlcmluZy5cbiAgICAgICAgICAgIGlmIChwcmVDb21wbGV0aW9uT3BzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJlQ29tcGxldGlvbk9wcykuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlRXhlY3V0aW9uVGltZU1zKGV4ZWN1dGlvblRpbWVNcyksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gLS0tIERlaHlkcmF0ZSAoc2VyaWFsaXplKSB0aGUgc3RlcCdzIHJldHVybiB2YWx1ZSAtLS1cbiAgICAgICAgICAgIC8vIEEgbm9uLXNlcmlhbGl6YWJsZSByZXR1cm4gdmFsdWUgaXMgYSB1c2VyLWNvZGUgYnVnLCBub3QgYW5cbiAgICAgICAgICAgIC8vIGluZnJhc3RydWN0dXJlIGZhaWx1cmUuIFJvdXRlIGl0IHRocm91Z2ggdGhlIHNhbWUgc3RlcC1mYWlsdXJlXG4gICAgICAgICAgICAvLyBwYXRoIGFzIGEgdGhyb3duIGVycm9yIHNvIFNlcmlhbGl6YXRpb25FcnJvciAod2hpY2ggaXMgbWFya2VkXG4gICAgICAgICAgICAvLyBgZmF0YWw6IHRydWVgKSBzaG9ydC1jaXJjdWl0cyB0aGUgcmV0cnkgbG9vcCBpbnN0ZWFkIG9mXG4gICAgICAgICAgICAvLyBidWJibGluZyBhcyBhbiBIVFRQIDUwMCBhbmQgYnVybmluZyB0aHJvdWdoIGFsbCA0IHF1ZXVlXG4gICAgICAgICAgICAvLyBkZWxpdmVyaWVzIG9uIGEgZ3VhcmFudGVlZC10by1mYWlsIG1lc3NhZ2UuXG4gICAgICAgICAgICBpZiAoIXVzZXJDb2RlRmFpbGVkKSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgdHJhY2UoXG4gICAgICAgICAgICAgICAgICAnc3RlcC5kZWh5ZHJhdGUnLFxuICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICBhc3luYyAoZGVoeWRyYXRlU3BhbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIHJldHVybiB2YWx1ZXMgYXJlIGNvbnN1bWVkIGJ5IHRoZSB3b3JrZmxvdyBWTVxuICAgICAgICAgICAgICAgICAgICAvLyBydW5uaW5nIG9uIHRoaXMgc2FtZSBkZXBsb3ltZW50ICh2ZXJzaW9uIHNrZXdcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJvdGVjdGlvbiBlbnN1cmVzIGl0KS4gQnl0ZS1zdHJlYW0gZnJhbWluZyBpc1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGVyZWZvcmUgYWx3YXlzIHNhZmUgaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVoeWRyYXRlZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICAgIG9wcyxcbiAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25Gb3JTdGVwKClcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZHVyYXRpb25NcyA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgICAgICAgICAgICAgIGRlaHlkcmF0ZVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZVNlcmlhbGl6ZVRpbWVNcyhkdXJhdGlvbk1zKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJlc3VsdFR5cGUodHlwZW9mIGRlaHlkcmF0ZWQpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlaHlkcmF0ZWQ7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdXNlckNvZGVFcnJvciA9IGVycjtcbiAgICAgICAgICAgICAgICB1c2VyQ29kZUZhaWxlZCA9IHRydWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gLS0tIEhhbmRsZSB1c2VyIGNvZGUgZXJyb3JzIC0tLVxuICAgICAgICAgICAgaWYgKHVzZXJDb2RlRmFpbGVkKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVyciA9IHVzZXJDb2RlRXJyb3I7XG5cbiAgICAgICAgICAgICAgLy8gSW5mcmFzdHJ1Y3R1cmUgZXJyb3JzIHRoYXQgc29tZWhvdyBzdXJmYWNlZCB0aHJvdWdoIHVzZXIgY29kZVxuICAgICAgICAgICAgICAvLyBzaG91bGQgcHJvcGFnYXRlIHRvIHRoZSBxdWV1ZSBoYW5kbGVyIGZvciByZXRyeSwgbm90IGNvbnN1bWVcbiAgICAgICAgICAgICAgLy8gc3RlcCBhdHRlbXB0cy5cbiAgICAgICAgICAgICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgLy8gV29ya2Zsb3cgaGFzIGFscmVhZHkgY29tcGxldGVkLCBzbyBuby1vcFxuICAgICAgICAgICAgICAgIHN0ZXBMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIHN0ZXAnLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChXb3JrZmxvd1dvcmxkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIuc3RhdHVzICE9PSB1bmRlZmluZWQgJiYgZXJyLnN0YXR1cyA+PSA1MDApIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAvLyBBYm9ydCBmYWlsdXJlcyBjYW4gY3Jvc3MgVk0vc2VyaWFsaXphdGlvbiByZWFsbXMsIHdoZXJlXG4gICAgICAgICAgICAgIC8vIGBpbnN0YW5jZW9mIEVycm9yYCBpcyBub3QgcmVsaWFibGUuXG4gICAgICAgICAgICAgIGNvbnN0IGVmZmVjdGl2ZUVyciA9IHByb21vdGVBYm9ydEVycm9yVG9GYXRhbChlcnIpO1xuICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkRXJyb3IgPSBhd2FpdCBub3JtYWxpemVVbmtub3duRXJyb3IoZWZmZWN0aXZlRXJyKTtcbiAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFN0YWNrID1cbiAgICAgICAgICAgICAgICBub3JtYWxpemVkRXJyb3Iuc3RhY2sgfHwgZ2V0RXJyb3JTdGFjayhlZmZlY3RpdmVFcnIpIHx8ICcnO1xuXG4gICAgICAgICAgICAgIC8vIFJlY29yZCBleGNlcHRpb24gZm9yIE9URUwgZXJyb3IgdHJhY2tpbmdcbiAgICAgICAgICAgICAgaWYgKGVmZmVjdGl2ZUVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICAgICAgc3Bhbj8ucmVjb3JkRXhjZXB0aW9uPy4oZWZmZWN0aXZlRXJyKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIERldGVybWluZSBlcnJvciBjYXRlZ29yeSBhbmQgcmV0cnlhYmlsaXR5XG4gICAgICAgICAgICAgIGNvbnN0IGlzRmF0YWwgPSBGYXRhbEVycm9yLmlzKGVmZmVjdGl2ZUVycik7XG4gICAgICAgICAgICAgIGNvbnN0IGlzUmV0cnlhYmxlID0gUmV0cnlhYmxlRXJyb3IuaXMoZWZmZWN0aXZlRXJyKTtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JDYXRlZ29yeSA9IGlzRmF0YWxcbiAgICAgICAgICAgICAgICA/ICdmYXRhbCdcbiAgICAgICAgICAgICAgICA6IGlzUmV0cnlhYmxlXG4gICAgICAgICAgICAgICAgICA/ICdyZXRyeWFibGUnXG4gICAgICAgICAgICAgICAgICA6ICd0cmFuc2llbnQnO1xuXG4gICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRXJyb3JOYW1lKGdldEVycm9yTmFtZShlZmZlY3RpdmVFcnIpKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEVycm9yTWVzc2FnZShub3JtYWxpemVkRXJyb3IubWVzc2FnZSksXG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLkVycm9yVHlwZShnZXRFcnJvck5hbWUoZWZmZWN0aXZlRXJyKSksXG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLkVycm9yQ2F0ZWdvcnkoZXJyb3JDYXRlZ29yeSksXG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLkVycm9yUmV0cnlhYmxlKCFpc0ZhdGFsKSxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgaWYgKGlzRmF0YWwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IGRlc2NyaWJlRXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcmllbmRseVN0ZXAgPSBmb3JtYXRTdGVwTmFtZShzdGVwTmFtZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZnJhbWluZyA9XG4gICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5hdHRyaWJ1dGlvbiA9PT0gJ3NkaydcbiAgICAgICAgICAgICAgICAgICAgPyBgU3RlcCAke2ZyaWVuZGx5U3RlcH0gZmFpbGVkIHdpdGggYSBGYXRhbEVycm9yIGZyb20gdGhlIFNESyBydW50aW1lIOKAlCBidWJibGluZyB1cCB0byBwYXJlbnQgd29ya2Zsb3dgXG4gICAgICAgICAgICAgICAgICAgIDogYFN0ZXAgJHtmcmllbmRseVN0ZXB9IHRocmV3IGEgRmF0YWxFcnJvciDigJQgYnViYmxpbmcgdXAgdG8gcGFyZW50IHdvcmtmbG93YDtcbiAgICAgICAgICAgICAgICAvLyBNaXJyb3IgdGhlIHdvcmtmbG93LWxldmVsIGxvZyBmb3JtYXR0aW5nOiBwdXQgdGhlIGZyYW1pbmcgK1xuICAgICAgICAgICAgICAgIC8vIHN0YWNrIGludG8gdGhlIG1lc3NhZ2Ugc28gY29uc29sZS5lcnJvciByZW5kZXJzIHRoZSBzdGFja1xuICAgICAgICAgICAgICAgIC8vIGlubGluZSwgYW5kIGtlZXAgdGhlIG1ldGFkYXRhIG9iamVjdCBzbWFsbCB3aXRoIG9ubHkgdGhlXG4gICAgICAgICAgICAgICAgLy8gc3RydWN0dXJlZCBmaWVsZHMgdGhhdCBsb2cgZHJhaW5zIHdhbnQgdG8gaW5kZXguXG4gICAgICAgICAgICAgICAgLy8gTm8gYGhpbnRgIGZpZWxkIGhlcmUg4oCUIGFjdGlvbmFibGUgaGludCB0ZXh0IGxpdmVzIG9uIHRoZVxuICAgICAgICAgICAgICAgIC8vIGVycm9yIG1lc3NhZ2UgaXRzZWxmIChzbyBpdCBzdXJ2aXZlcyBzZXJpYWxpemF0aW9uIOKGklxuICAgICAgICAgICAgICAgIC8vIGV2ZW50IGxvZyDihpIgb2JzZXJ2YWJpbGl0eSByZWh5ZHJhdGUpLCBhbmQgYWRkaW5nIGl0XG4gICAgICAgICAgICAgICAgLy8gYWdhaW4gaGVyZSBqdXN0IGR1cGxpY2F0ZXMgaXQgb24gc3RkZXJyLlxuICAgICAgICAgICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgICBgJHtmcmFtaW5nfVxcbiR7bm9ybWFsaXplZFN0YWNrIHx8IG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlfWAsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQXR0cmlidXRpb246IGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uLFxuICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IG5vcm1hbGl6ZWRFcnJvci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgICAvLyBQZXJzaXN0IHRoZSBwcm9tb3RlZCBGYXRhbEVycm9yIGZvciBhYm9ydHMgc28gdGhlIHBhcmVudFxuICAgICAgICAgICAgICAgIC8vIHdvcmtmbG93IGNhbiBkaXN0aW5ndWlzaCBjYW5jZWxsYXRpb24gZnJvbSByZXRyeSBleGhhdXN0aW9uLlxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdGl2ZUVycixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uRm9yU3RlcCgpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoc3RlcEZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gdGVybWluYWwgc3RhdGUg4oCUIGlkZW1wb3RlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IHN0ZXBGYWlsRXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhSZXRyaWVzID1cbiAgICAgICAgICAgICAgICAgIHN0ZXBGbi5tYXhSZXRyaWVzID8/IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUztcbiAgICAgICAgICAgICAgICAvLyBzdGVwLmF0dGVtcHQgd2FzIGluY3JlbWVudGVkIGJ5IHN0ZXBfc3RhcnRlZCwgdXNlIGl0IGhlcmVcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50QXR0ZW1wdCA9IHN0ZXAuYXR0ZW1wdDtcblxuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBdHRlbXB0KGN1cnJlbnRBdHRlbXB0KSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTWF4UmV0cmllcyhtYXhSZXRyaWVzKSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIE5vdGU6IG1heFJldHJpZXMgaXMgdGhlIG51bWJlciBvZiBSRVRSSUVTIGFmdGVyIHRoZSBmaXJzdCBhdHRlbXB0LCBzbyB0b3RhbCBhdHRlbXB0cyA9IG1heFJldHJpZXMgKyAxXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRBdHRlbXB0ID49IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAvLyBNYXggcmV0cmllcyByZWFjaGVkXG4gICAgICAgICAgICAgICAgICBjb25zdCByZXRyeUNvdW50ID0gc3RlcC5hdHRlbXB0IC0gMTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJpZW5kbHlTdGVwID0gZm9ybWF0U3RlcE5hbWUoc3RlcE5hbWUpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJhbWluZyA9XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uID09PSAnc2RrJ1xuICAgICAgICAgICAgICAgICAgICAgID8gYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyBvbiBhbiBTREsgcnVudGltZSBlcnJvciDigJQgYnViYmxpbmcgdG8gcGFyZW50IHdvcmtmbG93YFxuICAgICAgICAgICAgICAgICAgICAgIDogYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyDigJQgYnViYmxpbmcgZXJyb3IgdGhyb3duIGJ5IHlvdXIgc3RlcCB0byB0aGUgcGFyZW50IHdvcmtmbG93YDtcbiAgICAgICAgICAgICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGAke2ZyYW1pbmd9XFxuJHtub3JtYWxpemVkU3RhY2sgfHwgbm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0OiBzdGVwLmF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvckF0dHJpYnV0aW9uOiBkZXNjcmlwdGlvbi5hdHRyaWJ1dGlvbixcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IG5vcm1hbGl6ZWRFcnJvci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogbm9ybWFsaXplZEVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAvLyBEb24ndCBpbmNsdWRlIHRoZSBtYWNoaW5lIHN0ZXAgbmFtZSBpbiB0aGUgcGVyc2lzdGVkXG4gICAgICAgICAgICAgICAgICAvLyBlcnJvciBtZXNzYWdlIOKAlCBvYnNlcnZhYmlsaXR5IGFscmVhZHkgc2hvd3Mgd2hpY2ggc3RlcFxuICAgICAgICAgICAgICAgICAgLy8gcHJvZHVjZWQgdGhlIGV2ZW50LCBhbmQgYHN0ZXBOYW1lOiAnc3RlcC8vLi8uLi4vZm9vJ2BcbiAgICAgICAgICAgICAgICAgIC8vIGluIHRoZSB0aXRsZSBpcyBqdXN0IG5vaXNlLiBUaGUgQ0xJIGxvZ2dlciByZW5kZXJzXG4gICAgICAgICAgICAgICAgICAvLyBgU3RlcCBmb28gKC4vLi4uKSBoaXQgbWF4IHJldHJpZXNgIHNlcGFyYXRlbHkuXG4gICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBmYWlsZWQgYWZ0ZXIgJHttYXhSZXRyaWVzfSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIG1heFJldHJpZXMpfTogJHtub3JtYWxpemVkRXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgICAgIC8vIFdyYXAgdGhlIG9yaWdpbmFsIGVycm9yIHdpdGggYSBGYXRhbEVycm9yIHRoYXQgcHJlc2VydmVzXG4gICAgICAgICAgICAgICAgICAvLyB0aGUgd3JhcHBlZCBtZXNzYWdlIHBsdXMgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBhc1xuICAgICAgICAgICAgICAgICAgLy8gYGNhdXNlYCBzbyBpdCdzIHJlY292ZXJhYmxlIGFmdGVyIGh5ZHJhdGlvbi5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGVycjtcbiAgICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkU3RhY2spIHdyYXBwZWRFcnJvci5zdGFjayA9IG5vcm1hbGl6ZWRTdGFjaztcbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZEVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uRm9yU3RlcCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoc3RlcEZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoc3RlcEZhaWxFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlIOKAlCBpZGVtcG90ZW50LlxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IHN0ZXBGYWlsRXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogc3RlcEZhaWxFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeUV4aGF1c3RlZCh0cnVlKSxcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAvLyBOb3QgYXQgbWF4IHJldHJpZXMgeWV0IC0gbG9nIGFzIGEgcmV0cnlhYmxlIGVycm9yXG4gICAgICAgICAgICAgICAgICBpZiAoUmV0cnlhYmxlRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICBzdGVwTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ0VuY291bnRlcmVkIFJldHJ5YWJsZUVycm9yLCBzdGVwIHdpbGwgYmUgcmV0cmllZCcsXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0ZW1wdDogY3VycmVudEF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yU3RhY2s6IG5vcm1hbGl6ZWRTdGFjayxcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdGVwTG9nZ2VyLmluZm8oJ0VuY291bnRlcmVkIEVycm9yLCBzdGVwIHdpbGwgYmUgcmV0cmllZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgYXR0ZW1wdDogY3VycmVudEF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBub3JtYWxpemVkRXJyb3IubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yU3RhY2s6IG5vcm1hbGl6ZWRTdGFjayxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAvLyBTZXQgc3RlcCB0byBwZW5kaW5nIGZvciByZXRyeSB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKVxuICAgICAgICAgICAgICAgICAgLy8gc3RlcF9yZXRyeWluZyByZWNvcmRzIHRoZSBlcnJvciBhbmQgc2V0cyBzdGF0dXMgdG8gcGVuZGluZy5cbiAgICAgICAgICAgICAgICAgIC8vIFNlcmlhbGl6ZSB0aGUgb3JpZ2luYWwgdGhyb3duIHZhbHVlIHNvIGl0cyBmdWxsIHR5cGUgaWRlbnRpdHlcbiAgICAgICAgICAgICAgICAgIC8vIGFuZCBjdXN0b20gcHJvcGVydGllcyByb3VuZC10cmlwIHRocm91Z2ggdGhlIGV2ZW50IGxvZy5cbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX3JldHJ5aW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25Gb3JTdGVwKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKFJldHJ5YWJsZUVycm9yLmlzKGVycikgJiYge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHJ5QWZ0ZXI6IGVyci5yZXRyeUFmdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9IGNhdGNoIChzdGVwUmV0cnlFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoc3RlcFJldHJ5RXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIFN0ZXAgYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZSDigJQgaWRlbXBvdGVudC5cbiAgICAgICAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIHJldHJ5aW5nIHN0ZXAsIGJ1dCBzdGVwIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogc3RlcFJldHJ5RXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogc3RlcFJldHJ5RXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgc3RlcFJldHJ5RXJyO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBSZXRyeWFibGVFcnJvci5pcyhlcnIpXG4gICAgICAgICAgICAgICAgICAgICAgPyBNYXRoLmNlaWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICgrZXJyLnJldHJ5QWZ0ZXIuZ2V0VGltZSgpIC0gRGF0ZS5ub3coKSkgLyAxMDAwXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgOiAxXG4gICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeVRpbWVvdXRTZWNvbmRzKHRpbWVvdXRTZWNvbmRzKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeVdpbGxSZXRyeSh0cnVlKSxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAvLyBBZGQgc3BhbiBldmVudCBmb3IgcmV0cnkgc2NoZWR1bGluZ1xuICAgICAgICAgICAgICAgICAgc3Bhbj8uYWRkRXZlbnQ/LigncmV0cnkuc2NoZWR1bGVkJywge1xuICAgICAgICAgICAgICAgICAgICAncmV0cnkudGltZW91dF9zZWNvbmRzJzogdGltZW91dFNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICdyZXRyeS5hdHRlbXB0JzogY3VycmVudEF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICdyZXRyeS5tYXhfcmV0cmllcyc6IG1heFJldHJpZXMsXG4gICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgLy8gSXQncyBhIHJldHJ5YWJsZSBlcnJvciAtIHNvIGhhdmUgdGhlIHF1ZXVlIGtlZXAgdGhlIG1lc3NhZ2UgdmlzaWJsZVxuICAgICAgICAgICAgICAgICAgLy8gc28gdGhhdCBpdCBnZXRzIHJldHJpZWQuXG4gICAgICAgICAgICAgICAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kcyB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIFJlLWludm9rZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQvcmV0cnlpbmcgc3RlcFxuICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IG5leHRUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAtLS0gSW5mcmFzdHJ1Y3R1cmU6IGNvbXBsZXRlIHRoZSBzdGVwIC0tLVxuICAgICAgICAgICAgLy8gRXJyb3JzIGhlcmUgKG5ldHdvcmsgZmFpbHVyZXMsIHNlcnZlciBlcnJvcnMpIHByb3BhZ2F0ZSB0byB0aGVcbiAgICAgICAgICAgIC8vIHF1ZXVlIGhhbmRsZXIgZm9yIGF1dG9tYXRpYyByZXRyeS5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBOT1RFOiBOb25lIG9mIHRoZSBjb2RlIGZyb20gdGhpcyBwb2ludCBpcyBndWFyYW50ZWVkIHRvIHJ1bi5cbiAgICAgICAgICAgIC8vIFNpbmNlIHRoZSBzdGVwIG1pZ2h0IGZhaWwgb3IgY2F1c2UgYSBmdW5jdGlvbiB0aW1lb3V0IGFuZCB0aGVcbiAgICAgICAgICAgIC8vIHByb2Nlc3MgbWlnaHQgYmUgU0lHS0lMTCdkLCB0aGUgd29ya2Zsb3cgcnVudGltZSBtdXN0IGJlXG4gICAgICAgICAgICAvLyByZXNpbGllbnQgdG8gdGhlIGJlbG93IGNvZGUgbm90IGV4ZWN1dGluZyBvbiBhIGZhaWxlZCBzdGVwLlxuICAgICAgICAgICAgLy8gKERlaHlkcmF0aW9uIGFscmVhZHkgaGFwcGVuZWQgYWJvdmUgYW5kIGlzIGFjY291bnRlZCBmb3IgaW4gdGhlXG4gICAgICAgICAgICAvLyB1c2VyQ29kZUZhaWxlZCBwYXRoLilcbiAgICAgICAgICAgIC8vIFRoZXNlIHN0cmVhbSBvcHMgYXJlIGZsdXNoZWQgaW4gdGhlIGJhY2tncm91bmQ7IHRoZSBwcm9taXNlXG4gICAgICAgICAgICAvLyBoYW5kZWQgdG8gd2FpdFVudGlsIG11c3QgbmV2ZXIgcmVqZWN0IChhbiB1bmNvbnN1bWVkIHdhaXRVbnRpbFxuICAgICAgICAgICAgLy8gcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSwgc29cbiAgICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgZmFpbHVyZXMgYXJlIGxvZ2dlZCBpbnN0ZWFkLlxuICAgICAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgICAgJ0JhY2tncm91bmQgZmx1c2ggb2Ygc3RlcCBzdHJlYW0gb3BzIGZhaWxlZCcsXG4gICAgICAgICAgICAgICAgeyBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBSdW4gc3RlcF9jb21wbGV0ZWQgYW5kIHRyYWNlIHNlcmlhbGl6YXRpb24gY29uY3VycmVudGx5O1xuICAgICAgICAgICAgLy8gdGhlIHRyYWNlIGNhcnJpZXIgaXMgdXNlZCBpbiB0aGUgZmluYWwgcXVldWVNZXNzYWdlIGNhbGwgYmVsb3dcbiAgICAgICAgICAgIGxldCBzdGVwQ29tcGxldGVkNDA5ID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBbLCB0cmFjZUNhcnJpZXJdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICB3b3JsZC5ldmVudHNcbiAgICAgICAgICAgICAgICAuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jb21wbGV0ZWQnLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgcmVzdWx0OiByZXN1bHQgYXMgVWludDhBcnJheSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN0ZXAgYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZSDigJQgaWRlbXBvdGVudC5cbiAgICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAnVHJpZWQgY29tcGxldGluZyBzdGVwLCBidXQgc3RlcCBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgc3RlcENvbXBsZXRlZDQwOSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgbmV4dFRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIGlmIChzdGVwQ29tcGxldGVkNDA5KSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXN1bHRUeXBlKHR5cGVvZiByZXN1bHQpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFF1ZXVlIHRoZSB3b3JrZmxvdyBjb250aW51YXRpb24gd2l0aCB0aGUgY29uY3VycmVudGx5LXJlc29sdmVkIHRyYWNlIGNhcnJpZXJcbiAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgcmVzb2x2ZWROYW1lc3BhY2UpLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5jb25zdCBzdGVwSGFuZGxlciA9IGNyZWF0ZVN0ZXBIYW5kbGVyKCk7XG5cbi8qKlxuICogQSBzaW5nbGUgcm91dGUgdGhhdCBoYW5kbGVzIGFueSBzdGVwIGV4ZWN1dGlvbiByZXF1ZXN0IGFuZCByb3V0ZXMgdG8gdGhlXG4gKiBhcHByb3ByaWF0ZSBzdGVwIGZ1bmN0aW9uLiBXZSBtYXkgZXZlbnR1YWxseSB3YW50IHRvIGNyZWF0ZSBkaWZmZXJlbnQgYnVuZGxlc1xuICogZm9yIGVhY2ggc3RlcCwgdGhpcyBpcyB0ZW1wb3JhcnkuXG4gKi9cbmxldCBjYWNoZWRTdGVwSGFuZGxlcjogKChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+KSB8IHVuZGVmaW5lZDtcbmV4cG9ydCBjb25zdCBzdGVwRW50cnlwb2ludDogKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4gPVxuICAvKiBAX19QVVJFX18gKi8gd2l0aEhlYWx0aENoZWNrKGFzeW5jIChyZXEpID0+IHtcbiAgICBpZiAoIWNhY2hlZFN0ZXBIYW5kbGVyKSB7XG4gICAgICBjYWNoZWRTdGVwSGFuZGxlciA9IHN0ZXBIYW5kbGVyKGF3YWl0IGdldFdvcmxkSGFuZGxlcnMoKSk7XG4gICAgfVxuICAgIHJldHVybiBjYWNoZWRTdGVwSGFuZGxlcihyZXEpO1xuICB9KTtcbiJdfQ==