@workflow/world-local 4.2.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fs.d.ts +10 -0
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -16
- package/dist/instrumentObject.d.ts.map +1 -1
- package/dist/instrumentObject.js +69 -3
- package/dist/storage/events-storage.d.ts.map +1 -1
- package/dist/storage/events-storage.js +1043 -610
- package/dist/storage/helpers.d.ts +13 -0
- package/dist/storage/helpers.d.ts.map +1 -1
- package/dist/storage/helpers.js +23 -1
- package/dist/storage/hooks-storage.d.ts +2 -1
- package/dist/storage/hooks-storage.d.ts.map +1 -1
- package/dist/storage/hooks-storage.js +120 -7
- package/dist/telemetry.d.ts +8 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +5 -1
- package/package.json +4 -4
|
@@ -1,16 +1,52 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { EntityConflictError, HookNotFoundError, RunExpiredError, RunNotSupportedError, TooEarlyError, WorkflowWorldError, } from '@workflow/errors';
|
|
4
|
-
import { EventSchema, HookSchema, isLegacySpecVersion, requiresNewerWorld, SPEC_VERSION_CURRENT, StepSchema, validateUlidTimestamp, WaitSchema, WorkflowRunSchema, } from '@workflow/world';
|
|
4
|
+
import { EventSchema, HookSchema, isLegacySpecVersion, isTerminalStepStatus, isTerminalWorkflowRunStatus, requiresNewerWorld, SPEC_VERSION_CURRENT, StepSchema, ulidToDate, validateUlidTimestamp, WaitSchema, WorkflowRunSchema, } from '@workflow/world';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';
|
|
7
7
|
import { assertSafeEntityId, deleteJSON, jsonReplacer, listJSONFiles, paginatedFileSystemQuery, readJSON, readJSONWithFallback, resolveWithinBase, taggedPath, writeExclusive, writeJSON, } from '../fs.js';
|
|
8
8
|
import { stripEventDataRefs } from './filters.js';
|
|
9
|
-
import { getObjectCreatedAt, hashToken, monotonicUlid } from './helpers.js';
|
|
10
|
-
import { deleteAllHooksForRun } from './hooks-storage.js';
|
|
9
|
+
import { getObjectCreatedAt, hashToken, hookRecoveryMarkerPath, monotonicUlid, } from './helpers.js';
|
|
10
|
+
import { deleteAllHooksForRun, rebuildLiveHookByTokenFromEventLog, } from './hooks-storage.js';
|
|
11
11
|
import { handleLegacyEvent } from './legacy.js';
|
|
12
12
|
const HookTokenClaimSchema = z.object({
|
|
13
|
+
// The token-claim writer below has always persisted `hookId`, but
|
|
14
|
+
// this read schema previously omitted it, which is the bug fixed
|
|
15
|
+
// by https://github.com/vercel/workflow/issues/2283. `optional()`
|
|
16
|
+
// is defensive: any claim file that somehow lacks the field still
|
|
17
|
+
// parses (yielding `undefined`) and falls through to the cross-
|
|
18
|
+
// hook conflict branch, matching pre-fix behavior.
|
|
19
|
+
hookId: z.string().optional(),
|
|
13
20
|
runId: z.string(),
|
|
21
|
+
// `eventId` is the canonical hook_created event ID the claiming
|
|
22
|
+
// worker committed to publishing. Persisting it here turns the
|
|
23
|
+
// claim file into a durable convergence key for cross-worker /
|
|
24
|
+
// cross-process retries (see comment on the hook_created branch).
|
|
25
|
+
// `optional()` for backward compatibility: a legacy claim file
|
|
26
|
+
// written before this field existed falls through to the recovery-
|
|
27
|
+
// marker upgrade path, which atomically pins a canonical eventId
|
|
28
|
+
// via a sidecar marker (also a `writeExclusive`).
|
|
29
|
+
eventId: z.string().optional(),
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Sidecar recovery marker that pins a canonical `hook_created`
|
|
33
|
+
* eventId for a legacy token claim — one written by a version of
|
|
34
|
+
* this storage that did not yet persist `eventId` inline in the
|
|
35
|
+
* claim file. Without this marker, two cross-process retries
|
|
36
|
+
* reading a legacy claim each generate their own eventId, land
|
|
37
|
+
* their `writeExclusive(eventPath)` calls at different paths, and
|
|
38
|
+
* append two `hook_created` events for the same `(runId, hookId)`.
|
|
39
|
+
*
|
|
40
|
+
* The marker is written via `writeExclusive` — the first retry to
|
|
41
|
+
* land it pins its candidate eventId as canonical, and every
|
|
42
|
+
* subsequent retry reads and adopts that eventId before the common
|
|
43
|
+
* event publish. Schema is just `{ eventId }` because identity is
|
|
44
|
+
* already encoded in the marker's filename hash, so different token
|
|
45
|
+
* lifetimes can never share one marker (see
|
|
46
|
+
* `hookRecoveryMarkerPath`).
|
|
47
|
+
*/
|
|
48
|
+
const HookRecoveryMarkerSchema = z.object({
|
|
49
|
+
eventId: z.string(),
|
|
14
50
|
});
|
|
15
51
|
async function readHookTokenClaim(constraintPath) {
|
|
16
52
|
try {
|
|
@@ -23,6 +59,156 @@ async function readHookTokenClaim(constraintPath) {
|
|
|
23
59
|
throw error;
|
|
24
60
|
}
|
|
25
61
|
}
|
|
62
|
+
async function readHookRecoveryMarker(markerPath) {
|
|
63
|
+
try {
|
|
64
|
+
return await readJSON(markerPath, HookRecoveryMarkerSchema);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof SyntaxError || error instanceof z.ZodError) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Probe the run's event log for an existing `hook_created` event
|
|
75
|
+
* with the given correlationId. Used by the legacy-claim recovery
|
|
76
|
+
* path to detect "already published by a pre-upgrade write" before
|
|
77
|
+
* pinning a canonical eventId — without this check, a post-upgrade
|
|
78
|
+
* retry encountering a legacy claim whose `hook_created` was
|
|
79
|
+
* already written (with the pre-upgrade writer's own eventId) would
|
|
80
|
+
* pin a *different* eventId via the marker and publish a duplicate
|
|
81
|
+
* event at the marker's path.
|
|
82
|
+
*
|
|
83
|
+
* The inline-`eventId` fast path does NOT need this probe: the
|
|
84
|
+
* canonical eventId is durable in the claim file, so the existing
|
|
85
|
+
* publish (`writeExclusive(eventPath)`) will fail iff the event
|
|
86
|
+
* already exists at that exact path — which is the correct
|
|
87
|
+
* "already-published" semantic.
|
|
88
|
+
*/
|
|
89
|
+
async function findExistingHookCreatedEventId(basedir, runId, correlationId) {
|
|
90
|
+
const result = await paginatedFileSystemQuery({
|
|
91
|
+
directory: path.join(basedir, 'events'),
|
|
92
|
+
schema: EventSchema,
|
|
93
|
+
filePrefix: `${runId}-`,
|
|
94
|
+
filter: (event) => event.eventType === 'hook_created' &&
|
|
95
|
+
event.correlationId === correlationId,
|
|
96
|
+
limit: 1,
|
|
97
|
+
getCreatedAt: getObjectCreatedAt('evnt'),
|
|
98
|
+
getId: (event) => event.eventId,
|
|
99
|
+
});
|
|
100
|
+
return result.data[0]?.eventId ?? null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Repair an "event-first orphan": the hook entity write is deferred
|
|
104
|
+
* until after the `hook_created` event publish commits (so a failed
|
|
105
|
+
* publish cannot mutate already-committed state — see the comment on
|
|
106
|
+
* the deferred write), which opens the inverse crash window — a
|
|
107
|
+
* crash AFTER the event publish but BEFORE the deferred entity write
|
|
108
|
+
* leaves the event in the log with the hook entity missing. A retry
|
|
109
|
+
* then collides at the event publish and throws
|
|
110
|
+
* `EntityConflictError` (correct — the event IS committed), but
|
|
111
|
+
* without this repair the entity would stay missing forever and the
|
|
112
|
+
* hook would be unresolvable.
|
|
113
|
+
*
|
|
114
|
+
* The entity MUST be reconstructed from the persisted canonical
|
|
115
|
+
* event's payload — NOT the retry's `eventData` — otherwise a retry
|
|
116
|
+
* carrying different `metadata` / `isWebhook` would silently change
|
|
117
|
+
* committed state. The write uses `writeExclusive` (create-if-absent)
|
|
118
|
+
* so a concurrent writer racing this repair cannot be overwritten;
|
|
119
|
+
* whichever write lands first, the content is identical because both
|
|
120
|
+
* derive from the same persisted event.
|
|
121
|
+
*/
|
|
122
|
+
async function repairHookEntityFromPersistedEvent(basedir, runId, hookId, persistedEventId, tag) {
|
|
123
|
+
const compositeKey = `${runId}-${persistedEventId}`;
|
|
124
|
+
const persistedEvent = await readJSONWithFallback(basedir, 'events', compositeKey, EventSchema, tag);
|
|
125
|
+
if (!persistedEvent ||
|
|
126
|
+
persistedEvent.eventType !== 'hook_created' ||
|
|
127
|
+
persistedEvent.correlationId !== hookId) {
|
|
128
|
+
// Nothing trustworthy to repair from.
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const existingHook = await readJSONWithFallback(basedir, 'hooks', hookId, HookSchema, tag);
|
|
132
|
+
if (existingHook) {
|
|
133
|
+
// Entity already present — not an orphan, leave it untouched.
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const eventData = (persistedEvent.eventData ?? {});
|
|
137
|
+
if (typeof eventData.token !== 'string') {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const hook = {
|
|
141
|
+
runId,
|
|
142
|
+
hookId,
|
|
143
|
+
token: eventData.token,
|
|
144
|
+
metadata: eventData.metadata,
|
|
145
|
+
ownerId: 'local-owner',
|
|
146
|
+
projectId: 'local-project',
|
|
147
|
+
environment: 'local',
|
|
148
|
+
createdAt: persistedEvent.createdAt,
|
|
149
|
+
specVersion: persistedEvent.specVersion,
|
|
150
|
+
isWebhook: eventData.isWebhook ?? true,
|
|
151
|
+
};
|
|
152
|
+
await writeExclusive(taggedPath(basedir, 'hooks', hookId, tag), JSON.stringify(hook, jsonReplacer, 2));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Atomically pin a canonical `hook_created` eventId for a legacy
|
|
156
|
+
* claim (one without an inline `eventId`). The first retry to
|
|
157
|
+
* `writeExclusive` the recovery marker wins; its `candidateEventId`
|
|
158
|
+
* becomes canonical. Subsequent retries read the marker and adopt
|
|
159
|
+
* its `eventId`. Together with the `writeExclusive(eventPath)` in
|
|
160
|
+
* the outer event publish, this gives the legacy-fallback path the
|
|
161
|
+
* same single-event convergence guarantee as the inline-`eventId`
|
|
162
|
+
* fast path.
|
|
163
|
+
*
|
|
164
|
+
* Returns the canonical eventId for the caller to adopt, or `null`
|
|
165
|
+
* if we lost the marker race AND the resulting marker file is
|
|
166
|
+
* unreadable (extremely rare; corrupted disk). Callers treat `null`
|
|
167
|
+
* as "give up, throw `EntityConflictError`" so the runtime's
|
|
168
|
+
* concurrent-replay catch path swallows this attempt and lets
|
|
169
|
+
* another one through.
|
|
170
|
+
*/
|
|
171
|
+
async function pinCanonicalEventIdForLegacyClaim(basedir, token, runId, hookId, candidateEventId) {
|
|
172
|
+
const markerPath = hookRecoveryMarkerPath(basedir, token, runId, hookId);
|
|
173
|
+
const markerContent = JSON.stringify({ eventId: candidateEventId });
|
|
174
|
+
const won = await writeExclusive(markerPath, markerContent);
|
|
175
|
+
if (won) {
|
|
176
|
+
return candidateEventId;
|
|
177
|
+
}
|
|
178
|
+
const existing = await readHookRecoveryMarker(markerPath);
|
|
179
|
+
return existing?.eventId ?? null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* In-process per-key async mutex backed by a caller-supplied `Map`.
|
|
183
|
+
* Used by `createEventsStorage` to serialize same-key event writes
|
|
184
|
+
* (`step_*` for the same step, `hook_created` for the same hook).
|
|
185
|
+
* The map is instantiated per-storage-instance — different
|
|
186
|
+
* instances do NOT share locks, so two instances sharing one data
|
|
187
|
+
* directory behave exactly like two separate OS processes from the
|
|
188
|
+
* locking standpoint. Cross-instance / cross-process arbitration
|
|
189
|
+
* relies on the on-disk constraint / claim files instead.
|
|
190
|
+
*/
|
|
191
|
+
function withInProcessLock(locks, key, fn) {
|
|
192
|
+
const prev = locks.get(key);
|
|
193
|
+
const taskBox = {};
|
|
194
|
+
const task = (async () => {
|
|
195
|
+
if (prev) {
|
|
196
|
+
// Wait for the previous task to settle; don't inherit its errors.
|
|
197
|
+
await prev.catch(() => undefined);
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
return await fn();
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
if (locks.get(key) === taskBox.task) {
|
|
204
|
+
locks.delete(key);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
})();
|
|
208
|
+
taskBox.task = task;
|
|
209
|
+
locks.set(key, task);
|
|
210
|
+
return task;
|
|
211
|
+
}
|
|
26
212
|
/**
|
|
27
213
|
* Helper function to delete all waits associated with a workflow run.
|
|
28
214
|
* Called when a run reaches a terminal state.
|
|
@@ -44,10 +230,21 @@ async function deleteAllWaitsForRun(basedir, runId) {
|
|
|
44
230
|
* Implements the Storage['events'] interface with create, list, and listByCorrelationId operations.
|
|
45
231
|
*/
|
|
46
232
|
export function createEventsStorage(basedir, tag) {
|
|
233
|
+
// Per-instance in-process mutex. Two storage instances sharing
|
|
234
|
+
// one data directory get independent lock maps, which makes them
|
|
235
|
+
// behave like two separate OS processes from the locking
|
|
236
|
+
// standpoint — cross-instance arbitration relies on the on-disk
|
|
237
|
+
// `writeExclusive` constraint / claim files instead. Tests use
|
|
238
|
+
// this to exercise cross-process convergence without spawning
|
|
239
|
+
// subprocesses.
|
|
240
|
+
//
|
|
241
|
+
// `hookLocks` serializes `hook_created` calls for the same
|
|
242
|
+
// (runId, correlationId) so the "claim token, then write hook
|
|
243
|
+
// entity + event" sequence runs to completion before another
|
|
244
|
+
// in-process invocation enters the dedup branch.
|
|
245
|
+
const hookLocks = new Map();
|
|
47
246
|
return {
|
|
48
247
|
async create(runId, data, params) {
|
|
49
|
-
const eventId = `evnt_${monotonicUlid()}`;
|
|
50
|
-
const now = new Date();
|
|
51
248
|
// Validate request-supplied IDs before they're concatenated into
|
|
52
249
|
// filesystem paths. This is the primary defense against path traversal
|
|
53
250
|
// attacks where a client supplies runId / correlationId values like
|
|
@@ -64,663 +261,899 @@ export function createEventsStorage(basedir, tag) {
|
|
|
64
261
|
if ('correlationId' in data && typeof data.correlationId === 'string') {
|
|
65
262
|
assertSafeEntityId('correlationId', data.correlationId);
|
|
66
263
|
}
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
264
|
+
// `hook_created` is serialized per-(runId, hookId) so the
|
|
265
|
+
// "claim token, write hook entity, write event" sequence runs to
|
|
266
|
+
// completion before another in-process invocation enters the
|
|
267
|
+
// same-hook dedup branch. Without this, two same-tick concurrent
|
|
268
|
+
// callers can race between the winner's `writeExclusive(claim)`
|
|
269
|
+
// and `writeJSON(hook)`, making the second caller momentarily
|
|
270
|
+
// observe a claim with no matching hook entity — which the
|
|
271
|
+
// crash-recovery path below would misinterpret as a prior crash
|
|
272
|
+
// and incorrectly fall through to a second hook entity write.
|
|
273
|
+
if (data.eventType === 'hook_created' && runId && data.correlationId) {
|
|
274
|
+
const lockKey = tag
|
|
275
|
+
? `${runId}-${data.correlationId}.hook.${tag}`
|
|
276
|
+
: `${runId}-${data.correlationId}.hook`;
|
|
277
|
+
return withInProcessLock(hookLocks, lockKey, () => createImpl());
|
|
74
278
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
279
|
+
return createImpl();
|
|
280
|
+
async function createImpl() {
|
|
281
|
+
// Most paths use the freshly-generated candidate eventId. The
|
|
282
|
+
// hook_created dedup-recovery path below may reassign it to
|
|
283
|
+
// the canonical eventId persisted in the durable token claim
|
|
284
|
+
// so concurrent / cross-process workers converge on a single
|
|
285
|
+
// event in the log.
|
|
286
|
+
let eventId = `evnt_${monotonicUlid()}`;
|
|
287
|
+
const now = new Date();
|
|
288
|
+
// For run_created events, use client-provided runId or generate one server-side
|
|
289
|
+
let effectiveRunId;
|
|
290
|
+
if (data.eventType === 'run_created' && (!runId || runId === '')) {
|
|
291
|
+
effectiveRunId = `wrun_${monotonicUlid()}`;
|
|
83
292
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
data.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
error: undefined,
|
|
125
|
-
startedAt: undefined,
|
|
126
|
-
completedAt: undefined,
|
|
127
|
-
createdAt: now,
|
|
128
|
-
updatedAt: now,
|
|
129
|
-
};
|
|
130
|
-
const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);
|
|
131
|
-
const created = await writeExclusive(runPath, JSON.stringify(createdRun, jsonReplacer));
|
|
132
|
-
if (created) {
|
|
133
|
-
// We created the run — also write the run_created event.
|
|
134
|
-
const runCreatedEventId = `evnt_${monotonicUlid()}`;
|
|
135
|
-
const runCreatedEvent = {
|
|
136
|
-
eventType: 'run_created',
|
|
293
|
+
else if (!runId) {
|
|
294
|
+
throw new Error('runId is required for non-run_created events');
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
effectiveRunId = runId;
|
|
298
|
+
}
|
|
299
|
+
// Validate client-provided runId timestamp is within acceptable threshold
|
|
300
|
+
if (data.eventType === 'run_created' && runId && runId !== '') {
|
|
301
|
+
const validationError = validateUlidTimestamp(effectiveRunId, 'wrun_');
|
|
302
|
+
if (validationError) {
|
|
303
|
+
throw new WorkflowWorldError(validationError);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// specVersion is always sent by the runtime, but we provide a fallback for safety
|
|
307
|
+
const effectiveSpecVersion = data.specVersion ?? SPEC_VERSION_CURRENT;
|
|
308
|
+
// Get current run state for validation (if not creating a new run)
|
|
309
|
+
// Skip run validation for step_completed and step_retrying - they only operate
|
|
310
|
+
// on running steps, and running steps are always allowed to modify regardless
|
|
311
|
+
// of run state. This optimization saves filesystem reads per step event.
|
|
312
|
+
let currentRun = null;
|
|
313
|
+
const skipRunValidationEvents = ['step_completed', 'step_retrying'];
|
|
314
|
+
if (data.eventType !== 'run_created' &&
|
|
315
|
+
!skipRunValidationEvents.includes(data.eventType)) {
|
|
316
|
+
currentRun = await readJSONWithFallback(basedir, 'runs', effectiveRunId, WorkflowRunSchema, tag);
|
|
317
|
+
// Resilient start: run_started on non-existent run with eventData
|
|
318
|
+
// creates the run first, so the queue can bootstrap a run that
|
|
319
|
+
// failed to create during start().
|
|
320
|
+
if (data.eventType === 'run_started' &&
|
|
321
|
+
!currentRun &&
|
|
322
|
+
'eventData' in data &&
|
|
323
|
+
data.eventData) {
|
|
324
|
+
const runInputData = data.eventData;
|
|
325
|
+
if (runInputData.deploymentId &&
|
|
326
|
+
runInputData.workflowName &&
|
|
327
|
+
runInputData.input !== undefined) {
|
|
328
|
+
// Atomically try to publish the run entity so only the first
|
|
329
|
+
// writer wins, preventing a TOCTOU race where a concurrent
|
|
330
|
+
// run_created from start() could overwrite a run that was
|
|
331
|
+
// already transitioned to 'running'.
|
|
332
|
+
const createdRun = {
|
|
137
333
|
runId: effectiveRunId,
|
|
138
|
-
|
|
139
|
-
|
|
334
|
+
deploymentId: runInputData.deploymentId,
|
|
335
|
+
status: 'pending',
|
|
336
|
+
workflowName: runInputData.workflowName,
|
|
140
337
|
specVersion: effectiveSpecVersion,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
338
|
+
executionContext: runInputData.executionContext,
|
|
339
|
+
input: runInputData.input,
|
|
340
|
+
output: undefined,
|
|
341
|
+
error: undefined,
|
|
342
|
+
startedAt: undefined,
|
|
343
|
+
completedAt: undefined,
|
|
344
|
+
createdAt: now,
|
|
345
|
+
updatedAt: now,
|
|
147
346
|
};
|
|
148
|
-
const
|
|
149
|
-
await
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
347
|
+
const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);
|
|
348
|
+
const created = await writeExclusive(runPath, JSON.stringify(createdRun, jsonReplacer));
|
|
349
|
+
if (created) {
|
|
350
|
+
// We created the run — also write the run_created event.
|
|
351
|
+
const runCreatedEventId = `evnt_${monotonicUlid()}`;
|
|
352
|
+
const runCreatedEvent = {
|
|
353
|
+
eventType: 'run_created',
|
|
354
|
+
runId: effectiveRunId,
|
|
355
|
+
eventId: runCreatedEventId,
|
|
356
|
+
createdAt: now,
|
|
357
|
+
specVersion: effectiveSpecVersion,
|
|
358
|
+
eventData: {
|
|
359
|
+
deploymentId: runInputData.deploymentId,
|
|
360
|
+
workflowName: runInputData.workflowName,
|
|
361
|
+
input: runInputData.input,
|
|
362
|
+
executionContext: runInputData.executionContext,
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
const createdCompositeKey = `${effectiveRunId}-${runCreatedEventId}`;
|
|
366
|
+
await writeJSON(taggedPath(basedir, 'events', createdCompositeKey, tag), runCreatedEvent);
|
|
367
|
+
currentRun = createdRun;
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// Run already exists (concurrent run_created won the
|
|
371
|
+
// race). Re-read it so downstream logic sees the real state.
|
|
372
|
+
currentRun = await readJSONWithFallback(basedir, 'runs', effectiveRunId, WorkflowRunSchema, tag);
|
|
373
|
+
}
|
|
156
374
|
}
|
|
157
375
|
}
|
|
158
376
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
377
|
+
// ============================================================
|
|
378
|
+
// VERSION COMPATIBILITY: Check run spec version
|
|
379
|
+
// ============================================================
|
|
380
|
+
// For events that have fetched the run, check version compatibility.
|
|
381
|
+
// Skip for run_created (no existing run) and runtime events (step_completed, step_retrying).
|
|
382
|
+
if (currentRun) {
|
|
383
|
+
// Check if run requires a newer world version
|
|
384
|
+
if (requiresNewerWorld(currentRun.specVersion)) {
|
|
385
|
+
throw new RunNotSupportedError(currentRun.specVersion, SPEC_VERSION_CURRENT);
|
|
386
|
+
}
|
|
387
|
+
// Route to legacy handler for pre-event-sourcing runs
|
|
388
|
+
if (isLegacySpecVersion(currentRun.specVersion)) {
|
|
389
|
+
return handleLegacyEvent(basedir, effectiveRunId, data, currentRun, params);
|
|
390
|
+
}
|
|
169
391
|
}
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
392
|
+
// ============================================================
|
|
393
|
+
// VALIDATION: Terminal state and event ordering checks
|
|
394
|
+
// ============================================================
|
|
395
|
+
// Run terminal state validation
|
|
396
|
+
if (currentRun && isTerminalWorkflowRunStatus(currentRun.status)) {
|
|
397
|
+
const runTerminalEvents = [
|
|
398
|
+
'run_started',
|
|
399
|
+
'run_completed',
|
|
400
|
+
'run_failed',
|
|
401
|
+
];
|
|
402
|
+
// Idempotent operation: run_cancelled on already cancelled run is allowed
|
|
403
|
+
if (data.eventType === 'run_cancelled' &&
|
|
404
|
+
currentRun.status === 'cancelled') {
|
|
405
|
+
// Return existing state (idempotent)
|
|
406
|
+
const event = {
|
|
407
|
+
...data,
|
|
408
|
+
runId: effectiveRunId,
|
|
409
|
+
eventId,
|
|
410
|
+
createdAt: now,
|
|
411
|
+
specVersion: effectiveSpecVersion,
|
|
412
|
+
};
|
|
413
|
+
const compositeKey = `${effectiveRunId}-${eventId}`;
|
|
414
|
+
await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), event);
|
|
415
|
+
const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
416
|
+
return {
|
|
417
|
+
event: stripEventDataRefs(event, resolveData),
|
|
418
|
+
run: currentRun,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
// For run_started on terminal runs, use RunExpiredError so the
|
|
422
|
+
// runtime knows to exit without retrying.
|
|
423
|
+
if (data.eventType === 'run_started') {
|
|
424
|
+
throw new RunExpiredError(`Workflow run "${effectiveRunId}" is already in terminal state "${currentRun.status}"`);
|
|
425
|
+
}
|
|
426
|
+
// Other run state transitions are not allowed on terminal runs
|
|
427
|
+
if (runTerminalEvents.includes(data.eventType) ||
|
|
428
|
+
data.eventType === 'run_cancelled') {
|
|
429
|
+
throw new EntityConflictError(`Cannot transition run from terminal state "${currentRun.status}"`);
|
|
430
|
+
}
|
|
431
|
+
// Creating new entities on terminal runs is not allowed
|
|
432
|
+
if (data.eventType === 'step_created' ||
|
|
433
|
+
data.eventType === 'hook_created' ||
|
|
434
|
+
data.eventType === 'wait_created') {
|
|
435
|
+
throw new EntityConflictError(`Cannot create new entities on run in terminal state "${currentRun.status}"`);
|
|
436
|
+
}
|
|
173
437
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
'
|
|
182
|
-
'run_completed',
|
|
183
|
-
'run_failed',
|
|
438
|
+
// Step-related event validation (ordering and terminal state)
|
|
439
|
+
// Store existingStep so we can reuse it later (avoid double read)
|
|
440
|
+
let validatedStep = null;
|
|
441
|
+
const stepEvents = [
|
|
442
|
+
'step_started',
|
|
443
|
+
'step_completed',
|
|
444
|
+
'step_failed',
|
|
445
|
+
'step_retrying',
|
|
184
446
|
];
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
run: currentRun,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
// For run_started on terminal runs, use RunExpiredError so the
|
|
205
|
-
// runtime knows to exit without retrying.
|
|
206
|
-
if (data.eventType === 'run_started') {
|
|
207
|
-
throw new RunExpiredError(`Workflow run "${effectiveRunId}" is already in terminal state "${currentRun.status}"`);
|
|
208
|
-
}
|
|
209
|
-
// Other run state transitions are not allowed on terminal runs
|
|
210
|
-
if (runTerminalEvents.includes(data.eventType) ||
|
|
211
|
-
data.eventType === 'run_cancelled') {
|
|
212
|
-
throw new EntityConflictError(`Cannot transition run from terminal state "${currentRun.status}"`);
|
|
213
|
-
}
|
|
214
|
-
// Creating new entities on terminal runs is not allowed
|
|
215
|
-
if (data.eventType === 'step_created' ||
|
|
216
|
-
data.eventType === 'hook_created' ||
|
|
217
|
-
data.eventType === 'wait_created') {
|
|
218
|
-
throw new EntityConflictError(`Cannot create new entities on run in terminal state "${currentRun.status}"`);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
// Step-related event validation (ordering and terminal state)
|
|
222
|
-
// Store existingStep so we can reuse it later (avoid double read)
|
|
223
|
-
let validatedStep = null;
|
|
224
|
-
const stepEvents = [
|
|
225
|
-
'step_started',
|
|
226
|
-
'step_completed',
|
|
227
|
-
'step_failed',
|
|
228
|
-
'step_retrying',
|
|
229
|
-
];
|
|
230
|
-
if (stepEvents.includes(data.eventType) && data.correlationId) {
|
|
231
|
-
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
232
|
-
validatedStep = await readJSONWithFallback(basedir, 'steps', stepCompositeKey, StepSchema, tag);
|
|
233
|
-
// Event ordering: step must exist before these events
|
|
234
|
-
if (!validatedStep) {
|
|
235
|
-
throw new WorkflowWorldError(`Step "${data.correlationId}" not found`);
|
|
236
|
-
}
|
|
237
|
-
// Step terminal state validation
|
|
238
|
-
if (isStepTerminal(validatedStep.status)) {
|
|
239
|
-
throw new EntityConflictError(`Cannot modify step in terminal state "${validatedStep.status}"`);
|
|
240
|
-
}
|
|
241
|
-
// On terminal runs: only allow completing/failing in-progress steps
|
|
242
|
-
if (currentRun && isRunTerminal(currentRun.status)) {
|
|
243
|
-
if (validatedStep.status !== 'running') {
|
|
244
|
-
throw new RunExpiredError(`Cannot modify non-running step on run in terminal state "${currentRun.status}"`);
|
|
447
|
+
if (stepEvents.includes(data.eventType) && data.correlationId) {
|
|
448
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
449
|
+
validatedStep = await readJSONWithFallback(basedir, 'steps', stepCompositeKey, StepSchema, tag);
|
|
450
|
+
// Event ordering: step must exist before these events
|
|
451
|
+
if (!validatedStep) {
|
|
452
|
+
throw new WorkflowWorldError(`Step "${data.correlationId}" not found`);
|
|
453
|
+
}
|
|
454
|
+
// Step terminal state validation
|
|
455
|
+
if (isTerminalStepStatus(validatedStep.status)) {
|
|
456
|
+
throw new EntityConflictError(`Cannot modify step in terminal state "${validatedStep.status}"`);
|
|
457
|
+
}
|
|
458
|
+
// On terminal runs: only allow completing/failing in-progress steps
|
|
459
|
+
if (currentRun && isTerminalWorkflowRunStatus(currentRun.status)) {
|
|
460
|
+
if (validatedStep.status !== 'running') {
|
|
461
|
+
throw new RunExpiredError(`Cannot modify non-running step on run in terminal state "${currentRun.status}"`);
|
|
462
|
+
}
|
|
245
463
|
}
|
|
246
464
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
465
|
+
// Hook-related event validation (ordering)
|
|
466
|
+
const hookEventsRequiringExistence = ['hook_disposed', 'hook_received'];
|
|
467
|
+
if (hookEventsRequiringExistence.includes(data.eventType) &&
|
|
468
|
+
data.correlationId) {
|
|
469
|
+
const existingHook = await readJSONWithFallback(basedir, 'hooks', data.correlationId, HookSchema, tag);
|
|
470
|
+
if (!existingHook) {
|
|
471
|
+
throw new HookNotFoundError(data.correlationId);
|
|
472
|
+
}
|
|
255
473
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
};
|
|
264
|
-
// Strip eventData from run_started — it belongs on run_created only.
|
|
265
|
-
if (data.eventType === 'run_started' && 'eventData' in event) {
|
|
266
|
-
delete event.eventData;
|
|
267
|
-
}
|
|
268
|
-
// Track entity created/updated for EventResult
|
|
269
|
-
let run;
|
|
270
|
-
let step;
|
|
271
|
-
let hook;
|
|
272
|
-
let wait;
|
|
273
|
-
// Create/update entity based on event type (event-sourced architecture)
|
|
274
|
-
// Run lifecycle events
|
|
275
|
-
if (data.eventType === 'run_created' && 'eventData' in data) {
|
|
276
|
-
const runData = data.eventData;
|
|
277
|
-
run = {
|
|
474
|
+
// `event` may be reassigned later in the `hook_created`
|
|
475
|
+
// dedup-recovery branch to swap in a canonical eventId /
|
|
476
|
+
// createdAt persisted in the durable token claim so
|
|
477
|
+
// concurrent / cross-process workers converge on a single
|
|
478
|
+
// event in the log.
|
|
479
|
+
let event = {
|
|
480
|
+
...data,
|
|
278
481
|
runId: effectiveRunId,
|
|
279
|
-
|
|
280
|
-
status: 'pending',
|
|
281
|
-
workflowName: runData.workflowName,
|
|
282
|
-
// Propagate specVersion from the event to the run entity
|
|
283
|
-
specVersion: effectiveSpecVersion,
|
|
284
|
-
executionContext: runData.executionContext,
|
|
285
|
-
input: runData.input,
|
|
286
|
-
output: undefined,
|
|
287
|
-
error: undefined,
|
|
288
|
-
startedAt: undefined,
|
|
289
|
-
completedAt: undefined,
|
|
482
|
+
eventId,
|
|
290
483
|
createdAt: now,
|
|
291
|
-
|
|
484
|
+
specVersion: effectiveSpecVersion,
|
|
292
485
|
};
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// duplicate run_created events in the event log.
|
|
297
|
-
const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);
|
|
298
|
-
const created = await writeExclusive(runPath, JSON.stringify(run, jsonReplacer, 2));
|
|
299
|
-
if (!created) {
|
|
300
|
-
throw new EntityConflictError(`Workflow run "${effectiveRunId}" already exists`);
|
|
486
|
+
// Strip eventData from run_started — it belongs on run_created only.
|
|
487
|
+
if (data.eventType === 'run_started' && 'eventData' in event) {
|
|
488
|
+
delete event.eventData;
|
|
301
489
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
490
|
+
// Track entity created/updated for EventResult
|
|
491
|
+
let run;
|
|
492
|
+
let step;
|
|
493
|
+
let hook;
|
|
494
|
+
let wait;
|
|
495
|
+
// For `hook_created`, the hook entity write is deferred until
|
|
496
|
+
// AFTER the outer event publish succeeds, so a retry that
|
|
497
|
+
// collides with an already-published `hook_created` does not
|
|
498
|
+
// mutate the durable hook entity with the retry's payload.
|
|
499
|
+
// `hookEntityWriteOptions` carries the `{ overwrite }` mode
|
|
500
|
+
// chosen by the dedup-recovery branch above (undefined for
|
|
501
|
+
// first writers, `{ overwrite: true }` for retries that may
|
|
502
|
+
// be repairing an orphaned partial write).
|
|
503
|
+
let hookEntityWriteOptions;
|
|
504
|
+
// Create/update entity based on event type (event-sourced architecture)
|
|
505
|
+
// Run lifecycle events
|
|
506
|
+
if (data.eventType === 'run_created' && 'eventData' in data) {
|
|
507
|
+
const runData = data.eventData;
|
|
314
508
|
run = {
|
|
315
|
-
runId:
|
|
316
|
-
deploymentId:
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
status: 'running',
|
|
509
|
+
runId: effectiveRunId,
|
|
510
|
+
deploymentId: runData.deploymentId,
|
|
511
|
+
status: 'pending',
|
|
512
|
+
workflowName: runData.workflowName,
|
|
513
|
+
// Propagate specVersion from the event to the run entity
|
|
514
|
+
specVersion: effectiveSpecVersion,
|
|
515
|
+
executionContext: runData.executionContext,
|
|
516
|
+
input: runData.input,
|
|
324
517
|
output: undefined,
|
|
325
518
|
error: undefined,
|
|
519
|
+
startedAt: undefined,
|
|
326
520
|
completedAt: undefined,
|
|
327
|
-
|
|
521
|
+
createdAt: now,
|
|
328
522
|
updatedAt: now,
|
|
329
523
|
};
|
|
330
|
-
|
|
524
|
+
// Atomically publish the run entity file without overwriting an
|
|
525
|
+
// existing winner. This prevents a TOCTOU race with the resilient
|
|
526
|
+
// start path (run_started on non-existent run) that could result in
|
|
527
|
+
// duplicate run_created events in the event log.
|
|
528
|
+
const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);
|
|
529
|
+
const created = await writeExclusive(runPath, JSON.stringify(run, jsonReplacer, 2));
|
|
530
|
+
if (!created) {
|
|
531
|
+
throw new EntityConflictError(`Workflow run "${effectiveRunId}" already exists`);
|
|
532
|
+
}
|
|
331
533
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
534
|
+
else if (data.eventType === 'run_started') {
|
|
535
|
+
// Reuse currentRun from validation (already read above)
|
|
536
|
+
if (currentRun) {
|
|
537
|
+
// If already running, return the run without inserting a
|
|
538
|
+
// duplicate event. This makes run_started idempotent for
|
|
539
|
+
// concurrent invocations. We omit preloaded events here
|
|
540
|
+
// because this is a rare race-condition path — the runtime
|
|
541
|
+
// falls back to loading events separately.
|
|
542
|
+
if (currentRun.status === 'running') {
|
|
543
|
+
return { run: currentRun };
|
|
544
|
+
}
|
|
545
|
+
run = {
|
|
546
|
+
runId: currentRun.runId,
|
|
547
|
+
deploymentId: currentRun.deploymentId,
|
|
548
|
+
workflowName: currentRun.workflowName,
|
|
549
|
+
specVersion: currentRun.specVersion,
|
|
550
|
+
executionContext: currentRun.executionContext,
|
|
551
|
+
input: currentRun.input,
|
|
552
|
+
createdAt: currentRun.createdAt,
|
|
553
|
+
expiredAt: currentRun.expiredAt,
|
|
554
|
+
status: 'running',
|
|
555
|
+
output: undefined,
|
|
556
|
+
error: undefined,
|
|
557
|
+
completedAt: undefined,
|
|
558
|
+
startedAt: currentRun.startedAt ?? now,
|
|
559
|
+
updatedAt: now,
|
|
560
|
+
};
|
|
561
|
+
await writeJSON(taggedPath(basedir, 'runs', effectiveRunId, tag), run, { overwrite: true });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
else if (data.eventType === 'run_completed' && 'eventData' in data) {
|
|
565
|
+
const completedData = data.eventData;
|
|
566
|
+
// Reuse currentRun from validation (already read above)
|
|
567
|
+
if (currentRun) {
|
|
568
|
+
run = {
|
|
569
|
+
runId: currentRun.runId,
|
|
570
|
+
deploymentId: currentRun.deploymentId,
|
|
571
|
+
workflowName: currentRun.workflowName,
|
|
572
|
+
specVersion: currentRun.specVersion,
|
|
573
|
+
executionContext: currentRun.executionContext,
|
|
574
|
+
input: currentRun.input,
|
|
575
|
+
createdAt: currentRun.createdAt,
|
|
576
|
+
expiredAt: currentRun.expiredAt,
|
|
577
|
+
startedAt: currentRun.startedAt,
|
|
578
|
+
status: 'completed',
|
|
579
|
+
output: completedData.output,
|
|
580
|
+
error: undefined,
|
|
581
|
+
completedAt: now,
|
|
582
|
+
updatedAt: now,
|
|
583
|
+
};
|
|
584
|
+
await writeJSON(taggedPath(basedir, 'runs', effectiveRunId, tag), run, { overwrite: true });
|
|
585
|
+
await Promise.all([
|
|
586
|
+
deleteAllHooksForRun(basedir, effectiveRunId),
|
|
587
|
+
deleteAllWaitsForRun(basedir, effectiveRunId),
|
|
588
|
+
]);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
else if (data.eventType === 'run_failed' && 'eventData' in data) {
|
|
592
|
+
const failedData = data.eventData;
|
|
593
|
+
// Reuse currentRun from validation (already read above)
|
|
594
|
+
if (currentRun) {
|
|
595
|
+
run = {
|
|
596
|
+
runId: currentRun.runId,
|
|
597
|
+
deploymentId: currentRun.deploymentId,
|
|
598
|
+
workflowName: currentRun.workflowName,
|
|
599
|
+
specVersion: currentRun.specVersion,
|
|
600
|
+
executionContext: currentRun.executionContext,
|
|
601
|
+
input: currentRun.input,
|
|
602
|
+
createdAt: currentRun.createdAt,
|
|
603
|
+
expiredAt: currentRun.expiredAt,
|
|
604
|
+
startedAt: currentRun.startedAt,
|
|
605
|
+
status: 'failed',
|
|
606
|
+
output: undefined,
|
|
607
|
+
error: {
|
|
608
|
+
message: typeof failedData.error === 'string'
|
|
609
|
+
? failedData.error
|
|
610
|
+
: (failedData.error?.message ?? 'Unknown error'),
|
|
611
|
+
stack: failedData.error?.stack,
|
|
612
|
+
code: failedData.errorCode,
|
|
613
|
+
},
|
|
614
|
+
completedAt: now,
|
|
615
|
+
updatedAt: now,
|
|
616
|
+
};
|
|
617
|
+
await writeJSON(taggedPath(basedir, 'runs', effectiveRunId, tag), run, { overwrite: true });
|
|
618
|
+
await Promise.all([
|
|
619
|
+
deleteAllHooksForRun(basedir, effectiveRunId),
|
|
620
|
+
deleteAllWaitsForRun(basedir, effectiveRunId),
|
|
621
|
+
]);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
else if (data.eventType === 'run_cancelled') {
|
|
625
|
+
// Reuse currentRun from validation (already read above)
|
|
626
|
+
if (currentRun) {
|
|
627
|
+
run = {
|
|
628
|
+
runId: currentRun.runId,
|
|
629
|
+
deploymentId: currentRun.deploymentId,
|
|
630
|
+
workflowName: currentRun.workflowName,
|
|
631
|
+
specVersion: currentRun.specVersion,
|
|
632
|
+
executionContext: currentRun.executionContext,
|
|
633
|
+
input: currentRun.input,
|
|
634
|
+
createdAt: currentRun.createdAt,
|
|
635
|
+
expiredAt: currentRun.expiredAt,
|
|
636
|
+
startedAt: currentRun.startedAt,
|
|
637
|
+
status: 'cancelled',
|
|
638
|
+
output: undefined,
|
|
639
|
+
error: undefined,
|
|
640
|
+
completedAt: now,
|
|
641
|
+
updatedAt: now,
|
|
642
|
+
};
|
|
643
|
+
await writeJSON(taggedPath(basedir, 'runs', effectiveRunId, tag), run, { overwrite: true });
|
|
644
|
+
await Promise.all([
|
|
645
|
+
deleteAllHooksForRun(basedir, effectiveRunId),
|
|
646
|
+
deleteAllWaitsForRun(basedir, effectiveRunId),
|
|
647
|
+
]);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
else if (
|
|
651
|
+
// Step lifecycle events
|
|
652
|
+
data.eventType === 'step_created' &&
|
|
653
|
+
'eventData' in data) {
|
|
654
|
+
// step_created: Creates step entity with status 'pending', attempt=0, createdAt set
|
|
655
|
+
const stepData = data.eventData;
|
|
656
|
+
step = {
|
|
657
|
+
runId: effectiveRunId,
|
|
658
|
+
stepId: data.correlationId,
|
|
659
|
+
stepName: stepData.stepName,
|
|
660
|
+
status: 'pending',
|
|
661
|
+
input: stepData.input,
|
|
662
|
+
output: undefined,
|
|
349
663
|
error: undefined,
|
|
350
|
-
|
|
664
|
+
attempt: 0,
|
|
665
|
+
startedAt: undefined,
|
|
666
|
+
completedAt: undefined,
|
|
667
|
+
createdAt: now,
|
|
351
668
|
updatedAt: now,
|
|
669
|
+
// Propagate specVersion from the event to the step entity
|
|
670
|
+
specVersion: effectiveSpecVersion,
|
|
352
671
|
};
|
|
353
|
-
|
|
354
|
-
await
|
|
355
|
-
deleteAllHooksForRun(basedir, effectiveRunId),
|
|
356
|
-
deleteAllWaitsForRun(basedir, effectiveRunId),
|
|
357
|
-
]);
|
|
672
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
673
|
+
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step);
|
|
358
674
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
675
|
+
else if (data.eventType === 'step_started') {
|
|
676
|
+
// step_started: Increments attempt, sets status to 'running'
|
|
677
|
+
// Sets startedAt only on the first start (not updated on retries)
|
|
678
|
+
// Reuse validatedStep from validation (already read above)
|
|
679
|
+
if (validatedStep) {
|
|
680
|
+
// Check if retryAfter timestamp hasn't been reached yet
|
|
681
|
+
if (validatedStep.retryAfter &&
|
|
682
|
+
validatedStep.retryAfter.getTime() > Date.now()) {
|
|
683
|
+
throw new TooEarlyError(`Cannot start step "${data.correlationId}": retryAfter timestamp has not been reached yet`, {
|
|
684
|
+
retryAfter: Math.ceil((validatedStep.retryAfter.getTime() - Date.now()) / 1000),
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
// Best-effort guard: re-read the step entity to check if it
|
|
688
|
+
// reached terminal state between the validation read and now.
|
|
689
|
+
// This narrows the TOCTOU window but does not fully eliminate it
|
|
690
|
+
// (the local world is single-process / dev-only; the postgres
|
|
691
|
+
// world uses SQL-level atomic guards for production).
|
|
692
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
693
|
+
const freshStep = await readJSONWithFallback(basedir, 'steps', stepCompositeKey, StepSchema, tag);
|
|
694
|
+
if (freshStep && isTerminalStepStatus(freshStep.status)) {
|
|
695
|
+
throw new EntityConflictError(`Cannot modify step in terminal state "${freshStep.status}"`);
|
|
696
|
+
}
|
|
697
|
+
step = {
|
|
698
|
+
...validatedStep,
|
|
699
|
+
status: 'running',
|
|
700
|
+
// Only set startedAt on the first start
|
|
701
|
+
startedAt: validatedStep.startedAt ?? now,
|
|
702
|
+
// Increment attempt counter on every start
|
|
703
|
+
attempt: validatedStep.attempt + 1,
|
|
704
|
+
// Clear retryAfter now that the step has started
|
|
705
|
+
retryAfter: undefined,
|
|
706
|
+
updatedAt: now,
|
|
707
|
+
};
|
|
708
|
+
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step, { overwrite: true });
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
else if (data.eventType === 'step_completed' && 'eventData' in data) {
|
|
712
|
+
// step_completed: Terminal state with output
|
|
713
|
+
// Uses writeExclusive on a lock file to atomically prevent concurrent
|
|
714
|
+
// invocations from both completing the same step (TOCTOU race).
|
|
715
|
+
const completedData = data.eventData;
|
|
716
|
+
if (validatedStep) {
|
|
717
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
718
|
+
const lockName = tag
|
|
719
|
+
? `${stepCompositeKey}.terminal.${tag}`
|
|
720
|
+
: `${stepCompositeKey}.terminal`;
|
|
721
|
+
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
722
|
+
const claimed = await writeExclusive(terminalLockPath, '');
|
|
723
|
+
if (!claimed) {
|
|
724
|
+
throw new EntityConflictError('Cannot modify step in terminal state');
|
|
725
|
+
}
|
|
726
|
+
step = {
|
|
727
|
+
...validatedStep,
|
|
728
|
+
status: 'completed',
|
|
729
|
+
output: completedData.result,
|
|
730
|
+
completedAt: now,
|
|
731
|
+
updatedAt: now,
|
|
732
|
+
};
|
|
733
|
+
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step, { overwrite: true });
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
else if (data.eventType === 'step_failed' && 'eventData' in data) {
|
|
737
|
+
// step_failed: Terminal state with error
|
|
738
|
+
// Uses writeExclusive on a lock file to atomically prevent concurrent
|
|
739
|
+
// invocations from both failing the same step (TOCTOU race).
|
|
740
|
+
const failedData = data.eventData;
|
|
741
|
+
if (validatedStep) {
|
|
742
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
743
|
+
const lockName = tag
|
|
744
|
+
? `${stepCompositeKey}.terminal.${tag}`
|
|
745
|
+
: `${stepCompositeKey}.terminal`;
|
|
746
|
+
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
747
|
+
const claimed = await writeExclusive(terminalLockPath, '');
|
|
748
|
+
if (!claimed) {
|
|
749
|
+
throw new EntityConflictError('Cannot modify step in terminal state');
|
|
750
|
+
}
|
|
751
|
+
const error = {
|
|
377
752
|
message: typeof failedData.error === 'string'
|
|
378
753
|
? failedData.error
|
|
379
754
|
: (failedData.error?.message ?? 'Unknown error'),
|
|
380
|
-
stack: failedData.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
755
|
+
stack: failedData.stack,
|
|
756
|
+
};
|
|
757
|
+
step = {
|
|
758
|
+
...validatedStep,
|
|
759
|
+
status: 'failed',
|
|
760
|
+
error,
|
|
761
|
+
completedAt: now,
|
|
762
|
+
updatedAt: now,
|
|
763
|
+
};
|
|
764
|
+
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step, { overwrite: true });
|
|
765
|
+
}
|
|
391
766
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
await writeJSON(taggedPath(basedir, 'runs', effectiveRunId, tag), run, { overwrite: true });
|
|
413
|
-
await Promise.all([
|
|
414
|
-
deleteAllHooksForRun(basedir, effectiveRunId),
|
|
415
|
-
deleteAllWaitsForRun(basedir, effectiveRunId),
|
|
416
|
-
]);
|
|
767
|
+
else if (data.eventType === 'step_retrying' && 'eventData' in data) {
|
|
768
|
+
// step_retrying: Sets status back to 'pending', records error
|
|
769
|
+
// Reuse validatedStep from validation (already read above)
|
|
770
|
+
const retryData = data.eventData;
|
|
771
|
+
if (validatedStep) {
|
|
772
|
+
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
773
|
+
step = {
|
|
774
|
+
...validatedStep,
|
|
775
|
+
status: 'pending',
|
|
776
|
+
error: {
|
|
777
|
+
message: typeof retryData.error === 'string'
|
|
778
|
+
? retryData.error
|
|
779
|
+
: (retryData.error?.message ?? 'Unknown error'),
|
|
780
|
+
stack: retryData.stack,
|
|
781
|
+
},
|
|
782
|
+
retryAfter: retryData.retryAfter,
|
|
783
|
+
updatedAt: now,
|
|
784
|
+
};
|
|
785
|
+
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step, { overwrite: true });
|
|
786
|
+
}
|
|
417
787
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
input: stepData.input,
|
|
431
|
-
output: undefined,
|
|
432
|
-
error: undefined,
|
|
433
|
-
attempt: 0,
|
|
434
|
-
startedAt: undefined,
|
|
435
|
-
completedAt: undefined,
|
|
436
|
-
createdAt: now,
|
|
437
|
-
updatedAt: now,
|
|
438
|
-
// Propagate specVersion from the event to the step entity
|
|
439
|
-
specVersion: effectiveSpecVersion,
|
|
440
|
-
};
|
|
441
|
-
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
442
|
-
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step);
|
|
443
|
-
}
|
|
444
|
-
else if (data.eventType === 'step_started') {
|
|
445
|
-
// step_started: Increments attempt, sets status to 'running'
|
|
446
|
-
// Sets startedAt only on the first start (not updated on retries)
|
|
447
|
-
// Reuse validatedStep from validation (already read above)
|
|
448
|
-
if (validatedStep) {
|
|
449
|
-
// Check if retryAfter timestamp hasn't been reached yet
|
|
450
|
-
if (validatedStep.retryAfter &&
|
|
451
|
-
validatedStep.retryAfter.getTime() > Date.now()) {
|
|
452
|
-
throw new TooEarlyError(`Cannot start step "${data.correlationId}": retryAfter timestamp has not been reached yet`, {
|
|
453
|
-
retryAfter: Math.ceil((validatedStep.retryAfter.getTime() - Date.now()) / 1000),
|
|
454
|
-
});
|
|
788
|
+
else if (
|
|
789
|
+
// Hook lifecycle events
|
|
790
|
+
data.eventType === 'hook_created' &&
|
|
791
|
+
'eventData' in data) {
|
|
792
|
+
const hookData = data.eventData;
|
|
793
|
+
// Atomically claim the token using an exclusive-create constraint file.
|
|
794
|
+
// This avoids the TOCTOU race of the previous read-all-then-check approach.
|
|
795
|
+
const constraintPath = path.join(basedir, 'hooks', 'tokens', `${hashToken(hookData.token)}.json`);
|
|
796
|
+
// When the claim is absent, the event log is the only durable source
|
|
797
|
+
// that can distinguish a first hook from a crash-lost token cache.
|
|
798
|
+
if (!(await readHookTokenClaim(constraintPath))) {
|
|
799
|
+
await rebuildLiveHookByTokenFromEventLog(basedir, hookData.token, tag);
|
|
455
800
|
}
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
//
|
|
459
|
-
//
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
801
|
+
// Persist `eventId` in the claim so concurrent / cross-
|
|
802
|
+
// process retries can converge on a single canonical
|
|
803
|
+
// `hook_created` event path. See the recovery comment
|
|
804
|
+
// below.
|
|
805
|
+
const tokenClaimed = await writeExclusive(constraintPath, JSON.stringify({
|
|
806
|
+
token: hookData.token,
|
|
807
|
+
hookId: data.correlationId,
|
|
808
|
+
runId: effectiveRunId,
|
|
809
|
+
eventId,
|
|
810
|
+
}));
|
|
811
|
+
// Recovery shape: the durable record of a successful hook
|
|
812
|
+
// creation is the `hook_created` event in the event log. The
|
|
813
|
+
// claim file and hook entity are written before the event,
|
|
814
|
+
// and the three writes are NOT atomic, so a crash at any
|
|
815
|
+
// point can leave one or two of them on disk without the
|
|
816
|
+
// event. Treating those as "completed" would have the
|
|
817
|
+
// suspension handler swallow the retry and permanently lose
|
|
818
|
+
// the `hook_created` event from the log.
|
|
819
|
+
//
|
|
820
|
+
// When the dedup branch fires for the same `(runId, hookId)`,
|
|
821
|
+
// we converge on the canonical `eventId` persisted in the
|
|
822
|
+
// claim file by the original (winning) `writeExclusive`. By
|
|
823
|
+
// adopting that eventId for this retry's event write — and
|
|
824
|
+
// letting the outer no-overwrite `writeJSON` for the event
|
|
825
|
+
// throw `EntityConflictError` on collision — concurrent /
|
|
826
|
+
// cross-process workers either:
|
|
827
|
+
// - publish the same event at the same path exactly once
|
|
828
|
+
// (the loser's `writeJSON` throws EntityConflictError,
|
|
829
|
+
// which the runtime's existing concurrent-replay catch
|
|
830
|
+
// path at suspension-handler.ts:142 swallows), or
|
|
831
|
+
// - converge on a single recovery write when the prior
|
|
832
|
+
// claim was orphaned by a crash before the event landed.
|
|
833
|
+
//
|
|
834
|
+
// The legacy fallback (`existingClaim.eventId` undefined)
|
|
835
|
+
// is for claim files written before this field was added —
|
|
836
|
+
// those probe the event log directly and fall through to a
|
|
837
|
+
// fresh-eventId recovery write. The legacy path does not
|
|
838
|
+
// converge across workers but cannot regress behavior for
|
|
839
|
+
// freshly-written claims.
|
|
840
|
+
//
|
|
841
|
+
// The `withHookLock` in-process mutex above keeps two same-
|
|
842
|
+
// tick in-process callers from racing into this branch with
|
|
843
|
+
// the winner mid-write, but is not sufficient across
|
|
844
|
+
// processes — the durable convergence key (`claim.eventId`)
|
|
845
|
+
// is what closes the cross-process race.
|
|
846
|
+
let writeHookEntityWithOverwrite = false;
|
|
847
|
+
if (!tokenClaimed) {
|
|
848
|
+
const existingClaim = await readHookTokenClaim(constraintPath);
|
|
849
|
+
if (existingClaim?.runId === effectiveRunId &&
|
|
850
|
+
existingClaim.hookId === data.correlationId) {
|
|
851
|
+
// Adopt a canonical eventId for the recovery write. The
|
|
852
|
+
// outer event publish (`writeExclusive(eventPath)`)
|
|
853
|
+
// either succeeds (we publish the canonical event,
|
|
854
|
+
// repairing a partial write left by the original
|
|
855
|
+
// claimant) or returns `false` and we throw
|
|
856
|
+
// `EntityConflictError` (the event was already
|
|
857
|
+
// published — a real duplicate). Either way the log
|
|
858
|
+
// ends with exactly one `hook_created` event for this
|
|
859
|
+
// `(runId, hookId)`.
|
|
860
|
+
//
|
|
861
|
+
// The canonical eventId comes from one of two places:
|
|
862
|
+
//
|
|
863
|
+
// - `existingClaim.eventId` for claims written by
|
|
864
|
+
// this version (the writer above persists the
|
|
865
|
+
// candidate eventId atomically with the claim).
|
|
866
|
+
// The eventId is durable, so the outer
|
|
867
|
+
// `writeExclusive(eventPath)` alone is enough to
|
|
868
|
+
// arbitrate publication: it fails iff the event
|
|
869
|
+
// was already published at that exact path.
|
|
870
|
+
//
|
|
871
|
+
// - The recovery-marker sidecar for legacy claims
|
|
872
|
+
// written before `eventId` was persisted inline
|
|
873
|
+
// in the claim. The marker is itself a
|
|
874
|
+
// `writeExclusive`, so the first retry pins its
|
|
875
|
+
// candidate eventId as canonical and subsequent
|
|
876
|
+
// retries adopt it. Without this, two processes
|
|
877
|
+
// both reading the same legacy claim would each
|
|
878
|
+
// generate their own eventId, land their
|
|
879
|
+
// `writeExclusive(eventPath)` calls at different
|
|
880
|
+
// paths, and append two events.
|
|
881
|
+
//
|
|
882
|
+
// For legacy claims we also must probe the event
|
|
883
|
+
// log for an existing `hook_created` event BEFORE
|
|
884
|
+
// pinning a canonical eventId: the pre-upgrade
|
|
885
|
+
// writer may have already published the event
|
|
886
|
+
// with its own eventId, and the marker has no way
|
|
887
|
+
// of knowing that eventId after the fact. Without
|
|
888
|
+
// this probe, a post-upgrade retry would pin a
|
|
889
|
+
// different eventId, write a hook entity, and
|
|
890
|
+
// publish a duplicate event at the marker's path.
|
|
891
|
+
let canonicalEventId;
|
|
892
|
+
if (existingClaim.eventId) {
|
|
893
|
+
canonicalEventId = existingClaim.eventId;
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
const alreadyPublishedEventId = await findExistingHookCreatedEventId(basedir, effectiveRunId, data.correlationId);
|
|
897
|
+
if (alreadyPublishedEventId !== null) {
|
|
898
|
+
// The pre-upgrade writer may have crashed between
|
|
899
|
+
// its event publish and its hook entity write —
|
|
900
|
+
// repair the entity from the persisted event's
|
|
901
|
+
// payload before surfacing the benign duplicate.
|
|
902
|
+
await repairHookEntityFromPersistedEvent(basedir, effectiveRunId, data.correlationId, alreadyPublishedEventId, tag);
|
|
903
|
+
throw new EntityConflictError(`Hook "${data.correlationId}" already created`);
|
|
904
|
+
}
|
|
905
|
+
const pinned = await pinCanonicalEventIdForLegacyClaim(basedir, hookData.token, effectiveRunId, data.correlationId, eventId);
|
|
906
|
+
if (pinned === null) {
|
|
907
|
+
// Lost the marker race and the marker file is
|
|
908
|
+
// unreadable (extremely rare; corrupted disk).
|
|
909
|
+
// Treat as a real duplicate so the runtime's
|
|
910
|
+
// concurrent-replay catch path swallows this
|
|
911
|
+
// attempt instead of risking divergent
|
|
912
|
+
// publication.
|
|
913
|
+
throw new EntityConflictError(`Hook "${data.correlationId}" already created`);
|
|
914
|
+
}
|
|
915
|
+
canonicalEventId = pinned;
|
|
916
|
+
}
|
|
917
|
+
// Rebuild `event` with the canonical eventId and a
|
|
918
|
+
// deterministic `createdAt` derived from the eventId
|
|
919
|
+
// (a ULID) so two workers writing the same event
|
|
920
|
+
// produce byte-identical content.
|
|
921
|
+
eventId = canonicalEventId;
|
|
922
|
+
const canonicalCreatedAt = ulidToDate(eventId.replace(/^evnt_/, '')) ?? now;
|
|
923
|
+
event = {
|
|
924
|
+
...data,
|
|
925
|
+
runId: effectiveRunId,
|
|
926
|
+
eventId,
|
|
927
|
+
createdAt: canonicalCreatedAt,
|
|
928
|
+
specVersion: effectiveSpecVersion,
|
|
929
|
+
};
|
|
930
|
+
writeHookEntityWithOverwrite = true;
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
// Cross-hook / cross-run conflict: a different
|
|
934
|
+
// (runId, hookId) holds this token. Create a
|
|
935
|
+
// hook_conflict event so the workflow can fail
|
|
936
|
+
// gracefully when the hook is awaited.
|
|
937
|
+
const conflictEvent = {
|
|
938
|
+
eventType: 'hook_conflict',
|
|
939
|
+
correlationId: data.correlationId,
|
|
940
|
+
eventData: {
|
|
941
|
+
token: hookData.token,
|
|
942
|
+
...(existingClaim
|
|
943
|
+
? { conflictingRunId: existingClaim.runId }
|
|
944
|
+
: {}),
|
|
945
|
+
},
|
|
946
|
+
runId: effectiveRunId,
|
|
947
|
+
eventId,
|
|
948
|
+
createdAt: now,
|
|
949
|
+
specVersion: effectiveSpecVersion,
|
|
950
|
+
};
|
|
951
|
+
const compositeKey = `${effectiveRunId}-${eventId}`;
|
|
952
|
+
await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), conflictEvent);
|
|
953
|
+
const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
954
|
+
const filteredEvent = stripEventDataRefs(conflictEvent, resolveData);
|
|
955
|
+
// Return EventResult with conflict event (no hook entity created)
|
|
956
|
+
return {
|
|
957
|
+
event: filteredEvent,
|
|
958
|
+
run,
|
|
959
|
+
step,
|
|
960
|
+
hook: undefined,
|
|
961
|
+
};
|
|
962
|
+
}
|
|
465
963
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
964
|
+
// Compute the hook entity now, but defer its write until
|
|
965
|
+
// AFTER the outer event publish at the bottom of this
|
|
966
|
+
// function commits. The retry path can reach this branch
|
|
967
|
+
// for a hook whose `hook_created` event was already
|
|
968
|
+
// published successfully (an "already-committed
|
|
969
|
+
// duplicate"); in that case the outer `writeExclusive`
|
|
970
|
+
// for the event will return false and we will throw
|
|
971
|
+
// `EntityConflictError`. Writing the hook entity here
|
|
972
|
+
// first would mutate already-committed durable state with
|
|
973
|
+
// the retry's payload (e.g. different `metadata` or
|
|
974
|
+
// `isWebhook`) before the event publish proved which
|
|
975
|
+
// outcome we are in — leaving the entity and event log
|
|
976
|
+
// inconsistent. By deferring, the entity is only written
|
|
977
|
+
// when the publish actually succeeds (first writer or
|
|
978
|
+
// orphan recovery). See pranaygp's review on PR #2295 for
|
|
979
|
+
// the karthikscale3 repro.
|
|
980
|
+
hook = {
|
|
981
|
+
runId: effectiveRunId,
|
|
982
|
+
hookId: data.correlationId,
|
|
983
|
+
token: hookData.token,
|
|
984
|
+
metadata: hookData.metadata,
|
|
985
|
+
ownerId: 'local-owner',
|
|
986
|
+
projectId: 'local-project',
|
|
987
|
+
environment: 'local',
|
|
988
|
+
// Use the (possibly canonical) event's createdAt so two
|
|
989
|
+
// workers writing the same hook entity produce byte-
|
|
990
|
+
// identical content during convergence.
|
|
991
|
+
createdAt: event.createdAt,
|
|
992
|
+
// Propagate specVersion from the event to the hook entity
|
|
993
|
+
specVersion: effectiveSpecVersion,
|
|
994
|
+
isWebhook: hookData.isWebhook ?? false,
|
|
476
995
|
};
|
|
477
|
-
|
|
996
|
+
hookEntityWriteOptions = writeHookEntityWithOverwrite
|
|
997
|
+
? { overwrite: true }
|
|
998
|
+
: undefined;
|
|
478
999
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const
|
|
487
|
-
const
|
|
488
|
-
? `${stepCompositeKey}.terminal.${tag}`
|
|
489
|
-
: `${stepCompositeKey}.terminal`;
|
|
490
|
-
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
491
|
-
const claimed = await writeExclusive(terminalLockPath, '');
|
|
1000
|
+
else if (data.eventType === 'hook_disposed') {
|
|
1001
|
+
// hook_disposed: Deletes hook entity, rejects duplicates.
|
|
1002
|
+
// Uses writeExclusive on a lock file to atomically prevent concurrent
|
|
1003
|
+
// invocations from both disposing the same hook (TOCTOU race).
|
|
1004
|
+
const hookLockName = tag
|
|
1005
|
+
? `${data.correlationId}.disposed.${tag}`
|
|
1006
|
+
: `${data.correlationId}.disposed`;
|
|
1007
|
+
const lockPath = resolveWithinBase(basedir, '.locks', 'hooks', hookLockName);
|
|
1008
|
+
const claimed = await writeExclusive(lockPath, '');
|
|
492
1009
|
if (!claimed) {
|
|
493
|
-
throw new EntityConflictError(
|
|
1010
|
+
throw new EntityConflictError(`Hook "${data.correlationId}" already disposed`);
|
|
494
1011
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
1012
|
+
// Read the hook to get its token before deleting
|
|
1013
|
+
const hookPath = taggedPath(basedir, 'hooks', data.correlationId, tag);
|
|
1014
|
+
const existingHook = await readJSONWithFallback(basedir, 'hooks', data.correlationId, HookSchema, tag);
|
|
1015
|
+
if (existingHook) {
|
|
1016
|
+
// Delete the token constraint file to free up the token
|
|
1017
|
+
// for reuse, and delete this hook's recovery marker (if
|
|
1018
|
+
// any) for disk hygiene. The marker's filename hash
|
|
1019
|
+
// includes `(token, runId, hookId)` so different
|
|
1020
|
+
// lifetimes never collide, but cleaning up reduces disk
|
|
1021
|
+
// leak for hooks that go through the recovery path.
|
|
1022
|
+
const disposedConstraintPath = path.join(basedir, 'hooks', 'tokens', `${hashToken(existingHook.token)}.json`);
|
|
1023
|
+
await deleteJSON(disposedConstraintPath);
|
|
1024
|
+
await deleteJSON(hookRecoveryMarkerPath(basedir, existingHook.token, existingHook.runId, existingHook.hookId));
|
|
1025
|
+
}
|
|
1026
|
+
await deleteJSON(hookPath);
|
|
1027
|
+
}
|
|
1028
|
+
else if (data.eventType === 'wait_created' && 'eventData' in data) {
|
|
1029
|
+
// wait_created: Creates wait entity with status 'waiting'
|
|
1030
|
+
const waitData = data.eventData;
|
|
1031
|
+
const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
1032
|
+
const existingWait = await readJSONWithFallback(basedir, 'waits', waitCompositeKey, WaitSchema, tag);
|
|
1033
|
+
if (existingWait) {
|
|
1034
|
+
throw new EntityConflictError(`Wait "${data.correlationId}" already exists`);
|
|
1035
|
+
}
|
|
1036
|
+
wait = {
|
|
1037
|
+
waitId: waitCompositeKey,
|
|
1038
|
+
runId: effectiveRunId,
|
|
1039
|
+
status: 'waiting',
|
|
1040
|
+
resumeAt: waitData.resumeAt,
|
|
1041
|
+
completedAt: undefined,
|
|
1042
|
+
createdAt: now,
|
|
500
1043
|
updatedAt: now,
|
|
1044
|
+
specVersion: effectiveSpecVersion,
|
|
501
1045
|
};
|
|
502
|
-
await writeJSON(taggedPath(basedir, '
|
|
1046
|
+
await writeJSON(taggedPath(basedir, 'waits', waitCompositeKey, tag), wait);
|
|
503
1047
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
: `${stepCompositeKey}.terminal`;
|
|
515
|
-
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
516
|
-
const claimed = await writeExclusive(terminalLockPath, '');
|
|
1048
|
+
else if (data.eventType === 'wait_completed') {
|
|
1049
|
+
// wait_completed: Transitions wait to 'completed', rejects duplicates.
|
|
1050
|
+
// Uses writeExclusive on a lock file to atomically prevent concurrent
|
|
1051
|
+
// invocations from both completing the same wait (TOCTOU race).
|
|
1052
|
+
const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
1053
|
+
const waitLockName = tag
|
|
1054
|
+
? `${waitCompositeKey}.completed.${tag}`
|
|
1055
|
+
: `${waitCompositeKey}.completed`;
|
|
1056
|
+
const lockPath = resolveWithinBase(basedir, '.locks', 'waits', waitLockName);
|
|
1057
|
+
const claimed = await writeExclusive(lockPath, '');
|
|
517
1058
|
if (!claimed) {
|
|
518
|
-
throw new EntityConflictError(
|
|
1059
|
+
throw new EntityConflictError(`Wait "${data.correlationId}" already completed`);
|
|
519
1060
|
}
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
1061
|
+
const existingWait = await readJSONWithFallback(basedir, 'waits', waitCompositeKey, WaitSchema, tag);
|
|
1062
|
+
if (!existingWait) {
|
|
1063
|
+
// Clean up the lock file we just claimed — the wait doesn't exist
|
|
1064
|
+
await fs.unlink(lockPath).catch(() => { });
|
|
1065
|
+
throw new WorkflowWorldError(`Wait "${data.correlationId}" not found`);
|
|
1066
|
+
}
|
|
1067
|
+
// The lock file (writeExclusive above) already prevents concurrent
|
|
1068
|
+
// completions — no additional status check needed.
|
|
1069
|
+
wait = {
|
|
1070
|
+
...existingWait,
|
|
1071
|
+
status: 'completed',
|
|
530
1072
|
completedAt: now,
|
|
531
1073
|
updatedAt: now,
|
|
532
1074
|
};
|
|
533
|
-
await writeJSON(taggedPath(basedir, '
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else if (data.eventType === 'step_retrying' && 'eventData' in data) {
|
|
537
|
-
// step_retrying: Sets status back to 'pending', records error
|
|
538
|
-
// Reuse validatedStep from validation (already read above)
|
|
539
|
-
const retryData = data.eventData;
|
|
540
|
-
if (validatedStep) {
|
|
541
|
-
const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
542
|
-
step = {
|
|
543
|
-
...validatedStep,
|
|
544
|
-
status: 'pending',
|
|
545
|
-
error: {
|
|
546
|
-
message: typeof retryData.error === 'string'
|
|
547
|
-
? retryData.error
|
|
548
|
-
: (retryData.error?.message ?? 'Unknown error'),
|
|
549
|
-
stack: retryData.stack,
|
|
550
|
-
},
|
|
551
|
-
retryAfter: retryData.retryAfter,
|
|
552
|
-
updatedAt: now,
|
|
553
|
-
};
|
|
554
|
-
await writeJSON(taggedPath(basedir, 'steps', stepCompositeKey, tag), step, { overwrite: true });
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
else if (
|
|
558
|
-
// Hook lifecycle events
|
|
559
|
-
data.eventType === 'hook_created' &&
|
|
560
|
-
'eventData' in data) {
|
|
561
|
-
const hookData = data.eventData;
|
|
562
|
-
// Atomically claim the token using an exclusive-create constraint file.
|
|
563
|
-
// This avoids the TOCTOU race of the previous read-all-then-check approach.
|
|
564
|
-
const constraintPath = path.join(basedir, 'hooks', 'tokens', `${hashToken(hookData.token)}.json`);
|
|
565
|
-
const tokenClaimed = await writeExclusive(constraintPath, JSON.stringify({
|
|
566
|
-
token: hookData.token,
|
|
567
|
-
hookId: data.correlationId,
|
|
568
|
-
runId: effectiveRunId,
|
|
569
|
-
}));
|
|
570
|
-
if (!tokenClaimed) {
|
|
571
|
-
const existingClaim = await readHookTokenClaim(constraintPath);
|
|
572
|
-
// Create hook_conflict event instead of hook_created
|
|
573
|
-
// This allows the workflow to continue and fail gracefully when the hook is awaited
|
|
574
|
-
const conflictEvent = {
|
|
575
|
-
eventType: 'hook_conflict',
|
|
576
|
-
correlationId: data.correlationId,
|
|
577
|
-
eventData: {
|
|
578
|
-
token: hookData.token,
|
|
579
|
-
...(existingClaim
|
|
580
|
-
? { conflictingRunId: existingClaim.runId }
|
|
581
|
-
: {}),
|
|
582
|
-
},
|
|
583
|
-
runId: effectiveRunId,
|
|
584
|
-
eventId,
|
|
585
|
-
createdAt: now,
|
|
586
|
-
specVersion: effectiveSpecVersion,
|
|
587
|
-
};
|
|
588
|
-
// Store the conflict event
|
|
589
|
-
const compositeKey = `${effectiveRunId}-${eventId}`;
|
|
590
|
-
await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), conflictEvent);
|
|
591
|
-
const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
592
|
-
const filteredEvent = stripEventDataRefs(conflictEvent, resolveData);
|
|
593
|
-
// Return EventResult with conflict event (no hook entity created)
|
|
594
|
-
return {
|
|
595
|
-
event: filteredEvent,
|
|
596
|
-
run,
|
|
597
|
-
step,
|
|
598
|
-
hook: undefined,
|
|
599
|
-
};
|
|
1075
|
+
await writeJSON(taggedPath(basedir, 'waits', waitCompositeKey, tag), wait, { overwrite: true });
|
|
600
1076
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
//
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
1077
|
+
// Note: hook_received events are stored in the event log but don't
|
|
1078
|
+
// modify the Hook entity (which doesn't have a payload field)
|
|
1079
|
+
// Store event using composite key {runId}-{eventId}.
|
|
1080
|
+
//
|
|
1081
|
+
// `writeExclusive` (O_CREAT|O_EXCL via temp-file + hard-link)
|
|
1082
|
+
// is the cross-process atomic publish primitive: if the file
|
|
1083
|
+
// already exists, returns false instead of overwriting. This
|
|
1084
|
+
// is critical for the hook_created dedup-recovery convergence
|
|
1085
|
+
// (above) — two workers that adopt the same canonical eventId
|
|
1086
|
+
// race here; whoever links the file first wins, the loser
|
|
1087
|
+
// throws EntityConflictError, and the runtime's existing
|
|
1088
|
+
// concurrent-replay catch path at suspension-handler.ts:142
|
|
1089
|
+
// swallows it. For all other event types, eventIds are
|
|
1090
|
+
// monotonic ULIDs (globally unique by construction) so a
|
|
1091
|
+
// collision indicates a real bug and EntityConflictError is
|
|
1092
|
+
// also the right surface — same shape as step_created's
|
|
1093
|
+
// claim-file behavior.
|
|
1094
|
+
const compositeKey = `${effectiveRunId}-${eventId}`;
|
|
1095
|
+
const eventPublished = await writeExclusive(taggedPath(basedir, 'events', compositeKey, tag), JSON.stringify(event, jsonReplacer, 2));
|
|
1096
|
+
if (!eventPublished) {
|
|
1097
|
+
// For `hook_created`, losing the event publish means the
|
|
1098
|
+
// event was already committed at this exact (canonical)
|
|
1099
|
+
// path. The original publisher may have crashed between
|
|
1100
|
+
// its event publish and its deferred hook-entity write
|
|
1101
|
+
// (the inverse of the crash window the deferral closes),
|
|
1102
|
+
// leaving an event-first orphan: the event is in the log
|
|
1103
|
+
// but the entity is missing and the hook is unresolvable.
|
|
1104
|
+
// Repair the entity from the PERSISTED event's payload
|
|
1105
|
+
// (never the retry's — different retry metadata must not
|
|
1106
|
+
// change committed state) before surfacing the benign
|
|
1107
|
+
// duplicate to the runtime's concurrent-replay catch path.
|
|
1108
|
+
if (data.eventType === 'hook_created' && data.correlationId) {
|
|
1109
|
+
await repairHookEntityFromPersistedEvent(basedir, effectiveRunId, data.correlationId, eventId, tag);
|
|
1110
|
+
}
|
|
1111
|
+
throw new EntityConflictError(`Event "${eventId}" already exists for run "${effectiveRunId}"`);
|
|
627
1112
|
}
|
|
628
|
-
//
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
1113
|
+
// Write the hook entity ONLY now that the event publish has
|
|
1114
|
+
// committed. Doing this earlier (in the `hook_created`
|
|
1115
|
+
// branch above) would mutate an already-committed hook
|
|
1116
|
+
// entity with the retry's payload before the event publish
|
|
1117
|
+
// proved whether this attempt was repairing a missing event
|
|
1118
|
+
// or just colliding with an already-published `hook_created`.
|
|
1119
|
+
// The branch sets `hookEntityWriteOptions` iff this event
|
|
1120
|
+
// type writes an entity.
|
|
1121
|
+
if (hook && data.eventType === 'hook_created') {
|
|
1122
|
+
await writeJSON(taggedPath(basedir, 'hooks', hook.hookId, tag), hook, hookEntityWriteOptions);
|
|
635
1123
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
//
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
if (
|
|
644
|
-
|
|
1124
|
+
const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
1125
|
+
const filteredEvent = stripEventDataRefs(event, resolveData);
|
|
1126
|
+
// For run_started: include all events so the runtime can skip
|
|
1127
|
+
// the initial events.list call and reduce TTFB.
|
|
1128
|
+
let events;
|
|
1129
|
+
let cursor;
|
|
1130
|
+
let hasMore;
|
|
1131
|
+
if (data.eventType === 'run_started' && run) {
|
|
1132
|
+
const allEvents = await paginatedFileSystemQuery({
|
|
1133
|
+
directory: path.join(basedir, 'events'),
|
|
1134
|
+
schema: EventSchema,
|
|
1135
|
+
filePrefix: `${effectiveRunId}-`,
|
|
1136
|
+
sortOrder: 'asc',
|
|
1137
|
+
limit: 1000,
|
|
1138
|
+
getCreatedAt: getObjectCreatedAt('evnt'),
|
|
1139
|
+
getId: (e) => e.eventId,
|
|
1140
|
+
});
|
|
1141
|
+
events = allEvents.data;
|
|
1142
|
+
cursor = allEvents.cursor;
|
|
1143
|
+
hasMore = allEvents.hasMore;
|
|
645
1144
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
await writeJSON(taggedPath(basedir, 'waits', waitCompositeKey, tag), wait);
|
|
657
|
-
}
|
|
658
|
-
else if (data.eventType === 'wait_completed') {
|
|
659
|
-
// wait_completed: Transitions wait to 'completed', rejects duplicates.
|
|
660
|
-
// Uses writeExclusive on a lock file to atomically prevent concurrent
|
|
661
|
-
// invocations from both completing the same wait (TOCTOU race).
|
|
662
|
-
const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;
|
|
663
|
-
const waitLockName = tag
|
|
664
|
-
? `${waitCompositeKey}.completed.${tag}`
|
|
665
|
-
: `${waitCompositeKey}.completed`;
|
|
666
|
-
const lockPath = resolveWithinBase(basedir, '.locks', 'waits', waitLockName);
|
|
667
|
-
const claimed = await writeExclusive(lockPath, '');
|
|
668
|
-
if (!claimed) {
|
|
669
|
-
throw new EntityConflictError(`Wait "${data.correlationId}" already completed`);
|
|
670
|
-
}
|
|
671
|
-
const existingWait = await readJSONWithFallback(basedir, 'waits', waitCompositeKey, WaitSchema, tag);
|
|
672
|
-
if (!existingWait) {
|
|
673
|
-
// Clean up the lock file we just claimed — the wait doesn't exist
|
|
674
|
-
await fs.unlink(lockPath).catch(() => { });
|
|
675
|
-
throw new WorkflowWorldError(`Wait "${data.correlationId}" not found`);
|
|
676
|
-
}
|
|
677
|
-
// The lock file (writeExclusive above) already prevents concurrent
|
|
678
|
-
// completions — no additional status check needed.
|
|
679
|
-
wait = {
|
|
680
|
-
...existingWait,
|
|
681
|
-
status: 'completed',
|
|
682
|
-
completedAt: now,
|
|
683
|
-
updatedAt: now,
|
|
1145
|
+
// Return EventResult with event and any created/updated entity
|
|
1146
|
+
return {
|
|
1147
|
+
event: filteredEvent,
|
|
1148
|
+
run,
|
|
1149
|
+
step,
|
|
1150
|
+
hook,
|
|
1151
|
+
wait,
|
|
1152
|
+
events,
|
|
1153
|
+
cursor,
|
|
1154
|
+
hasMore,
|
|
684
1155
|
};
|
|
685
|
-
|
|
686
|
-
}
|
|
687
|
-
// Note: hook_received events are stored in the event log but don't
|
|
688
|
-
// modify the Hook entity (which doesn't have a payload field)
|
|
689
|
-
// Store event using composite key {runId}-{eventId}
|
|
690
|
-
const compositeKey = `${effectiveRunId}-${eventId}`;
|
|
691
|
-
await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), event);
|
|
692
|
-
const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
693
|
-
const filteredEvent = stripEventDataRefs(event, resolveData);
|
|
694
|
-
// For run_started: include all events so the runtime can skip
|
|
695
|
-
// the initial events.list call and reduce TTFB.
|
|
696
|
-
let events;
|
|
697
|
-
let cursor;
|
|
698
|
-
let hasMore;
|
|
699
|
-
if (data.eventType === 'run_started' && run) {
|
|
700
|
-
const allEvents = await paginatedFileSystemQuery({
|
|
701
|
-
directory: path.join(basedir, 'events'),
|
|
702
|
-
schema: EventSchema,
|
|
703
|
-
filePrefix: `${effectiveRunId}-`,
|
|
704
|
-
sortOrder: 'asc',
|
|
705
|
-
limit: 1000,
|
|
706
|
-
getCreatedAt: getObjectCreatedAt('evnt'),
|
|
707
|
-
getId: (e) => e.eventId,
|
|
708
|
-
});
|
|
709
|
-
events = allEvents.data;
|
|
710
|
-
cursor = allEvents.cursor;
|
|
711
|
-
hasMore = allEvents.hasMore;
|
|
712
|
-
}
|
|
713
|
-
// Return EventResult with event and any created/updated entity
|
|
714
|
-
return {
|
|
715
|
-
event: filteredEvent,
|
|
716
|
-
run,
|
|
717
|
-
step,
|
|
718
|
-
hook,
|
|
719
|
-
wait,
|
|
720
|
-
events,
|
|
721
|
-
cursor,
|
|
722
|
-
hasMore,
|
|
723
|
-
};
|
|
1156
|
+
} // end createImpl
|
|
724
1157
|
},
|
|
725
1158
|
async get(runId, eventId, params) {
|
|
726
1159
|
assertSafeEntityId('runId', runId);
|
|
@@ -786,4 +1219,4 @@ export function createEventsStorage(basedir, tag) {
|
|
|
786
1219
|
},
|
|
787
1220
|
};
|
|
788
1221
|
}
|
|
789
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLXN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmFnZS9ldmVudHMtc3RvcmFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsQyxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixFQUNwQixhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0sa0JBQWtCLENBQUM7QUFXMUIsT0FBTyxFQUNMLFdBQVcsRUFDWCxVQUFVLEVBQ1YsbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQixvQkFBb0IsRUFDcEIsVUFBVSxFQUNWLHFCQUFxQixFQUNyQixVQUFVLEVBQ1YsaUJBQWlCLEdBQ2xCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUN4QixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDM0QsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsWUFBWSxFQUNaLGFBQWEsRUFDYix3QkFBd0IsRUFDeEIsUUFBUSxFQUNSLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsVUFBVSxFQUNWLGNBQWMsRUFDZCxTQUFTLEdBQ1YsTUFBTSxVQUFVLENBQUM7QUFDbEIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzFELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVoRCxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxN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RSxDQUFDLEtBQUssQ0FBQyxhQUFhLEtBQUssYUFBYTtnQkFDeEQsMkRBQTJEO2dCQUMzRCxtREFBbUQ7Z0JBQ25ELFNBQVMsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLFNBQVMsSUFBSSxLQUFLO2dCQUNoRCxLQUFLLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxLQUFLO2dCQUMvQixNQUFNLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxNQUFNO2dCQUNqQyxZQUFZLEVBQUUsa0JBQWtCLENBQUMsTUFBTSxDQUFDO2dCQUN4QyxLQUFLLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPO2FBQ2hDLENBQUMsQ0FBQztZQUVILHlEQUF5RDtZQUN6RCxJQUFJLFdBQVcsS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDM0IsT0FBTztvQkFDTCxHQUFHLE1BQU07b0JBQ1QsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDOUIsa0JBQWtCLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUN2QztpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBSdW5Ob3RTdXBwb3J0ZWRFcnJvcixcbiAgVG9vRWFybHlFcnJvcixcbiAgV29ya2Zsb3dXb3JsZEVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB0eXBlIHtcbiAgRXZlbnQsXG4gIEV2ZW50UmVzdWx0LFxuICBIb29rLFxuICBTZXJpYWxpemVkRGF0YSxcbiAgU3RlcCxcbiAgU3RvcmFnZSxcbiAgV2FpdCxcbiAgV29ya2Zsb3dSdW4sXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQge1xuICBFdmVudFNjaGVtYSxcbiAgSG9va1NjaGVtYSxcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgcmVxdWlyZXNOZXdlcldvcmxkLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU3RlcFNjaGVtYSxcbiAgdmFsaWRhdGVVbGlkVGltZXN0YW1wLFxuICBXYWl0U2NoZW1hLFxuICBXb3JrZmxvd1J1blNjaGVtYSxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IHogfSBmcm9tICd6b2QnO1xuaW1wb3J0IHsgREVGQVVMVF9SRVNPTFZFX0RBVEFfT1BUSU9OIH0gZnJvbSAnLi4vY29uZmlnLmpzJztcbmltcG9ydCB7XG4gIGFzc2VydFNhZmVFbnRpdHlJZCxcbiAgZGVsZXRlSlNPTixcbiAganNvblJlcGxhY2VyLFxuICBsaXN0SlNPTkZpbGVzLFxuICBwYWdpbmF0ZWRGaWxlU3lzdGVtUXVlcnksXG4gIHJlYWRKU09OLFxuICByZWFkSlNPTldpdGhGYWxsYmFjayxcbiAgcmVzb2x2ZVdpdGhpbkJhc2UsXG4gIHRhZ2dlZFBhdGgsXG4gIHdyaXRlRXhjbHVzaXZlLFxuICB3cml0ZUpTT04sXG59IGZyb20gJy4uL2ZzLmpzJztcbmltcG9ydCB7IHN0cmlwRXZlbnREYXRhUmVmcyB9IGZyb20gJy4vZmlsdGVycy5qcyc7XG5pbXBvcnQgeyBnZXRPYmplY3RDcmVhdGVkQXQsIGhhc2hUb2tlbiwgbW9ub3RvbmljVWxpZCB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBkZWxldGVBbGxIb29rc0ZvclJ1biB9IGZyb20gJy4vaG9va3Mtc3RvcmFnZS5qcyc7XG5pbXBvcnQgeyBoYW5kbGVMZWdhY3lFdmVudCB9IGZyb20gJy4vbGVnYWN5LmpzJztcblxuY29uc3QgSG9va1Rva2VuQ2xhaW1TY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHJ1bklkOiB6LnN0cmluZygpLFxufSk7XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRIb29rVG9rZW5DbGFpbShcbiAgY29uc3RyYWludFBhdGg6IHN0cmluZ1xuKTogUHJvbWlzZTx6LmluZmVyPHR5cGVvZiBIb29rVG9rZW5DbGFpbVNjaGVtYT4gfCBudWxsPiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHJlYWRKU09OKGNvbnN0cmFpbnRQYXRoLCBIb29rVG9rZW5DbGFpbVNjaGVtYSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgU3ludGF4RXJyb3IgfHwgZXJyb3IgaW5zdGFuY2VvZiB6LlpvZEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gZGVsZXRlIGFsbCB3YWl0cyBhc3NvY2lhdGVkIHdpdGggYSB3b3JrZmxvdyBydW4uXG4gKiBDYWxsZWQgd2hlbiBhIHJ1biByZWFjaGVzIGEgdGVybWluYWwgc3RhdGUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUFsbFdhaXRzRm9yUnVuKFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIHJ1bklkOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB3YWl0c0RpciA9IHBhdGguam9pbihiYXNlZGlyLCAnd2FpdHMnKTtcbiAgY29uc3QgZmlsZXMgPSBhd2FpdCBsaXN0SlNPTkZpbGVzKHdhaXRzRGlyKTtcblxuICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAvLyBmaWxlSWRzIG1heSBjb250YWluIHRhZyBzdWZmaXhlcyAoZS5nLiwgXCJ3cnVuX0FCQy1jb3JySWQudml0ZXN0LTBcIilcbiAgICAvLyBidXQgc3RhcnRzV2l0aCBzdGlsbCBtYXRjaGVzIGNvcnJlY3RseSBzaW5jZSB0aGUgdGFnIGlzIGEgc3VmZml4LlxuICAgIGlmIChmaWxlLnN0YXJ0c1dpdGgoYCR7cnVuSWR9LWApKSB7XG4gICAgICBjb25zdCB3YWl0UGF0aCA9IHBhdGguam9pbih3YWl0c0RpciwgYCR7ZmlsZX0uanNvbmApO1xuICAgICAgYXdhaXQgZGVsZXRlSlNPTih3YWl0UGF0aCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgZXZlbnRzIHN0b3JhZ2UgaW1wbGVtZW50YXRpb24gdXNpbmcgdGhlIGZpbGVzeXN0ZW0uXG4gKiBJbXBsZW1lbnRzIHRoZSBTdG9yYWdlWydldmVudHMnXSBpbnRlcmZhY2Ugd2l0aCBjcmVhdGUsIGxpc3QsIGFuZCBsaXN0QnlDb3JyZWxhdGlvbklkIG9wZXJhdGlvbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFdmVudHNTdG9yYWdlKFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIHRhZz86IHN0cmluZ1xuKTogU3RvcmFnZVsnZXZlbnRzJ10ge1xuICByZXR1cm4ge1xuICAgIGFzeW5jIGNyZWF0ZShydW5JZCwgZGF0YSwgcGFyYW1zKTogUHJvbWlzZTxFdmVudFJlc3VsdD4ge1xuICAgICAgY29uc3QgZXZlbnRJZCA9IGBldm50XyR7bW9ub3RvbmljVWxpZCgpfWA7XG4gICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAvLyBWYWxpZGF0ZSByZXF1ZXN0LXN1cHBsaWVkIElEcyBiZWZvcmUgdGhleSdyZSBjb25jYXRlbmF0ZWQgaW50b1xuICAgICAgLy8gZmlsZXN5c3RlbSBwYXRocy4gVGhpcyBpcyB0aGUgcHJpbWFyeSBkZWZlbnNlIGFnYWluc3QgcGF0aCB0cmF2ZXJzYWxcbiAgICAgIC8vIGF0dGFja3Mgd2hlcmUgYSBjbGllbnQgc3VwcGxpZXMgcnVuSWQgLyBjb3JyZWxhdGlvbklkIHZhbHVlcyBsaWtlXG4gICAgICAvLyBcIi4uLy4uLy4uL3BhY2thZ2VcIiB0byByZWFkIG9yIHdyaXRlIGZpbGVzIG91dHNpZGUgdGhlIHN0b3JhZ2Ugcm9vdC5cbiAgICAgIC8vXG4gICAgICAvLyBFbXB0eSBgY29ycmVsYXRpb25JZGAgdmFsdWVzIGFyZSBhbHNvIHJlamVjdGVkIGhlcmU6IHRoZSBldmVudFxuICAgICAgLy8gc2NoZW1hcyBvbmx5IHJlcXVpcmUgYHouc3RyaW5nKClgLCBzbyB3aXRob3V0IHRoaXMgY2hlY2sgYVxuICAgICAgLy8gc3RlcF9jcmVhdGVkIC8gaG9va19jcmVhdGVkIC8gd2FpdF9jcmVhdGVkIHJlcXVlc3Qgd2l0aFxuICAgICAgLy8gYGNvcnJlbGF0aW9uSWQ6ICcnYCB3b3VsZCBzaWxlbnRseSBiZSB3cml0dGVuIHVuZGVyIGEgbWFsZm9ybWVkXG4gICAgICAvLyBjb21wb3NpdGUga2V5IGxpa2UgYCR7cnVuSWR9LWAuXG4gICAgICBpZiAocnVuSWQgIT0gbnVsbCAmJiBydW5JZCAhPT0gJycpIHtcbiAgICAgICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdydW5JZCcsIHJ1bklkKTtcbiAgICAgIH1cbiAgICAgIGlmICgnY29ycmVsYXRpb25JZCcgaW4gZGF0YSAmJiB0eXBlb2YgZGF0YS5jb3JyZWxhdGlvbklkID09PSAnc3RyaW5nJykge1xuICAgICAgICBhc3NlcnRTYWZlRW50aXR5SWQoJ2NvcnJlbGF0aW9uSWQnLCBkYXRhLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBGb3IgcnVuX2NyZWF0ZWQgZXZlbnRzLCB1c2UgY2xpZW50LXByb3ZpZGVkIHJ1bklkIG9yIGdlbmVyYXRlIG9uZSBzZXJ2ZXItc2lkZVxuICAgICAgbGV0IGVmZmVjdGl2ZVJ1bklkOiBzdHJpbmc7XG4gICAgICBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fY3JlYXRlZCcgJiYgKCFydW5JZCB8fCBydW5JZCA9PT0gJycpKSB7XG4gICAgICAgIGVmZmVjdGl2ZVJ1bklkID0gYHdydW5fJHttb25vdG9uaWNVbGlkKCl9YDtcbiAgICAgIH0gZWxzZSBpZiAoIXJ1bklkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncnVuSWQgaXMgcmVxdWlyZWQgZm9yIG5vbi1ydW5fY3JlYXRlZCBldmVudHMnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVmZmVjdGl2ZVJ1bklkID0gcnVuSWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIGNsaWVudC1wcm92aWRlZCBydW5JZCB0aW1lc3RhbXAgaXMgd2l0aGluIGFjY2VwdGFibGUgdGhyZXNob2xkXG4gICAgICBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fY3JlYXRlZCcgJiYgcnVuSWQgJiYgcnVuSWQgIT09ICcnKSB7XG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25FcnJvciA9IHZhbGlkYXRlVWxpZFRpbWVzdGFtcChlZmZlY3RpdmVSdW5JZCwgJ3dydW5fJyk7XG4gICAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKHZhbGlkYXRpb25FcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gc3BlY1ZlcnNpb24gaXMgYWx3YXlzIHNlbnQgYnkgdGhlIHJ1bnRpbWUsIGJ1dCB3ZSBwcm92aWRlIGEgZmFsbGJhY2sgZm9yIHNhZmV0eVxuICAgICAgY29uc3QgZWZmZWN0aXZlU3BlY1ZlcnNpb24gPSBkYXRhLnNwZWNWZXJzaW9uID8/IFNQRUNfVkVSU0lPTl9DVVJSRU5UO1xuXG4gICAgICAvLyBIZWxwZXIgdG8gY2hlY2sgaWYgcnVuIGlzIGluIHRlcm1pbmFsIHN0YXRlXG4gICAgICBjb25zdCBpc1J1blRlcm1pbmFsID0gKHN0YXR1czogc3RyaW5nKSA9PlxuICAgICAgICBbJ2NvbXBsZXRlZCcsICdmYWlsZWQnLCAnY2FuY2VsbGVkJ10uaW5jbHVkZXMoc3RhdHVzKTtcblxuICAgICAgLy8gSGVscGVyIHRvIGNoZWNrIGlmIHN0ZXAgaXMgaW4gdGVybWluYWwgc3RhdGVcbiAgICAgIGNvbnN0IGlzU3RlcFRlcm1pbmFsID0gKHN0YXR1czogc3RyaW5nKSA9PlxuICAgICAgICBbJ2NvbXBsZXRlZCcsICdmYWlsZWQnLCAnY2FuY2VsbGVkJ10uaW5jbHVkZXMoc3RhdHVzKTtcblxuICAgICAgLy8gR2V0IGN1cnJlbnQgcnVuIHN0YXRlIGZvciB2YWxpZGF0aW9uIChpZiBub3QgY3JlYXRpbmcgYSBuZXcgcnVuKVxuICAgICAgLy8gU2tpcCBydW4gdmFsaWRhdGlvbiBmb3Igc3RlcF9jb21wbGV0ZWQgYW5kIHN0ZXBfcmV0cnlpbmcgLSB0aGV5IG9ubHkgb3BlcmF0ZVxuICAgICAgLy8gb24gcnVubmluZyBzdGVwcywgYW5kIHJ1bm5pbmcgc3RlcHMgYXJlIGFsd2F5cyBhbGxvd2VkIHRvIG1vZGlmeSByZWdhcmRsZXNzXG4gICAgICAvLyBvZiBydW4gc3RhdGUuIFRoaXMgb3B0aW1pemF0aW9uIHNhdmVzIGZpbGVzeXN0ZW0gcmVhZHMgcGVyIHN0ZXAgZXZlbnQuXG4gICAgICBsZXQgY3VycmVudFJ1bjogV29ya2Zsb3dSdW4gfCBudWxsID0gbnVsbDtcbiAgICAgIGNvbnN0IHNraXBSdW5WYWxpZGF0aW9uRXZlbnRzID0gWydzdGVwX2NvbXBsZXRlZCcsICdzdGVwX3JldHJ5aW5nJ107XG4gICAgICBpZiAoXG4gICAgICAgIGRhdGEuZXZlbnRUeXBlICE9PSAncnVuX2NyZWF0ZWQnICYmXG4gICAgICAgICFza2lwUnVuVmFsaWRhdGlvbkV2ZW50cy5pbmNsdWRlcyhkYXRhLmV2ZW50VHlwZSlcbiAgICAgICkge1xuICAgICAgICBjdXJyZW50UnVuID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAncnVucycsXG4gICAgICAgICAgZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgV29ya2Zsb3dSdW5TY2hlbWEsXG4gICAgICAgICAgdGFnXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzaWxpZW50IHN0YXJ0OiBydW5fc3RhcnRlZCBvbiBub24tZXhpc3RlbnQgcnVuIHdpdGggZXZlbnREYXRhXG4gICAgICAgIC8vIGNyZWF0ZXMgdGhlIHJ1biBmaXJzdCwgc28gdGhlIHF1ZXVlIGNhbiBib290c3RyYXAgYSBydW4gdGhhdFxuICAgICAgICAvLyBmYWlsZWQgdG8gY3JlYXRlIGR1cmluZyBzdGFydCgpLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgZGF0YS5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcgJiZcbiAgICAgICAgICAhY3VycmVudFJ1biAmJlxuICAgICAgICAgICdldmVudERhdGEnIGluIGRhdGEgJiZcbiAgICAgICAgICBkYXRhLmV2ZW50RGF0YVxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBydW5JbnB1dERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgICBkZXBsb3ltZW50SWQ/OiBzdHJpbmc7XG4gICAgICAgICAgICB3b3JrZmxvd05hbWU/OiBzdHJpbmc7XG4gICAgICAgICAgICBpbnB1dD86IGFueTtcbiAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcnVuSW5wdXREYXRhLmRlcGxveW1lbnRJZCAmJlxuICAgICAgICAgICAgcnVuSW5wdXREYXRhLndvcmtmbG93TmFtZSAmJlxuICAgICAgICAgICAgcnVuSW5wdXREYXRhLmlucHV0ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIEF0b21pY2FsbHkgdHJ5IHRvIHB1Ymxpc2ggdGhlIHJ1biBlbnRpdHkgc28gb25seSB0aGUgZmlyc3RcbiAgICAgICAgICAgIC8vIHdyaXRlciB3aW5zLCBwcmV2ZW50aW5nIGEgVE9DVE9VIHJhY2Ugd2hlcmUgYSBjb25jdXJyZW50XG4gICAgICAgICAgICAvLyBydW5fY3JlYXRlZCBmcm9tIHN0YXJ0KCkgY291bGQgb3ZlcndyaXRlIGEgcnVuIHRoYXQgd2FzXG4gICAgICAgICAgICAvLyBhbHJlYWR5IHRyYW5zaXRpb25lZCB0byAncnVubmluZycuXG4gICAgICAgICAgICBjb25zdCBjcmVhdGVkUnVuOiBXb3JrZmxvd1J1biA9IHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IHJ1bklucHV0RGF0YS5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICAgICAgICB3b3JrZmxvd05hbWU6IHJ1bklucHV0RGF0YS53b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogcnVuSW5wdXREYXRhLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgIGlucHV0OiBydW5JbnB1dERhdGEuaW5wdXQsXG4gICAgICAgICAgICAgIG91dHB1dDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBzdGFydGVkQXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY29tcGxldGVkQXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJ1blBhdGggPSB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyk7XG4gICAgICAgICAgICBjb25zdCBjcmVhdGVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUoXG4gICAgICAgICAgICAgIHJ1blBhdGgsXG4gICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGNyZWF0ZWRSdW4sIGpzb25SZXBsYWNlcilcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGlmIChjcmVhdGVkKSB7XG4gICAgICAgICAgICAgIC8vIFdlIGNyZWF0ZWQgdGhlIHJ1biDigJQgYWxzbyB3cml0ZSB0aGUgcnVuX2NyZWF0ZWQgZXZlbnQuXG4gICAgICAgICAgICAgIGNvbnN0IHJ1bkNyZWF0ZWRFdmVudElkID0gYGV2bnRfJHttb25vdG9uaWNVbGlkKCl9YDtcbiAgICAgICAgICAgICAgY29uc3QgcnVuQ3JlYXRlZEV2ZW50OiBFdmVudCA9IHtcbiAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fY3JlYXRlZCcsXG4gICAgICAgICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHJ1bkNyZWF0ZWRFdmVudElkLFxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcnVuSW5wdXREYXRhLmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuSW5wdXREYXRhLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiBydW5JbnB1dERhdGEuaW5wdXQsXG4gICAgICAgICAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBydW5JbnB1dERhdGEuZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7cnVuQ3JlYXRlZEV2ZW50SWR9YDtcbiAgICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ2V2ZW50cycsIGNyZWF0ZWRDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICAgICAgcnVuQ3JlYXRlZEV2ZW50XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGN1cnJlbnRSdW4gPSBjcmVhdGVkUnVuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gUnVuIGFscmVhZHkgZXhpc3RzIChjb25jdXJyZW50IHJ1bl9jcmVhdGVkIHdvbiB0aGVcbiAgICAgICAgICAgICAgLy8gcmFjZSkuIFJlLXJlYWQgaXQgc28gZG93bnN0cmVhbSBsb2dpYyBzZWVzIHRoZSByZWFsIHN0YXRlLlxuICAgICAgICAgICAgICBjdXJyZW50UnVuID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgICAncnVucycsXG4gICAgICAgICAgICAgICAgZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgV29ya2Zsb3dSdW5TY2hlbWEsXG4gICAgICAgICAgICAgICAgdGFnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgICAgLy8gVkVSU0lPTiBDT01QQVRJQklMSVRZOiBDaGVjayBydW4gc3BlYyB2ZXJzaW9uXG4gICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgIC8vIEZvciBldmVudHMgdGhhdCBoYXZlIGZldGNoZWQgdGhlIHJ1biwgY2hlY2sgdmVyc2lvbiBjb21wYXRpYmlsaXR5LlxuICAgICAgLy8gU2tpcCBmb3IgcnVuX2NyZWF0ZWQgKG5vIGV4aXN0aW5nIHJ1bikgYW5kIHJ1bnRpbWUgZXZlbnRzIChzdGVwX2NvbXBsZXRlZCwgc3RlcF9yZXRyeWluZykuXG4gICAgICBpZiAoY3VycmVudFJ1bikge1xuICAgICAgICAvLyBDaGVjayBpZiBydW4gcmVxdWlyZXMgYSBuZXdlciB3b3JsZCB2ZXJzaW9uXG4gICAgICAgIGlmIChyZXF1aXJlc05ld2VyV29ybGQoY3VycmVudFJ1bi5zcGVjVmVyc2lvbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUnVuTm90U3VwcG9ydGVkRXJyb3IoXG4gICAgICAgICAgICBjdXJyZW50UnVuLnNwZWNWZXJzaW9uISxcbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9DVVJSRU5UXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJvdXRlIHRvIGxlZ2FjeSBoYW5kbGVyIGZvciBwcmUtZXZlbnQtc291cmNpbmcgcnVuc1xuICAgICAgICBpZiAoaXNMZWdhY3lTcGVjVmVyc2lvbihjdXJyZW50UnVuLnNwZWNWZXJzaW9uKSkge1xuICAgICAgICAgIHJldHVybiBoYW5kbGVMZWdhY3lFdmVudChcbiAgICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgICBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBjdXJyZW50UnVuLFxuICAgICAgICAgICAgcGFyYW1zXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgIC8vIFZBTElEQVRJT046IFRlcm1pbmFsIHN0YXRlIGFuZCBldmVudCBvcmRlcmluZyBjaGVja3NcbiAgICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgICAvLyBSdW4gdGVybWluYWwgc3RhdGUgdmFsaWRhdGlvblxuICAgICAgaWYgKGN1cnJlbnRSdW4gJiYgaXNSdW5UZXJtaW5hbChjdXJyZW50UnVuLnN0YXR1cykpIHtcbiAgICAgICAgY29uc3QgcnVuVGVybWluYWxFdmVudHMgPSBbXG4gICAgICAgICAgJ3J1bl9zdGFydGVkJyxcbiAgICAgICAgICAncnVuX2NvbXBsZXRlZCcsXG4gICAgICAgICAgJ3J1bl9mYWlsZWQnLFxuICAgICAgICBdO1xuXG4gICAgICAgIC8vIElkZW1wb3RlbnQgb3BlcmF0aW9uOiBydW5fY2FuY2VsbGVkIG9uIGFscmVhZHkgY2FuY2VsbGVkIHJ1biBpcyBhbGxvd2VkXG4gICAgICAgIGlmIChcbiAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jYW5jZWxsZWQnICYmXG4gICAgICAgICAgY3VycmVudFJ1bi5zdGF0dXMgPT09ICdjYW5jZWxsZWQnXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIFJldHVybiBleGlzdGluZyBzdGF0ZSAoaWRlbXBvdGVudClcbiAgICAgICAgICBjb25zdCBldmVudDogRXZlbnQgPSB7XG4gICAgICAgICAgICAuLi5kYXRhLFxuICAgICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3QgY29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZXZlbnRJZH1gO1xuICAgICAgICAgIGF3YWl0IHdyaXRlSlNPTihcbiAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ2V2ZW50cycsIGNvbXBvc2l0ZUtleSwgdGFnKSxcbiAgICAgICAgICAgIGV2ZW50XG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCByZXNvbHZlRGF0YSA9XG4gICAgICAgICAgICBwYXJhbXM/LnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXZlbnQ6IHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpLFxuICAgICAgICAgICAgcnVuOiBjdXJyZW50UnVuLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGb3IgcnVuX3N0YXJ0ZWQgb24gdGVybWluYWwgcnVucywgdXNlIFJ1bkV4cGlyZWRFcnJvciBzbyB0aGVcbiAgICAgICAgLy8gcnVudGltZSBrbm93cyB0byBleGl0IHdpdGhvdXQgcmV0cnlpbmcuXG4gICAgICAgIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9zdGFydGVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBSdW5FeHBpcmVkRXJyb3IoXG4gICAgICAgICAgICBgV29ya2Zsb3cgcnVuIFwiJHtlZmZlY3RpdmVSdW5JZH1cIiBpcyBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlIFwiJHtjdXJyZW50UnVuLnN0YXR1c31cImBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT3RoZXIgcnVuIHN0YXRlIHRyYW5zaXRpb25zIGFyZSBub3QgYWxsb3dlZCBvbiB0ZXJtaW5hbCBydW5zXG4gICAgICAgIGlmIChcbiAgICAgICAgICBydW5UZXJtaW5hbEV2ZW50cy5pbmNsdWRlcyhkYXRhLmV2ZW50VHlwZSkgfHxcbiAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jYW5jZWxsZWQnXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgYENhbm5vdCB0cmFuc2l0aW9uIHJ1biBmcm9tIHRlcm1pbmFsIHN0YXRlIFwiJHtjdXJyZW50UnVuLnN0YXR1c31cImBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRpbmcgbmV3IGVudGl0aWVzIG9uIHRlcm1pbmFsIHJ1bnMgaXMgbm90IGFsbG93ZWRcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGRhdGEuZXZlbnRUeXBlID09PSAnc3RlcF9jcmVhdGVkJyB8fFxuICAgICAgICAgIGRhdGEuZXZlbnRUeXBlID09PSAnaG9va19jcmVhdGVkJyB8fFxuICAgICAgICAgIGRhdGEuZXZlbnRUeXBlID09PSAnd2FpdF9jcmVhdGVkJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgIGBDYW5ub3QgY3JlYXRlIG5ldyBlbnRpdGllcyBvbiBydW4gaW4gdGVybWluYWwgc3RhdGUgXCIke2N1cnJlbnRSdW4uc3RhdHVzfVwiYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gU3RlcC1yZWxhdGVkIGV2ZW50IHZhbGlkYXRpb24gKG9yZGVyaW5nIGFuZCB0ZXJtaW5hbCBzdGF0ZSlcbiAgICAgIC8vIFN0b3JlIGV4aXN0aW5nU3RlcCBzbyB3ZSBjYW4gcmV1c2UgaXQgbGF0ZXIgKGF2b2lkIGRvdWJsZSByZWFkKVxuICAgICAgbGV0IHZhbGlkYXRlZFN0ZXA6IFN0ZXAgfCBudWxsID0gbnVsbDtcbiAgICAgIGNvbnN0IHN0ZXBFdmVudHMgPSBbXG4gICAgICAgICdzdGVwX3N0YXJ0ZWQnLFxuICAgICAgICAnc3RlcF9jb21wbGV0ZWQnLFxuICAgICAgICAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAnc3RlcF9yZXRyeWluZycsXG4gICAgICBdO1xuICAgICAgaWYgKHN0ZXBFdmVudHMuaW5jbHVkZXMoZGF0YS5ldmVudFR5cGUpICYmIGRhdGEuY29ycmVsYXRpb25JZCkge1xuICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgIHZhbGlkYXRlZFN0ZXAgPSBhd2FpdCByZWFkSlNPTldpdGhGYWxsYmFjayhcbiAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICdzdGVwcycsXG4gICAgICAgICAgc3RlcENvbXBvc2l0ZUtleSxcbiAgICAgICAgICBTdGVwU2NoZW1hLFxuICAgICAgICAgIHRhZ1xuICAgICAgICApO1xuXG4gICAgICAgIC8vIEV2ZW50IG9yZGVyaW5nOiBzdGVwIG11c3QgZXhpc3QgYmVmb3JlIHRoZXNlIGV2ZW50c1xuICAgICAgICBpZiAoIXZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKFxuICAgICAgICAgICAgYFN0ZXAgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBub3QgZm91bmRgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0ZXAgdGVybWluYWwgc3RhdGUgdmFsaWRhdGlvblxuICAgICAgICBpZiAoaXNTdGVwVGVybWluYWwodmFsaWRhdGVkU3RlcC5zdGF0dXMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICBgQ2Fubm90IG1vZGlmeSBzdGVwIGluIHRlcm1pbmFsIHN0YXRlIFwiJHt2YWxpZGF0ZWRTdGVwLnN0YXR1c31cImBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT24gdGVybWluYWwgcnVuczogb25seSBhbGxvdyBjb21wbGV0aW5nL2ZhaWxpbmcgaW4tcHJvZ3Jlc3Mgc3RlcHNcbiAgICAgICAgaWYgKGN1cnJlbnRSdW4gJiYgaXNSdW5UZXJtaW5hbChjdXJyZW50UnVuLnN0YXR1cykpIHtcbiAgICAgICAgICBpZiAodmFsaWRhdGVkU3RlcC5zdGF0dXMgIT09ICdydW5uaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bkV4cGlyZWRFcnJvcihcbiAgICAgICAgICAgICAgYENhbm5vdCBtb2RpZnkgbm9uLXJ1bm5pbmcgc3RlcCBvbiBydW4gaW4gdGVybWluYWwgc3RhdGUgXCIke2N1cnJlbnRSdW4uc3RhdHVzfVwiYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSG9vay1yZWxhdGVkIGV2ZW50IHZhbGlkYXRpb24gKG9yZGVyaW5nKVxuICAgICAgY29uc3QgaG9va0V2ZW50c1JlcXVpcmluZ0V4aXN0ZW5jZSA9IFsnaG9va19kaXNwb3NlZCcsICdob29rX3JlY2VpdmVkJ107XG4gICAgICBpZiAoXG4gICAgICAgIGhvb2tFdmVudHNSZXF1aXJpbmdFeGlzdGVuY2UuaW5jbHVkZXMoZGF0YS5ldmVudFR5cGUpICYmXG4gICAgICAgIGRhdGEuY29ycmVsYXRpb25JZFxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nSG9vayA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgJ2hvb2tzJyxcbiAgICAgICAgICBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgSG9va1NjaGVtYSxcbiAgICAgICAgICB0YWdcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWV4aXN0aW5nSG9vaykge1xuICAgICAgICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcihkYXRhLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBldmVudDogRXZlbnQgPSB7XG4gICAgICAgIC4uLmRhdGEsXG4gICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgIH07XG4gICAgICAvLyBTdHJpcCBldmVudERhdGEgZnJvbSBydW5fc3RhcnRlZCDigJQgaXQgYmVsb25ncyBvbiBydW5fY3JlYXRlZCBvbmx5LlxuICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX3N0YXJ0ZWQnICYmICdldmVudERhdGEnIGluIGV2ZW50KSB7XG4gICAgICAgIGRlbGV0ZSAoZXZlbnQgYXMgYW55KS5ldmVudERhdGE7XG4gICAgICB9XG5cbiAgICAgIC8vIFRyYWNrIGVudGl0eSBjcmVhdGVkL3VwZGF0ZWQgZm9yIEV2ZW50UmVzdWx0XG4gICAgICBsZXQgcnVuOiBXb3JrZmxvd1J1biB8IHVuZGVmaW5lZDtcbiAgICAgIGxldCBzdGVwOiBTdGVwIHwgdW5kZWZpbmVkO1xuICAgICAgbGV0IGhvb2s6IEhvb2sgfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgd2FpdDogV2FpdCB8IHVuZGVmaW5lZDtcblxuICAgICAgLy8gQ3JlYXRlL3VwZGF0ZSBlbnRpdHkgYmFzZWQgb24gZXZlbnQgdHlwZSAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAvLyBSdW4gbGlmZWN5Y2xlIGV2ZW50c1xuICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX2NyZWF0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgY29uc3QgcnVuRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICBkZXBsb3ltZW50SWQ6IHN0cmluZztcbiAgICAgICAgICB3b3JrZmxvd05hbWU6IHN0cmluZztcbiAgICAgICAgICBpbnB1dDogU2VyaWFsaXplZERhdGE7XG4gICAgICAgICAgZXhlY3V0aW9uQ29udGV4dD86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgICAgIH07XG4gICAgICAgIHJ1biA9IHtcbiAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgZGVwbG95bWVudElkOiBydW5EYXRhLmRlcGxveW1lbnRJZCxcbiAgICAgICAgICBzdGF0dXM6ICdwZW5kaW5nJyxcbiAgICAgICAgICB3b3JrZmxvd05hbWU6IHJ1bkRhdGEud29ya2Zsb3dOYW1lLFxuICAgICAgICAgIC8vIFByb3BhZ2F0ZSBzcGVjVmVyc2lvbiBmcm9tIHRoZSBldmVudCB0byB0aGUgcnVuIGVudGl0eVxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBydW5EYXRhLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgaW5wdXQ6IHJ1bkRhdGEuaW5wdXQsXG4gICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgZXJyb3I6IHVuZGVmaW5lZCxcbiAgICAgICAgICBzdGFydGVkQXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICBjb21wbGV0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICB9O1xuICAgICAgICAvLyBBdG9taWNhbGx5IHB1Ymxpc2ggdGhlIHJ1biBlbnRpdHkgZmlsZSB3aXRob3V0IG92ZXJ3cml0aW5nIGFuXG4gICAgICAgIC8vIGV4aXN0aW5nIHdpbm5lci4gVGhpcyBwcmV2ZW50cyBhIFRPQ1RPVSByYWNlIHdpdGggdGhlIHJlc2lsaWVudFxuICAgICAgICAvLyBzdGFydCBwYXRoIChydW5fc3RhcnRlZCBvbiBub24tZXhpc3RlbnQgcnVuKSB0aGF0IGNvdWxkIHJlc3VsdCBpblxuICAgICAgICAvLyBkdXBsaWNhdGUgcnVuX2NyZWF0ZWQgZXZlbnRzIGluIHRoZSBldmVudCBsb2cuXG4gICAgICAgIGNvbnN0IHJ1blBhdGggPSB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyk7XG4gICAgICAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB3cml0ZUV4Y2x1c2l2ZShcbiAgICAgICAgICBydW5QYXRoLFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJ1biwganNvblJlcGxhY2VyLCAyKVxuICAgICAgICApO1xuICAgICAgICBpZiAoIWNyZWF0ZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgIGBXb3JrZmxvdyBydW4gXCIke2VmZmVjdGl2ZVJ1bklkfVwiIGFscmVhZHkgZXhpc3RzYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcpIHtcbiAgICAgICAgLy8gUmV1c2UgY3VycmVudFJ1biBmcm9tIHZhbGlkYXRpb24gKGFscmVhZHkgcmVhZCBhYm92ZSlcbiAgICAgICAgaWYgKGN1cnJlbnRSdW4pIHtcbiAgICAgICAgICAvLyBJZiBhbHJlYWR5IHJ1bm5pbmcsIHJldHVybiB0aGUgcnVuIHdpdGhvdXQgaW5zZXJ0aW5nIGFcbiAgICAgICAgICAvLyBkdXBsaWNhdGUgZXZlbnQuICBUaGlzIG1ha2VzIHJ1bl9zdGFydGVkIGlkZW1wb3RlbnQgZm9yXG4gICAgICAgICAgLy8gY29uY3VycmVudCBpbnZvY2F0aW9ucy4gIFdlIG9taXQgcHJlbG9hZGVkIGV2ZW50cyBoZXJlXG4gICAgICAgICAgLy8gYmVjYXVzZSB0aGlzIGlzIGEgcmFyZSByYWNlLWNvbmRpdGlvbiBwYXRoIOKAlCB0aGUgcnVudGltZVxuICAgICAgICAgIC8vIGZhbGxzIGJhY2sgdG8gbG9hZGluZyBldmVudHMgc2VwYXJhdGVseS5cbiAgICAgICAgICBpZiAoY3VycmVudFJ1bi5zdGF0dXMgPT09ICdydW5uaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHsgcnVuOiBjdXJyZW50UnVuIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcnVuID0ge1xuICAgICAgICAgICAgcnVuSWQ6IGN1cnJlbnRSdW4ucnVuSWQsXG4gICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBjdXJyZW50UnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBjdXJyZW50UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgaW5wdXQ6IGN1cnJlbnRSdW4uaW5wdXQsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IGN1cnJlbnRSdW4uY3JlYXRlZEF0LFxuICAgICAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY29tcGxldGVkQXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHN0YXJ0ZWRBdDogY3VycmVudFJ1bi5zdGFydGVkQXQgPz8gbm93LFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICBydW4sXG4gICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jb21wbGV0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgY29uc3QgY29tcGxldGVkRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHsgb3V0cHV0PzogYW55IH07XG4gICAgICAgIC8vIFJldXNlIGN1cnJlbnRSdW4gZnJvbSB2YWxpZGF0aW9uIChhbHJlYWR5IHJlYWQgYWJvdmUpXG4gICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgcnVuID0ge1xuICAgICAgICAgICAgcnVuSWQ6IGN1cnJlbnRSdW4ucnVuSWQsXG4gICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBjdXJyZW50UnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBjdXJyZW50UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgaW5wdXQ6IGN1cnJlbnRSdW4uaW5wdXQsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IGN1cnJlbnRSdW4uY3JlYXRlZEF0LFxuICAgICAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgICAgIHN0YXJ0ZWRBdDogY3VycmVudFJ1bi5zdGFydGVkQXQsXG4gICAgICAgICAgICBzdGF0dXM6ICdjb21wbGV0ZWQnLFxuICAgICAgICAgICAgb3V0cHV0OiBjb21wbGV0ZWREYXRhLm91dHB1dCxcbiAgICAgICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjb21wbGV0ZWRBdDogbm93LFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICBydW4sXG4gICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICBkZWxldGVBbGxIb29rc0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgICBkZWxldGVBbGxXYWl0c0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fZmFpbGVkJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnN0IGZhaWxlZERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgZXJyb3I6IGFueTtcbiAgICAgICAgICBlcnJvckNvZGU/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFJldXNlIGN1cnJlbnRSdW4gZnJvbSB2YWxpZGF0aW9uIChhbHJlYWR5IHJlYWQgYWJvdmUpXG4gICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgcnVuID0ge1xuICAgICAgICAgICAgcnVuSWQ6IGN1cnJlbnRSdW4ucnVuSWQsXG4gICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBjdXJyZW50UnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBjdXJyZW50UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgaW5wdXQ6IGN1cnJlbnRSdW4uaW5wdXQsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IGN1cnJlbnRSdW4uY3JlYXRlZEF0LFxuICAgICAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgICAgIHN0YXJ0ZWRBdDogY3VycmVudFJ1bi5zdGFydGVkQXQsXG4gICAgICAgICAgICBzdGF0dXM6ICdmYWlsZWQnLFxuICAgICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICAgICAgIHR5cGVvZiBmYWlsZWREYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgICAgPyBmYWlsZWREYXRhLmVycm9yXG4gICAgICAgICAgICAgICAgICA6IChmYWlsZWREYXRhLmVycm9yPy5tZXNzYWdlID8/ICdVbmtub3duIGVycm9yJyksXG4gICAgICAgICAgICAgIHN0YWNrOiBmYWlsZWREYXRhLmVycm9yPy5zdGFjayxcbiAgICAgICAgICAgICAgY29kZTogZmFpbGVkRGF0YS5lcnJvckNvZGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICAgIH07XG4gICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAncnVucycsIGVmZmVjdGl2ZVJ1bklkLCB0YWcpLFxuICAgICAgICAgICAgcnVuLFxuICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgZGVsZXRlQWxsSG9va3NGb3JSdW4oYmFzZWRpciwgZWZmZWN0aXZlUnVuSWQpLFxuICAgICAgICAgICAgZGVsZXRlQWxsV2FpdHNGb3JSdW4oYmFzZWRpciwgZWZmZWN0aXZlUnVuSWQpLFxuICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX2NhbmNlbGxlZCcpIHtcbiAgICAgICAgLy8gUmV1c2UgY3VycmVudFJ1biBmcm9tIHZhbGlkYXRpb24gKGFscmVhZHkgcmVhZCBhYm92ZSlcbiAgICAgICAgaWYgKGN1cnJlbnRSdW4pIHtcbiAgICAgICAgICBydW4gPSB7XG4gICAgICAgICAgICBydW5JZDogY3VycmVudFJ1bi5ydW5JZCxcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZDogY3VycmVudFJ1bi5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICB3b3JrZmxvd05hbWU6IGN1cnJlbnRSdW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IGN1cnJlbnRSdW4uc3BlY1ZlcnNpb24sXG4gICAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBjdXJyZW50UnVuLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICBpbnB1dDogY3VycmVudFJ1bi5pbnB1dCxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogY3VycmVudFJ1bi5jcmVhdGVkQXQsXG4gICAgICAgICAgICBleHBpcmVkQXQ6IGN1cnJlbnRSdW4uZXhwaXJlZEF0LFxuICAgICAgICAgICAgc3RhcnRlZEF0OiBjdXJyZW50UnVuLnN0YXJ0ZWRBdCxcbiAgICAgICAgICAgIHN0YXR1czogJ2NhbmNlbGxlZCcsXG4gICAgICAgICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjb21wbGV0ZWRBdDogbm93LFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICBydW4sXG4gICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICBkZWxldGVBbGxIb29rc0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgICBkZWxldGVBbGxXYWl0c0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIC8vIFN0ZXAgbGlmZWN5Y2xlIGV2ZW50c1xuICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3N0ZXBfY3JlYXRlZCcgJiZcbiAgICAgICAgJ2V2ZW50RGF0YScgaW4gZGF0YVxuICAgICAgKSB7XG4gICAgICAgIC8vIHN0ZXBfY3JlYXRlZDogQ3JlYXRlcyBzdGVwIGVudGl0eSB3aXRoIHN0YXR1cyAncGVuZGluZycsIGF0dGVtcHQ9MCwgY3JlYXRlZEF0IHNldFxuICAgICAgICBjb25zdCBzdGVwRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICBzdGVwTmFtZTogc3RyaW5nO1xuICAgICAgICAgIGlucHV0OiBhbnk7XG4gICAgICAgIH07XG4gICAgICAgIHN0ZXAgPSB7XG4gICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgIHN0ZXBJZDogZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIHN0ZXBOYW1lOiBzdGVwRGF0YS5zdGVwTmFtZSxcbiAgICAgICAgICBzdGF0dXM6ICdwZW5kaW5nJyxcbiAgICAgICAgICBpbnB1dDogc3RlcERhdGEuaW5wdXQsXG4gICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgZXJyb3I6IHVuZGVmaW5lZCxcbiAgICAgICAgICBhdHRlbXB0OiAwLFxuICAgICAgICAgIHN0YXJ0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgIGNvbXBsZXRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgLy8gUHJvcGFnYXRlIHNwZWNWZXJzaW9uIGZyb20gdGhlIGV2ZW50IHRvIHRoZSBzdGVwIGVudGl0eVxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgc3RlcENvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2RhdGEuY29ycmVsYXRpb25JZH1gO1xuICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnc3RlcHMnLCBzdGVwQ29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgIHN0ZXBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdzdGVwX3N0YXJ0ZWQnKSB7XG4gICAgICAgIC8vIHN0ZXBfc3RhcnRlZDogSW5jcmVtZW50cyBhdHRlbXB0LCBzZXRzIHN0YXR1cyB0byAncnVubmluZydcbiAgICAgICAgLy8gU2V0cyBzdGFydGVkQXQgb25seSBvbiB0aGUgZmlyc3Qgc3RhcnQgKG5vdCB1cGRhdGVkIG9uIHJldHJpZXMpXG4gICAgICAgIC8vIFJldXNlIHZhbGlkYXRlZFN0ZXAgZnJvbSB2YWxpZGF0aW9uIChhbHJlYWR5IHJlYWQgYWJvdmUpXG4gICAgICAgIGlmICh2YWxpZGF0ZWRTdGVwKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgcmV0cnlBZnRlciB0aW1lc3RhbXAgaGFzbid0IGJlZW4gcmVhY2hlZCB5ZXRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB2YWxpZGF0ZWRTdGVwLnJldHJ5QWZ0ZXIgJiZcbiAgICAgICAgICAgIHZhbGlkYXRlZFN0ZXAucmV0cnlBZnRlci5nZXRUaW1lKCkgPiBEYXRlLm5vdygpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVG9vRWFybHlFcnJvcihcbiAgICAgICAgICAgICAgYENhbm5vdCBzdGFydCBzdGVwIFwiJHtkYXRhLmNvcnJlbGF0aW9uSWR9XCI6IHJldHJ5QWZ0ZXIgdGltZXN0YW1wIGhhcyBub3QgYmVlbiByZWFjaGVkIHlldGAsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICByZXRyeUFmdGVyOiBNYXRoLmNlaWwoXG4gICAgICAgICAgICAgICAgICAodmFsaWRhdGVkU3RlcC5yZXRyeUFmdGVyLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQmVzdC1lZmZvcnQgZ3VhcmQ6IHJlLXJlYWQgdGhlIHN0ZXAgZW50aXR5IHRvIGNoZWNrIGlmIGl0XG4gICAgICAgICAgLy8gcmVhY2hlZCB0ZXJtaW5hbCBzdGF0ZSBiZXR3ZWVuIHRoZSB2YWxpZGF0aW9uIHJlYWQgYW5kIG5vdy5cbiAgICAgICAgICAvLyBUaGlzIG5hcnJvd3MgdGhlIFRPQ1RPVSB3aW5kb3cgYnV0IGRvZXMgbm90IGZ1bGx5IGVsaW1pbmF0ZSBpdFxuICAgICAgICAgIC8vICh0aGUgbG9jYWwgd29ybGQgaXMgc2luZ2xlLXByb2Nlc3MgLyBkZXYtb25seTsgdGhlIHBvc3RncmVzXG4gICAgICAgICAgLy8gd29ybGQgdXNlcyBTUUwtbGV2ZWwgYXRvbWljIGd1YXJkcyBmb3IgcHJvZHVjdGlvbikuXG4gICAgICAgICAgY29uc3Qgc3RlcENvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2RhdGEuY29ycmVsYXRpb25JZH1gO1xuICAgICAgICAgIGNvbnN0IGZyZXNoU3RlcCA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdzdGVwcycsXG4gICAgICAgICAgICBzdGVwQ29tcG9zaXRlS2V5LFxuICAgICAgICAgICAgU3RlcFNjaGVtYSxcbiAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGZyZXNoU3RlcCAmJiBpc1N0ZXBUZXJtaW5hbChmcmVzaFN0ZXAuc3RhdHVzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgIGBDYW5ub3QgbW9kaWZ5IHN0ZXAgaW4gdGVybWluYWwgc3RhdGUgXCIke2ZyZXNoU3RlcC5zdGF0dXN9XCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN0ZXAgPSB7XG4gICAgICAgICAgICAuLi52YWxpZGF0ZWRTdGVwLFxuICAgICAgICAgICAgc3RhdHVzOiAncnVubmluZycsXG4gICAgICAgICAgICAvLyBPbmx5IHNldCBzdGFydGVkQXQgb24gdGhlIGZpcnN0IHN0YXJ0XG4gICAgICAgICAgICBzdGFydGVkQXQ6IHZhbGlkYXRlZFN0ZXAuc3RhcnRlZEF0ID8/IG5vdyxcbiAgICAgICAgICAgIC8vIEluY3JlbWVudCBhdHRlbXB0IGNvdW50ZXIgb24gZXZlcnkgc3RhcnRcbiAgICAgICAgICAgIGF0dGVtcHQ6IHZhbGlkYXRlZFN0ZXAuYXR0ZW1wdCArIDEsXG4gICAgICAgICAgICAvLyBDbGVhciByZXRyeUFmdGVyIG5vdyB0aGF0IHRoZSBzdGVwIGhhcyBzdGFydGVkXG4gICAgICAgICAgICByZXRyeUFmdGVyOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGF3YWl0IHdyaXRlSlNPTihcbiAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ3N0ZXBzJywgc3RlcENvbXBvc2l0ZUtleSwgdGFnKSxcbiAgICAgICAgICAgIHN0ZXAsXG4gICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3N0ZXBfY29tcGxldGVkJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgIC8vIHN0ZXBfY29tcGxldGVkOiBUZXJtaW5hbCBzdGF0ZSB3aXRoIG91dHB1dFxuICAgICAgICAvLyBVc2VzIHdyaXRlRXhjbHVzaXZlIG9uIGEgbG9jayBmaWxlIHRvIGF0b21pY2FsbHkgcHJldmVudCBjb25jdXJyZW50XG4gICAgICAgIC8vIGludm9jYXRpb25zIGZyb20gYm90aCBjb21wbGV0aW5nIHRoZSBzYW1lIHN0ZXAgKFRPQ1RPVSByYWNlKS5cbiAgICAgICAgY29uc3QgY29tcGxldGVkRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHsgcmVzdWx0OiBhbnkgfTtcbiAgICAgICAgaWYgKHZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgY29uc3QgbG9ja05hbWUgPSB0YWdcbiAgICAgICAgICAgID8gYCR7c3RlcENvbXBvc2l0ZUtleX0udGVybWluYWwuJHt0YWd9YFxuICAgICAgICAgICAgOiBgJHtzdGVwQ29tcG9zaXRlS2V5fS50ZXJtaW5hbGA7XG4gICAgICAgICAgY29uc3QgdGVybWluYWxMb2NrUGF0aCA9IHJlc29sdmVXaXRoaW5CYXNlKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICcubG9ja3MnLFxuICAgICAgICAgICAgJ3N0ZXBzJyxcbiAgICAgICAgICAgIGxvY2tOYW1lXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjbGFpbWVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUodGVybWluYWxMb2NrUGF0aCwgJycpO1xuICAgICAgICAgIGlmICghY2xhaW1lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgICdDYW5ub3QgbW9kaWZ5IHN0ZXAgaW4gdGVybWluYWwgc3RhdGUnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzdGVwID0ge1xuICAgICAgICAgICAgLi4udmFsaWRhdGVkU3RlcCxcbiAgICAgICAgICAgIHN0YXR1czogJ2NvbXBsZXRlZCcsXG4gICAgICAgICAgICBvdXRwdXQ6IGNvbXBsZXRlZERhdGEucmVzdWx0LFxuICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICAgIH07XG4gICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnc3RlcHMnLCBzdGVwQ29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgc3RlcCxcbiAgICAgICAgICAgIHsgb3ZlcndyaXRlOiB0cnVlIH1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAnc3RlcF9mYWlsZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgLy8gc3RlcF9mYWlsZWQ6IFRlcm1pbmFsIHN0YXRlIHdpdGggZXJyb3JcbiAgICAgICAgLy8gVXNlcyB3cml0ZUV4Y2x1c2l2ZSBvbiBhIGxvY2sgZmlsZSB0byBhdG9taWNhbGx5IHByZXZlbnQgY29uY3VycmVudFxuICAgICAgICAvLyBpbnZvY2F0aW9ucyBmcm9tIGJvdGggZmFpbGluZyB0aGUgc2FtZSBzdGVwIChUT0NUT1UgcmFjZSkuXG4gICAgICAgIGNvbnN0IGZhaWxlZERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgZXJyb3I6IGFueTtcbiAgICAgICAgICBzdGFjaz86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgY29uc3QgbG9ja05hbWUgPSB0YWdcbiAgICAgICAgICAgID8gYCR7c3RlcENvbXBvc2l0ZUtleX0udGVybWluYWwuJHt0YWd9YFxuICAgICAgICAgICAgOiBgJHtzdGVwQ29tcG9zaXRlS2V5fS50ZXJtaW5hbGA7XG4gICAgICAgICAgY29uc3QgdGVybWluYWxMb2NrUGF0aCA9IHJlc29sdmVXaXRoaW5CYXNlKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICcubG9ja3MnLFxuICAgICAgICAgICAgJ3N0ZXBzJyxcbiAgICAgICAgICAgIGxvY2tOYW1lXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjbGFpbWVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUodGVybWluYWxMb2NrUGF0aCwgJycpO1xuICAgICAgICAgIGlmICghY2xhaW1lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgICdDYW5ub3QgbW9kaWZ5IHN0ZXAgaW4gdGVybWluYWwgc3RhdGUnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBlcnJvciA9IHtcbiAgICAgICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgICAgIHR5cGVvZiBmYWlsZWREYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgID8gZmFpbGVkRGF0YS5lcnJvclxuICAgICAgICAgICAgICAgIDogKGZhaWxlZERhdGEuZXJyb3I/Lm1lc3NhZ2UgPz8gJ1Vua25vd24gZXJyb3InKSxcbiAgICAgICAgICAgIHN0YWNrOiBmYWlsZWREYXRhLnN0YWNrLFxuICAgICAgICAgIH07XG4gICAgICAgICAgc3RlcCA9IHtcbiAgICAgICAgICAgIC4uLnZhbGlkYXRlZFN0ZXAsXG4gICAgICAgICAgICBzdGF0dXM6ICdmYWlsZWQnLFxuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICBjb21wbGV0ZWRBdDogbm93LFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICBzdGVwLFxuICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdzdGVwX3JldHJ5aW5nJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgIC8vIHN0ZXBfcmV0cnlpbmc6IFNldHMgc3RhdHVzIGJhY2sgdG8gJ3BlbmRpbmcnLCByZWNvcmRzIGVycm9yXG4gICAgICAgIC8vIFJldXNlIHZhbGlkYXRlZFN0ZXAgZnJvbSB2YWxpZGF0aW9uIChhbHJlYWR5IHJlYWQgYWJvdmUpXG4gICAgICAgIGNvbnN0IHJldHJ5RGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICBlcnJvcjogYW55O1xuICAgICAgICAgIHN0YWNrPzogc3RyaW5nO1xuICAgICAgICAgIHJldHJ5QWZ0ZXI/OiBEYXRlO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodmFsaWRhdGVkU3RlcCkge1xuICAgICAgICAgIGNvbnN0IHN0ZXBDb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9YDtcbiAgICAgICAgICBzdGVwID0ge1xuICAgICAgICAgICAgLi4udmFsaWRhdGVkU3RlcCxcbiAgICAgICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICAgICAgZXJyb3I6IHtcbiAgICAgICAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAgICAgICB0eXBlb2YgcmV0cnlEYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgICAgPyByZXRyeURhdGEuZXJyb3JcbiAgICAgICAgICAgICAgICAgIDogKHJldHJ5RGF0YS5lcnJvcj8ubWVzc2FnZSA/PyAnVW5rbm93biBlcnJvcicpLFxuICAgICAgICAgICAgICBzdGFjazogcmV0cnlEYXRhLnN0YWNrLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJldHJ5QWZ0ZXI6IHJldHJ5RGF0YS5yZXRyeUFmdGVyLFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICBzdGVwLFxuICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIC8vIEhvb2sgbGlmZWN5Y2xlIGV2ZW50c1xuICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfY3JlYXRlZCcgJiZcbiAgICAgICAgJ2V2ZW50RGF0YScgaW4gZGF0YVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGhvb2tEYXRhID0gZGF0YS5ldmVudERhdGEgYXMge1xuICAgICAgICAgIHRva2VuOiBzdHJpbmc7XG4gICAgICAgICAgbWV0YWRhdGE/OiBhbnk7XG4gICAgICAgICAgaXNXZWJob29rPzogYm9vbGVhbjtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBBdG9taWNhbGx5IGNsYWltIHRoZSB0b2tlbiB1c2luZyBhbiBleGNsdXNpdmUtY3JlYXRlIGNvbnN0cmFpbnQgZmlsZS5cbiAgICAgICAgLy8gVGhpcyBhdm9pZHMgdGhlIFRPQ1RPVSByYWNlIG9mIHRoZSBwcmV2aW91cyByZWFkLWFsbC10aGVuLWNoZWNrIGFwcHJvYWNoLlxuICAgICAgICBjb25zdCBjb25zdHJhaW50UGF0aCA9IHBhdGguam9pbihcbiAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgJ3Rva2VucycsXG4gICAgICAgICAgYCR7aGFzaFRva2VuKGhvb2tEYXRhLnRva2VuKX0uanNvbmBcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9rZW5DbGFpbWVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUoXG4gICAgICAgICAgY29uc3RyYWludFBhdGgsXG4gICAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgdG9rZW46IGhvb2tEYXRhLnRva2VuLFxuICAgICAgICAgICAgaG9va0lkOiBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIXRva2VuQ2xhaW1lZCkge1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nQ2xhaW0gPSBhd2FpdCByZWFkSG9va1Rva2VuQ2xhaW0oY29uc3RyYWludFBhdGgpO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWRcbiAgICAgICAgICAvLyBUaGlzIGFsbG93cyB0aGUgd29ya2Zsb3cgdG8gY29udGludWUgYW5kIGZhaWwgZ3JhY2VmdWxseSB3aGVuIHRoZSBob29rIGlzIGF3YWl0ZWRcbiAgICAgICAgICBjb25zdCBjb25mbGljdEV2ZW50OiBFdmVudCA9IHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY29uZmxpY3QnLFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHRva2VuOiBob29rRGF0YS50b2tlbixcbiAgICAgICAgICAgICAgLi4uKGV4aXN0aW5nQ2xhaW1cbiAgICAgICAgICAgICAgICA/IHsgY29uZmxpY3RpbmdSdW5JZDogZXhpc3RpbmdDbGFpbS5ydW5JZCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICAvLyBTdG9yZSB0aGUgY29uZmxpY3QgZXZlbnRcbiAgICAgICAgICBjb25zdCBjb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtldmVudElkfWA7XG4gICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnZXZlbnRzJywgY29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgY29uZmxpY3RFdmVudFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCByZXNvbHZlRGF0YSA9XG4gICAgICAgICAgICBwYXJhbXM/LnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcbiAgICAgICAgICBjb25zdCBmaWx0ZXJlZEV2ZW50ID0gc3RyaXBFdmVudERhdGFSZWZzKGNvbmZsaWN0RXZlbnQsIHJlc29sdmVEYXRhKTtcblxuICAgICAgICAgIC8vIFJldHVybiBFdmVudFJlc3VsdCB3aXRoIGNvbmZsaWN0IGV2ZW50IChubyBob29rIGVudGl0eSBjcmVhdGVkKVxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBldmVudDogZmlsdGVyZWRFdmVudCxcbiAgICAgICAgICAgIHJ1bixcbiAgICAgICAgICAgIHN0ZXAsXG4gICAgICAgICAgICBob29rOiB1bmRlZmluZWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGhvb2sgPSB7XG4gICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgIGhvb2tJZDogZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIHRva2VuOiBob29rRGF0YS50b2tlbixcbiAgICAgICAgICBtZXRhZGF0YTogaG9va0RhdGEubWV0YWRhdGEsXG4gICAgICAgICAgb3duZXJJZDogJ2xvY2FsLW93bmVyJyxcbiAgICAgICAgICBwcm9qZWN0SWQ6ICdsb2NhbC1wcm9qZWN0JyxcbiAgICAgICAgICBlbnZpcm9ubWVudDogJ2xvY2FsJyxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAvLyBQcm9wYWdhdGUgc3BlY1ZlcnNpb24gZnJvbSB0aGUgZXZlbnQgdG8gdGhlIGhvb2sgZW50aXR5XG4gICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgIGlzV2ViaG9vazogaG9va0RhdGEuaXNXZWJob29rID8/IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnaG9va3MnLCBkYXRhLmNvcnJlbGF0aW9uSWQsIHRhZyksXG4gICAgICAgICAgaG9va1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfZGlzcG9zZWQnKSB7XG4gICAgICAgIC8vIGhvb2tfZGlzcG9zZWQ6IERlbGV0ZXMgaG9vayBlbnRpdHksIHJlamVjdHMgZHVwbGljYXRlcy5cbiAgICAgICAgLy8gVXNlcyB3cml0ZUV4Y2x1c2l2ZSBvbiBhIGxvY2sgZmlsZSB0byBhdG9taWNhbGx5IHByZXZlbnQgY29uY3VycmVudFxuICAgICAgICAvLyBpbnZvY2F0aW9ucyBmcm9tIGJvdGggZGlzcG9zaW5nIHRoZSBzYW1lIGhvb2sgKFRPQ1RPVSByYWNlKS5cbiAgICAgICAgY29uc3QgaG9va0xvY2tOYW1lID0gdGFnXG4gICAgICAgICAgPyBgJHtkYXRhLmNvcnJlbGF0aW9uSWR9LmRpc3Bvc2VkLiR7dGFnfWBcbiAgICAgICAgICA6IGAke2RhdGEuY29ycmVsYXRpb25JZH0uZGlzcG9zZWRgO1xuICAgICAgICBjb25zdCBsb2NrUGF0aCA9IHJlc29sdmVXaXRoaW5CYXNlKFxuICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgJy5sb2NrcycsXG4gICAgICAgICAgJ2hvb2tzJyxcbiAgICAgICAgICBob29rTG9ja05hbWVcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY2xhaW1lZCA9IGF3YWl0IHdyaXRlRXhjbHVzaXZlKGxvY2tQYXRoLCAnJyk7XG4gICAgICAgIGlmICghY2xhaW1lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgYEhvb2sgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBhbHJlYWR5IGRpc3Bvc2VkYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVhZCB0aGUgaG9vayB0byBnZXQgaXRzIHRva2VuIGJlZm9yZSBkZWxldGluZ1xuICAgICAgICBjb25zdCBob29rUGF0aCA9IHRhZ2dlZFBhdGgoYmFzZWRpciwgJ2hvb2tzJywgZGF0YS5jb3JyZWxhdGlvbklkLCB0YWcpO1xuICAgICAgICBjb25zdCBleGlzdGluZ0hvb2sgPSBhd2FpdCByZWFkSlNPTldpdGhGYWxsYmFjayhcbiAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIEhvb2tTY2hlbWEsXG4gICAgICAgICAgdGFnXG4gICAgICAgICk7XG4gICAgICAgIGlmIChleGlzdGluZ0hvb2spIHtcbiAgICAgICAgICAvLyBEZWxldGUgdGhlIHRva2VuIGNvbnN0cmFpbnQgZmlsZSB0byBmcmVlIHVwIHRoZSB0b2tlbiBmb3IgcmV1c2VcbiAgICAgICAgICBjb25zdCBkaXNwb3NlZENvbnN0cmFpbnRQYXRoID0gcGF0aC5qb2luKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgICAndG9rZW5zJyxcbiAgICAgICAgICAgIGAke2hhc2hUb2tlbihleGlzdGluZ0hvb2sudG9rZW4pfS5qc29uYFxuICAgICAgICAgICk7XG4gICAgICAgICAgYXdhaXQgZGVsZXRlSlNPTihkaXNwb3NlZENvbnN0cmFpbnRQYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBkZWxldGVKU09OKGhvb2tQYXRoKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICd3YWl0X2NyZWF0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgLy8gd2FpdF9jcmVhdGVkOiBDcmVhdGVzIHdhaXQgZW50aXR5IHdpdGggc3RhdHVzICd3YWl0aW5nJ1xuICAgICAgICBjb25zdCB3YWl0RGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICByZXN1bWVBdD86IERhdGU7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHdhaXRDb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9YDtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdXYWl0ID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAnd2FpdHMnLFxuICAgICAgICAgIHdhaXRDb21wb3NpdGVLZXksXG4gICAgICAgICAgV2FpdFNjaGVtYSxcbiAgICAgICAgICB0YWdcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nV2FpdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgYFdhaXQgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBhbHJlYWR5IGV4aXN0c2BcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHdhaXQgPSB7XG4gICAgICAgICAgd2FpdElkOiB3YWl0Q29tcG9zaXRlS2V5LFxuICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICBzdGF0dXM6ICd3YWl0aW5nJyxcbiAgICAgICAgICByZXN1bWVBdDogd2FpdERhdGEucmVzdW1lQXQsXG4gICAgICAgICAgY29tcGxldGVkQXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogZWZmZWN0aXZlU3BlY1ZlcnNpb24sXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHdyaXRlSlNPTihcbiAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICd3YWl0cycsIHdhaXRDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgd2FpdFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY29tcGxldGVkJykge1xuICAgICAgICAvLyB3YWl0X2NvbXBsZXRlZDogVHJhbnNpdGlvbnMgd2FpdCB0byAnY29tcGxldGVkJywgcmVqZWN0cyBkdXBsaWNhdGVzLlxuICAgICAgICAvLyBVc2VzIHdyaXRlRXhjbHVzaXZlIG9uIGEgbG9jayBmaWxlIHRvIGF0b21pY2FsbHkgcHJldmVudCBjb25jdXJyZW50XG4gICAgICAgIC8vIGludm9jYXRpb25zIGZyb20gYm90aCBjb21wbGV0aW5nIHRoZSBzYW1lIHdhaXQgKFRPQ1RPVSByYWNlKS5cbiAgICAgICAgY29uc3Qgd2FpdENvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2RhdGEuY29ycmVsYXRpb25JZH1gO1xuICAgICAgICBjb25zdCB3YWl0TG9ja05hbWUgPSB0YWdcbiAgICAgICAgICA/IGAke3dhaXRDb21wb3NpdGVLZXl9LmNvbXBsZXRlZC4ke3RhZ31gXG4gICAgICAgICAgOiBgJHt3YWl0Q29tcG9zaXRlS2V5fS5jb21wbGV0ZWRgO1xuICAgICAgICBjb25zdCBsb2NrUGF0aCA9IHJlc29sdmVXaXRoaW5CYXNlKFxuICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgJy5sb2NrcycsXG4gICAgICAgICAgJ3dhaXRzJyxcbiAgICAgICAgICB3YWl0TG9ja05hbWVcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY2xhaW1lZCA9IGF3YWl0IHdyaXRlRXhjbHVzaXZlKGxvY2tQYXRoLCAnJyk7XG4gICAgICAgIGlmICghY2xhaW1lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgYFdhaXQgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBhbHJlYWR5IGNvbXBsZXRlZGBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nV2FpdCA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgJ3dhaXRzJyxcbiAgICAgICAgICB3YWl0Q29tcG9zaXRlS2V5LFxuICAgICAgICAgIFdhaXRTY2hlbWEsXG4gICAgICAgICAgdGFnXG4gICAgICAgICk7XG4gICAgICAgIGlmICghZXhpc3RpbmdXYWl0KSB7XG4gICAgICAgICAgLy8gQ2xlYW4gdXAgdGhlIGxvY2sgZmlsZSB3ZSBqdXN0IGNsYWltZWQg4oCUIHRoZSB3YWl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgICBhd2FpdCBmcy51bmxpbmsobG9ja1BhdGgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKFxuICAgICAgICAgICAgYFdhaXQgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBub3QgZm91bmRgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgbG9jayBmaWxlICh3cml0ZUV4Y2x1c2l2ZSBhYm92ZSkgYWxyZWFkeSBwcmV2ZW50cyBjb25jdXJyZW50XG4gICAgICAgIC8vIGNvbXBsZXRpb25zIOKAlCBubyBhZGRpdGlvbmFsIHN0YXR1cyBjaGVjayBuZWVkZWQuXG4gICAgICAgIHdhaXQgPSB7XG4gICAgICAgICAgLi4uZXhpc3RpbmdXYWl0LFxuICAgICAgICAgIHN0YXR1czogJ2NvbXBsZXRlZCcsXG4gICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgfTtcbiAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ3dhaXRzJywgd2FpdENvbXBvc2l0ZUtleSwgdGFnKSxcbiAgICAgICAgICB3YWl0LFxuICAgICAgICAgIHsgb3ZlcndyaXRlOiB0cnVlIH1cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIC8vIE5vdGU6IGhvb2tfcmVjZWl2ZWQgZXZlbnRzIGFyZSBzdG9yZWQgaW4gdGhlIGV2ZW50IGxvZyBidXQgZG9uJ3RcbiAgICAgIC8vIG1vZGlmeSB0aGUgSG9vayBlbnRpdHkgKHdoaWNoIGRvZXNuJ3QgaGF2ZSBhIHBheWxvYWQgZmllbGQpXG5cbiAgICAgIC8vIFN0b3JlIGV2ZW50IHVzaW5nIGNvbXBvc2l0ZSBrZXkge3J1bklkfS17ZXZlbnRJZH1cbiAgICAgIGNvbnN0IGNvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2V2ZW50SWR9YDtcbiAgICAgIGF3YWl0IHdyaXRlSlNPTih0YWdnZWRQYXRoKGJhc2VkaXIsICdldmVudHMnLCBjb21wb3NpdGVLZXksIHRhZyksIGV2ZW50KTtcblxuICAgICAgY29uc3QgcmVzb2x2ZURhdGEgPSBwYXJhbXM/LnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcbiAgICAgIGNvbnN0IGZpbHRlcmVkRXZlbnQgPSBzdHJpcEV2ZW50RGF0YVJlZnMoZXZlbnQsIHJlc29sdmVEYXRhKTtcblxuICAgICAgLy8gRm9yIHJ1bl9zdGFydGVkOiBpbmNsdWRlIGFsbCBldmVudHMgc28gdGhlIHJ1bnRpbWUgY2FuIHNraXBcbiAgICAgIC8vIHRoZSBpbml0aWFsIGV2ZW50cy5saXN0IGNhbGwgYW5kIHJlZHVjZSBUVEZCLlxuICAgICAgbGV0IGV2ZW50czogRXZlbnRbXSB8IHVuZGVmaW5lZDtcbiAgICAgIGxldCBjdXJzb3I6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgaGFzTW9yZTogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgICAgIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9zdGFydGVkJyAmJiBydW4pIHtcbiAgICAgICAgY29uc3QgYWxsRXZlbnRzID0gYXdhaXQgcGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5KHtcbiAgICAgICAgICBkaXJlY3Rvcnk6IHBhdGguam9pbihiYXNlZGlyLCAnZXZlbnRzJyksXG4gICAgICAgICAgc2NoZW1hOiBFdmVudFNjaGVtYSxcbiAgICAgICAgICBmaWxlUHJlZml4OiBgJHtlZmZlY3RpdmVSdW5JZH0tYCxcbiAgICAgICAgICBzb3J0T3JkZXI6ICdhc2MnLFxuICAgICAgICAgIGxpbWl0OiAxMDAwLFxuICAgICAgICAgIGdldENyZWF0ZWRBdDogZ2V0T2JqZWN0Q3JlYXRlZEF0KCdldm50JyksXG4gICAgICAgICAgZ2V0SWQ6IChlKSA9PiBlLmV2ZW50SWQsXG4gICAgICAgIH0pO1xuICAgICAgICBldmVudHMgPSBhbGxFdmVudHMuZGF0YTtcbiAgICAgICAgY3Vyc29yID0gYWxsRXZlbnRzLmN1cnNvcjtcbiAgICAgICAgaGFzTW9yZSA9IGFsbEV2ZW50cy5oYXNNb3JlO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXR1cm4gRXZlbnRSZXN1bHQgd2l0aCBldmVudCBhbmQgYW55IGNyZWF0ZWQvdXBkYXRlZCBlbnRpdHlcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGV2ZW50OiBmaWx0ZXJlZEV2ZW50LFxuICAgICAgICBydW4sXG4gICAgICAgIHN0ZXAsXG4gICAgICAgIGhvb2ssXG4gICAgICAgIHdhaXQsXG4gICAgICAgIGV2ZW50cyxcbiAgICAgICAgY3Vyc29yLFxuICAgICAgICBoYXNNb3JlLFxuICAgICAgfTtcbiAgICB9LFxuXG4gICAgYXN5bmMgZ2V0KHJ1bklkLCBldmVudElkLCBwYXJhbXMpIHtcbiAgICAgIGFzc2VydFNhZmVFbnRpdHlJZCgncnVuSWQnLCBydW5JZCk7XG4gICAgICBhc3NlcnRTYWZlRW50aXR5SWQoJ2V2ZW50SWQnLCBldmVudElkKTtcbiAgICAgIGNvbnN0IGNvbXBvc2l0ZUtleSA9IGAke3J1bklkfS0ke2V2ZW50SWR9YDtcbiAgICAgIGNvbnN0IGV2ZW50ID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgIGJhc2VkaXIsXG4gICAgICAgICdldmVudHMnLFxuICAgICAgICBjb21wb3NpdGVLZXksXG4gICAgICAgIEV2ZW50U2NoZW1hLFxuICAgICAgICB0YWdcbiAgICAgICk7XG4gICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXZlbnQgJHtldmVudElkfSBpbiBydW4gJHtydW5JZH0gbm90IGZvdW5kYCk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXNvbHZlRGF0YSA9IHBhcmFtcz8ucmVzb2x2ZURhdGEgPz8gREVGQVVMVF9SRVNPTFZFX0RBVEFfT1BUSU9OO1xuICAgICAgcmV0dXJuIHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpO1xuICAgIH0sXG5cbiAgICBhc3luYyBsaXN0KHBhcmFtcykge1xuICAgICAgY29uc3QgeyBydW5JZCB9ID0gcGFyYW1zO1xuICAgICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdydW5JZCcsIHJ1bklkKTtcbiAgICAgIGNvbnN0IHJlc29sdmVEYXRhID0gcGFyYW1zLnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBhZ2luYXRlZEZpbGVTeXN0ZW1RdWVyeSh7XG4gICAgICAgIGRpcmVjdG9yeTogcGF0aC5qb2luKGJhc2VkaXIsICdldmVudHMnKSxcbiAgICAgICAgc2NoZW1hOiBFdmVudFNjaGVtYSxcbiAgICAgICAgZmlsZVByZWZpeDogYCR7cnVuSWR9LWAsXG4gICAgICAgIC8vIEV2ZW50cyBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyIChvbGRlc3QgZmlyc3QpIGJ5IGRlZmF1bHQsXG4gICAgICAgIC8vIGRpZmZlcmVudCBmcm9tIHRoZSBkZWZhdWx0IGZvciBvdGhlciBsaXN0IGNhbGxzLlxuICAgICAgICBzb3J0T3JkZXI6IHBhcmFtcy5wYWdpbmF0aW9uPy5zb3J0T3JkZXIgPz8gJ2FzYycsXG4gICAgICAgIGxpbWl0OiBwYXJhbXMucGFnaW5hdGlvbj8ubGltaXQsXG4gICAgICAgIGN1cnNvcjogcGFyYW1zLnBhZ2luYXRpb24/LmN1cnNvcixcbiAgICAgICAgZ2V0Q3JlYXRlZEF0OiBnZXRPYmplY3RDcmVhdGVkQXQoJ2V2bnQnKSxcbiAgICAgICAgZ2V0SWQ6IChldmVudCkgPT4gZXZlbnQuZXZlbnRJZCxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBJZiByZXNvbHZlRGF0YSBpcyBcIm5vbmVcIiwgcmVtb3ZlIGV2ZW50RGF0YSBmcm9tIGV2ZW50c1xuICAgICAgaWYgKHJlc29sdmVEYXRhID09PSAnbm9uZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgZGF0YTogcmVzdWx0LmRhdGEubWFwKChldmVudCkgPT5cbiAgICAgICAgICAgIHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpXG4gICAgICAgICAgKSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgYXN5bmMgbGlzdEJ5Q29ycmVsYXRpb25JZChwYXJhbXMpIHtcbiAgICAgIGNvbnN0IGNvcnJlbGF0aW9uSWQgPSBwYXJhbXMuY29ycmVsYXRpb25JZDtcbiAgICAgIGFzc2VydFNhZmVFbnRpdHlJZCgnY29ycmVsYXRpb25JZCcsIGNvcnJlbGF0aW9uSWQpO1xuICAgICAgY29uc3QgcmVzb2x2ZURhdGEgPSBwYXJhbXMucmVzb2x2ZURhdGEgPz8gREVGQVVMVF9SRVNPTFZFX0RBVEFfT1BUSU9OO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5KHtcbiAgICAgICAgZGlyZWN0b3J5OiBwYXRoLmpvaW4oYmFzZWRpciwgJ2V2ZW50cycpLFxuICAgICAgICBzY2hlbWE6IEV2ZW50U2NoZW1hLFxuICAgICAgICAvLyBObyBmaWxlUHJlZml4IC0gc2VhcmNoIGFsbCBldmVudHNcbiAgICAgICAgZmlsdGVyOiAoZXZlbnQpID0+IGV2ZW50LmNvcnJlbGF0aW9uSWQgPT09IGNvcnJlbGF0aW9uSWQsXG4gICAgICAgIC8vIEV2ZW50cyBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyIChvbGRlc3QgZmlyc3QpIGJ5IGRlZmF1bHQsXG4gICAgICAgIC8vIGRpZmZlcmVudCBmcm9tIHRoZSBkZWZhdWx0IGZvciBvdGhlciBsaXN0IGNhbGxzLlxuICAgICAgICBzb3J0T3JkZXI6IHBhcmFtcy5wYWdpbmF0aW9uPy5zb3J0T3JkZXIgPz8gJ2FzYycsXG4gICAgICAgIGxpbWl0OiBwYXJhbXMucGFnaW5hdGlvbj8ubGltaXQsXG4gICAgICAgIGN1cnNvcjogcGFyYW1zLnBhZ2luYXRpb24/LmN1cnNvcixcbiAgICAgICAgZ2V0Q3JlYXRlZEF0OiBnZXRPYmplY3RDcmVhdGVkQXQoJ2V2bnQnKSxcbiAgICAgICAgZ2V0SWQ6IChldmVudCkgPT4gZXZlbnQuZXZlbnRJZCxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBJZiByZXNvbHZlRGF0YSBpcyBcIm5vbmVcIiwgcmVtb3ZlIGV2ZW50RGF0YSBmcm9tIGV2ZW50c1xuICAgICAgaWYgKHJlc29sdmVEYXRhID09PSAnbm9uZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgZGF0YTogcmVzdWx0LmRhdGEubWFwKChldmVudCkgPT5cbiAgICAgICAgICAgIHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpXG4gICAgICAgICAgKSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuICB9O1xufVxuIl19
|
|
1222
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLXN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmFnZS9ldmVudHMtc3RvcmFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsQyxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixFQUNwQixhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0sa0JBQWtCLENBQUM7QUFXMUIsT0FBTyxFQUNMLFdBQVcsRUFDWCxVQUFVLEVBQ1YsbUJBQW1CLEVBQ25CLG9CQUFvQixFQUNwQiwyQkFBMkIsRUFDM0Isa0JBQWtCLEVBQ2xCLG9CQUFvQixFQUNwQixVQUFVLEVBQ1YsVUFBVSxFQUNWLHFCQUFxQixFQUNyQixVQUFVLEVBQ1YsaUJBQWlCLEdBQ2xCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUN4QixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDM0QsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsWUFBWSxFQUNaLGFBQWEsRUFDYix3QkFBd0IsRUFDeEIsUUFBUSxFQUNSLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsVUFBVSxFQUNWLGNBQWMsRUFDZCxTQUFTLEdBQ1YsTUFBTSxVQUFVLENBQUM7QUFDbEIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsU0FBUyxFQUNULHNCQUFzQixFQUN0QixhQUFhLEdBQ2QsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixrQ0FBa0MsR0FDbkMsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVB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LGVBQWUsRUFBRSxhQUFhLENBQUMsQ0FBQztZQUNuRCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxJQUFJLDJCQUEyQixDQUFDO1lBQ3RFLE1BQU0sTUFBTSxHQUFHLE1BQU0sd0JBQXdCLENBQUM7Z0JBQzVDLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUM7Z0JBQ3ZDLE1BQU0sRUFBRSxXQUFXO2dCQUNuQixvQ0FBb0M7Z0JBQ3BDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsS0FBSyxhQUFhO2dCQUN4RCwyREFBMkQ7Z0JBQzNELG1EQUFtRDtnQkFDbkQsU0FBUyxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsU0FBUyxJQUFJLEtBQUs7Z0JBQ2hELEtBQUssRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLEtBQUs7Z0JBQy9CLE1BQU0sRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLE1BQU07Z0JBQ2pDLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hDLEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU87YUFDaEMsQ0FBQyxDQUFDO1lBRUgseURBQXlEO1lBQ3pELElBQUksV0FBVyxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUMzQixPQUFPO29CQUNMLEdBQUcsTUFBTTtvQkFDVCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUM5QixrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQ3ZDO2lCQUNGLENBQUM7WUFDSixDQUFDO1lBRUQsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7XG4gIEVudGl0eUNvbmZsaWN0RXJyb3IsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFJ1bk5vdFN1cHBvcnRlZEVycm9yLFxuICBUb29FYXJseUVycm9yLFxuICBXb3JrZmxvd1dvcmxkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHR5cGUge1xuICBFdmVudCxcbiAgRXZlbnRSZXN1bHQsXG4gIEhvb2ssXG4gIFNlcmlhbGl6ZWREYXRhLFxuICBTdGVwLFxuICBTdG9yYWdlLFxuICBXYWl0LFxuICBXb3JrZmxvd1J1bixcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7XG4gIEV2ZW50U2NoZW1hLFxuICBIb29rU2NoZW1hLFxuICBpc0xlZ2FjeVNwZWNWZXJzaW9uLFxuICBpc1Rlcm1pbmFsU3RlcFN0YXR1cyxcbiAgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzLFxuICByZXF1aXJlc05ld2VyV29ybGQsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTdGVwU2NoZW1hLFxuICB1bGlkVG9EYXRlLFxuICB2YWxpZGF0ZVVsaWRUaW1lc3RhbXAsXG4gIFdhaXRTY2hlbWEsXG4gIFdvcmtmbG93UnVuU2NoZW1hLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5pbXBvcnQgeyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT04gfSBmcm9tICcuLi9jb25maWcuanMnO1xuaW1wb3J0IHtcbiAgYXNzZXJ0U2FmZUVudGl0eUlkLFxuICBkZWxldGVKU09OLFxuICBqc29uUmVwbGFjZXIsXG4gIGxpc3RKU09ORmlsZXMsXG4gIHBhZ2luYXRlZEZpbGVTeXN0ZW1RdWVyeSxcbiAgcmVhZEpTT04sXG4gIHJlYWRKU09OV2l0aEZhbGxiYWNrLFxuICByZXNvbHZlV2l0aGluQmFzZSxcbiAgdGFnZ2VkUGF0aCxcbiAgd3JpdGVFeGNsdXNpdmUsXG4gIHdyaXRlSlNPTixcbn0gZnJvbSAnLi4vZnMuanMnO1xuaW1wb3J0IHsgc3RyaXBFdmVudERhdGFSZWZzIH0gZnJvbSAnLi9maWx0ZXJzLmpzJztcbmltcG9ydCB7XG4gIGdldE9iamVjdENyZWF0ZWRBdCxcbiAgaGFzaFRva2VuLFxuICBob29rUmVjb3ZlcnlNYXJrZXJQYXRoLFxuICBtb25vdG9uaWNVbGlkLFxufSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHtcbiAgZGVsZXRlQWxsSG9va3NGb3JSdW4sXG4gIHJlYnVpbGRMaXZlSG9va0J5VG9rZW5Gcm9tRXZlbnRMb2csXG59IGZyb20gJy4vaG9va3Mtc3RvcmFnZS5qcyc7XG5pbXBvcnQgeyBoYW5kbGVMZWdhY3lFdmVudCB9IGZyb20gJy4vbGVnYWN5LmpzJztcblxuY29uc3QgSG9va1Rva2VuQ2xhaW1TY2hlbWEgPSB6Lm9iamVjdCh7XG4gIC8vIFRoZSB0b2tlbi1jbGFpbSB3cml0ZXIgYmVsb3cgaGFzIGFsd2F5cyBwZXJzaXN0ZWQgYGhvb2tJZGAsIGJ1dFxuICAvLyB0aGlzIHJlYWQgc2NoZW1hIHByZXZpb3VzbHkgb21pdHRlZCBpdCwgd2hpY2ggaXMgdGhlIGJ1ZyBmaXhlZFxuICAvLyBieSBodHRwczovL2dpdGh1Yi5jb20vdmVyY2VsL3dvcmtmbG93L2lzc3Vlcy8yMjgzLiBgb3B0aW9uYWwoKWBcbiAgLy8gaXMgZGVmZW5zaXZlOiBhbnkgY2xhaW0gZmlsZSB0aGF0IHNvbWVob3cgbGFja3MgdGhlIGZpZWxkIHN0aWxsXG4gIC8vIHBhcnNlcyAoeWllbGRpbmcgYHVuZGVmaW5lZGApIGFuZCBmYWxscyB0aHJvdWdoIHRvIHRoZSBjcm9zcy1cbiAgLy8gaG9vayBjb25mbGljdCBicmFuY2gsIG1hdGNoaW5nIHByZS1maXggYmVoYXZpb3IuXG4gIGhvb2tJZDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBydW5JZDogei5zdHJpbmcoKSxcbiAgLy8gYGV2ZW50SWRgIGlzIHRoZSBjYW5vbmljYWwgaG9va19jcmVhdGVkIGV2ZW50IElEIHRoZSBjbGFpbWluZ1xuICAvLyB3b3JrZXIgY29tbWl0dGVkIHRvIHB1Ymxpc2hpbmcuIFBlcnNpc3RpbmcgaXQgaGVyZSB0dXJucyB0aGVcbiAgLy8gY2xhaW0gZmlsZSBpbnRvIGEgZHVyYWJsZSBjb252ZXJnZW5jZSBrZXkgZm9yIGNyb3NzLXdvcmtlciAvXG4gIC8vIGNyb3NzLXByb2Nlc3MgcmV0cmllcyAoc2VlIGNvbW1lbnQgb24gdGhlIGhvb2tfY3JlYXRlZCBicmFuY2gpLlxuICAvLyBgb3B0aW9uYWwoKWAgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHk6IGEgbGVnYWN5IGNsYWltIGZpbGVcbiAgLy8gd3JpdHRlbiBiZWZvcmUgdGhpcyBmaWVsZCBleGlzdGVkIGZhbGxzIHRocm91Z2ggdG8gdGhlIHJlY292ZXJ5LVxuICAvLyBtYXJrZXIgdXBncmFkZSBwYXRoLCB3aGljaCBhdG9taWNhbGx5IHBpbnMgYSBjYW5vbmljYWwgZXZlbnRJZFxuICAvLyB2aWEgYSBzaWRlY2FyIG1hcmtlciAoYWxzbyBhIGB3cml0ZUV4Y2x1c2l2ZWApLlxuICBldmVudElkOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG59KTtcblxuLyoqXG4gKiBTaWRlY2FyIHJlY292ZXJ5IG1hcmtlciB0aGF0IHBpbnMgYSBjYW5vbmljYWwgYGhvb2tfY3JlYXRlZGBcbiAqIGV2ZW50SWQgZm9yIGEgbGVnYWN5IHRva2VuIGNsYWltIOKAlCBvbmUgd3JpdHRlbiBieSBhIHZlcnNpb24gb2ZcbiAqIHRoaXMgc3RvcmFnZSB0aGF0IGRpZCBub3QgeWV0IHBlcnNpc3QgYGV2ZW50SWRgIGlubGluZSBpbiB0aGVcbiAqIGNsYWltIGZpbGUuIFdpdGhvdXQgdGhpcyBtYXJrZXIsIHR3byBjcm9zcy1wcm9jZXNzIHJldHJpZXNcbiAqIHJlYWRpbmcgYSBsZWdhY3kgY2xhaW0gZWFjaCBnZW5lcmF0ZSB0aGVpciBvd24gZXZlbnRJZCwgbGFuZFxuICogdGhlaXIgYHdyaXRlRXhjbHVzaXZlKGV2ZW50UGF0aClgIGNhbGxzIGF0IGRpZmZlcmVudCBwYXRocywgYW5kXG4gKiBhcHBlbmQgdHdvIGBob29rX2NyZWF0ZWRgIGV2ZW50cyBmb3IgdGhlIHNhbWUgYChydW5JZCwgaG9va0lkKWAuXG4gKlxuICogVGhlIG1hcmtlciBpcyB3cml0dGVuIHZpYSBgd3JpdGVFeGNsdXNpdmVgIOKAlCB0aGUgZmlyc3QgcmV0cnkgdG9cbiAqIGxhbmQgaXQgcGlucyBpdHMgY2FuZGlkYXRlIGV2ZW50SWQgYXMgY2Fub25pY2FsLCBhbmQgZXZlcnlcbiAqIHN1YnNlcXVlbnQgcmV0cnkgcmVhZHMgYW5kIGFkb3B0cyB0aGF0IGV2ZW50SWQgYmVmb3JlIHRoZSBjb21tb25cbiAqIGV2ZW50IHB1Ymxpc2guIFNjaGVtYSBpcyBqdXN0IGB7IGV2ZW50SWQgfWAgYmVjYXVzZSBpZGVudGl0eSBpc1xuICogYWxyZWFkeSBlbmNvZGVkIGluIHRoZSBtYXJrZXIncyBmaWxlbmFtZSBoYXNoLCBzbyBkaWZmZXJlbnQgdG9rZW5cbiAqIGxpZmV0aW1lcyBjYW4gbmV2ZXIgc2hhcmUgb25lIG1hcmtlciAoc2VlXG4gKiBgaG9va1JlY292ZXJ5TWFya2VyUGF0aGApLlxuICovXG5jb25zdCBIb29rUmVjb3ZlcnlNYXJrZXJTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGV2ZW50SWQ6IHouc3RyaW5nKCksXG59KTtcblxuYXN5bmMgZnVuY3Rpb24gcmVhZEhvb2tUb2tlbkNsYWltKFxuICBjb25zdHJhaW50UGF0aDogc3RyaW5nXG4pOiBQcm9taXNlPHouaW5mZXI8dHlwZW9mIEhvb2tUb2tlbkNsYWltU2NoZW1hPiB8IG51bGw+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcmVhZEpTT04oY29uc3RyYWludFBhdGgsIEhvb2tUb2tlbkNsYWltU2NoZW1hKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTeW50YXhFcnJvciB8fCBlcnJvciBpbnN0YW5jZW9mIHouWm9kRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkSG9va1JlY292ZXJ5TWFya2VyKFxuICBtYXJrZXJQYXRoOiBzdHJpbmdcbik6IFByb21pc2U8ei5pbmZlcjx0eXBlb2YgSG9va1JlY292ZXJ5TWFya2VyU2NoZW1hPiB8IG51bGw+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcmVhZEpTT04obWFya2VyUGF0aCwgSG9va1JlY292ZXJ5TWFya2VyU2NoZW1hKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTeW50YXhFcnJvciB8fCBlcnJvciBpbnN0YW5jZW9mIHouWm9kRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIFByb2JlIHRoZSBydW4ncyBldmVudCBsb2cgZm9yIGFuIGV4aXN0aW5nIGBob29rX2NyZWF0ZWRgIGV2ZW50XG4gKiB3aXRoIHRoZSBnaXZlbiBjb3JyZWxhdGlvbklkLiBVc2VkIGJ5IHRoZSBsZWdhY3ktY2xhaW0gcmVjb3ZlcnlcbiAqIHBhdGggdG8gZGV0ZWN0IFwiYWxyZWFkeSBwdWJsaXNoZWQgYnkgYSBwcmUtdXBncmFkZSB3cml0ZVwiIGJlZm9yZVxuICogcGlubmluZyBhIGNhbm9uaWNhbCBldmVudElkIOKAlCB3aXRob3V0IHRoaXMgY2hlY2ssIGEgcG9zdC11cGdyYWRlXG4gKiByZXRyeSBlbmNvdW50ZXJpbmcgYSBsZWdhY3kgY2xhaW0gd2hvc2UgYGhvb2tfY3JlYXRlZGAgd2FzXG4gKiBhbHJlYWR5IHdyaXR0ZW4gKHdpdGggdGhlIHByZS11cGdyYWRlIHdyaXRlcidzIG93biBldmVudElkKSB3b3VsZFxuICogcGluIGEgKmRpZmZlcmVudCogZXZlbnRJZCB2aWEgdGhlIG1hcmtlciBhbmQgcHVibGlzaCBhIGR1cGxpY2F0ZVxuICogZXZlbnQgYXQgdGhlIG1hcmtlcidzIHBhdGguXG4gKlxuICogVGhlIGlubGluZS1gZXZlbnRJZGAgZmFzdCBwYXRoIGRvZXMgTk9UIG5lZWQgdGhpcyBwcm9iZTogdGhlXG4gKiBjYW5vbmljYWwgZXZlbnRJZCBpcyBkdXJhYmxlIGluIHRoZSBjbGFpbSBmaWxlLCBzbyB0aGUgZXhpc3RpbmdcbiAqIHB1Ymxpc2ggKGB3cml0ZUV4Y2x1c2l2ZShldmVudFBhdGgpYCkgd2lsbCBmYWlsIGlmZiB0aGUgZXZlbnRcbiAqIGFscmVhZHkgZXhpc3RzIGF0IHRoYXQgZXhhY3QgcGF0aCDigJQgd2hpY2ggaXMgdGhlIGNvcnJlY3RcbiAqIFwiYWxyZWFkeS1wdWJsaXNoZWRcIiBzZW1hbnRpYy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZmluZEV4aXN0aW5nSG9va0NyZWF0ZWRFdmVudElkKFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGNvcnJlbGF0aW9uSWQ6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBhZ2luYXRlZEZpbGVTeXN0ZW1RdWVyeSh7XG4gICAgZGlyZWN0b3J5OiBwYXRoLmpvaW4oYmFzZWRpciwgJ2V2ZW50cycpLFxuICAgIHNjaGVtYTogRXZlbnRTY2hlbWEsXG4gICAgZmlsZVByZWZpeDogYCR7cnVuSWR9LWAsXG4gICAgZmlsdGVyOiAoZXZlbnQpID0+XG4gICAgICBldmVudC5ldmVudFR5cGUgPT09ICdob29rX2NyZWF0ZWQnICYmXG4gICAgICBldmVudC5jb3JyZWxhdGlvbklkID09PSBjb3JyZWxhdGlvbklkLFxuICAgIGxpbWl0OiAxLFxuICAgIGdldENyZWF0ZWRBdDogZ2V0T2JqZWN0Q3JlYXRlZEF0KCdldm50JyksXG4gICAgZ2V0SWQ6IChldmVudCkgPT4gZXZlbnQuZXZlbnRJZCxcbiAgfSk7XG4gIHJldHVybiByZXN1bHQuZGF0YVswXT8uZXZlbnRJZCA/PyBudWxsO1xufVxuXG4vKipcbiAqIFJlcGFpciBhbiBcImV2ZW50LWZpcnN0IG9ycGhhblwiOiB0aGUgaG9vayBlbnRpdHkgd3JpdGUgaXMgZGVmZXJyZWRcbiAqIHVudGlsIGFmdGVyIHRoZSBgaG9va19jcmVhdGVkYCBldmVudCBwdWJsaXNoIGNvbW1pdHMgKHNvIGEgZmFpbGVkXG4gKiBwdWJsaXNoIGNhbm5vdCBtdXRhdGUgYWxyZWFkeS1jb21taXR0ZWQgc3RhdGUg4oCUIHNlZSB0aGUgY29tbWVudCBvblxuICogdGhlIGRlZmVycmVkIHdyaXRlKSwgd2hpY2ggb3BlbnMgdGhlIGludmVyc2UgY3Jhc2ggd2luZG93IOKAlCBhXG4gKiBjcmFzaCBBRlRFUiB0aGUgZXZlbnQgcHVibGlzaCBidXQgQkVGT1JFIHRoZSBkZWZlcnJlZCBlbnRpdHkgd3JpdGVcbiAqIGxlYXZlcyB0aGUgZXZlbnQgaW4gdGhlIGxvZyB3aXRoIHRoZSBob29rIGVudGl0eSBtaXNzaW5nLiBBIHJldHJ5XG4gKiB0aGVuIGNvbGxpZGVzIGF0IHRoZSBldmVudCBwdWJsaXNoIGFuZCB0aHJvd3NcbiAqIGBFbnRpdHlDb25mbGljdEVycm9yYCAoY29ycmVjdCDigJQgdGhlIGV2ZW50IElTIGNvbW1pdHRlZCksIGJ1dFxuICogd2l0aG91dCB0aGlzIHJlcGFpciB0aGUgZW50aXR5IHdvdWxkIHN0YXkgbWlzc2luZyBmb3JldmVyIGFuZCB0aGVcbiAqIGhvb2sgd291bGQgYmUgdW5yZXNvbHZhYmxlLlxuICpcbiAqIFRoZSBlbnRpdHkgTVVTVCBiZSByZWNvbnN0cnVjdGVkIGZyb20gdGhlIHBlcnNpc3RlZCBjYW5vbmljYWxcbiAqIGV2ZW50J3MgcGF5bG9hZCDigJQgTk9UIHRoZSByZXRyeSdzIGBldmVudERhdGFgIOKAlCBvdGhlcndpc2UgYSByZXRyeVxuICogY2FycnlpbmcgZGlmZmVyZW50IGBtZXRhZGF0YWAgLyBgaXNXZWJob29rYCB3b3VsZCBzaWxlbnRseSBjaGFuZ2VcbiAqIGNvbW1pdHRlZCBzdGF0ZS4gVGhlIHdyaXRlIHVzZXMgYHdyaXRlRXhjbHVzaXZlYCAoY3JlYXRlLWlmLWFic2VudClcbiAqIHNvIGEgY29uY3VycmVudCB3cml0ZXIgcmFjaW5nIHRoaXMgcmVwYWlyIGNhbm5vdCBiZSBvdmVyd3JpdHRlbjtcbiAqIHdoaWNoZXZlciB3cml0ZSBsYW5kcyBmaXJzdCwgdGhlIGNvbnRlbnQgaXMgaWRlbnRpY2FsIGJlY2F1c2UgYm90aFxuICogZGVyaXZlIGZyb20gdGhlIHNhbWUgcGVyc2lzdGVkIGV2ZW50LlxuICovXG5hc3luYyBmdW5jdGlvbiByZXBhaXJIb29rRW50aXR5RnJvbVBlcnNpc3RlZEV2ZW50KFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGhvb2tJZDogc3RyaW5nLFxuICBwZXJzaXN0ZWRFdmVudElkOiBzdHJpbmcsXG4gIHRhZzogc3RyaW5nIHwgdW5kZWZpbmVkXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29tcG9zaXRlS2V5ID0gYCR7cnVuSWR9LSR7cGVyc2lzdGVkRXZlbnRJZH1gO1xuICBjb25zdCBwZXJzaXN0ZWRFdmVudCA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgIGJhc2VkaXIsXG4gICAgJ2V2ZW50cycsXG4gICAgY29tcG9zaXRlS2V5LFxuICAgIEV2ZW50U2NoZW1hLFxuICAgIHRhZ1xuICApO1xuICBpZiAoXG4gICAgIXBlcnNpc3RlZEV2ZW50IHx8XG4gICAgcGVyc2lzdGVkRXZlbnQuZXZlbnRUeXBlICE9PSAnaG9va19jcmVhdGVkJyB8fFxuICAgIHBlcnNpc3RlZEV2ZW50LmNvcnJlbGF0aW9uSWQgIT09IGhvb2tJZFxuICApIHtcbiAgICAvLyBOb3RoaW5nIHRydXN0d29ydGh5IHRvIHJlcGFpciBmcm9tLlxuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBleGlzdGluZ0hvb2sgPSBhd2FpdCByZWFkSlNPTldpdGhGYWxsYmFjayhcbiAgICBiYXNlZGlyLFxuICAgICdob29rcycsXG4gICAgaG9va0lkLFxuICAgIEhvb2tTY2hlbWEsXG4gICAgdGFnXG4gICk7XG4gIGlmIChleGlzdGluZ0hvb2spIHtcbiAgICAvLyBFbnRpdHkgYWxyZWFkeSBwcmVzZW50IOKAlCBub3QgYW4gb3JwaGFuLCBsZWF2ZSBpdCB1bnRvdWNoZWQuXG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IGV2ZW50RGF0YSA9IChwZXJzaXN0ZWRFdmVudC5ldmVudERhdGEgPz8ge30pIGFzIHtcbiAgICB0b2tlbj86IHN0cmluZztcbiAgICBtZXRhZGF0YT86IFNlcmlhbGl6ZWREYXRhO1xuICAgIGlzV2ViaG9vaz86IGJvb2xlYW47XG4gIH07XG4gIGlmICh0eXBlb2YgZXZlbnREYXRhLnRva2VuICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBob29rOiBIb29rID0ge1xuICAgIHJ1bklkLFxuICAgIGhvb2tJZCxcbiAgICB0b2tlbjogZXZlbnREYXRhLnRva2VuLFxuICAgIG1ldGFkYXRhOiBldmVudERhdGEubWV0YWRhdGEsXG4gICAgb3duZXJJZDogJ2xvY2FsLW93bmVyJyxcbiAgICBwcm9qZWN0SWQ6ICdsb2NhbC1wcm9qZWN0JyxcbiAgICBlbnZpcm9ubWVudDogJ2xvY2FsJyxcbiAgICBjcmVhdGVkQXQ6IHBlcnNpc3RlZEV2ZW50LmNyZWF0ZWRBdCxcbiAgICBzcGVjVmVyc2lvbjogcGVyc2lzdGVkRXZlbnQuc3BlY1ZlcnNpb24sXG4gICAgaXNXZWJob29rOiBldmVudERhdGEuaXNXZWJob29rID8/IHRydWUsXG4gIH07XG4gIGF3YWl0IHdyaXRlRXhjbHVzaXZlKFxuICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ2hvb2tzJywgaG9va0lkLCB0YWcpLFxuICAgIEpTT04uc3RyaW5naWZ5KGhvb2ssIGpzb25SZXBsYWNlciwgMilcbiAgKTtcbn1cblxuLyoqXG4gKiBBdG9taWNhbGx5IHBpbiBhIGNhbm9uaWNhbCBgaG9va19jcmVhdGVkYCBldmVudElkIGZvciBhIGxlZ2FjeVxuICogY2xhaW0gKG9uZSB3aXRob3V0IGFuIGlubGluZSBgZXZlbnRJZGApLiBUaGUgZmlyc3QgcmV0cnkgdG9cbiAqIGB3cml0ZUV4Y2x1c2l2ZWAgdGhlIHJlY292ZXJ5IG1hcmtlciB3aW5zOyBpdHMgYGNhbmRpZGF0ZUV2ZW50SWRgXG4gKiBiZWNvbWVzIGNhbm9uaWNhbC4gU3Vic2VxdWVudCByZXRyaWVzIHJlYWQgdGhlIG1hcmtlciBhbmQgYWRvcHRcbiAqIGl0cyBgZXZlbnRJZGAuIFRvZ2V0aGVyIHdpdGggdGhlIGB3cml0ZUV4Y2x1c2l2ZShldmVudFBhdGgpYCBpblxuICogdGhlIG91dGVyIGV2ZW50IHB1Ymxpc2gsIHRoaXMgZ2l2ZXMgdGhlIGxlZ2FjeS1mYWxsYmFjayBwYXRoIHRoZVxuICogc2FtZSBzaW5nbGUtZXZlbnQgY29udmVyZ2VuY2UgZ3VhcmFudGVlIGFzIHRoZSBpbmxpbmUtYGV2ZW50SWRgXG4gKiBmYXN0IHBhdGguXG4gKlxuICogUmV0dXJucyB0aGUgY2Fub25pY2FsIGV2ZW50SWQgZm9yIHRoZSBjYWxsZXIgdG8gYWRvcHQsIG9yIGBudWxsYFxuICogaWYgd2UgbG9zdCB0aGUgbWFya2VyIHJhY2UgQU5EIHRoZSByZXN1bHRpbmcgbWFya2VyIGZpbGUgaXNcbiAqIHVucmVhZGFibGUgKGV4dHJlbWVseSByYXJlOyBjb3JydXB0ZWQgZGlzaykuIENhbGxlcnMgdHJlYXQgYG51bGxgXG4gKiBhcyBcImdpdmUgdXAsIHRocm93IGBFbnRpdHlDb25mbGljdEVycm9yYFwiIHNvIHRoZSBydW50aW1lJ3NcbiAqIGNvbmN1cnJlbnQtcmVwbGF5IGNhdGNoIHBhdGggc3dhbGxvd3MgdGhpcyBhdHRlbXB0IGFuZCBsZXRzXG4gKiBhbm90aGVyIG9uZSB0aHJvdWdoLlxuICovXG5hc3luYyBmdW5jdGlvbiBwaW5DYW5vbmljYWxFdmVudElkRm9yTGVnYWN5Q2xhaW0oXG4gIGJhc2VkaXI6IHN0cmluZyxcbiAgdG9rZW46IHN0cmluZyxcbiAgcnVuSWQ6IHN0cmluZyxcbiAgaG9va0lkOiBzdHJpbmcsXG4gIGNhbmRpZGF0ZUV2ZW50SWQ6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBob29rUmVjb3ZlcnlNYXJrZXJQYXRoKGJhc2VkaXIsIHRva2VuLCBydW5JZCwgaG9va0lkKTtcbiAgY29uc3QgbWFya2VyQ29udGVudCA9IEpTT04uc3RyaW5naWZ5KHsgZXZlbnRJZDogY2FuZGlkYXRlRXZlbnRJZCB9KTtcbiAgY29uc3Qgd29uID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUobWFya2VyUGF0aCwgbWFya2VyQ29udGVudCk7XG4gIGlmICh3b24pIHtcbiAgICByZXR1cm4gY2FuZGlkYXRlRXZlbnRJZDtcbiAgfVxuICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHJlYWRIb29rUmVjb3ZlcnlNYXJrZXIobWFya2VyUGF0aCk7XG4gIHJldHVybiBleGlzdGluZz8uZXZlbnRJZCA/PyBudWxsO1xufVxuXG4vKipcbiAqIEluLXByb2Nlc3MgcGVyLWtleSBhc3luYyBtdXRleCBiYWNrZWQgYnkgYSBjYWxsZXItc3VwcGxpZWQgYE1hcGAuXG4gKiBVc2VkIGJ5IGBjcmVhdGVFdmVudHNTdG9yYWdlYCB0byBzZXJpYWxpemUgc2FtZS1rZXkgZXZlbnQgd3JpdGVzXG4gKiAoYHN0ZXBfKmAgZm9yIHRoZSBzYW1lIHN0ZXAsIGBob29rX2NyZWF0ZWRgIGZvciB0aGUgc2FtZSBob29rKS5cbiAqIFRoZSBtYXAgaXMgaW5zdGFudGlhdGVkIHBlci1zdG9yYWdlLWluc3RhbmNlIOKAlCBkaWZmZXJlbnRcbiAqIGluc3RhbmNlcyBkbyBOT1Qgc2hhcmUgbG9ja3MsIHNvIHR3byBpbnN0YW5jZXMgc2hhcmluZyBvbmUgZGF0YVxuICogZGlyZWN0b3J5IGJlaGF2ZSBleGFjdGx5IGxpa2UgdHdvIHNlcGFyYXRlIE9TIHByb2Nlc3NlcyBmcm9tIHRoZVxuICogbG9ja2luZyBzdGFuZHBvaW50LiBDcm9zcy1pbnN0YW5jZSAvIGNyb3NzLXByb2Nlc3MgYXJiaXRyYXRpb25cbiAqIHJlbGllcyBvbiB0aGUgb24tZGlzayBjb25zdHJhaW50IC8gY2xhaW0gZmlsZXMgaW5zdGVhZC5cbiAqL1xuZnVuY3Rpb24gd2l0aEluUHJvY2Vzc0xvY2s8VD4oXG4gIGxvY2tzOiBNYXA8c3RyaW5nLCBQcm9taXNlPHVua25vd24+PixcbiAga2V5OiBzdHJpbmcsXG4gIGZuOiAoKSA9PiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgcHJldiA9IGxvY2tzLmdldChrZXkpO1xuICBjb25zdCB0YXNrQm94OiB7IHRhc2s/OiBQcm9taXNlPFQ+IH0gPSB7fTtcbiAgY29uc3QgdGFzayA9IChhc3luYyAoKSA9PiB7XG4gICAgaWYgKHByZXYpIHtcbiAgICAgIC8vIFdhaXQgZm9yIHRoZSBwcmV2aW91cyB0YXNrIHRvIHNldHRsZTsgZG9uJ3QgaW5oZXJpdCBpdHMgZXJyb3JzLlxuICAgICAgYXdhaXQgcHJldi5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGZuKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChsb2Nrcy5nZXQoa2V5KSA9PT0gdGFza0JveC50YXNrKSB7XG4gICAgICAgIGxvY2tzLmRlbGV0ZShrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgfSkoKTtcbiAgdGFza0JveC50YXNrID0gdGFzaztcbiAgbG9ja3Muc2V0KGtleSwgdGFzayk7XG4gIHJldHVybiB0YXNrO1xufVxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0byBkZWxldGUgYWxsIHdhaXRzIGFzc29jaWF0ZWQgd2l0aCBhIHdvcmtmbG93IHJ1bi5cbiAqIENhbGxlZCB3aGVuIGEgcnVuIHJlYWNoZXMgYSB0ZXJtaW5hbCBzdGF0ZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVsZXRlQWxsV2FpdHNGb3JSdW4oXG4gIGJhc2VkaXI6IHN0cmluZyxcbiAgcnVuSWQ6IHN0cmluZ1xuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHdhaXRzRGlyID0gcGF0aC5qb2luKGJhc2VkaXIsICd3YWl0cycpO1xuICBjb25zdCBmaWxlcyA9IGF3YWl0IGxpc3RKU09ORmlsZXMod2FpdHNEaXIpO1xuXG4gIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgIC8vIGZpbGVJZHMgbWF5IGNvbnRhaW4gdGFnIHN1ZmZpeGVzIChlLmcuLCBcIndydW5fQUJDLWNvcnJJZC52aXRlc3QtMFwiKVxuICAgIC8vIGJ1dCBzdGFydHNXaXRoIHN0aWxsIG1hdGNoZXMgY29ycmVjdGx5IHNpbmNlIHRoZSB0YWcgaXMgYSBzdWZmaXguXG4gICAgaWYgKGZpbGUuc3RhcnRzV2l0aChgJHtydW5JZH0tYCkpIHtcbiAgICAgIGNvbnN0IHdhaXRQYXRoID0gcGF0aC5qb2luKHdhaXRzRGlyLCBgJHtmaWxlfS5qc29uYCk7XG4gICAgICBhd2FpdCBkZWxldGVKU09OKHdhaXRQYXRoKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBldmVudHMgc3RvcmFnZSBpbXBsZW1lbnRhdGlvbiB1c2luZyB0aGUgZmlsZXN5c3RlbS5cbiAqIEltcGxlbWVudHMgdGhlIFN0b3JhZ2VbJ2V2ZW50cyddIGludGVyZmFjZSB3aXRoIGNyZWF0ZSwgbGlzdCwgYW5kIGxpc3RCeUNvcnJlbGF0aW9uSWQgb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUV2ZW50c1N0b3JhZ2UoXG4gIGJhc2VkaXI6IHN0cmluZyxcbiAgdGFnPzogc3RyaW5nXG4pOiBTdG9yYWdlWydldmVudHMnXSB7XG4gIC8vIFBlci1pbnN0YW5jZSBpbi1wcm9jZXNzIG11dGV4LiBUd28gc3RvcmFnZSBpbnN0YW5jZXMgc2hhcmluZ1xuICAvLyBvbmUgZGF0YSBkaXJlY3RvcnkgZ2V0IGluZGVwZW5kZW50IGxvY2sgbWFwcywgd2hpY2ggbWFrZXMgdGhlbVxuICAvLyBiZWhhdmUgbGlrZSB0d28gc2VwYXJhdGUgT1MgcHJvY2Vzc2VzIGZyb20gdGhlIGxvY2tpbmdcbiAgLy8gc3RhbmRwb2ludCDigJQgY3Jvc3MtaW5zdGFuY2UgYXJiaXRyYXRpb24gcmVsaWVzIG9uIHRoZSBvbi1kaXNrXG4gIC8vIGB3cml0ZUV4Y2x1c2l2ZWAgY29uc3RyYWludCAvIGNsYWltIGZpbGVzIGluc3RlYWQuIFRlc3RzIHVzZVxuICAvLyB0aGlzIHRvIGV4ZXJjaXNlIGNyb3NzLXByb2Nlc3MgY29udmVyZ2VuY2Ugd2l0aG91dCBzcGF3bmluZ1xuICAvLyBzdWJwcm9jZXNzZXMuXG4gIC8vXG4gIC8vIGBob29rTG9ja3NgIHNlcmlhbGl6ZXMgYGhvb2tfY3JlYXRlZGAgY2FsbHMgZm9yIHRoZSBzYW1lXG4gIC8vIChydW5JZCwgY29ycmVsYXRpb25JZCkgc28gdGhlIFwiY2xhaW0gdG9rZW4sIHRoZW4gd3JpdGUgaG9va1xuICAvLyBlbnRpdHkgKyBldmVudFwiIHNlcXVlbmNlIHJ1bnMgdG8gY29tcGxldGlvbiBiZWZvcmUgYW5vdGhlclxuICAvLyBpbi1wcm9jZXNzIGludm9jYXRpb24gZW50ZXJzIHRoZSBkZWR1cCBicmFuY2guXG4gIGNvbnN0IGhvb2tMb2NrcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHVua25vd24+PigpO1xuXG4gIHJldHVybiB7XG4gICAgYXN5bmMgY3JlYXRlKHJ1bklkLCBkYXRhLCBwYXJhbXMpOiBQcm9taXNlPEV2ZW50UmVzdWx0PiB7XG4gICAgICAvLyBWYWxpZGF0ZSByZXF1ZXN0LXN1cHBsaWVkIElEcyBiZWZvcmUgdGhleSdyZSBjb25jYXRlbmF0ZWQgaW50b1xuICAgICAgLy8gZmlsZXN5c3RlbSBwYXRocy4gVGhpcyBpcyB0aGUgcHJpbWFyeSBkZWZlbnNlIGFnYWluc3QgcGF0aCB0cmF2ZXJzYWxcbiAgICAgIC8vIGF0dGFja3Mgd2hlcmUgYSBjbGllbnQgc3VwcGxpZXMgcnVuSWQgLyBjb3JyZWxhdGlvbklkIHZhbHVlcyBsaWtlXG4gICAgICAvLyBcIi4uLy4uLy4uL3BhY2thZ2VcIiB0byByZWFkIG9yIHdyaXRlIGZpbGVzIG91dHNpZGUgdGhlIHN0b3JhZ2Ugcm9vdC5cbiAgICAgIC8vXG4gICAgICAvLyBFbXB0eSBgY29ycmVsYXRpb25JZGAgdmFsdWVzIGFyZSBhbHNvIHJlamVjdGVkIGhlcmU6IHRoZSBldmVudFxuICAgICAgLy8gc2NoZW1hcyBvbmx5IHJlcXVpcmUgYHouc3RyaW5nKClgLCBzbyB3aXRob3V0IHRoaXMgY2hlY2sgYVxuICAgICAgLy8gc3RlcF9jcmVhdGVkIC8gaG9va19jcmVhdGVkIC8gd2FpdF9jcmVhdGVkIHJlcXVlc3Qgd2l0aFxuICAgICAgLy8gYGNvcnJlbGF0aW9uSWQ6ICcnYCB3b3VsZCBzaWxlbnRseSBiZSB3cml0dGVuIHVuZGVyIGEgbWFsZm9ybWVkXG4gICAgICAvLyBjb21wb3NpdGUga2V5IGxpa2UgYCR7cnVuSWR9LWAuXG4gICAgICBpZiAocnVuSWQgIT0gbnVsbCAmJiBydW5JZCAhPT0gJycpIHtcbiAgICAgICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdydW5JZCcsIHJ1bklkKTtcbiAgICAgIH1cbiAgICAgIGlmICgnY29ycmVsYXRpb25JZCcgaW4gZGF0YSAmJiB0eXBlb2YgZGF0YS5jb3JyZWxhdGlvbklkID09PSAnc3RyaW5nJykge1xuICAgICAgICBhc3NlcnRTYWZlRW50aXR5SWQoJ2NvcnJlbGF0aW9uSWQnLCBkYXRhLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBgaG9va19jcmVhdGVkYCBpcyBzZXJpYWxpemVkIHBlci0ocnVuSWQsIGhvb2tJZCkgc28gdGhlXG4gICAgICAvLyBcImNsYWltIHRva2VuLCB3cml0ZSBob29rIGVudGl0eSwgd3JpdGUgZXZlbnRcIiBzZXF1ZW5jZSBydW5zIHRvXG4gICAgICAvLyBjb21wbGV0aW9uIGJlZm9yZSBhbm90aGVyIGluLXByb2Nlc3MgaW52b2NhdGlvbiBlbnRlcnMgdGhlXG4gICAgICAvLyBzYW1lLWhvb2sgZGVkdXAgYnJhbmNoLiBXaXRob3V0IHRoaXMsIHR3byBzYW1lLXRpY2sgY29uY3VycmVudFxuICAgICAgLy8gY2FsbGVycyBjYW4gcmFjZSBiZXR3ZWVuIHRoZSB3aW5uZXIncyBgd3JpdGVFeGNsdXNpdmUoY2xhaW0pYFxuICAgICAgLy8gYW5kIGB3cml0ZUpTT04oaG9vaylgLCBtYWtpbmcgdGhlIHNlY29uZCBjYWxsZXIgbW9tZW50YXJpbHlcbiAgICAgIC8vIG9ic2VydmUgYSBjbGFpbSB3aXRoIG5vIG1hdGNoaW5nIGhvb2sgZW50aXR5IOKAlCB3aGljaCB0aGVcbiAgICAgIC8vIGNyYXNoLXJlY292ZXJ5IHBhdGggYmVsb3cgd291bGQgbWlzaW50ZXJwcmV0IGFzIGEgcHJpb3IgY3Jhc2hcbiAgICAgIC8vIGFuZCBpbmNvcnJlY3RseSBmYWxsIHRocm91Z2ggdG8gYSBzZWNvbmQgaG9vayBlbnRpdHkgd3JpdGUuXG4gICAgICBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdob29rX2NyZWF0ZWQnICYmIHJ1bklkICYmIGRhdGEuY29ycmVsYXRpb25JZCkge1xuICAgICAgICBjb25zdCBsb2NrS2V5ID0gdGFnXG4gICAgICAgICAgPyBgJHtydW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9Lmhvb2suJHt0YWd9YFxuICAgICAgICAgIDogYCR7cnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfS5ob29rYDtcbiAgICAgICAgcmV0dXJuIHdpdGhJblByb2Nlc3NMb2NrKGhvb2tMb2NrcywgbG9ja0tleSwgKCkgPT4gY3JlYXRlSW1wbCgpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjcmVhdGVJbXBsKCk7XG5cbiAgICAgIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUltcGwoKTogUHJvbWlzZTxFdmVudFJlc3VsdD4ge1xuICAgICAgICAvLyBNb3N0IHBhdGhzIHVzZSB0aGUgZnJlc2hseS1nZW5lcmF0ZWQgY2FuZGlkYXRlIGV2ZW50SWQuIFRoZVxuICAgICAgICAvLyBob29rX2NyZWF0ZWQgZGVkdXAtcmVjb3ZlcnkgcGF0aCBiZWxvdyBtYXkgcmVhc3NpZ24gaXQgdG9cbiAgICAgICAgLy8gdGhlIGNhbm9uaWNhbCBldmVudElkIHBlcnNpc3RlZCBpbiB0aGUgZHVyYWJsZSB0b2tlbiBjbGFpbVxuICAgICAgICAvLyBzbyBjb25jdXJyZW50IC8gY3Jvc3MtcHJvY2VzcyB3b3JrZXJzIGNvbnZlcmdlIG9uIGEgc2luZ2xlXG4gICAgICAgIC8vIGV2ZW50IGluIHRoZSBsb2cuXG4gICAgICAgIGxldCBldmVudElkID0gYGV2bnRfJHttb25vdG9uaWNVbGlkKCl9YDtcbiAgICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICAgICAgICAvLyBGb3IgcnVuX2NyZWF0ZWQgZXZlbnRzLCB1c2UgY2xpZW50LXByb3ZpZGVkIHJ1bklkIG9yIGdlbmVyYXRlIG9uZSBzZXJ2ZXItc2lkZVxuICAgICAgICBsZXQgZWZmZWN0aXZlUnVuSWQ6IHN0cmluZztcbiAgICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX2NyZWF0ZWQnICYmICghcnVuSWQgfHwgcnVuSWQgPT09ICcnKSkge1xuICAgICAgICAgIGVmZmVjdGl2ZVJ1bklkID0gYHdydW5fJHttb25vdG9uaWNVbGlkKCl9YDtcbiAgICAgICAgfSBlbHNlIGlmICghcnVuSWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3J1bklkIGlzIHJlcXVpcmVkIGZvciBub24tcnVuX2NyZWF0ZWQgZXZlbnRzJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWZmZWN0aXZlUnVuSWQgPSBydW5JZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRlIGNsaWVudC1wcm92aWRlZCBydW5JZCB0aW1lc3RhbXAgaXMgd2l0aGluIGFjY2VwdGFibGUgdGhyZXNob2xkXG4gICAgICAgIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jcmVhdGVkJyAmJiBydW5JZCAmJiBydW5JZCAhPT0gJycpIHtcbiAgICAgICAgICBjb25zdCB2YWxpZGF0aW9uRXJyb3IgPSB2YWxpZGF0ZVVsaWRUaW1lc3RhbXAoXG4gICAgICAgICAgICBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgICd3cnVuXydcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1dvcmxkRXJyb3IodmFsaWRhdGlvbkVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzcGVjVmVyc2lvbiBpcyBhbHdheXMgc2VudCBieSB0aGUgcnVudGltZSwgYnV0IHdlIHByb3ZpZGUgYSBmYWxsYmFjayBmb3Igc2FmZXR5XG4gICAgICAgIGNvbnN0IGVmZmVjdGl2ZVNwZWNWZXJzaW9uID0gZGF0YS5zcGVjVmVyc2lvbiA/PyBTUEVDX1ZFUlNJT05fQ1VSUkVOVDtcblxuICAgICAgICAvLyBHZXQgY3VycmVudCBydW4gc3RhdGUgZm9yIHZhbGlkYXRpb24gKGlmIG5vdCBjcmVhdGluZyBhIG5ldyBydW4pXG4gICAgICAgIC8vIFNraXAgcnVuIHZhbGlkYXRpb24gZm9yIHN0ZXBfY29tcGxldGVkIGFuZCBzdGVwX3JldHJ5aW5nIC0gdGhleSBvbmx5IG9wZXJhdGVcbiAgICAgICAgLy8gb24gcnVubmluZyBzdGVwcywgYW5kIHJ1bm5pbmcgc3RlcHMgYXJlIGFsd2F5cyBhbGxvd2VkIHRvIG1vZGlmeSByZWdhcmRsZXNzXG4gICAgICAgIC8vIG9mIHJ1biBzdGF0ZS4gVGhpcyBvcHRpbWl6YXRpb24gc2F2ZXMgZmlsZXN5c3RlbSByZWFkcyBwZXIgc3RlcCBldmVudC5cbiAgICAgICAgbGV0IGN1cnJlbnRSdW46IFdvcmtmbG93UnVuIHwgbnVsbCA9IG51bGw7XG4gICAgICAgIGNvbnN0IHNraXBSdW5WYWxpZGF0aW9uRXZlbnRzID0gWydzdGVwX2NvbXBsZXRlZCcsICdzdGVwX3JldHJ5aW5nJ107XG4gICAgICAgIGlmIChcbiAgICAgICAgICBkYXRhLmV2ZW50VHlwZSAhPT0gJ3J1bl9jcmVhdGVkJyAmJlxuICAgICAgICAgICFza2lwUnVuVmFsaWRhdGlvbkV2ZW50cy5pbmNsdWRlcyhkYXRhLmV2ZW50VHlwZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgY3VycmVudFJ1biA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdydW5zJyxcbiAgICAgICAgICAgIGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgV29ya2Zsb3dSdW5TY2hlbWEsXG4gICAgICAgICAgICB0YWdcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gUmVzaWxpZW50IHN0YXJ0OiBydW5fc3RhcnRlZCBvbiBub24tZXhpc3RlbnQgcnVuIHdpdGggZXZlbnREYXRhXG4gICAgICAgICAgLy8gY3JlYXRlcyB0aGUgcnVuIGZpcnN0LCBzbyB0aGUgcXVldWUgY2FuIGJvb3RzdHJhcCBhIHJ1biB0aGF0XG4gICAgICAgICAgLy8gZmFpbGVkIHRvIGNyZWF0ZSBkdXJpbmcgc3RhcnQoKS5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9zdGFydGVkJyAmJlxuICAgICAgICAgICAgIWN1cnJlbnRSdW4gJiZcbiAgICAgICAgICAgICdldmVudERhdGEnIGluIGRhdGEgJiZcbiAgICAgICAgICAgIGRhdGEuZXZlbnREYXRhXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBydW5JbnB1dERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgICAgIGRlcGxveW1lbnRJZD86IHN0cmluZztcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lPzogc3RyaW5nO1xuICAgICAgICAgICAgICBpbnB1dD86IGFueTtcbiAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dD86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICBydW5JbnB1dERhdGEuZGVwbG95bWVudElkICYmXG4gICAgICAgICAgICAgIHJ1bklucHV0RGF0YS53b3JrZmxvd05hbWUgJiZcbiAgICAgICAgICAgICAgcnVuSW5wdXREYXRhLmlucHV0ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAvLyBBdG9taWNhbGx5IHRyeSB0byBwdWJsaXNoIHRoZSBydW4gZW50aXR5IHNvIG9ubHkgdGhlIGZpcnN0XG4gICAgICAgICAgICAgIC8vIHdyaXRlciB3aW5zLCBwcmV2ZW50aW5nIGEgVE9DVE9VIHJhY2Ugd2hlcmUgYSBjb25jdXJyZW50XG4gICAgICAgICAgICAgIC8vIHJ1bl9jcmVhdGVkIGZyb20gc3RhcnQoKSBjb3VsZCBvdmVyd3JpdGUgYSBydW4gdGhhdCB3YXNcbiAgICAgICAgICAgICAgLy8gYWxyZWFkeSB0cmFuc2l0aW9uZWQgdG8gJ3J1bm5pbmcnLlxuICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkUnVuOiBXb3JrZmxvd1J1biA9IHtcbiAgICAgICAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgZGVwbG95bWVudElkOiBydW5JbnB1dERhdGEuZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuSW5wdXREYXRhLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogZWZmZWN0aXZlU3BlY1ZlcnNpb24sXG4gICAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogcnVuSW5wdXREYXRhLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgICAgaW5wdXQ6IHJ1bklucHV0RGF0YS5pbnB1dCxcbiAgICAgICAgICAgICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIHN0YXJ0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGNvbXBsZXRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGNvbnN0IHJ1blBhdGggPSB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyk7XG4gICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB3cml0ZUV4Y2x1c2l2ZShcbiAgICAgICAgICAgICAgICBydW5QYXRoLFxuICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGNyZWF0ZWRSdW4sIGpzb25SZXBsYWNlcilcbiAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICBpZiAoY3JlYXRlZCkge1xuICAgICAgICAgICAgICAgIC8vIFdlIGNyZWF0ZWQgdGhlIHJ1biDigJQgYWxzbyB3cml0ZSB0aGUgcnVuX2NyZWF0ZWQgZXZlbnQuXG4gICAgICAgICAgICAgICAgY29uc3QgcnVuQ3JlYXRlZEV2ZW50SWQgPSBgZXZudF8ke21vbm90b25pY1VsaWQoKX1gO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJ1bkNyZWF0ZWRFdmVudDogRXZlbnQgPSB7XG4gICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fY3JlYXRlZCcsXG4gICAgICAgICAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgICBldmVudElkOiBydW5DcmVhdGVkRXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcnVuSW5wdXREYXRhLmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW5JbnB1dERhdGEud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICBpbnB1dDogcnVuSW5wdXREYXRhLmlucHV0LFxuICAgICAgICAgICAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBydW5JbnB1dERhdGEuZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7cnVuQ3JlYXRlZEV2ZW50SWR9YDtcbiAgICAgICAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdldmVudHMnLCBjcmVhdGVkQ29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgICAgICAgcnVuQ3JlYXRlZEV2ZW50XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UnVuID0gY3JlYXRlZFJ1bjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSdW4gYWxyZWFkeSBleGlzdHMgKGNvbmN1cnJlbnQgcnVuX2NyZWF0ZWQgd29uIHRoZVxuICAgICAgICAgICAgICAgIC8vIHJhY2UpLiBSZS1yZWFkIGl0IHNvIGRvd25zdHJlYW0gbG9naWMgc2VlcyB0aGUgcmVhbCBzdGF0ZS5cbiAgICAgICAgICAgICAgICBjdXJyZW50UnVuID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgICAgICAgJ3J1bnMnLFxuICAgICAgICAgICAgICAgICAgZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgICBXb3JrZmxvd1J1blNjaGVtYSxcbiAgICAgICAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgICAgLy8gVkVSU0lPTiBDT01QQVRJQklMSVRZOiBDaGVjayBydW4gc3BlYyB2ZXJzaW9uXG4gICAgICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgICAgICAvLyBGb3IgZXZlbnRzIHRoYXQgaGF2ZSBmZXRjaGVkIHRoZSBydW4sIGNoZWNrIHZlcnNpb24gY29tcGF0aWJpbGl0eS5cbiAgICAgICAgLy8gU2tpcCBmb3IgcnVuX2NyZWF0ZWQgKG5vIGV4aXN0aW5nIHJ1bikgYW5kIHJ1bnRpbWUgZXZlbnRzIChzdGVwX2NvbXBsZXRlZCwgc3RlcF9yZXRyeWluZykuXG4gICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgcnVuIHJlcXVpcmVzIGEgbmV3ZXIgd29ybGQgdmVyc2lvblxuICAgICAgICAgIGlmIChyZXF1aXJlc05ld2VyV29ybGQoY3VycmVudFJ1bi5zcGVjVmVyc2lvbikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBSdW5Ob3RTdXBwb3J0ZWRFcnJvcihcbiAgICAgICAgICAgICAgY3VycmVudFJ1bi5zcGVjVmVyc2lvbiEsXG4gICAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9DVVJSRU5UXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFJvdXRlIHRvIGxlZ2FjeSBoYW5kbGVyIGZvciBwcmUtZXZlbnQtc291cmNpbmcgcnVuc1xuICAgICAgICAgIGlmIChpc0xlZ2FjeVNwZWNWZXJzaW9uKGN1cnJlbnRSdW4uc3BlY1ZlcnNpb24pKSB7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlTGVnYWN5RXZlbnQoXG4gICAgICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgICAgIGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICBjdXJyZW50UnVuLFxuICAgICAgICAgICAgICBwYXJhbXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgICAgIC8vIFZBTElEQVRJT046IFRlcm1pbmFsIHN0YXRlIGFuZCBldmVudCBvcmRlcmluZyBjaGVja3NcbiAgICAgICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAgICAgLy8gUnVuIHRlcm1pbmFsIHN0YXRlIHZhbGlkYXRpb25cbiAgICAgICAgaWYgKGN1cnJlbnRSdW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGN1cnJlbnRSdW4uc3RhdHVzKSkge1xuICAgICAgICAgIGNvbnN0IHJ1blRlcm1pbmFsRXZlbnRzID0gW1xuICAgICAgICAgICAgJ3J1bl9zdGFydGVkJyxcbiAgICAgICAgICAgICdydW5fY29tcGxldGVkJyxcbiAgICAgICAgICAgICdydW5fZmFpbGVkJyxcbiAgICAgICAgICBdO1xuXG4gICAgICAgICAgLy8gSWRlbXBvdGVudCBvcGVyYXRpb246IHJ1bl9jYW5jZWxsZWQgb24gYWxyZWFkeSBjYW5jZWxsZWQgcnVuIGlzIGFsbG93ZWRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jYW5jZWxsZWQnICYmXG4gICAgICAgICAgICBjdXJyZW50UnVuLnN0YXR1cyA9PT0gJ2NhbmNlbGxlZCdcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIFJldHVybiBleGlzdGluZyBzdGF0ZSAoaWRlbXBvdGVudClcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50OiBFdmVudCA9IHtcbiAgICAgICAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGNvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2V2ZW50SWR9YDtcbiAgICAgICAgICAgIGF3YWl0IHdyaXRlSlNPTihcbiAgICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnZXZlbnRzJywgY29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgICBldmVudFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVEYXRhID1cbiAgICAgICAgICAgICAgcGFyYW1zPy5yZXNvbHZlRGF0YSA/PyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBldmVudDogc3RyaXBFdmVudERhdGFSZWZzKGV2ZW50LCByZXNvbHZlRGF0YSksXG4gICAgICAgICAgICAgIHJ1bjogY3VycmVudFJ1bixcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRm9yIHJ1bl9zdGFydGVkIG9uIHRlcm1pbmFsIHJ1bnMsIHVzZSBSdW5FeHBpcmVkRXJyb3Igc28gdGhlXG4gICAgICAgICAgLy8gcnVudGltZSBrbm93cyB0byBleGl0IHdpdGhvdXQgcmV0cnlpbmcuXG4gICAgICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX3N0YXJ0ZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUnVuRXhwaXJlZEVycm9yKFxuICAgICAgICAgICAgICBgV29ya2Zsb3cgcnVuIFwiJHtlZmZlY3RpdmVSdW5JZH1cIiBpcyBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlIFwiJHtjdXJyZW50UnVuLnN0YXR1c31cImBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gT3RoZXIgcnVuIHN0YXRlIHRyYW5zaXRpb25zIGFyZSBub3QgYWxsb3dlZCBvbiB0ZXJtaW5hbCBydW5zXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcnVuVGVybWluYWxFdmVudHMuaW5jbHVkZXMoZGF0YS5ldmVudFR5cGUpIHx8XG4gICAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jYW5jZWxsZWQnXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgYENhbm5vdCB0cmFuc2l0aW9uIHJ1biBmcm9tIHRlcm1pbmFsIHN0YXRlIFwiJHtjdXJyZW50UnVuLnN0YXR1c31cImBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ3JlYXRpbmcgbmV3IGVudGl0aWVzIG9uIHRlcm1pbmFsIHJ1bnMgaXMgbm90IGFsbG93ZWRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBkYXRhLmV2ZW50VHlwZSA9PT0gJ3N0ZXBfY3JlYXRlZCcgfHxcbiAgICAgICAgICAgIGRhdGEuZXZlbnRUeXBlID09PSAnaG9va19jcmVhdGVkJyB8fFxuICAgICAgICAgICAgZGF0YS5ldmVudFR5cGUgPT09ICd3YWl0X2NyZWF0ZWQnXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgYENhbm5vdCBjcmVhdGUgbmV3IGVudGl0aWVzIG9uIHJ1biBpbiB0ZXJtaW5hbCBzdGF0ZSBcIiR7Y3VycmVudFJ1bi5zdGF0dXN9XCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0ZXAtcmVsYXRlZCBldmVudCB2YWxpZGF0aW9uIChvcmRlcmluZyBhbmQgdGVybWluYWwgc3RhdGUpXG4gICAgICAgIC8vIFN0b3JlIGV4aXN0aW5nU3RlcCBzbyB3ZSBjYW4gcmV1c2UgaXQgbGF0ZXIgKGF2b2lkIGRvdWJsZSByZWFkKVxuICAgICAgICBsZXQgdmFsaWRhdGVkU3RlcDogU3RlcCB8IG51bGwgPSBudWxsO1xuICAgICAgICBjb25zdCBzdGVwRXZlbnRzID0gW1xuICAgICAgICAgICdzdGVwX3N0YXJ0ZWQnLFxuICAgICAgICAgICdzdGVwX2NvbXBsZXRlZCcsXG4gICAgICAgICAgJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAnc3RlcF9yZXRyeWluZycsXG4gICAgICAgIF07XG4gICAgICAgIGlmIChzdGVwRXZlbnRzLmluY2x1ZGVzKGRhdGEuZXZlbnRUeXBlKSAmJiBkYXRhLmNvcnJlbGF0aW9uSWQpIHtcbiAgICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgdmFsaWRhdGVkU3RlcCA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdzdGVwcycsXG4gICAgICAgICAgICBzdGVwQ29tcG9zaXRlS2V5LFxuICAgICAgICAgICAgU3RlcFNjaGVtYSxcbiAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICk7XG5cbiAgICAgICAgICAvLyBFdmVudCBvcmRlcmluZzogc3RlcCBtdXN0IGV4aXN0IGJlZm9yZSB0aGVzZSBldmVudHNcbiAgICAgICAgICBpZiAoIXZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1dvcmxkRXJyb3IoXG4gICAgICAgICAgICAgIGBTdGVwIFwiJHtkYXRhLmNvcnJlbGF0aW9uSWR9XCIgbm90IGZvdW5kYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBTdGVwIHRlcm1pbmFsIHN0YXRlIHZhbGlkYXRpb25cbiAgICAgICAgICBpZiAoaXNUZXJtaW5hbFN0ZXBTdGF0dXModmFsaWRhdGVkU3RlcC5zdGF0dXMpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgYENhbm5vdCBtb2RpZnkgc3RlcCBpbiB0ZXJtaW5hbCBzdGF0ZSBcIiR7dmFsaWRhdGVkU3RlcC5zdGF0dXN9XCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIE9uIHRlcm1pbmFsIHJ1bnM6IG9ubHkgYWxsb3cgY29tcGxldGluZy9mYWlsaW5nIGluLXByb2dyZXNzIHN0ZXBzXG4gICAgICAgICAgaWYgKGN1cnJlbnRSdW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGN1cnJlbnRSdW4uc3RhdHVzKSkge1xuICAgICAgICAgICAgaWYgKHZhbGlkYXRlZFN0ZXAuc3RhdHVzICE9PSAncnVubmluZycpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bkV4cGlyZWRFcnJvcihcbiAgICAgICAgICAgICAgICBgQ2Fubm90IG1vZGlmeSBub24tcnVubmluZyBzdGVwIG9uIHJ1biBpbiB0ZXJtaW5hbCBzdGF0ZSBcIiR7Y3VycmVudFJ1bi5zdGF0dXN9XCJgXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSG9vay1yZWxhdGVkIGV2ZW50IHZhbGlkYXRpb24gKG9yZGVyaW5nKVxuICAgICAgICBjb25zdCBob29rRXZlbnRzUmVxdWlyaW5nRXhpc3RlbmNlID0gWydob29rX2Rpc3Bvc2VkJywgJ2hvb2tfcmVjZWl2ZWQnXTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGhvb2tFdmVudHNSZXF1aXJpbmdFeGlzdGVuY2UuaW5jbHVkZXMoZGF0YS5ldmVudFR5cGUpICYmXG4gICAgICAgICAgZGF0YS5jb3JyZWxhdGlvbklkXG4gICAgICAgICkge1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nSG9vayA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgICBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBIb29rU2NoZW1hLFxuICAgICAgICAgICAgdGFnXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmICghZXhpc3RpbmdIb29rKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoZGF0YS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gYGV2ZW50YCBtYXkgYmUgcmVhc3NpZ25lZCBsYXRlciBpbiB0aGUgYGhvb2tfY3JlYXRlZGBcbiAgICAgICAgLy8gZGVkdXAtcmVjb3ZlcnkgYnJhbmNoIHRvIHN3YXAgaW4gYSBjYW5vbmljYWwgZXZlbnRJZCAvXG4gICAgICAgIC8vIGNyZWF0ZWRBdCBwZXJzaXN0ZWQgaW4gdGhlIGR1cmFibGUgdG9rZW4gY2xhaW0gc29cbiAgICAgICAgLy8gY29uY3VycmVudCAvIGNyb3NzLXByb2Nlc3Mgd29ya2VycyBjb252ZXJnZSBvbiBhIHNpbmdsZVxuICAgICAgICAvLyBldmVudCBpbiB0aGUgbG9nLlxuICAgICAgICBsZXQgZXZlbnQ6IEV2ZW50ID0ge1xuICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgcnVuSWQ6IGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICB9O1xuICAgICAgICAvLyBTdHJpcCBldmVudERhdGEgZnJvbSBydW5fc3RhcnRlZCDigJQgaXQgYmVsb25ncyBvbiBydW5fY3JlYXRlZCBvbmx5LlxuICAgICAgICBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcgJiYgJ2V2ZW50RGF0YScgaW4gZXZlbnQpIHtcbiAgICAgICAgICBkZWxldGUgKGV2ZW50IGFzIGFueSkuZXZlbnREYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhY2sgZW50aXR5IGNyZWF0ZWQvdXBkYXRlZCBmb3IgRXZlbnRSZXN1bHRcbiAgICAgICAgbGV0IHJ1bjogV29ya2Zsb3dSdW4gfCB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBzdGVwOiBTdGVwIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgaG9vazogSG9vayB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHdhaXQ6IFdhaXQgfCB1bmRlZmluZWQ7XG4gICAgICAgIC8vIEZvciBgaG9va19jcmVhdGVkYCwgdGhlIGhvb2sgZW50aXR5IHdyaXRlIGlzIGRlZmVycmVkIHVudGlsXG4gICAgICAgIC8vIEFGVEVSIHRoZSBvdXRlciBldmVudCBwdWJsaXNoIHN1Y2NlZWRzLCBzbyBhIHJldHJ5IHRoYXRcbiAgICAgICAgLy8gY29sbGlkZXMgd2l0aCBhbiBhbHJlYWR5LXB1Ymxpc2hlZCBgaG9va19jcmVhdGVkYCBkb2VzIG5vdFxuICAgICAgICAvLyBtdXRhdGUgdGhlIGR1cmFibGUgaG9vayBlbnRpdHkgd2l0aCB0aGUgcmV0cnkncyBwYXlsb2FkLlxuICAgICAgICAvLyBgaG9va0VudGl0eVdyaXRlT3B0aW9uc2AgY2FycmllcyB0aGUgYHsgb3ZlcndyaXRlIH1gIG1vZGVcbiAgICAgICAgLy8gY2hvc2VuIGJ5IHRoZSBkZWR1cC1yZWNvdmVyeSBicmFuY2ggYWJvdmUgKHVuZGVmaW5lZCBmb3JcbiAgICAgICAgLy8gZmlyc3Qgd3JpdGVycywgYHsgb3ZlcndyaXRlOiB0cnVlIH1gIGZvciByZXRyaWVzIHRoYXQgbWF5XG4gICAgICAgIC8vIGJlIHJlcGFpcmluZyBhbiBvcnBoYW5lZCBwYXJ0aWFsIHdyaXRlKS5cbiAgICAgICAgbGV0IGhvb2tFbnRpdHlXcml0ZU9wdGlvbnM6IHsgb3ZlcndyaXRlOiBib29sZWFuIH0gfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gQ3JlYXRlL3VwZGF0ZSBlbnRpdHkgYmFzZWQgb24gZXZlbnQgdHlwZSAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAgIC8vIFJ1biBsaWZlY3ljbGUgZXZlbnRzXG4gICAgICAgIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jcmVhdGVkJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgICAgY29uc3QgcnVuRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZDogc3RyaW5nO1xuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBzdHJpbmc7XG4gICAgICAgICAgICBpbnB1dDogU2VyaWFsaXplZERhdGE7XG4gICAgICAgICAgICBleGVjdXRpb25Db250ZXh0PzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJ1biA9IHtcbiAgICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcnVuRGF0YS5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICBzdGF0dXM6ICdwZW5kaW5nJyxcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuRGF0YS53b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAvLyBQcm9wYWdhdGUgc3BlY1ZlcnNpb24gZnJvbSB0aGUgZXZlbnQgdG8gdGhlIHJ1biBlbnRpdHlcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQ6IHJ1bkRhdGEuZXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgICAgIGlucHV0OiBydW5EYXRhLmlucHV0LFxuICAgICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgc3RhcnRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjb21wbGV0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICB9O1xuICAgICAgICAgIC8vIEF0b21pY2FsbHkgcHVibGlzaCB0aGUgcnVuIGVudGl0eSBmaWxlIHdpdGhvdXQgb3ZlcndyaXRpbmcgYW5cbiAgICAgICAgICAvLyBleGlzdGluZyB3aW5uZXIuIFRoaXMgcHJldmVudHMgYSBUT0NUT1UgcmFjZSB3aXRoIHRoZSByZXNpbGllbnRcbiAgICAgICAgICAvLyBzdGFydCBwYXRoIChydW5fc3RhcnRlZCBvbiBub24tZXhpc3RlbnQgcnVuKSB0aGF0IGNvdWxkIHJlc3VsdCBpblxuICAgICAgICAgIC8vIGR1cGxpY2F0ZSBydW5fY3JlYXRlZCBldmVudHMgaW4gdGhlIGV2ZW50IGxvZy5cbiAgICAgICAgICBjb25zdCBydW5QYXRoID0gdGFnZ2VkUGF0aChiYXNlZGlyLCAncnVucycsIGVmZmVjdGl2ZVJ1bklkLCB0YWcpO1xuICAgICAgICAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB3cml0ZUV4Y2x1c2l2ZShcbiAgICAgICAgICAgIHJ1blBhdGgsXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeShydW4sIGpzb25SZXBsYWNlciwgMilcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICghY3JlYXRlZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgIGBXb3JrZmxvdyBydW4gXCIke2VmZmVjdGl2ZVJ1bklkfVwiIGFscmVhZHkgZXhpc3RzYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcpIHtcbiAgICAgICAgICAvLyBSZXVzZSBjdXJyZW50UnVuIGZyb20gdmFsaWRhdGlvbiAoYWxyZWFkeSByZWFkIGFib3ZlKVxuICAgICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgICAvLyBJZiBhbHJlYWR5IHJ1bm5pbmcsIHJldHVybiB0aGUgcnVuIHdpdGhvdXQgaW5zZXJ0aW5nIGFcbiAgICAgICAgICAgIC8vIGR1cGxpY2F0ZSBldmVudC4gIFRoaXMgbWFrZXMgcnVuX3N0YXJ0ZWQgaWRlbXBvdGVudCBmb3JcbiAgICAgICAgICAgIC8vIGNvbmN1cnJlbnQgaW52b2NhdGlvbnMuICBXZSBvbWl0IHByZWxvYWRlZCBldmVudHMgaGVyZVxuICAgICAgICAgICAgLy8gYmVjYXVzZSB0aGlzIGlzIGEgcmFyZSByYWNlLWNvbmRpdGlvbiBwYXRoIOKAlCB0aGUgcnVudGltZVxuICAgICAgICAgICAgLy8gZmFsbHMgYmFjayB0byBsb2FkaW5nIGV2ZW50cyBzZXBhcmF0ZWx5LlxuICAgICAgICAgICAgaWYgKGN1cnJlbnRSdW4uc3RhdHVzID09PSAncnVubmluZycpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgcnVuOiBjdXJyZW50UnVuIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJ1biA9IHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGN1cnJlbnRSdW4ucnVuSWQsXG4gICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogY3VycmVudFJ1bi5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogY3VycmVudFJ1bi53b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBjdXJyZW50UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBjdXJyZW50UnVuLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgIGlucHV0OiBjdXJyZW50UnVuLmlucHV0LFxuICAgICAgICAgICAgICBjcmVhdGVkQXQ6IGN1cnJlbnRSdW4uY3JlYXRlZEF0LFxuICAgICAgICAgICAgICBleHBpcmVkQXQ6IGN1cnJlbnRSdW4uZXhwaXJlZEF0LFxuICAgICAgICAgICAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICAgICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbXBsZXRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIHN0YXJ0ZWRBdDogY3VycmVudFJ1bi5zdGFydGVkQXQgPz8gbm93LFxuICAgICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ3J1bnMnLCBlZmZlY3RpdmVSdW5JZCwgdGFnKSxcbiAgICAgICAgICAgICAgcnVuLFxuICAgICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3J1bl9jb21wbGV0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgICBjb25zdCBjb21wbGV0ZWREYXRhID0gZGF0YS5ldmVudERhdGEgYXMgeyBvdXRwdXQ/OiBhbnkgfTtcbiAgICAgICAgICAvLyBSZXVzZSBjdXJyZW50UnVuIGZyb20gdmFsaWRhdGlvbiAoYWxyZWFkeSByZWFkIGFib3ZlKVxuICAgICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgICBydW4gPSB7XG4gICAgICAgICAgICAgIHJ1bklkOiBjdXJyZW50UnVuLnJ1bklkLFxuICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICB3b3JrZmxvd05hbWU6IGN1cnJlbnRSdW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogY3VycmVudFJ1bi5zcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgICBpbnB1dDogY3VycmVudFJ1bi5pbnB1dCxcbiAgICAgICAgICAgICAgY3JlYXRlZEF0OiBjdXJyZW50UnVuLmNyZWF0ZWRBdCxcbiAgICAgICAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgICAgICAgc3RhcnRlZEF0OiBjdXJyZW50UnVuLnN0YXJ0ZWRBdCxcbiAgICAgICAgICAgICAgc3RhdHVzOiAnY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgb3V0cHV0OiBjb21wbGV0ZWREYXRhLm91dHB1dCxcbiAgICAgICAgICAgICAgZXJyb3I6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICAgIHJ1bixcbiAgICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgZGVsZXRlQWxsSG9va3NGb3JSdW4oYmFzZWRpciwgZWZmZWN0aXZlUnVuSWQpLFxuICAgICAgICAgICAgICBkZWxldGVBbGxXYWl0c0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fZmFpbGVkJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgICAgY29uc3QgZmFpbGVkRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICAgIGVycm9yOiBhbnk7XG4gICAgICAgICAgICBlcnJvckNvZGU/OiBzdHJpbmc7XG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBSZXVzZSBjdXJyZW50UnVuIGZyb20gdmFsaWRhdGlvbiAoYWxyZWFkeSByZWFkIGFib3ZlKVxuICAgICAgICAgIGlmIChjdXJyZW50UnVuKSB7XG4gICAgICAgICAgICBydW4gPSB7XG4gICAgICAgICAgICAgIHJ1bklkOiBjdXJyZW50UnVuLnJ1bklkLFxuICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICB3b3JrZmxvd05hbWU6IGN1cnJlbnRSdW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogY3VycmVudFJ1bi5zcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICAgICAgICBpbnB1dDogY3VycmVudFJ1bi5pbnB1dCxcbiAgICAgICAgICAgICAgY3JlYXRlZEF0OiBjdXJyZW50UnVuLmNyZWF0ZWRBdCxcbiAgICAgICAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgICAgICAgc3RhcnRlZEF0OiBjdXJyZW50UnVuLnN0YXJ0ZWRBdCxcbiAgICAgICAgICAgICAgc3RhdHVzOiAnZmFpbGVkJyxcbiAgICAgICAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAgICAgICAgIHR5cGVvZiBmYWlsZWREYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgICAgICA/IGZhaWxlZERhdGEuZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgOiAoZmFpbGVkRGF0YS5lcnJvcj8ubWVzc2FnZSA/PyAnVW5rbm93biBlcnJvcicpLFxuICAgICAgICAgICAgICAgIHN0YWNrOiBmYWlsZWREYXRhLmVycm9yPy5zdGFjayxcbiAgICAgICAgICAgICAgICBjb2RlOiBmYWlsZWREYXRhLmVycm9yQ29kZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICAgIHJ1bixcbiAgICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgZGVsZXRlQWxsSG9va3NGb3JSdW4oYmFzZWRpciwgZWZmZWN0aXZlUnVuSWQpLFxuICAgICAgICAgICAgICBkZWxldGVBbGxXYWl0c0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdydW5fY2FuY2VsbGVkJykge1xuICAgICAgICAgIC8vIFJldXNlIGN1cnJlbnRSdW4gZnJvbSB2YWxpZGF0aW9uIChhbHJlYWR5IHJlYWQgYWJvdmUpXG4gICAgICAgICAgaWYgKGN1cnJlbnRSdW4pIHtcbiAgICAgICAgICAgIHJ1biA9IHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGN1cnJlbnRSdW4ucnVuSWQsXG4gICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogY3VycmVudFJ1bi5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogY3VycmVudFJ1bi53b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBjdXJyZW50UnVuLnNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgICBleGVjdXRpb25Db250ZXh0OiBjdXJyZW50UnVuLmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgIGlucHV0OiBjdXJyZW50UnVuLmlucHV0LFxuICAgICAgICAgICAgICBjcmVhdGVkQXQ6IGN1cnJlbnRSdW4uY3JlYXRlZEF0LFxuICAgICAgICAgICAgICBleHBpcmVkQXQ6IGN1cnJlbnRSdW4uZXhwaXJlZEF0LFxuICAgICAgICAgICAgICBzdGFydGVkQXQ6IGN1cnJlbnRSdW4uc3RhcnRlZEF0LFxuICAgICAgICAgICAgICBzdGF0dXM6ICdjYW5jZWxsZWQnLFxuICAgICAgICAgICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgZXJyb3I6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdydW5zJywgZWZmZWN0aXZlUnVuSWQsIHRhZyksXG4gICAgICAgICAgICAgIHJ1bixcbiAgICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgZGVsZXRlQWxsSG9va3NGb3JSdW4oYmFzZWRpciwgZWZmZWN0aXZlUnVuSWQpLFxuICAgICAgICAgICAgICBkZWxldGVBbGxXYWl0c0ZvclJ1bihiYXNlZGlyLCBlZmZlY3RpdmVSdW5JZCksXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgLy8gU3RlcCBsaWZlY3ljbGUgZXZlbnRzXG4gICAgICAgICAgZGF0YS5ldmVudFR5cGUgPT09ICdzdGVwX2NyZWF0ZWQnICYmXG4gICAgICAgICAgJ2V2ZW50RGF0YScgaW4gZGF0YVxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBzdGVwX2NyZWF0ZWQ6IENyZWF0ZXMgc3RlcCBlbnRpdHkgd2l0aCBzdGF0dXMgJ3BlbmRpbmcnLCBhdHRlbXB0PTAsIGNyZWF0ZWRBdCBzZXRcbiAgICAgICAgICBjb25zdCBzdGVwRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICAgIHN0ZXBOYW1lOiBzdHJpbmc7XG4gICAgICAgICAgICBpbnB1dDogYW55O1xuICAgICAgICAgIH07XG4gICAgICAgICAgc3RlcCA9IHtcbiAgICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgIHN0ZXBJZDogZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgc3RlcE5hbWU6IHN0ZXBEYXRhLnN0ZXBOYW1lLFxuICAgICAgICAgICAgc3RhdHVzOiAncGVuZGluZycsXG4gICAgICAgICAgICBpbnB1dDogc3RlcERhdGEuaW5wdXQsXG4gICAgICAgICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBhdHRlbXB0OiAwLFxuICAgICAgICAgICAgc3RhcnRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjb21wbGV0ZWRBdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIC8vIFByb3BhZ2F0ZSBzcGVjVmVyc2lvbiBmcm9tIHRoZSBldmVudCB0byB0aGUgc3RlcCBlbnRpdHlcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNvbnN0IHN0ZXBDb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9YDtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICBzdGVwXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ3N0ZXBfc3RhcnRlZCcpIHtcbiAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQ6IEluY3JlbWVudHMgYXR0ZW1wdCwgc2V0cyBzdGF0dXMgdG8gJ3J1bm5pbmcnXG4gICAgICAgICAgLy8gU2V0cyBzdGFydGVkQXQgb25seSBvbiB0aGUgZmlyc3Qgc3RhcnQgKG5vdCB1cGRhdGVkIG9uIHJldHJpZXMpXG4gICAgICAgICAgLy8gUmV1c2UgdmFsaWRhdGVkU3RlcCBmcm9tIHZhbGlkYXRpb24gKGFscmVhZHkgcmVhZCBhYm92ZSlcbiAgICAgICAgICBpZiAodmFsaWRhdGVkU3RlcCkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgcmV0cnlBZnRlciB0aW1lc3RhbXAgaGFzbid0IGJlZW4gcmVhY2hlZCB5ZXRcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgdmFsaWRhdGVkU3RlcC5yZXRyeUFmdGVyICYmXG4gICAgICAgICAgICAgIHZhbGlkYXRlZFN0ZXAucmV0cnlBZnRlci5nZXRUaW1lKCkgPiBEYXRlLm5vdygpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFRvb0Vhcmx5RXJyb3IoXG4gICAgICAgICAgICAgICAgYENhbm5vdCBzdGFydCBzdGVwIFwiJHtkYXRhLmNvcnJlbGF0aW9uSWR9XCI6IHJldHJ5QWZ0ZXIgdGltZXN0YW1wIGhhcyBub3QgYmVlbiByZWFjaGVkIHlldGAsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlcjogTWF0aC5jZWlsKFxuICAgICAgICAgICAgICAgICAgICAodmFsaWRhdGVkU3RlcC5yZXRyeUFmdGVyLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMFxuICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IGd1YXJkOiByZS1yZWFkIHRoZSBzdGVwIGVudGl0eSB0byBjaGVjayBpZiBpdFxuICAgICAgICAgICAgLy8gcmVhY2hlZCB0ZXJtaW5hbCBzdGF0ZSBiZXR3ZWVuIHRoZSB2YWxpZGF0aW9uIHJlYWQgYW5kIG5vdy5cbiAgICAgICAgICAgIC8vIFRoaXMgbmFycm93cyB0aGUgVE9DVE9VIHdpbmRvdyBidXQgZG9lcyBub3QgZnVsbHkgZWxpbWluYXRlIGl0XG4gICAgICAgICAgICAvLyAodGhlIGxvY2FsIHdvcmxkIGlzIHNpbmdsZS1wcm9jZXNzIC8gZGV2LW9ubHk7IHRoZSBwb3N0Z3Jlc1xuICAgICAgICAgICAgLy8gd29ybGQgdXNlcyBTUUwtbGV2ZWwgYXRvbWljIGd1YXJkcyBmb3IgcHJvZHVjdGlvbikuXG4gICAgICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgICBjb25zdCBmcmVzaFN0ZXAgPSBhd2FpdCByZWFkSlNPTldpdGhGYWxsYmFjayhcbiAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgJ3N0ZXBzJyxcbiAgICAgICAgICAgICAgc3RlcENvbXBvc2l0ZUtleSxcbiAgICAgICAgICAgICAgU3RlcFNjaGVtYSxcbiAgICAgICAgICAgICAgdGFnXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGZyZXNoU3RlcCAmJiBpc1Rlcm1pbmFsU3RlcFN0YXR1cyhmcmVzaFN0ZXAuc3RhdHVzKSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgICBgQ2Fubm90IG1vZGlmeSBzdGVwIGluIHRlcm1pbmFsIHN0YXRlIFwiJHtmcmVzaFN0ZXAuc3RhdHVzfVwiYFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdGVwID0ge1xuICAgICAgICAgICAgICAuLi52YWxpZGF0ZWRTdGVwLFxuICAgICAgICAgICAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICAgICAgICAgICAgLy8gT25seSBzZXQgc3RhcnRlZEF0IG9uIHRoZSBmaXJzdCBzdGFydFxuICAgICAgICAgICAgICBzdGFydGVkQXQ6IHZhbGlkYXRlZFN0ZXAuc3RhcnRlZEF0ID8/IG5vdyxcbiAgICAgICAgICAgICAgLy8gSW5jcmVtZW50IGF0dGVtcHQgY291bnRlciBvbiBldmVyeSBzdGFydFxuICAgICAgICAgICAgICBhdHRlbXB0OiB2YWxpZGF0ZWRTdGVwLmF0dGVtcHQgKyAxLFxuICAgICAgICAgICAgICAvLyBDbGVhciByZXRyeUFmdGVyIG5vdyB0aGF0IHRoZSBzdGVwIGhhcyBzdGFydGVkXG4gICAgICAgICAgICAgIHJldHJ5QWZ0ZXI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICAgIHN0ZXAsXG4gICAgICAgICAgICAgIHsgb3ZlcndyaXRlOiB0cnVlIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAnc3RlcF9jb21wbGV0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgICAvLyBzdGVwX2NvbXBsZXRlZDogVGVybWluYWwgc3RhdGUgd2l0aCBvdXRwdXRcbiAgICAgICAgICAvLyBVc2VzIHdyaXRlRXhjbHVzaXZlIG9uIGEgbG9jayBmaWxlIHRvIGF0b21pY2FsbHkgcHJldmVudCBjb25jdXJyZW50XG4gICAgICAgICAgLy8gaW52b2NhdGlvbnMgZnJvbSBib3RoIGNvbXBsZXRpbmcgdGhlIHNhbWUgc3RlcCAoVE9DVE9VIHJhY2UpLlxuICAgICAgICAgIGNvbnN0IGNvbXBsZXRlZERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7IHJlc3VsdDogYW55IH07XG4gICAgICAgICAgaWYgKHZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICAgIGNvbnN0IHN0ZXBDb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9YDtcbiAgICAgICAgICAgIGNvbnN0IGxvY2tOYW1lID0gdGFnXG4gICAgICAgICAgICAgID8gYCR7c3RlcENvbXBvc2l0ZUtleX0udGVybWluYWwuJHt0YWd9YFxuICAgICAgICAgICAgICA6IGAke3N0ZXBDb21wb3NpdGVLZXl9LnRlcm1pbmFsYDtcbiAgICAgICAgICAgIGNvbnN0IHRlcm1pbmFsTG9ja1BhdGggPSByZXNvbHZlV2l0aGluQmFzZShcbiAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgJy5sb2NrcycsXG4gICAgICAgICAgICAgICdzdGVwcycsXG4gICAgICAgICAgICAgIGxvY2tOYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgY2xhaW1lZCA9IGF3YWl0IHdyaXRlRXhjbHVzaXZlKHRlcm1pbmFsTG9ja1BhdGgsICcnKTtcbiAgICAgICAgICAgIGlmICghY2xhaW1lZCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgICAnQ2Fubm90IG1vZGlmeSBzdGVwIGluIHRlcm1pbmFsIHN0YXRlJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RlcCA9IHtcbiAgICAgICAgICAgICAgLi4udmFsaWRhdGVkU3RlcCxcbiAgICAgICAgICAgICAgc3RhdHVzOiAnY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgb3V0cHV0OiBjb21wbGV0ZWREYXRhLnJlc3VsdCxcbiAgICAgICAgICAgICAgY29tcGxldGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICAgIHN0ZXAsXG4gICAgICAgICAgICAgIHsgb3ZlcndyaXRlOiB0cnVlIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAnc3RlcF9mYWlsZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgICAvLyBzdGVwX2ZhaWxlZDogVGVybWluYWwgc3RhdGUgd2l0aCBlcnJvclxuICAgICAgICAgIC8vIFVzZXMgd3JpdGVFeGNsdXNpdmUgb24gYSBsb2NrIGZpbGUgdG8gYXRvbWljYWxseSBwcmV2ZW50IGNvbmN1cnJlbnRcbiAgICAgICAgICAvLyBpbnZvY2F0aW9ucyBmcm9tIGJvdGggZmFpbGluZyB0aGUgc2FtZSBzdGVwIChUT0NUT1UgcmFjZSkuXG4gICAgICAgICAgY29uc3QgZmFpbGVkRGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICAgIGVycm9yOiBhbnk7XG4gICAgICAgICAgICBzdGFjaz86IHN0cmluZztcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmICh2YWxpZGF0ZWRTdGVwKSB7XG4gICAgICAgICAgICBjb25zdCBzdGVwQ29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgICBjb25zdCBsb2NrTmFtZSA9IHRhZ1xuICAgICAgICAgICAgICA/IGAke3N0ZXBDb21wb3NpdGVLZXl9LnRlcm1pbmFsLiR7dGFnfWBcbiAgICAgICAgICAgICAgOiBgJHtzdGVwQ29tcG9zaXRlS2V5fS50ZXJtaW5hbGA7XG4gICAgICAgICAgICBjb25zdCB0ZXJtaW5hbExvY2tQYXRoID0gcmVzb2x2ZVdpdGhpbkJhc2UoXG4gICAgICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgICAgICcubG9ja3MnLFxuICAgICAgICAgICAgICAnc3RlcHMnLFxuICAgICAgICAgICAgICBsb2NrTmFtZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGNsYWltZWQgPSBhd2FpdCB3cml0ZUV4Y2x1c2l2ZSh0ZXJtaW5hbExvY2tQYXRoLCAnJyk7XG4gICAgICAgICAgICBpZiAoIWNsYWltZWQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgICAgJ0Nhbm5vdCBtb2RpZnkgc3RlcCBpbiB0ZXJtaW5hbCBzdGF0ZSdcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0ge1xuICAgICAgICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICAgICAgIHR5cGVvZiBmYWlsZWREYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgICAgPyBmYWlsZWREYXRhLmVycm9yXG4gICAgICAgICAgICAgICAgICA6IChmYWlsZWREYXRhLmVycm9yPy5tZXNzYWdlID8/ICdVbmtub3duIGVycm9yJyksXG4gICAgICAgICAgICAgIHN0YWNrOiBmYWlsZWREYXRhLnN0YWNrLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHN0ZXAgPSB7XG4gICAgICAgICAgICAgIC4uLnZhbGlkYXRlZFN0ZXAsXG4gICAgICAgICAgICAgIHN0YXR1czogJ2ZhaWxlZCcsXG4gICAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgICBjb21wbGV0ZWRBdDogbm93LFxuICAgICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ3N0ZXBzJywgc3RlcENvbXBvc2l0ZUtleSwgdGFnKSxcbiAgICAgICAgICAgICAgc3RlcCxcbiAgICAgICAgICAgICAgeyBvdmVyd3JpdGU6IHRydWUgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICdzdGVwX3JldHJ5aW5nJyAmJiAnZXZlbnREYXRhJyBpbiBkYXRhKSB7XG4gICAgICAgICAgLy8gc3RlcF9yZXRyeWluZzogU2V0cyBzdGF0dXMgYmFjayB0byAncGVuZGluZycsIHJlY29yZHMgZXJyb3JcbiAgICAgICAgICAvLyBSZXVzZSB2YWxpZGF0ZWRTdGVwIGZyb20gdmFsaWRhdGlvbiAoYWxyZWFkeSByZWFkIGFib3ZlKVxuICAgICAgICAgIGNvbnN0IHJldHJ5RGF0YSA9IGRhdGEuZXZlbnREYXRhIGFzIHtcbiAgICAgICAgICAgIGVycm9yOiBhbnk7XG4gICAgICAgICAgICBzdGFjaz86IHN0cmluZztcbiAgICAgICAgICAgIHJldHJ5QWZ0ZXI/OiBEYXRlO1xuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKHZhbGlkYXRlZFN0ZXApIHtcbiAgICAgICAgICAgIGNvbnN0IHN0ZXBDb21wb3NpdGVLZXkgPSBgJHtlZmZlY3RpdmVSdW5JZH0tJHtkYXRhLmNvcnJlbGF0aW9uSWR9YDtcbiAgICAgICAgICAgIHN0ZXAgPSB7XG4gICAgICAgICAgICAgIC4uLnZhbGlkYXRlZFN0ZXAsXG4gICAgICAgICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgICAgICAgICB0eXBlb2YgcmV0cnlEYXRhLmVycm9yID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgICAgICA/IHJldHJ5RGF0YS5lcnJvclxuICAgICAgICAgICAgICAgICAgICA6IChyZXRyeURhdGEuZXJyb3I/Lm1lc3NhZ2UgPz8gJ1Vua25vd24gZXJyb3InKSxcbiAgICAgICAgICAgICAgICBzdGFjazogcmV0cnlEYXRhLnN0YWNrLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICByZXRyeUFmdGVyOiByZXRyeURhdGEucmV0cnlBZnRlcixcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdzdGVwcycsIHN0ZXBDb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgICAgIHN0ZXAsXG4gICAgICAgICAgICAgIHsgb3ZlcndyaXRlOiB0cnVlIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIC8vIEhvb2sgbGlmZWN5Y2xlIGV2ZW50c1xuICAgICAgICAgIGRhdGEuZXZlbnRUeXBlID09PSAnaG9va19jcmVhdGVkJyAmJlxuICAgICAgICAgICdldmVudERhdGEnIGluIGRhdGFcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgaG9va0RhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgICB0b2tlbjogc3RyaW5nO1xuICAgICAgICAgICAgbWV0YWRhdGE/OiBhbnk7XG4gICAgICAgICAgICBpc1dlYmhvb2s/OiBib29sZWFuO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICAvLyBBdG9taWNhbGx5IGNsYWltIHRoZSB0b2tlbiB1c2luZyBhbiBleGNsdXNpdmUtY3JlYXRlIGNvbnN0cmFpbnQgZmlsZS5cbiAgICAgICAgICAvLyBUaGlzIGF2b2lkcyB0aGUgVE9DVE9VIHJhY2Ugb2YgdGhlIHByZXZpb3VzIHJlYWQtYWxsLXRoZW4tY2hlY2sgYXBwcm9hY2guXG4gICAgICAgICAgY29uc3QgY29uc3RyYWludFBhdGggPSBwYXRoLmpvaW4oXG4gICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgJ2hvb2tzJyxcbiAgICAgICAgICAgICd0b2tlbnMnLFxuICAgICAgICAgICAgYCR7aGFzaFRva2VuKGhvb2tEYXRhLnRva2VuKX0uanNvbmBcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIFdoZW4gdGhlIGNsYWltIGlzIGFic2VudCwgdGhlIGV2ZW50IGxvZyBpcyB0aGUgb25seSBkdXJhYmxlIHNvdXJjZVxuICAgICAgICAgIC8vIHRoYXQgY2FuIGRpc3Rpbmd1aXNoIGEgZmlyc3QgaG9vayBmcm9tIGEgY3Jhc2gtbG9zdCB0b2tlbiBjYWNoZS5cbiAgICAgICAgICBpZiAoIShhd2FpdCByZWFkSG9va1Rva2VuQ2xhaW0oY29uc3RyYWludFBhdGgpKSkge1xuICAgICAgICAgICAgYXdhaXQgcmVidWlsZExpdmVIb29rQnlUb2tlbkZyb21FdmVudExvZyhcbiAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgaG9va0RhdGEudG9rZW4sXG4gICAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gUGVyc2lzdCBgZXZlbnRJZGAgaW4gdGhlIGNsYWltIHNvIGNvbmN1cnJlbnQgLyBjcm9zcy1cbiAgICAgICAgICAvLyBwcm9jZXNzIHJldHJpZXMgY2FuIGNvbnZlcmdlIG9uIGEgc2luZ2xlIGNhbm9uaWNhbFxuICAgICAgICAgIC8vIGBob29rX2NyZWF0ZWRgIGV2ZW50IHBhdGguIFNlZSB0aGUgcmVjb3ZlcnkgY29tbWVudFxuICAgICAgICAgIC8vIGJlbG93LlxuICAgICAgICAgIGNvbnN0IHRva2VuQ2xhaW1lZCA9IGF3YWl0IHdyaXRlRXhjbHVzaXZlKFxuICAgICAgICAgICAgY29uc3RyYWludFBhdGgsXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHRva2VuOiBob29rRGF0YS50b2tlbixcbiAgICAgICAgICAgICAgaG9va0lkOiBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIFJlY292ZXJ5IHNoYXBlOiB0aGUgZHVyYWJsZSByZWNvcmQgb2YgYSBzdWNjZXNzZnVsIGhvb2tcbiAgICAgICAgICAvLyBjcmVhdGlvbiBpcyB0aGUgYGhvb2tfY3JlYXRlZGAgZXZlbnQgaW4gdGhlIGV2ZW50IGxvZy4gVGhlXG4gICAgICAgICAgLy8gY2xhaW0gZmlsZSBhbmQgaG9vayBlbnRpdHkgYXJlIHdyaXR0ZW4gYmVmb3JlIHRoZSBldmVudCxcbiAgICAgICAgICAvLyBhbmQgdGhlIHRocmVlIHdyaXRlcyBhcmUgTk9UIGF0b21pYywgc28gYSBjcmFzaCBhdCBhbnlcbiAgICAgICAgICAvLyBwb2ludCBjYW4gbGVhdmUgb25lIG9yIHR3byBvZiB0aGVtIG9uIGRpc2sgd2l0aG91dCB0aGVcbiAgICAgICAgICAvLyBldmVudC4gVHJlYXRpbmcgdGhvc2UgYXMgXCJjb21wbGV0ZWRcIiB3b3VsZCBoYXZlIHRoZVxuICAgICAgICAgIC8vIHN1c3BlbnNpb24gaGFuZGxlciBzd2FsbG93IHRoZSByZXRyeSBhbmQgcGVybWFuZW50bHkgbG9zZVxuICAgICAgICAgIC8vIHRoZSBgaG9va19jcmVhdGVkYCBldmVudCBmcm9tIHRoZSBsb2cuXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyBXaGVuIHRoZSBkZWR1cCBicmFuY2ggZmlyZXMgZm9yIHRoZSBzYW1lIGAocnVuSWQsIGhvb2tJZClgLFxuICAgICAgICAgIC8vIHdlIGNvbnZlcmdlIG9uIHRoZSBjYW5vbmljYWwgYGV2ZW50SWRgIHBlcnNpc3RlZCBpbiB0aGVcbiAgICAgICAgICAvLyBjbGFpbSBmaWxlIGJ5IHRoZSBvcmlnaW5hbCAod2lubmluZykgYHdyaXRlRXhjbHVzaXZlYC4gQnlcbiAgICAgICAgICAvLyBhZG9wdGluZyB0aGF0IGV2ZW50SWQgZm9yIHRoaXMgcmV0cnkncyBldmVudCB3cml0ZSDigJQgYW5kXG4gICAgICAgICAgLy8gbGV0dGluZyB0aGUgb3V0ZXIgbm8tb3ZlcndyaXRlIGB3cml0ZUpTT05gIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAvLyB0aHJvdyBgRW50aXR5Q29uZmxpY3RFcnJvcmAgb24gY29sbGlzaW9uIOKAlCBjb25jdXJyZW50IC9cbiAgICAgICAgICAvLyBjcm9zcy1wcm9jZXNzIHdvcmtlcnMgZWl0aGVyOlxuICAgICAgICAgIC8vICAgLSBwdWJsaXNoIHRoZSBzYW1lIGV2ZW50IGF0IHRoZSBzYW1lIHBhdGggZXhhY3RseSBvbmNlXG4gICAgICAgICAgLy8gICAgICh0aGUgbG9zZXIncyBgd3JpdGVKU09OYCB0aHJvd3MgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgICAgICAgICAvLyAgICAgd2hpY2ggdGhlIHJ1bnRpbWUncyBleGlzdGluZyBjb25jdXJyZW50LXJlcGxheSBjYXRjaFxuICAgICAgICAgIC8vICAgICBwYXRoIGF0IHN1c3BlbnNpb24taGFuZGxlci50czoxNDIgc3dhbGxvd3MpLCBvclxuICAgICAgICAgIC8vICAgLSBjb252ZXJnZSBvbiBhIHNpbmdsZSByZWNvdmVyeSB3cml0ZSB3aGVuIHRoZSBwcmlvclxuICAgICAgICAgIC8vICAgICBjbGFpbSB3YXMgb3JwaGFuZWQgYnkgYSBjcmFzaCBiZWZvcmUgdGhlIGV2ZW50IGxhbmRlZC5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIFRoZSBsZWdhY3kgZmFsbGJhY2sgKGBleGlzdGluZ0NsYWltLmV2ZW50SWRgIHVuZGVmaW5lZClcbiAgICAgICAgICAvLyBpcyBmb3IgY2xhaW0gZmlsZXMgd3JpdHRlbiBiZWZvcmUgdGhpcyBmaWVsZCB3YXMgYWRkZWQg4oCUXG4gICAgICAgICAgLy8gdGhvc2UgcHJvYmUgdGhlIGV2ZW50IGxvZyBkaXJlY3RseSBhbmQgZmFsbCB0aHJvdWdoIHRvIGFcbiAgICAgICAgICAvLyBmcmVzaC1ldmVudElkIHJlY292ZXJ5IHdyaXRlLiBUaGUgbGVnYWN5IHBhdGggZG9lcyBub3RcbiAgICAgICAgICAvLyBjb252ZXJnZSBhY3Jvc3Mgd29ya2VycyBidXQgY2Fubm90IHJlZ3Jlc3MgYmVoYXZpb3IgZm9yXG4gICAgICAgICAgLy8gZnJlc2hseS13cml0dGVuIGNsYWltcy5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIFRoZSBgd2l0aEhvb2tMb2NrYCBpbi1wcm9jZXNzIG11dGV4IGFib3ZlIGtlZXBzIHR3byBzYW1lLVxuICAgICAgICAgIC8vIHRpY2sgaW4tcHJvY2VzcyBjYWxsZXJzIGZyb20gcmFjaW5nIGludG8gdGhpcyBicmFuY2ggd2l0aFxuICAgICAgICAgIC8vIHRoZSB3aW5uZXIgbWlkLXdyaXRlLCBidXQgaXMgbm90IHN1ZmZpY2llbnQgYWNyb3NzXG4gICAgICAgICAgLy8gcHJvY2Vzc2VzIOKAlCB0aGUgZHVyYWJsZSBjb252ZXJnZW5jZSBrZXkgKGBjbGFpbS5ldmVudElkYClcbiAgICAgICAgICAvLyBpcyB3aGF0IGNsb3NlcyB0aGUgY3Jvc3MtcHJvY2VzcyByYWNlLlxuICAgICAgICAgIGxldCB3cml0ZUhvb2tFbnRpdHlXaXRoT3ZlcndyaXRlID0gZmFsc2U7XG5cbiAgICAgICAgICBpZiAoIXRva2VuQ2xhaW1lZCkge1xuICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdDbGFpbSA9IGF3YWl0IHJlYWRIb29rVG9rZW5DbGFpbShjb25zdHJhaW50UGF0aCk7XG5cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgZXhpc3RpbmdDbGFpbT8ucnVuSWQgPT09IGVmZmVjdGl2ZVJ1bklkICYmXG4gICAgICAgICAgICAgIGV4aXN0aW5nQ2xhaW0uaG9va0lkID09PSBkYXRhLmNvcnJlbGF0aW9uSWRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAvLyBBZG9wdCBhIGNhbm9uaWNhbCBldmVudElkIGZvciB0aGUgcmVjb3Zlcnkgd3JpdGUuIFRoZVxuICAgICAgICAgICAgICAvLyBvdXRlciBldmVudCBwdWJsaXNoIChgd3JpdGVFeGNsdXNpdmUoZXZlbnRQYXRoKWApXG4gICAgICAgICAgICAgIC8vIGVpdGhlciBzdWNjZWVkcyAod2UgcHVibGlzaCB0aGUgY2Fub25pY2FsIGV2ZW50LFxuICAgICAgICAgICAgICAvLyByZXBhaXJpbmcgYSBwYXJ0aWFsIHdyaXRlIGxlZnQgYnkgdGhlIG9yaWdpbmFsXG4gICAgICAgICAgICAgIC8vIGNsYWltYW50KSBvciByZXR1cm5zIGBmYWxzZWAgYW5kIHdlIHRocm93XG4gICAgICAgICAgICAgIC8vIGBFbnRpdHlDb25mbGljdEVycm9yYCAodGhlIGV2ZW50IHdhcyBhbHJlYWR5XG4gICAgICAgICAgICAgIC8vIHB1Ymxpc2hlZCDigJQgYSByZWFsIGR1cGxpY2F0ZSkuIEVpdGhlciB3YXkgdGhlIGxvZ1xuICAgICAgICAgICAgICAvLyBlbmRzIHdpdGggZXhhY3RseSBvbmUgYGhvb2tfY3JlYXRlZGAgZXZlbnQgZm9yIHRoaXNcbiAgICAgICAgICAgICAgLy8gYChydW5JZCwgaG9va0lkKWAuXG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIC8vIFRoZSBjYW5vbmljYWwgZXZlbnRJZCBjb21lcyBmcm9tIG9uZSBvZiB0d28gcGxhY2VzOlxuICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAvLyAgIC0gYGV4aXN0aW5nQ2xhaW0uZXZlbnRJZGAgZm9yIGNsYWltcyB3cml0dGVuIGJ5XG4gICAgICAgICAgICAgIC8vICAgICB0aGlzIHZlcnNpb24gKHRoZSB3cml0ZXIgYWJvdmUgcGVyc2lzdHMgdGhlXG4gICAgICAgICAgICAgIC8vICAgICBjYW5kaWRhdGUgZXZlbnRJZCBhdG9taWNhbGx5IHdpdGggdGhlIGNsYWltKS5cbiAgICAgICAgICAgICAgLy8gICAgIFRoZSBldmVudElkIGlzIGR1cmFibGUsIHNvIHRoZSBvdXRlclxuICAgICAgICAgICAgICAvLyAgICAgYHdyaXRlRXhjbHVzaXZlKGV2ZW50UGF0aClgIGFsb25lIGlzIGVub3VnaCB0b1xuICAgICAgICAgICAgICAvLyAgICAgYXJiaXRyYXRlIHB1YmxpY2F0aW9uOiBpdCBmYWlscyBpZmYgdGhlIGV2ZW50XG4gICAgICAgICAgICAgIC8vICAgICB3YXMgYWxyZWFkeSBwdWJsaXNoZWQgYXQgdGhhdCBleGFjdCBwYXRoLlxuICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAvLyAgIC0gVGhlIHJlY292ZXJ5LW1hcmtlciBzaWRlY2FyIGZvciBsZWdhY3kgY2xhaW1zXG4gICAgICAgICAgICAgIC8vICAgICB3cml0dGVuIGJlZm9yZSBgZXZlbnRJZGAgd2FzIHBlcnNpc3RlZCBpbmxpbmVcbiAgICAgICAgICAgICAgLy8gICAgIGluIHRoZSBjbGFpbS4gVGhlIG1hcmtlciBpcyBpdHNlbGYgYVxuICAgICAgICAgICAgICAvLyAgICAgYHdyaXRlRXhjbHVzaXZlYCwgc28gdGhlIGZpcnN0IHJldHJ5IHBpbnMgaXRzXG4gICAgICAgICAgICAgIC8vICAgICBjYW5kaWRhdGUgZXZlbnRJZCBhcyBjYW5vbmljYWwgYW5kIHN1YnNlcXVlbnRcbiAgICAgICAgICAgICAgLy8gICAgIHJldHJpZXMgYWRvcHQgaXQuIFdpdGhvdXQgdGhpcywgdHdvIHByb2Nlc3Nlc1xuICAgICAgICAgICAgICAvLyAgICAgYm90aCByZWFkaW5nIHRoZSBzYW1lIGxlZ2FjeSBjbGFpbSB3b3VsZCBlYWNoXG4gICAgICAgICAgICAgIC8vICAgICBnZW5lcmF0ZSB0aGVpciBvd24gZXZlbnRJZCwgbGFuZCB0aGVpclxuICAgICAgICAgICAgICAvLyAgICAgYHdyaXRlRXhjbHVzaXZlKGV2ZW50UGF0aClgIGNhbGxzIGF0IGRpZmZlcmVudFxuICAgICAgICAgICAgICAvLyAgICAgcGF0aHMsIGFuZCBhcHBlbmQgdHdvIGV2ZW50cy5cbiAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgLy8gICAgIEZvciBsZWdhY3kgY2xhaW1zIHdlIGFsc28gbXVzdCBwcm9iZSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgLy8gICAgIGxvZyBmb3IgYW4gZXhpc3RpbmcgYGhvb2tfY3JlYXRlZGAgZXZlbnQgQkVGT1JFXG4gICAgICAgICAgICAgIC8vICAgICBwaW5uaW5nIGEgY2Fub25pY2FsIGV2ZW50SWQ6IHRoZSBwcmUtdXBncmFkZVxuICAgICAgICAgICAgICAvLyAgICAgd3JpdGVyIG1heSBoYXZlIGFscmVhZHkgcHVibGlzaGVkIHRoZSBldmVudFxuICAgICAgICAgICAgICAvLyAgICAgd2l0aCBpdHMgb3duIGV2ZW50SWQsIGFuZCB0aGUgbWFya2VyIGhhcyBubyB3YXlcbiAgICAgICAgICAgICAgLy8gICAgIG9mIGtub3dpbmcgdGhhdCBldmVudElkIGFmdGVyIHRoZSBmYWN0LiBXaXRob3V0XG4gICAgICAgICAgICAgIC8vICAgICB0aGlzIHByb2JlLCBhIHBvc3QtdXBncmFkZSByZXRyeSB3b3VsZCBwaW4gYVxuICAgICAgICAgICAgICAvLyAgICAgZGlmZmVyZW50IGV2ZW50SWQsIHdyaXRlIGEgaG9vayBlbnRpdHksIGFuZFxuICAgICAgICAgICAgICAvLyAgICAgcHVibGlzaCBhIGR1cGxpY2F0ZSBldmVudCBhdCB0aGUgbWFya2VyJ3MgcGF0aC5cbiAgICAgICAgICAgICAgbGV0IGNhbm9uaWNhbEV2ZW50SWQ6IHN0cmluZztcbiAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nQ2xhaW0uZXZlbnRJZCkge1xuICAgICAgICAgICAgICAgIGNhbm9uaWNhbEV2ZW50SWQgPSBleGlzdGluZ0NsYWltLmV2ZW50SWQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYWxyZWFkeVB1Ymxpc2hlZEV2ZW50SWQgPVxuICAgICAgICAgICAgICAgICAgYXdhaXQgZmluZEV4aXN0aW5nSG9va0NyZWF0ZWRFdmVudElkKFxuICAgICAgICAgICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgICAgICAgICBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmIChhbHJlYWR5UHVibGlzaGVkRXZlbnRJZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgLy8gVGhlIHByZS11cGdyYWRlIHdyaXRlciBtYXkgaGF2ZSBjcmFzaGVkIGJldHdlZW5cbiAgICAgICAgICAgICAgICAgIC8vIGl0cyBldmVudCBwdWJsaXNoIGFuZCBpdHMgaG9vayBlbnRpdHkgd3JpdGUg4oCUXG4gICAgICAgICAgICAgICAgICAvLyByZXBhaXIgdGhlIGVudGl0eSBmcm9tIHRoZSBwZXJzaXN0ZWQgZXZlbnQnc1xuICAgICAgICAgICAgICAgICAgLy8gcGF5bG9hZCBiZWZvcmUgc3VyZmFjaW5nIHRoZSBiZW5pZ24gZHVwbGljYXRlLlxuICAgICAgICAgICAgICAgICAgYXdhaXQgcmVwYWlySG9va0VudGl0eUZyb21QZXJzaXN0ZWRFdmVudChcbiAgICAgICAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgICAgICAgZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgYWxyZWFkeVB1Ymxpc2hlZEV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgSG9vayBcIiR7ZGF0YS5jb3JyZWxhdGlvbklkfVwiIGFscmVhZHkgY3JlYXRlZGBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHBpbm5lZCA9IGF3YWl0IHBpbkNhbm9uaWNhbEV2ZW50SWRGb3JMZWdhY3lDbGFpbShcbiAgICAgICAgICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgICAgICAgICBob29rRGF0YS50b2tlbixcbiAgICAgICAgICAgICAgICAgIGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICAgICAgZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgZXZlbnRJZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKHBpbm5lZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgLy8gTG9zdCB0aGUgbWFya2VyIHJhY2UgYW5kIHRoZSBtYXJrZXIgZmlsZSBpc1xuICAgICAgICAgICAgICAgICAgLy8gdW5yZWFkYWJsZSAoZXh0cmVtZWx5IHJhcmU7IGNvcnJ1cHRlZCBkaXNrKS5cbiAgICAgICAgICAgICAgICAgIC8vIFRyZWF0IGFzIGEgcmVhbCBkdXBsaWNhdGUgc28gdGhlIHJ1bnRpbWUnc1xuICAgICAgICAgICAgICAgICAgLy8gY29uY3VycmVudC1yZXBsYXkgY2F0Y2ggcGF0aCBzd2FsbG93cyB0aGlzXG4gICAgICAgICAgICAgICAgICAvLyBhdHRlbXB0IGluc3RlYWQgb2Ygcmlza2luZyBkaXZlcmdlbnRcbiAgICAgICAgICAgICAgICAgIC8vIHB1YmxpY2F0aW9uLlxuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGBIb29rIFwiJHtkYXRhLmNvcnJlbGF0aW9uSWR9XCIgYWxyZWFkeSBjcmVhdGVkYFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2Fub25pY2FsRXZlbnRJZCA9IHBpbm5lZDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIFJlYnVpbGQgYGV2ZW50YCB3aXRoIHRoZSBjYW5vbmljYWwgZXZlbnRJZCBhbmQgYVxuICAgICAgICAgICAgICAvLyBkZXRlcm1pbmlzdGljIGBjcmVhdGVkQXRgIGRlcml2ZWQgZnJvbSB0aGUgZXZlbnRJZFxuICAgICAgICAgICAgICAvLyAoYSBVTElEKSBzbyB0d28gd29ya2VycyB3cml0aW5nIHRoZSBzYW1lIGV2ZW50XG4gICAgICAgICAgICAgIC8vIHByb2R1Y2UgYnl0ZS1pZGVudGljYWwgY29udGVudC5cbiAgICAgICAgICAgICAgZXZlbnRJZCA9IGNhbm9uaWNhbEV2ZW50SWQ7XG4gICAgICAgICAgICAgIGNvbnN0IGNhbm9uaWNhbENyZWF0ZWRBdCA9XG4gICAgICAgICAgICAgICAgdWxpZFRvRGF0ZShldmVudElkLnJlcGxhY2UoL15ldm50Xy8sICcnKSkgPz8gbm93O1xuICAgICAgICAgICAgICBldmVudCA9IHtcbiAgICAgICAgICAgICAgICAuLi5kYXRhLFxuICAgICAgICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogY2Fub25pY2FsQ3JlYXRlZEF0LFxuICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBlZmZlY3RpdmVTcGVjVmVyc2lvbixcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgd3JpdGVIb29rRW50aXR5V2l0aE92ZXJ3cml0ZSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBDcm9zcy1ob29rIC8gY3Jvc3MtcnVuIGNvbmZsaWN0OiBhIGRpZmZlcmVudFxuICAgICAgICAgICAgICAvLyAocnVuSWQsIGhvb2tJZCkgaG9sZHMgdGhpcyB0b2tlbi4gQ3JlYXRlIGFcbiAgICAgICAgICAgICAgLy8gaG9va19jb25mbGljdCBldmVudCBzbyB0aGUgd29ya2Zsb3cgY2FuIGZhaWxcbiAgICAgICAgICAgICAgLy8gZ3JhY2VmdWxseSB3aGVuIHRoZSBob29rIGlzIGF3YWl0ZWQuXG4gICAgICAgICAgICAgIGNvbnN0IGNvbmZsaWN0RXZlbnQ6IEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY29uZmxpY3QnLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGRhdGEuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgIHRva2VuOiBob29rRGF0YS50b2tlbixcbiAgICAgICAgICAgICAgICAgIC4uLihleGlzdGluZ0NsYWltXG4gICAgICAgICAgICAgICAgICAgID8geyBjb25mbGljdGluZ1J1bklkOiBleGlzdGluZ0NsYWltLnJ1bklkIH1cbiAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogZWZmZWN0aXZlU3BlY1ZlcnNpb24sXG4gICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgY29uc3QgY29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZXZlbnRJZH1gO1xuICAgICAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnZXZlbnRzJywgY29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgICAgIGNvbmZsaWN0RXZlbnRcbiAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICBjb25zdCByZXNvbHZlRGF0YSA9XG4gICAgICAgICAgICAgICAgcGFyYW1zPy5yZXNvbHZlRGF0YSA/PyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG4gICAgICAgICAgICAgIGNvbnN0IGZpbHRlcmVkRXZlbnQgPSBzdHJpcEV2ZW50RGF0YVJlZnMoXG4gICAgICAgICAgICAgICAgY29uZmxpY3RFdmVudCxcbiAgICAgICAgICAgICAgICByZXNvbHZlRGF0YVxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIC8vIFJldHVybiBFdmVudFJlc3VsdCB3aXRoIGNvbmZsaWN0IGV2ZW50IChubyBob29rIGVudGl0eSBjcmVhdGVkKVxuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGV2ZW50OiBmaWx0ZXJlZEV2ZW50LFxuICAgICAgICAgICAgICAgIHJ1bixcbiAgICAgICAgICAgICAgICBzdGVwLFxuICAgICAgICAgICAgICAgIGhvb2s6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBDb21wdXRlIHRoZSBob29rIGVudGl0eSBub3csIGJ1dCBkZWZlciBpdHMgd3JpdGUgdW50aWxcbiAgICAgICAgICAvLyBBRlRFUiB0aGUgb3V0ZXIgZXZlbnQgcHVibGlzaCBhdCB0aGUgYm90dG9tIG9mIHRoaXNcbiAgICAgICAgICAvLyBmdW5jdGlvbiBjb21taXRzLiBUaGUgcmV0cnkgcGF0aCBjYW4gcmVhY2ggdGhpcyBicmFuY2hcbiAgICAgICAgICAvLyBmb3IgYSBob29rIHdob3NlIGBob29rX2NyZWF0ZWRgIGV2ZW50IHdhcyBhbHJlYWR5XG4gICAgICAgICAgLy8gcHVibGlzaGVkIHN1Y2Nlc3NmdWxseSAoYW4gXCJhbHJlYWR5LWNvbW1pdHRlZFxuICAgICAgICAgIC8vIGR1cGxpY2F0ZVwiKTsgaW4gdGhhdCBjYXNlIHRoZSBvdXRlciBgd3JpdGVFeGNsdXNpdmVgXG4gICAgICAgICAgLy8gZm9yIHRoZSBldmVudCB3aWxsIHJldHVybiBmYWxzZSBhbmQgd2Ugd2lsbCB0aHJvd1xuICAgICAgICAgIC8vIGBFbnRpdHlDb25mbGljdEVycm9yYC4gV3JpdGluZyB0aGUgaG9vayBlbnRpdHkgaGVyZVxuICAgICAgICAgIC8vIGZpcnN0IHdvdWxkIG11dGF0ZSBhbHJlYWR5LWNvbW1pdHRlZCBkdXJhYmxlIHN0YXRlIHdpdGhcbiAgICAgICAgICAvLyB0aGUgcmV0cnkncyBwYXlsb2FkIChlLmcuIGRpZmZlcmVudCBgbWV0YWRhdGFgIG9yXG4gICAgICAgICAgLy8gYGlzV2ViaG9va2ApIGJlZm9yZSB0aGUgZXZlbnQgcHVibGlzaCBwcm92ZWQgd2hpY2hcbiAgICAgICAgICAvLyBvdXRjb21lIHdlIGFyZSBpbiDigJQgbGVhdmluZyB0aGUgZW50aXR5IGFuZCBldmVudCBsb2dcbiAgICAgICAgICAvLyBpbmNvbnNpc3RlbnQuIEJ5IGRlZmVycmluZywgdGhlIGVudGl0eSBpcyBvbmx5IHdyaXR0ZW5cbiAgICAgICAgICAvLyB3aGVuIHRoZSBwdWJsaXNoIGFjdHVhbGx5IHN1Y2NlZWRzIChmaXJzdCB3cml0ZXIgb3JcbiAgICAgICAgICAvLyBvcnBoYW4gcmVjb3ZlcnkpLiBTZWUgcHJhbmF5Z3AncyByZXZpZXcgb24gUFIgIzIyOTUgZm9yXG4gICAgICAgICAgLy8gdGhlIGthcnRoaWtzY2FsZTMgcmVwcm8uXG4gICAgICAgICAgaG9vayA9IHtcbiAgICAgICAgICAgIHJ1bklkOiBlZmZlY3RpdmVSdW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogZGF0YS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgdG9rZW46IGhvb2tEYXRhLnRva2VuLFxuICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tEYXRhLm1ldGFkYXRhLFxuICAgICAgICAgICAgb3duZXJJZDogJ2xvY2FsLW93bmVyJyxcbiAgICAgICAgICAgIHByb2plY3RJZDogJ2xvY2FsLXByb2plY3QnLFxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6ICdsb2NhbCcsXG4gICAgICAgICAgICAvLyBVc2UgdGhlIChwb3NzaWJseSBjYW5vbmljYWwpIGV2ZW50J3MgY3JlYXRlZEF0IHNvIHR3b1xuICAgICAgICAgICAgLy8gd29ya2VycyB3cml0aW5nIHRoZSBzYW1lIGhvb2sgZW50aXR5IHByb2R1Y2UgYnl0ZS1cbiAgICAgICAgICAgIC8vIGlkZW50aWNhbCBjb250ZW50IGR1cmluZyBjb252ZXJnZW5jZS5cbiAgICAgICAgICAgIGNyZWF0ZWRBdDogZXZlbnQuY3JlYXRlZEF0LFxuICAgICAgICAgICAgLy8gUHJvcGFnYXRlIHNwZWNWZXJzaW9uIGZyb20gdGhlIGV2ZW50IHRvIHRoZSBob29rIGVudGl0eVxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgICAgaXNXZWJob29rOiBob29rRGF0YS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBob29rRW50aXR5V3JpdGVPcHRpb25zID0gd3JpdGVIb29rRW50aXR5V2l0aE92ZXJ3cml0ZVxuICAgICAgICAgICAgPyB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfZGlzcG9zZWQnKSB7XG4gICAgICAgICAgLy8gaG9va19kaXNwb3NlZDogRGVsZXRlcyBob29rIGVudGl0eSwgcmVqZWN0cyBkdXBsaWNhdGVzLlxuICAgICAgICAgIC8vIFVzZXMgd3JpdGVFeGNsdXNpdmUgb24gYSBsb2NrIGZpbGUgdG8gYXRvbWljYWxseSBwcmV2ZW50IGNvbmN1cnJlbnRcbiAgICAgICAgICAvLyBpbnZvY2F0aW9ucyBmcm9tIGJvdGggZGlzcG9zaW5nIHRoZSBzYW1lIGhvb2sgKFRPQ1RPVSByYWNlKS5cbiAgICAgICAgICBjb25zdCBob29rTG9ja05hbWUgPSB0YWdcbiAgICAgICAgICAgID8gYCR7ZGF0YS5jb3JyZWxhdGlvbklkfS5kaXNwb3NlZC4ke3RhZ31gXG4gICAgICAgICAgICA6IGAke2RhdGEuY29ycmVsYXRpb25JZH0uZGlzcG9zZWRgO1xuICAgICAgICAgIGNvbnN0IGxvY2tQYXRoID0gcmVzb2x2ZVdpdGhpbkJhc2UoXG4gICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgJy5sb2NrcycsXG4gICAgICAgICAgICAnaG9va3MnLFxuICAgICAgICAgICAgaG9va0xvY2tOYW1lXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjbGFpbWVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUobG9ja1BhdGgsICcnKTtcbiAgICAgICAgICBpZiAoIWNsYWltZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgICBgSG9vayBcIiR7ZGF0YS5jb3JyZWxhdGlvbklkfVwiIGFscmVhZHkgZGlzcG9zZWRgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBSZWFkIHRoZSBob29rIHRvIGdldCBpdHMgdG9rZW4gYmVmb3JlIGRlbGV0aW5nXG4gICAgICAgICAgY29uc3QgaG9va1BhdGggPSB0YWdnZWRQYXRoKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgICBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICB0YWdcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nSG9vayA9IGF3YWl0IHJlYWRKU09OV2l0aEZhbGxiYWNrKFxuICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICdob29rcycsXG4gICAgICAgICAgICBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBIb29rU2NoZW1hLFxuICAgICAgICAgICAgdGFnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoZXhpc3RpbmdIb29rKSB7XG4gICAgICAgICAgICAvLyBEZWxldGUgdGhlIHRva2VuIGNvbnN0cmFpbnQgZmlsZSB0byBmcmVlIHVwIHRoZSB0b2tlblxuICAgICAgICAgICAgLy8gZm9yIHJldXNlLCBhbmQgZGVsZXRlIHRoaXMgaG9vaydzIHJlY292ZXJ5IG1hcmtlciAoaWZcbiAgICAgICAgICAgIC8vIGFueSkgZm9yIGRpc2sgaHlnaWVuZS4gVGhlIG1hcmtlcidzIGZpbGVuYW1lIGhhc2hcbiAgICAgICAgICAgIC8vIGluY2x1ZGVzIGAodG9rZW4sIHJ1bklkLCBob29rSWQpYCBzbyBkaWZmZXJlbnRcbiAgICAgICAgICAgIC8vIGxpZmV0aW1lcyBuZXZlciBjb2xsaWRlLCBidXQgY2xlYW5pbmcgdXAgcmVkdWNlcyBkaXNrXG4gICAgICAgICAgICAvLyBsZWFrIGZvciBob29rcyB0aGF0IGdvIHRocm91Z2ggdGhlIHJlY292ZXJ5IHBhdGguXG4gICAgICAgICAgICBjb25zdCBkaXNwb3NlZENvbnN0cmFpbnRQYXRoID0gcGF0aC5qb2luKFxuICAgICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgICAnaG9va3MnLFxuICAgICAgICAgICAgICAndG9rZW5zJyxcbiAgICAgICAgICAgICAgYCR7aGFzaFRva2VuKGV4aXN0aW5nSG9vay50b2tlbil9Lmpzb25gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYXdhaXQgZGVsZXRlSlNPTihkaXNwb3NlZENvbnN0cmFpbnRQYXRoKTtcbiAgICAgICAgICAgIGF3YWl0IGRlbGV0ZUpTT04oXG4gICAgICAgICAgICAgIGhvb2tSZWNvdmVyeU1hcmtlclBhdGgoXG4gICAgICAgICAgICAgICAgYmFzZWRpcixcbiAgICAgICAgICAgICAgICBleGlzdGluZ0hvb2sudG9rZW4sXG4gICAgICAgICAgICAgICAgZXhpc3RpbmdIb29rLnJ1bklkLFxuICAgICAgICAgICAgICAgIGV4aXN0aW5nSG9vay5ob29rSWRcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgZGVsZXRlSlNPTihob29rUGF0aCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICd3YWl0X2NyZWF0ZWQnICYmICdldmVudERhdGEnIGluIGRhdGEpIHtcbiAgICAgICAgICAvLyB3YWl0X2NyZWF0ZWQ6IENyZWF0ZXMgd2FpdCBlbnRpdHkgd2l0aCBzdGF0dXMgJ3dhaXRpbmcnXG4gICAgICAgICAgY29uc3Qgd2FpdERhdGEgPSBkYXRhLmV2ZW50RGF0YSBhcyB7XG4gICAgICAgICAgICByZXN1bWVBdD86IERhdGU7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCB3YWl0Q29tcG9zaXRlS2V5ID0gYCR7ZWZmZWN0aXZlUnVuSWR9LSR7ZGF0YS5jb3JyZWxhdGlvbklkfWA7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmdXYWl0ID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgJ3dhaXRzJyxcbiAgICAgICAgICAgIHdhaXRDb21wb3NpdGVLZXksXG4gICAgICAgICAgICBXYWl0U2NoZW1hLFxuICAgICAgICAgICAgdGFnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoZXhpc3RpbmdXYWl0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgICAgICAgYFdhaXQgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBhbHJlYWR5IGV4aXN0c2BcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHdhaXQgPSB7XG4gICAgICAgICAgICB3YWl0SWQ6IHdhaXRDb21wb3NpdGVLZXksXG4gICAgICAgICAgICBydW5JZDogZWZmZWN0aXZlUnVuSWQsXG4gICAgICAgICAgICBzdGF0dXM6ICd3YWl0aW5nJyxcbiAgICAgICAgICAgIHJlc3VtZUF0OiB3YWl0RGF0YS5yZXN1bWVBdCxcbiAgICAgICAgICAgIGNvbXBsZXRlZEF0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IGVmZmVjdGl2ZVNwZWNWZXJzaW9uLFxuICAgICAgICAgIH07XG4gICAgICAgICAgYXdhaXQgd3JpdGVKU09OKFxuICAgICAgICAgICAgdGFnZ2VkUGF0aChiYXNlZGlyLCAnd2FpdHMnLCB3YWl0Q29tcG9zaXRlS2V5LCB0YWcpLFxuICAgICAgICAgICAgd2FpdFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YS5ldmVudFR5cGUgPT09ICd3YWl0X2NvbXBsZXRlZCcpIHtcbiAgICAgICAgICAvLyB3YWl0X2NvbXBsZXRlZDogVHJhbnNpdGlvbnMgd2FpdCB0byAnY29tcGxldGVkJywgcmVqZWN0cyBkdXBsaWNhdGVzLlxuICAgICAgICAgIC8vIFVzZXMgd3JpdGVFeGNsdXNpdmUgb24gYSBsb2NrIGZpbGUgdG8gYXRvbWljYWxseSBwcmV2ZW50IGNvbmN1cnJlbnRcbiAgICAgICAgICAvLyBpbnZvY2F0aW9ucyBmcm9tIGJvdGggY29tcGxldGluZyB0aGUgc2FtZSB3YWl0IChUT0NUT1UgcmFjZSkuXG4gICAgICAgICAgY29uc3Qgd2FpdENvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2RhdGEuY29ycmVsYXRpb25JZH1gO1xuICAgICAgICAgIGNvbnN0IHdhaXRMb2NrTmFtZSA9IHRhZ1xuICAgICAgICAgICAgPyBgJHt3YWl0Q29tcG9zaXRlS2V5fS5jb21wbGV0ZWQuJHt0YWd9YFxuICAgICAgICAgICAgOiBgJHt3YWl0Q29tcG9zaXRlS2V5fS5jb21wbGV0ZWRgO1xuICAgICAgICAgIGNvbnN0IGxvY2tQYXRoID0gcmVzb2x2ZVdpdGhpbkJhc2UoXG4gICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgJy5sb2NrcycsXG4gICAgICAgICAgICAnd2FpdHMnLFxuICAgICAgICAgICAgd2FpdExvY2tOYW1lXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjbGFpbWVkID0gYXdhaXQgd3JpdGVFeGNsdXNpdmUobG9ja1BhdGgsICcnKTtcbiAgICAgICAgICBpZiAoIWNsYWltZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFbnRpdHlDb25mbGljdEVycm9yKFxuICAgICAgICAgICAgICBgV2FpdCBcIiR7ZGF0YS5jb3JyZWxhdGlvbklkfVwiIGFscmVhZHkgY29tcGxldGVkYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmdXYWl0ID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICAgICAgICBiYXNlZGlyLFxuICAgICAgICAgICAgJ3dhaXRzJyxcbiAgICAgICAgICAgIHdhaXRDb21wb3NpdGVLZXksXG4gICAgICAgICAgICBXYWl0U2NoZW1hLFxuICAgICAgICAgICAgdGFnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIWV4aXN0aW5nV2FpdCkge1xuICAgICAgICAgICAgLy8gQ2xlYW4gdXAgdGhlIGxvY2sgZmlsZSB3ZSBqdXN0IGNsYWltZWQg4oCUIHRoZSB3YWl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgICAgIGF3YWl0IGZzLnVubGluayhsb2NrUGF0aCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93V29ybGRFcnJvcihcbiAgICAgICAgICAgICAgYFdhaXQgXCIke2RhdGEuY29ycmVsYXRpb25JZH1cIiBub3QgZm91bmRgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBUaGUgbG9jayBmaWxlICh3cml0ZUV4Y2x1c2l2ZSBhYm92ZSkgYWxyZWFkeSBwcmV2ZW50cyBjb25jdXJyZW50XG4gICAgICAgICAgLy8gY29tcGxldGlvbnMg4oCUIG5vIGFkZGl0aW9uYWwgc3RhdHVzIGNoZWNrIG5lZWRlZC5cbiAgICAgICAgICB3YWl0ID0ge1xuICAgICAgICAgICAgLi4uZXhpc3RpbmdXYWl0LFxuICAgICAgICAgICAgc3RhdHVzOiAnY29tcGxldGVkJyxcbiAgICAgICAgICAgIGNvbXBsZXRlZEF0OiBub3csXG4gICAgICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGF3YWl0IHdyaXRlSlNPTihcbiAgICAgICAgICAgIHRhZ2dlZFBhdGgoYmFzZWRpciwgJ3dhaXRzJywgd2FpdENvbXBvc2l0ZUtleSwgdGFnKSxcbiAgICAgICAgICAgIHdhaXQsXG4gICAgICAgICAgICB7IG92ZXJ3cml0ZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3RlOiBob29rX3JlY2VpdmVkIGV2ZW50cyBhcmUgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYnV0IGRvbid0XG4gICAgICAgIC8vIG1vZGlmeSB0aGUgSG9vayBlbnRpdHkgKHdoaWNoIGRvZXNuJ3QgaGF2ZSBhIHBheWxvYWQgZmllbGQpXG5cbiAgICAgICAgLy8gU3RvcmUgZXZlbnQgdXNpbmcgY29tcG9zaXRlIGtleSB7cnVuSWR9LXtldmVudElkfS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gYHdyaXRlRXhjbHVzaXZlYCAoT19DUkVBVHxPX0VYQ0wgdmlhIHRlbXAtZmlsZSArIGhhcmQtbGluaylcbiAgICAgICAgLy8gaXMgdGhlIGNyb3NzLXByb2Nlc3MgYXRvbWljIHB1Ymxpc2ggcHJpbWl0aXZlOiBpZiB0aGUgZmlsZVxuICAgICAgICAvLyBhbHJlYWR5IGV4aXN0cywgcmV0dXJucyBmYWxzZSBpbnN0ZWFkIG9mIG92ZXJ3cml0aW5nLiBUaGlzXG4gICAgICAgIC8vIGlzIGNyaXRpY2FsIGZvciB0aGUgaG9va19jcmVhdGVkIGRlZHVwLXJlY292ZXJ5IGNvbnZlcmdlbmNlXG4gICAgICAgIC8vIChhYm92ZSkg4oCUIHR3byB3b3JrZXJzIHRoYXQgYWRvcHQgdGhlIHNhbWUgY2Fub25pY2FsIGV2ZW50SWRcbiAgICAgICAgLy8gcmFjZSBoZXJlOyB3aG9ldmVyIGxpbmtzIHRoZSBmaWxlIGZpcnN0IHdpbnMsIHRoZSBsb3NlclxuICAgICAgICAvLyB0aHJvd3MgRW50aXR5Q29uZmxpY3RFcnJvciwgYW5kIHRoZSBydW50aW1lJ3MgZXhpc3RpbmdcbiAgICAgICAgLy8gY29uY3VycmVudC1yZXBsYXkgY2F0Y2ggcGF0aCBhdCBzdXNwZW5zaW9uLWhhbmRsZXIudHM6MTQyXG4gICAgICAgIC8vIHN3YWxsb3dzIGl0LiBGb3IgYWxsIG90aGVyIGV2ZW50IHR5cGVzLCBldmVudElkcyBhcmVcbiAgICAgICAgLy8gbW9ub3RvbmljIFVMSURzIChnbG9iYWxseSB1bmlxdWUgYnkgY29uc3RydWN0aW9uKSBzbyBhXG4gICAgICAgIC8vIGNvbGxpc2lvbiBpbmRpY2F0ZXMgYSByZWFsIGJ1ZyBhbmQgRW50aXR5Q29uZmxpY3RFcnJvciBpc1xuICAgICAgICAvLyBhbHNvIHRoZSByaWdodCBzdXJmYWNlIOKAlCBzYW1lIHNoYXBlIGFzIHN0ZXBfY3JlYXRlZCdzXG4gICAgICAgIC8vIGNsYWltLWZpbGUgYmVoYXZpb3IuXG4gICAgICAgIGNvbnN0IGNvbXBvc2l0ZUtleSA9IGAke2VmZmVjdGl2ZVJ1bklkfS0ke2V2ZW50SWR9YDtcbiAgICAgICAgY29uc3QgZXZlbnRQdWJsaXNoZWQgPSBhd2FpdCB3cml0ZUV4Y2x1c2l2ZShcbiAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdldmVudHMnLCBjb21wb3NpdGVLZXksIHRhZyksXG4gICAgICAgICAgSlNPTi5zdHJpbmdpZnkoZXZlbnQsIGpzb25SZXBsYWNlciwgMilcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFldmVudFB1Ymxpc2hlZCkge1xuICAgICAgICAgIC8vIEZvciBgaG9va19jcmVhdGVkYCwgbG9zaW5nIHRoZSBldmVudCBwdWJsaXNoIG1lYW5zIHRoZVxuICAgICAgICAgIC8vIGV2ZW50IHdhcyBhbHJlYWR5IGNvbW1pdHRlZCBhdCB0aGlzIGV4YWN0IChjYW5vbmljYWwpXG4gICAgICAgICAgLy8gcGF0aC4gVGhlIG9yaWdpbmFsIHB1Ymxpc2hlciBtYXkgaGF2ZSBjcmFzaGVkIGJldHdlZW5cbiAgICAgICAgICAvLyBpdHMgZXZlbnQgcHVibGlzaCBhbmQgaXRzIGRlZmVycmVkIGhvb2stZW50aXR5IHdyaXRlXG4gICAgICAgICAgLy8gKHRoZSBpbnZlcnNlIG9mIHRoZSBjcmFzaCB3aW5kb3cgdGhlIGRlZmVycmFsIGNsb3NlcyksXG4gICAgICAgICAgLy8gbGVhdmluZyBhbiBldmVudC1maXJzdCBvcnBoYW46IHRoZSBldmVudCBpcyBpbiB0aGUgbG9nXG4gICAgICAgICAgLy8gYnV0IHRoZSBlbnRpdHkgaXMgbWlzc2luZyBhbmQgdGhlIGhvb2sgaXMgdW5yZXNvbHZhYmxlLlxuICAgICAgICAgIC8vIFJlcGFpciB0aGUgZW50aXR5IGZyb20gdGhlIFBFUlNJU1RFRCBldmVudCdzIHBheWxvYWRcbiAgICAgICAgICAvLyAobmV2ZXIgdGhlIHJldHJ5J3Mg4oCUIGRpZmZlcmVudCByZXRyeSBtZXRhZGF0YSBtdXN0IG5vdFxuICAgICAgICAgIC8vIGNoYW5nZSBjb21taXR0ZWQgc3RhdGUpIGJlZm9yZSBzdXJmYWNpbmcgdGhlIGJlbmlnblxuICAgICAgICAgIC8vIGR1cGxpY2F0ZSB0byB0aGUgcnVudGltZSdzIGNvbmN1cnJlbnQtcmVwbGF5IGNhdGNoIHBhdGguXG4gICAgICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAnaG9va19jcmVhdGVkJyAmJiBkYXRhLmNvcnJlbGF0aW9uSWQpIHtcbiAgICAgICAgICAgIGF3YWl0IHJlcGFpckhvb2tFbnRpdHlGcm9tUGVyc2lzdGVkRXZlbnQoXG4gICAgICAgICAgICAgIGJhc2VkaXIsXG4gICAgICAgICAgICAgIGVmZmVjdGl2ZVJ1bklkLFxuICAgICAgICAgICAgICBkYXRhLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgICAgIHRhZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgbmV3IEVudGl0eUNvbmZsaWN0RXJyb3IoXG4gICAgICAgICAgICBgRXZlbnQgXCIke2V2ZW50SWR9XCIgYWxyZWFkeSBleGlzdHMgZm9yIHJ1biBcIiR7ZWZmZWN0aXZlUnVuSWR9XCJgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdyaXRlIHRoZSBob29rIGVudGl0eSBPTkxZIG5vdyB0aGF0IHRoZSBldmVudCBwdWJsaXNoIGhhc1xuICAgICAgICAvLyBjb21taXR0ZWQuIERvaW5nIHRoaXMgZWFybGllciAoaW4gdGhlIGBob29rX2NyZWF0ZWRgXG4gICAgICAgIC8vIGJyYW5jaCBhYm92ZSkgd291bGQgbXV0YXRlIGFuIGFscmVhZHktY29tbWl0dGVkIGhvb2tcbiAgICAgICAgLy8gZW50aXR5IHdpdGggdGhlIHJldHJ5J3MgcGF5bG9hZCBiZWZvcmUgdGhlIGV2ZW50IHB1Ymxpc2hcbiAgICAgICAgLy8gcHJvdmVkIHdoZXRoZXIgdGhpcyBhdHRlbXB0IHdhcyByZXBhaXJpbmcgYSBtaXNzaW5nIGV2ZW50XG4gICAgICAgIC8vIG9yIGp1c3QgY29sbGlkaW5nIHdpdGggYW4gYWxyZWFkeS1wdWJsaXNoZWQgYGhvb2tfY3JlYXRlZGAuXG4gICAgICAgIC8vIFRoZSBicmFuY2ggc2V0cyBgaG9va0VudGl0eVdyaXRlT3B0aW9uc2AgaWZmIHRoaXMgZXZlbnRcbiAgICAgICAgLy8gdHlwZSB3cml0ZXMgYW4gZW50aXR5LlxuICAgICAgICBpZiAoaG9vayAmJiBkYXRhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfY3JlYXRlZCcpIHtcbiAgICAgICAgICBhd2FpdCB3cml0ZUpTT04oXG4gICAgICAgICAgICB0YWdnZWRQYXRoKGJhc2VkaXIsICdob29rcycsIGhvb2suaG9va0lkLCB0YWcpLFxuICAgICAgICAgICAgaG9vayxcbiAgICAgICAgICAgIGhvb2tFbnRpdHlXcml0ZU9wdGlvbnNcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzb2x2ZURhdGEgPSBwYXJhbXM/LnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcbiAgICAgICAgY29uc3QgZmlsdGVyZWRFdmVudCA9IHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpO1xuXG4gICAgICAgIC8vIEZvciBydW5fc3RhcnRlZDogaW5jbHVkZSBhbGwgZXZlbnRzIHNvIHRoZSBydW50aW1lIGNhbiBza2lwXG4gICAgICAgIC8vIHRoZSBpbml0aWFsIGV2ZW50cy5saXN0IGNhbGwgYW5kIHJlZHVjZSBUVEZCLlxuICAgICAgICBsZXQgZXZlbnRzOiBFdmVudFtdIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgY3Vyc29yOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgaGFzTW9yZTogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGRhdGEuZXZlbnRUeXBlID09PSAncnVuX3N0YXJ0ZWQnICYmIHJ1bikge1xuICAgICAgICAgIGNvbnN0IGFsbEV2ZW50cyA9IGF3YWl0IHBhZ2luYXRlZEZpbGVTeXN0ZW1RdWVyeSh7XG4gICAgICAgICAgICBkaXJlY3Rvcnk6IHBhdGguam9pbihiYXNlZGlyLCAnZXZlbnRzJyksXG4gICAgICAgICAgICBzY2hlbWE6IEV2ZW50U2NoZW1hLFxuICAgICAgICAgICAgZmlsZVByZWZpeDogYCR7ZWZmZWN0aXZlUnVuSWR9LWAsXG4gICAgICAgICAgICBzb3J0T3JkZXI6ICdhc2MnLFxuICAgICAgICAgICAgbGltaXQ6IDEwMDAsXG4gICAgICAgICAgICBnZXRDcmVhdGVkQXQ6IGdldE9iamVjdENyZWF0ZWRBdCgnZXZudCcpLFxuICAgICAgICAgICAgZ2V0SWQ6IChlKSA9PiBlLmV2ZW50SWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZXZlbnRzID0gYWxsRXZlbnRzLmRhdGE7XG4gICAgICAgICAgY3Vyc29yID0gYWxsRXZlbnRzLmN1cnNvcjtcbiAgICAgICAgICBoYXNNb3JlID0gYWxsRXZlbnRzLmhhc01vcmU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXR1cm4gRXZlbnRSZXN1bHQgd2l0aCBldmVudCBhbmQgYW55IGNyZWF0ZWQvdXBkYXRlZCBlbnRpdHlcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBldmVudDogZmlsdGVyZWRFdmVudCxcbiAgICAgICAgICBydW4sXG4gICAgICAgICAgc3RlcCxcbiAgICAgICAgICBob29rLFxuICAgICAgICAgIHdhaXQsXG4gICAgICAgICAgZXZlbnRzLFxuICAgICAgICAgIGN1cnNvcixcbiAgICAgICAgICBoYXNNb3JlLFxuICAgICAgICB9O1xuICAgICAgfSAvLyBlbmQgY3JlYXRlSW1wbFxuICAgIH0sXG5cbiAgICBhc3luYyBnZXQocnVuSWQsIGV2ZW50SWQsIHBhcmFtcykge1xuICAgICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdydW5JZCcsIHJ1bklkKTtcbiAgICAgIGFzc2VydFNhZmVFbnRpdHlJZCgnZXZlbnRJZCcsIGV2ZW50SWQpO1xuICAgICAgY29uc3QgY29tcG9zaXRlS2V5ID0gYCR7cnVuSWR9LSR7ZXZlbnRJZH1gO1xuICAgICAgY29uc3QgZXZlbnQgPSBhd2FpdCByZWFkSlNPTldpdGhGYWxsYmFjayhcbiAgICAgICAgYmFzZWRpcixcbiAgICAgICAgJ2V2ZW50cycsXG4gICAgICAgIGNvbXBvc2l0ZUtleSxcbiAgICAgICAgRXZlbnRTY2hlbWEsXG4gICAgICAgIHRhZ1xuICAgICAgKTtcbiAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFdmVudCAke2V2ZW50SWR9IGluIHJ1biAke3J1bklkfSBub3QgZm91bmRgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc29sdmVEYXRhID0gcGFyYW1zPy5yZXNvbHZlRGF0YSA/PyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG4gICAgICByZXR1cm4gc3RyaXBFdmVudERhdGFSZWZzKGV2ZW50LCByZXNvbHZlRGF0YSk7XG4gICAgfSxcblxuICAgIGFzeW5jIGxpc3QocGFyYW1zKSB7XG4gICAgICBjb25zdCB7IHJ1bklkIH0gPSBwYXJhbXM7XG4gICAgICBhc3NlcnRTYWZlRW50aXR5SWQoJ3J1bklkJywgcnVuSWQpO1xuICAgICAgY29uc3QgcmVzb2x2ZURhdGEgPSBwYXJhbXMucmVzb2x2ZURhdGEgPz8gREVGQVVMVF9SRVNPTFZFX0RBVEFfT1BUSU9OO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5KHtcbiAgICAgICAgZGlyZWN0b3J5OiBwYXRoLmpvaW4oYmFzZWRpciwgJ2V2ZW50cycpLFxuICAgICAgICBzY2hlbWE6IEV2ZW50U2NoZW1hLFxuICAgICAgICBmaWxlUHJlZml4OiBgJHtydW5JZH0tYCxcbiAgICAgICAgLy8gRXZlbnRzIGluIGNocm9ub2xvZ2ljYWwgb3JkZXIgKG9sZGVzdCBmaXJzdCkgYnkgZGVmYXVsdCxcbiAgICAgICAgLy8gZGlmZmVyZW50IGZyb20gdGhlIGRlZmF1bHQgZm9yIG90aGVyIGxpc3QgY2FsbHMuXG4gICAgICAgIHNvcnRPcmRlcjogcGFyYW1zLnBhZ2luYXRpb24/LnNvcnRPcmRlciA/PyAnYXNjJyxcbiAgICAgICAgbGltaXQ6IHBhcmFtcy5wYWdpbmF0aW9uPy5saW1pdCxcbiAgICAgICAgY3Vyc29yOiBwYXJhbXMucGFnaW5hdGlvbj8uY3Vyc29yLFxuICAgICAgICBnZXRDcmVhdGVkQXQ6IGdldE9iamVjdENyZWF0ZWRBdCgnZXZudCcpLFxuICAgICAgICBnZXRJZDogKGV2ZW50KSA9PiBldmVudC5ldmVudElkLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIElmIHJlc29sdmVEYXRhIGlzIFwibm9uZVwiLCByZW1vdmUgZXZlbnREYXRhIGZyb20gZXZlbnRzXG4gICAgICBpZiAocmVzb2x2ZURhdGEgPT09ICdub25lJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICBkYXRhOiByZXN1bHQuZGF0YS5tYXAoKGV2ZW50KSA9PlxuICAgICAgICAgICAgc3RyaXBFdmVudERhdGFSZWZzKGV2ZW50LCByZXNvbHZlRGF0YSlcbiAgICAgICAgICApLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBhc3luYyBsaXN0QnlDb3JyZWxhdGlvbklkKHBhcmFtcykge1xuICAgICAgY29uc3QgY29ycmVsYXRpb25JZCA9IHBhcmFtcy5jb3JyZWxhdGlvbklkO1xuICAgICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdjb3JyZWxhdGlvbklkJywgY29ycmVsYXRpb25JZCk7XG4gICAgICBjb25zdCByZXNvbHZlRGF0YSA9IHBhcmFtcy5yZXNvbHZlRGF0YSA/PyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwYWdpbmF0ZWRGaWxlU3lzdGVtUXVlcnkoe1xuICAgICAgICBkaXJlY3Rvcnk6IHBhdGguam9pbihiYXNlZGlyLCAnZXZlbnRzJyksXG4gICAgICAgIHNjaGVtYTogRXZlbnRTY2hlbWEsXG4gICAgICAgIC8vIE5vIGZpbGVQcmVmaXggLSBzZWFyY2ggYWxsIGV2ZW50c1xuICAgICAgICBmaWx0ZXI6IChldmVudCkgPT4gZXZlbnQuY29ycmVsYXRpb25JZCA9PT0gY29ycmVsYXRpb25JZCxcbiAgICAgICAgLy8gRXZlbnRzIGluIGNocm9ub2xvZ2ljYWwgb3JkZXIgKG9sZGVzdCBmaXJzdCkgYnkgZGVmYXVsdCxcbiAgICAgICAgLy8gZGlmZmVyZW50IGZyb20gdGhlIGRlZmF1bHQgZm9yIG90aGVyIGxpc3QgY2FsbHMuXG4gICAgICAgIHNvcnRPcmRlcjogcGFyYW1zLnBhZ2luYXRpb24/LnNvcnRPcmRlciA/PyAnYXNjJyxcbiAgICAgICAgbGltaXQ6IHBhcmFtcy5wYWdpbmF0aW9uPy5saW1pdCxcbiAgICAgICAgY3Vyc29yOiBwYXJhbXMucGFnaW5hdGlvbj8uY3Vyc29yLFxuICAgICAgICBnZXRDcmVhdGVkQXQ6IGdldE9iamVjdENyZWF0ZWRBdCgnZXZudCcpLFxuICAgICAgICBnZXRJZDogKGV2ZW50KSA9PiBldmVudC5ldmVudElkLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIElmIHJlc29sdmVEYXRhIGlzIFwibm9uZVwiLCByZW1vdmUgZXZlbnREYXRhIGZyb20gZXZlbnRzXG4gICAgICBpZiAocmVzb2x2ZURhdGEgPT09ICdub25lJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICBkYXRhOiByZXN1bHQuZGF0YS5tYXAoKGV2ZW50KSA9PlxuICAgICAgICAgICAgc3RyaXBFdmVudERhdGFSZWZzKGV2ZW50LCByZXNvbHZlRGF0YSlcbiAgICAgICAgICApLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG4gIH07XG59XG4iXX0=
|