sonamu 0.9.8 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/ai/agents/agent.d.ts.map +1 -1
  2. package/dist/ai/agents/agent.js +4 -2
  3. package/dist/ai/providers/rtzr/api.d.ts +1 -1
  4. package/dist/api/decorators.d.ts +0 -1
  5. package/dist/api/decorators.d.ts.map +1 -1
  6. package/dist/api/decorators.js +8 -6
  7. package/dist/api/sonamu.d.ts.map +1 -1
  8. package/dist/api/sonamu.js +123 -12
  9. package/dist/api/websocket-helpers.d.ts +1 -3
  10. package/dist/api/websocket-helpers.d.ts.map +1 -1
  11. package/dist/api/websocket-helpers.js +2 -15
  12. package/dist/stream/index.d.ts +3 -0
  13. package/dist/stream/index.d.ts.map +1 -1
  14. package/dist/stream/index.js +8 -2
  15. package/dist/stream/ws-core.d.ts +1 -0
  16. package/dist/stream/ws-core.d.ts.map +1 -1
  17. package/dist/stream/ws-delivery.d.ts +8 -0
  18. package/dist/stream/ws-delivery.d.ts.map +1 -1
  19. package/dist/stream/ws-delivery.js +160 -14
  20. package/dist/stream/ws-local-connection-store.d.ts +2 -0
  21. package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
  22. package/dist/stream/ws-local-connection-store.js +21 -1
  23. package/dist/stream/ws-registry.d.ts +6 -2
  24. package/dist/stream/ws-registry.d.ts.map +1 -1
  25. package/dist/stream/ws-registry.js +170 -6
  26. package/dist/stream/ws-telemetry-memory.d.ts +28 -0
  27. package/dist/stream/ws-telemetry-memory.d.ts.map +1 -0
  28. package/dist/stream/ws-telemetry-memory.js +180 -0
  29. package/dist/stream/ws-telemetry-trace.d.ts +12 -0
  30. package/dist/stream/ws-telemetry-trace.d.ts.map +1 -0
  31. package/dist/stream/ws-telemetry-trace.js +41 -0
  32. package/dist/stream/ws-telemetry.d.ts +509 -0
  33. package/dist/stream/ws-telemetry.d.ts.map +1 -0
  34. package/dist/stream/ws-telemetry.js +931 -0
  35. package/dist/stream/ws.d.ts +10 -3
  36. package/dist/stream/ws.d.ts.map +1 -1
  37. package/dist/stream/ws.js +306 -27
  38. package/dist/syncer/file-patterns.js +2 -2
  39. package/dist/syncer/syncer-actions.d.ts +2 -8
  40. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  41. package/dist/syncer/syncer-actions.js +4 -11
  42. package/dist/syncer/syncer.d.ts +1 -1
  43. package/dist/syncer/syncer.d.ts.map +1 -1
  44. package/dist/syncer/syncer.js +8 -6
  45. package/dist/template/template.d.ts +1 -2
  46. package/dist/template/template.d.ts.map +1 -1
  47. package/dist/template/template.js +3 -4
  48. package/dist/template/zod-converter.d.ts +2 -2
  49. package/dist/testing/dev-vitest-manager.d.ts +1 -1
  50. package/dist/testing/dev-vitest-manager.js +2 -2
  51. package/dist/types/types.d.ts +11 -5
  52. package/dist/types/types.d.ts.map +1 -1
  53. package/dist/types/types.js +2 -2
  54. package/dist/utils/class-name.d.ts +6 -0
  55. package/dist/utils/class-name.d.ts.map +1 -0
  56. package/dist/utils/class-name.js +19 -0
  57. package/package.json +2 -2
  58. package/src/ai/agents/agent.ts +2 -1
  59. package/src/api/__tests__/sonamu.websocket.test.ts +84 -10
  60. package/src/api/decorators.ts +6 -6
  61. package/src/api/sonamu.ts +142 -7
  62. package/src/api/websocket-helpers.ts +2 -28
  63. package/src/shared/app.shared.ts.txt +16 -8
  64. package/src/shared/web.shared.ts.txt +8 -7
  65. package/src/skills/sonamu/testing-devrunner.md +1 -1
  66. package/src/stream/__tests__/ws-telemetry.test.ts +821 -0
  67. package/src/stream/__tests__/ws.test.ts +362 -2
  68. package/src/stream/index.ts +3 -0
  69. package/src/stream/ws-core.ts +2 -0
  70. package/src/stream/ws-delivery.ts +161 -19
  71. package/src/stream/ws-local-connection-store.ts +33 -0
  72. package/src/stream/ws-registry.ts +186 -5
  73. package/src/stream/ws-telemetry-memory.ts +246 -0
  74. package/src/stream/ws-telemetry-trace.ts +52 -0
  75. package/src/stream/ws-telemetry.ts +1772 -0
  76. package/src/stream/ws.ts +332 -34
  77. package/src/syncer/file-patterns.ts +3 -3
  78. package/src/syncer/syncer-actions.ts +3 -15
  79. package/src/syncer/syncer.ts +9 -13
  80. package/src/template/__tests__/services.template.websocket.test.ts +2 -0
  81. package/src/template/template.ts +2 -3
  82. package/src/testing/dev-vitest-manager.ts +1 -1
  83. package/src/types/types.ts +10 -3
  84. package/src/utils/class-name.ts +12 -0
package/dist/stream/ws.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { __esmMin } from "../_virtual/rolldown_runtime.js";
2
+ import { generateSpanId, init_ws_telemetry_trace, parseTraceParent } from "./ws-telemetry-trace.js";
3
+ import { createWebSocketTelemetryController, init_ws_telemetry, isPromiseLike } from "./ws-telemetry.js";
2
4
  import { WebSocketRegistry, init_ws_registry } from "./ws-registry.js";
3
5
  import { z as z$1 } from "zod";
4
6
  import { randomUUID } from "node:crypto";
7
+ import { hostname } from "node:os";
5
8
 
6
9
  //#region src/stream/ws.ts
7
10
  function createWebSocketRuntime(options = {}) {
@@ -37,19 +40,22 @@ function truncateCloseReason(reason) {
37
40
  }
38
41
  return Buffer.byteLength(reason, "utf-8") <= 123 ? reason : Buffer.from(reason).subarray(0, 123).toString("utf-8");
39
42
  }
40
- function isPromiseLike(value) {
41
- return typeof value === "object" && value !== null && "then" in value && "catch" in value;
43
+ function deriveLifetimeStatus(code) {
44
+ if (code === undefined) return "unset";
45
+ if (code === 1e3 || code === 1001) return "ok";
46
+ return "error";
42
47
  }
43
- var WS_CONNECTING, WS_OPEN, WS_CLOSED, WS_CLOSE_CODE_GOING_AWAY, WS_CLOSE_CODE_INVALID_FRAME_PAYLOAD_DATA, WS_CLOSE_CODE_POLICY_VIOLATION, WS_CLOSE_CODE_MESSAGE_TOO_BIG, WS_CLOSE_CODE_INTERNAL_ERROR, WS_CLOSE_CODE_TRY_AGAIN_LATER, MAX_PENDING_MESSAGES, MAX_PENDING_OUTBOUND_MESSAGES, MAX_SOCKET_BUFFERED_AMOUNT, OUTBOUND_BATCH_SIZE, OUTBOUND_RETRY_DELAY_MS, WebSocketEnvelopeSchema, WebSocketRuntime, WebSocketConnectionImpl;
48
+ var WS_CONNECTING, WS_OPEN, WS_CLOSED, WS_CLOSE_CODE_GOING_AWAY, WS_CLOSE_CODE_INVALID_FRAME_PAYLOAD_DATA, WS_CLOSE_CODE_POLICY_VIOLATION, WS_CLOSE_CODE_INTERNAL_ERROR, WS_CLOSE_CODE_TRY_AGAIN_LATER, MAX_PENDING_MESSAGES, MAX_PENDING_OUTBOUND_MESSAGES, MAX_SOCKET_BUFFERED_AMOUNT, OUTBOUND_BATCH_SIZE, OUTBOUND_RETRY_DELAY_MS, WebSocketEnvelopeSchema, WebSocketRuntime, WebSocketConnectionImpl;
44
49
  var init_ws = __esmMin((() => {
45
50
  init_ws_registry();
51
+ init_ws_telemetry();
52
+ init_ws_telemetry_trace();
46
53
  WS_CONNECTING = 0;
47
54
  WS_OPEN = 1;
48
55
  WS_CLOSED = 3;
49
56
  WS_CLOSE_CODE_GOING_AWAY = 1001;
50
57
  WS_CLOSE_CODE_INVALID_FRAME_PAYLOAD_DATA = 1007;
51
58
  WS_CLOSE_CODE_POLICY_VIOLATION = 1008;
52
- WS_CLOSE_CODE_MESSAGE_TOO_BIG = 1009;
53
59
  WS_CLOSE_CODE_INTERNAL_ERROR = 1011;
54
60
  WS_CLOSE_CODE_TRY_AGAIN_LATER = 1013;
55
61
  MAX_PENDING_MESSAGES = 100;
@@ -59,22 +65,34 @@ var init_ws = __esmMin((() => {
59
65
  OUTBOUND_RETRY_DELAY_MS = 5;
60
66
  WebSocketEnvelopeSchema = z$1.object({
61
67
  event: z$1.string(),
62
- data: z$1.unknown()
68
+ data: z$1.unknown(),
69
+ meta: z$1.object({
70
+ traceparent: z$1.string().optional(),
71
+ tracestate: z$1.string().optional()
72
+ }).optional()
63
73
  });
64
74
  WebSocketRuntime = class {
65
75
  registry;
76
+ telemetryController;
66
77
  constructor(options = {}) {
78
+ const resolvedNodeId = options.nodeId ?? `${hostname()}-${process.pid}`;
79
+ this.telemetryController = createWebSocketTelemetryController(options.telemetry, {
80
+ runtimeId: randomUUID(),
81
+ nodeId: resolvedNodeId
82
+ });
67
83
  const registryOptions = {
68
- nodeId: options.nodeId,
84
+ nodeId: resolvedNodeId,
69
85
  presenceStore: options.presenceStore,
70
- clusterBus: options.clusterBus
86
+ clusterBus: options.clusterBus,
87
+ telemetryController: this.telemetryController
71
88
  };
72
89
  this.registry = new WebSocketRegistry(registryOptions);
73
90
  }
74
91
  registerConnection(socket, options) {
75
92
  return new WebSocketConnectionImpl(socket, {
76
93
  ...options,
77
- registry: this.registry
94
+ registry: this.registry,
95
+ telemetryController: this.telemetryController
78
96
  });
79
97
  }
80
98
  activateConnection(connectionId) {
@@ -94,6 +112,7 @@ var init_ws = __esmMin((() => {
94
112
  }
95
113
  async shutdown(code = WS_CLOSE_CODE_GOING_AWAY, reason = "Server shutting down") {
96
114
  await this.registry.shutdown(code, reason);
115
+ await this.telemetryController.shutdown();
97
116
  }
98
117
  };
99
118
  WebSocketConnectionImpl = class {
@@ -107,9 +126,17 @@ var init_ws = __esmMin((() => {
107
126
  closePromise;
108
127
  resolveClosePromise;
109
128
  heartbeatMs;
110
- maxPayload;
111
129
  eventSchemasIn;
112
130
  eventSchemasOut;
131
+ connectionTraceId;
132
+ connectionSpanId;
133
+ connectionParentSpanId;
134
+ connectionSampled;
135
+ connectionStartedAt = performance.now();
136
+ _userId;
137
+ get userId() {
138
+ return this._userId;
139
+ }
113
140
  closedInternal = false;
114
141
  closeStarted = false;
115
142
  awaitingPong = false;
@@ -121,7 +148,10 @@ var init_ws = __esmMin((() => {
121
148
  this.options = options;
122
149
  this.namespace = options.namespace ?? "default";
123
150
  this.heartbeatMs = options.heartbeat ?? 3e4;
124
- this.maxPayload = options.maxPayload;
151
+ this.connectionTraceId = options.traceId;
152
+ this.connectionSpanId = options.spanId;
153
+ this.connectionParentSpanId = options.parentSpanId;
154
+ this.connectionSampled = options.sampled;
125
155
  this.eventSchemasIn = options.inEvents.shape;
126
156
  this.eventSchemasOut = options.outEvents.shape;
127
157
  let resolveClosePromise;
@@ -165,11 +195,62 @@ var init_ws = __esmMin((() => {
165
195
  this.options.registry.leave(this.id, roomId);
166
196
  }
167
197
  setUserId(userId) {
198
+ this._userId = String(userId);
168
199
  this.options.registry.setUserId(this.id, userId);
169
200
  }
170
201
  clearUserId() {
202
+ this._userId = undefined;
171
203
  this.options.registry.clearUserId(this.id);
172
204
  }
205
+ getTelemetrySnapshot() {
206
+ return {
207
+ pendingInboundMessages: this.pendingMessages.length,
208
+ pendingOutboundMessages: this.pendingOutboundMessages.length,
209
+ socketBufferedBytes: this.socket.readyState === WS_OPEN ? this.socket.bufferedAmount : 0
210
+ };
211
+ }
212
+ getTelemetryContext() {
213
+ return {
214
+ traceId: this.connectionTraceId,
215
+ spanId: this.connectionSpanId,
216
+ parentSpanId: this.connectionParentSpanId,
217
+ sampled: this.connectionSampled
218
+ };
219
+ }
220
+ telemetryFields() {
221
+ return {
222
+ connectionId: this.id,
223
+ namespace: this.namespace,
224
+ userId: this._userId,
225
+ traceId: this.connectionTraceId,
226
+ spanId: this.connectionSpanId,
227
+ parentSpanId: this.connectionParentSpanId,
228
+ sampled: this.connectionSampled
229
+ };
230
+ }
231
+ emitInboundRejected(reason, event) {
232
+ const fields = this.telemetryFields();
233
+ this.options.telemetryController.emit({
234
+ name: "ws.message.rejected",
235
+ level: "warn",
236
+ ...fields,
237
+ detail: event !== undefined ? {
238
+ reason,
239
+ event
240
+ } : { reason }
241
+ });
242
+ this.options.telemetryController.recordMetric({
243
+ name: "sonamu.ws.messages",
244
+ kind: "counter",
245
+ value: 1,
246
+ unit: "1",
247
+ tags: {
248
+ direction: "inbound",
249
+ outcome: "rejected"
250
+ },
251
+ ...fields
252
+ });
253
+ }
173
254
  close(code, reason) {
174
255
  if (this.closedInternal || this.closeStarted || this.socket.readyState === WS_CLOSED) {
175
256
  return;
@@ -178,27 +259,32 @@ var init_ws = __esmMin((() => {
178
259
  try {
179
260
  this.closeTransport(code, reason);
180
261
  } finally {
181
- this.markClosed();
262
+ this.markClosed(code, reason);
182
263
  }
183
264
  }
184
265
  handleMessage = (raw) => {
185
266
  this.enqueueMessageTask(async () => {
186
267
  const text = normalizeMessage(raw);
187
- if (this.maxPayload !== undefined && Buffer.byteLength(text) > this.maxPayload) {
188
- this.close(WS_CLOSE_CODE_MESSAGE_TOO_BIG, "Message too large");
189
- return;
190
- }
191
268
  const parsedEnvelope = safeParseEnvelope(text);
192
269
  if (!parsedEnvelope) {
270
+ this.emitInboundRejected("invalidPayload");
193
271
  this.close(WS_CLOSE_CODE_INVALID_FRAME_PAYLOAD_DATA, "Invalid message payload");
194
272
  return;
195
273
  }
274
+ this.options.telemetryController.emit({
275
+ name: "ws.message.received",
276
+ level: "debug",
277
+ ...this.telemetryFields(),
278
+ detail: { event: parsedEnvelope.event },
279
+ payload: parsedEnvelope.data
280
+ });
196
281
  this.options.registry.touch(this.id);
197
282
  await this.dispatchEnvelope(parsedEnvelope);
198
283
  });
199
284
  };
200
- handleClose = () => {
201
- this.markClosed();
285
+ handleClose = (code, reason) => {
286
+ const reasonText = typeof reason === "string" ? reason : reason?.toString();
287
+ this.markClosed(code, reasonText);
202
288
  };
203
289
  handleError = () => {
204
290
  this.close(WS_CLOSE_CODE_INTERNAL_ERROR, "WebSocket transport error");
@@ -207,27 +293,108 @@ var init_ws = __esmMin((() => {
207
293
  this.awaitingPong = false;
208
294
  this.options.registry.touch(this.id);
209
295
  };
296
+ resolveMessageTraceContext(envelope) {
297
+ const messageSpanId = generateSpanId();
298
+ if (this.options.telemetryController.getTraceOptions().propagateMessageTrace && envelope.meta?.traceparent) {
299
+ const parsed = parseTraceParent(envelope.meta.traceparent);
300
+ if (parsed) {
301
+ return {
302
+ traceId: parsed.traceId,
303
+ spanId: messageSpanId,
304
+ parentSpanId: parsed.parentId,
305
+ sampled: parsed.sampled
306
+ };
307
+ }
308
+ this.options.telemetryController.emit({
309
+ name: "ws.trace.invalid",
310
+ level: "debug",
311
+ ...this.telemetryFields(),
312
+ detail: {
313
+ source: "message",
314
+ traceparent: envelope.meta.traceparent
315
+ }
316
+ });
317
+ }
318
+ return {
319
+ traceId: this.connectionTraceId,
320
+ spanId: messageSpanId,
321
+ parentSpanId: this.connectionSpanId ?? this.connectionParentSpanId,
322
+ sampled: this.connectionSampled
323
+ };
324
+ }
210
325
  async dispatchEnvelope(envelope) {
211
326
  const handlers = this.messageHandlers.get(envelope.event);
212
327
  const schema = this.eventSchemasIn[envelope.event];
213
328
  if (!schema) {
329
+ this.emitInboundRejected("unknownEvent", envelope.event);
214
330
  this.close(WS_CLOSE_CODE_POLICY_VIOLATION, "Unknown event");
215
331
  return;
216
332
  }
217
333
  const parsed = schema.safeParse(envelope.data);
218
334
  if (!parsed.success) {
335
+ this.emitInboundRejected("invalidData", envelope.event);
219
336
  this.close(WS_CLOSE_CODE_INVALID_FRAME_PAYLOAD_DATA, "Invalid event data");
220
337
  return;
221
338
  }
222
339
  if (!handlers || handlers.length === 0) {
223
340
  if (this.pendingMessages.length >= MAX_PENDING_MESSAGES) {
341
+ this.options.telemetryController.emit({
342
+ name: "ws.message.buffer.dropped",
343
+ level: "warn",
344
+ ...this.telemetryFields(),
345
+ detail: { event: envelope.event }
346
+ });
224
347
  this.pendingMessages.shift();
225
348
  }
226
349
  this.pendingMessages.push(envelope);
350
+ this.options.telemetryController.emit({
351
+ name: "ws.message.buffered",
352
+ level: "debug",
353
+ ...this.telemetryFields(),
354
+ detail: { event: envelope.event }
355
+ });
227
356
  return;
228
357
  }
229
- for (const handler of handlers) {
230
- await handler(parsed.data);
358
+ const traceCtx = this.resolveMessageTraceContext(envelope);
359
+ const messageTraceFields = {
360
+ connectionId: this.id,
361
+ namespace: this.namespace,
362
+ userId: this._userId,
363
+ traceId: traceCtx.traceId,
364
+ spanId: traceCtx.spanId,
365
+ parentSpanId: traceCtx.parentSpanId,
366
+ sampled: traceCtx.sampled
367
+ };
368
+ try {
369
+ for (const handler of handlers) {
370
+ await handler(parsed.data, traceCtx);
371
+ }
372
+ this.options.telemetryController.emit({
373
+ name: "ws.message.dispatched",
374
+ level: "debug",
375
+ ...messageTraceFields,
376
+ detail: { event: envelope.event }
377
+ });
378
+ this.options.telemetryController.recordMetric({
379
+ name: "sonamu.ws.messages",
380
+ kind: "counter",
381
+ value: 1,
382
+ unit: "1",
383
+ tags: {
384
+ direction: "inbound",
385
+ event: envelope.event,
386
+ outcome: "accepted"
387
+ },
388
+ ...messageTraceFields
389
+ });
390
+ } catch (error) {
391
+ this.options.telemetryController.emit({
392
+ name: "ws.message.failed",
393
+ level: "error",
394
+ ...messageTraceFields,
395
+ detail: { event: envelope.event }
396
+ });
397
+ throw error;
231
398
  }
232
399
  }
233
400
  flushPendingMessages(event) {
@@ -251,27 +418,69 @@ var init_ws = __esmMin((() => {
251
418
  publishValidated(event, data) {
252
419
  const schema = this.eventSchemasOut[event];
253
420
  if (!schema) {
421
+ this.options.telemetryController.emit({
422
+ name: "ws.publish.rejected",
423
+ level: "error",
424
+ ...this.telemetryFields(),
425
+ detail: {
426
+ event,
427
+ reason: "unknownEvent"
428
+ }
429
+ });
254
430
  throw new Error(`Unknown websocket event: ${event}`);
255
431
  }
256
432
  const parsed = schema.safeParse(data);
257
433
  if (!parsed.success) {
434
+ this.options.telemetryController.emit({
435
+ name: "ws.publish.rejected",
436
+ level: "error",
437
+ ...this.telemetryFields(),
438
+ detail: {
439
+ event,
440
+ reason: "invalidPayload"
441
+ }
442
+ });
258
443
  throw new Error(`Invalid websocket event payload: ${event}`);
259
444
  }
260
445
  if (this.closedInternal || this.socket.readyState !== WS_OPEN) {
446
+ this.options.telemetryController.emit({
447
+ name: "ws.publish.dropped",
448
+ level: "debug",
449
+ ...this.telemetryFields(),
450
+ detail: {
451
+ event,
452
+ reason: "connectionClosed"
453
+ }
454
+ });
261
455
  return;
262
456
  }
263
457
  this.enqueueOutboundMessage(JSON.stringify({
264
458
  event,
265
459
  data: parsed.data
266
- }));
460
+ }), event, parsed.data);
267
461
  }
268
- markClosed() {
462
+ markClosed(code, _reason) {
269
463
  if (this.closedInternal) {
270
464
  return;
271
465
  }
272
466
  this.closedInternal = true;
273
467
  this.closeStarted = false;
274
468
  this.stopHeartbeat();
469
+ const fields = this.telemetryFields();
470
+ this.options.telemetryController.emit({
471
+ name: "ws.connection.closed",
472
+ level: "info",
473
+ ...fields
474
+ });
475
+ if (this.options.telemetryController.getTraceOptions().recordConnectionLifetimeSpan) {
476
+ this.options.telemetryController.recordSpan({
477
+ operationName: "ws.connection.lifetime",
478
+ kind: "server",
479
+ durationMs: performance.now() - this.connectionStartedAt,
480
+ status: deriveLifetimeStatus(code),
481
+ ...fields
482
+ });
483
+ }
275
484
  this.socket.off("message", this.handleMessage);
276
485
  this.socket.off("close", this.handleClose);
277
486
  this.socket.off("error", this.handleError);
@@ -299,6 +508,11 @@ var init_ws = __esmMin((() => {
299
508
  return;
300
509
  }
301
510
  if (this.awaitingPong) {
511
+ this.options.telemetryController.emit({
512
+ name: "ws.heartbeat.timeout",
513
+ level: "warn",
514
+ ...this.telemetryFields()
515
+ });
302
516
  this.close(WS_CLOSE_CODE_GOING_AWAY, "Heartbeat timeout");
303
517
  return;
304
518
  }
@@ -336,12 +550,27 @@ var init_ws = __esmMin((() => {
336
550
  this.close(WS_CLOSE_CODE_INTERNAL_ERROR, "Message handling failed");
337
551
  });
338
552
  }
339
- enqueueOutboundMessage(payload) {
553
+ enqueueOutboundMessage(payload, event, data) {
340
554
  if (this.pendingOutboundMessages.length >= MAX_PENDING_OUTBOUND_MESSAGES) {
555
+ this.options.telemetryController.emit({
556
+ name: "ws.backpressure.overflow",
557
+ level: "error",
558
+ ...this.telemetryFields()
559
+ });
341
560
  this.close(WS_CLOSE_CODE_TRY_AGAIN_LATER, "WebSocket backpressure overflow");
342
561
  return;
343
562
  }
344
- this.pendingOutboundMessages.push(payload);
563
+ this.pendingOutboundMessages.push({
564
+ payload,
565
+ event
566
+ });
567
+ this.options.telemetryController.emit({
568
+ name: "ws.publish.queued",
569
+ level: "debug",
570
+ ...this.telemetryFields(),
571
+ detail: { event },
572
+ payload: data
573
+ });
345
574
  this.scheduleOutboundFlush();
346
575
  }
347
576
  scheduleOutboundFlush(delayMs = 0) {
@@ -364,18 +593,68 @@ var init_ws = __esmMin((() => {
364
593
  return;
365
594
  }
366
595
  if (this.socket.bufferedAmount > MAX_SOCKET_BUFFERED_AMOUNT) {
596
+ this.options.telemetryController.emit({
597
+ name: "ws.backpressure.delayed",
598
+ level: "warn",
599
+ ...this.telemetryFields()
600
+ });
367
601
  this.scheduleOutboundFlush(OUTBOUND_RETRY_DELAY_MS);
368
602
  return;
369
603
  }
370
604
  let sent = 0;
371
605
  while (sent < OUTBOUND_BATCH_SIZE && this.pendingOutboundMessages.length > 0 && this.socket.readyState === WS_OPEN) {
372
- const payload = this.pendingOutboundMessages.shift();
373
- if (!payload) {
606
+ const next = this.pendingOutboundMessages.shift();
607
+ if (!next) {
374
608
  break;
375
609
  }
610
+ const { payload, event } = next;
611
+ const startedAt = performance.now();
612
+ const fields = this.telemetryFields();
376
613
  try {
377
614
  this.socket.send(payload);
378
- } catch {
615
+ const durationMs = performance.now() - startedAt;
616
+ this.options.telemetryController.emit({
617
+ name: "ws.publish.sent",
618
+ level: "debug",
619
+ ...fields,
620
+ detail: { event }
621
+ });
622
+ this.options.telemetryController.recordSpan({
623
+ operationName: "ws.publish.send",
624
+ kind: "producer",
625
+ durationMs,
626
+ status: "unset",
627
+ ...fields,
628
+ attributes: { event }
629
+ });
630
+ this.options.telemetryController.recordMetric({
631
+ name: "sonamu.ws.publishes",
632
+ kind: "counter",
633
+ value: 1,
634
+ unit: "1",
635
+ tags: {
636
+ outcome: "sent",
637
+ event
638
+ },
639
+ ...fields
640
+ });
641
+ } catch (error) {
642
+ const durationMs = performance.now() - startedAt;
643
+ this.options.telemetryController.emit({
644
+ name: "ws.publish.failed",
645
+ level: "error",
646
+ ...fields,
647
+ detail: { event }
648
+ });
649
+ this.options.telemetryController.recordSpan({
650
+ operationName: "ws.publish.send",
651
+ kind: "producer",
652
+ durationMs,
653
+ status: "error",
654
+ ...fields,
655
+ attributes: { event },
656
+ errorType: error instanceof Error ? error.name : typeof error
657
+ });
379
658
  this.close(WS_CLOSE_CODE_INTERNAL_ERROR, "Outbound publish failed");
380
659
  return;
381
660
  }
@@ -394,4 +673,4 @@ var init_ws = __esmMin((() => {
394
673
  //#endregion
395
674
  init_ws();
396
675
  export { WebSocketRuntime, createWebSocketRuntime, init_ws };
397
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MuanMiLCJuYW1lcyI6WyJ6IiwicmVnaXN0cnlPcHRpb25zOiBXZWJTb2NrZXRSZWdpc3RyeU9wdGlvbnMiLCJzb2NrZXQ6IFdlYlNvY2tldCIsIm9wdGlvbnM6IFdlYlNvY2tldENvbm5lY3Rpb25PcHRpb25zPFRPdXRTY2hlbWEsIFRJblNjaGVtYT4iLCJyZXNvbHZlQ2xvc2VQcm9taXNlITogKCkgPT4gdm9pZCIsInJlbWFpbmluZzogUGFyc2VkRW52ZWxvcGVbXSIsInRvRmx1c2g6IFBhcnNlZEVudmVsb3BlW10iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWFtL3dzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcblxuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0QXVkaWVuY2UgfSBmcm9tIFwiLi93cy1hdWRpZW5jZVwiO1xuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXRDbHVzdGVyQnVzIH0gZnJvbSBcIi4vd3MtY2x1c3Rlci1idXNcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0UHJlc2VuY2VTdG9yZSB9IGZyb20gXCIuL3dzLXByZXNlbmNlLXN0b3JlXCI7XG5pbXBvcnQge1xuICB0eXBlIE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uLFxuICBXZWJTb2NrZXRSZWdpc3RyeSxcbiAgdHlwZSBXZWJTb2NrZXRSZWdpc3RyeU9wdGlvbnMsXG4gIHR5cGUgV2ViU29ja2V0Um9vbUlkLFxuICB0eXBlIFdlYlNvY2tldFVzZXJJZCxcbn0gZnJvbSBcIi4vd3MtcmVnaXN0cnlcIjtcblxuLy8gdHJhbnNwb3J0LWxldmVsIOyDgeyImOyZgCBxdWV1ZSB0aHJlc2hvbGTrpbwg7ZWcIO2MjOydvOyXkCDrqqjslYQgbGlmZWN5Y2xlL2JhY2twcmVzc3VyZSDsoJXssYXsnYQg7KSR7JWZ7ZmU7ZWoXG5jb25zdCBXU19DT05ORUNUSU5HID0gMDtcbmNvbnN0IFdTX09QRU4gPSAxO1xuY29uc3QgV1NfQ0xPU0VEID0gMztcbi8vIFJGQyA2NDU1IGNsb3NlIGNvZGVzIHVzZWQgYnkgU29uYW11J3MgV2ViU29ja2V0IHJ1bnRpbWUuXG5jb25zdCBXU19DTE9TRV9DT0RFX0dPSU5HX0FXQVkgPSAxMDAxO1xuY29uc3QgV1NfQ0xPU0VfQ09ERV9JTlZBTElEX0ZSQU1FX1BBWUxPQURfREFUQSA9IDEwMDc7XG5jb25zdCBXU19DTE9TRV9DT0RFX1BPTElDWV9WSU9MQVRJT04gPSAxMDA4O1xuY29uc3QgV1NfQ0xPU0VfQ09ERV9NRVNTQUdFX1RPT19CSUcgPSAxMDA5O1xuY29uc3QgV1NfQ0xPU0VfQ09ERV9JTlRFUk5BTF9FUlJPUiA9IDEwMTE7XG5jb25zdCBXU19DTE9TRV9DT0RFX1RSWV9BR0FJTl9MQVRFUiA9IDEwMTM7XG5jb25zdCBNQVhfUEVORElOR19NRVNTQUdFUyA9IDEwMDtcbmNvbnN0IE1BWF9QRU5ESU5HX09VVEJPVU5EX01FU1NBR0VTID0gMV8wMDA7XG5jb25zdCBNQVhfU09DS0VUX0JVRkZFUkVEX0FNT1VOVCA9IDFfMDQ4XzU3NjtcbmNvbnN0IE9VVEJPVU5EX0JBVENIX1NJWkUgPSA1MDtcbmNvbnN0IE9VVEJPVU5EX1JFVFJZX0RFTEFZX01TID0gNTtcblxuLy8gZW52ZWxvcGXsnYQgYHtldmVudCwgZGF0YX1gIO2Yle2DnOuhnCDqs6DsoJXtlbQgc2VydmVyIGhhbmRsZXLsmYAgZ2VuZXJhdGVkIGNsaWVudOqwgCDqsJnsnYAgZnJhbWluZyBjb250cmFjdOulvCDsk7Dqsowg7ZWoXG5jb25zdCBXZWJTb2NrZXRFbnZlbG9wZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZXZlbnQ6IHouc3RyaW5nKCksXG4gIGRhdGE6IHoudW5rbm93bigpLFxufSk7XG5cbnR5cGUgTWVzc2FnZUhhbmRsZXI8VD4gPSAoZGF0YTogVCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG50eXBlIENsb3NlSGFuZGxlciA9ICgpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRFdmVudE1hcCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG50eXBlIEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VFNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGU+ID0gei5pbmZlcjx6LlpvZE9iamVjdDxUU2NoZW1hPj47XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldE91dEV2ZW50czxUT3V0IGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcD4gPSBUT3V0O1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRJbkV2ZW50czxUSW4gZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCA9IFdlYlNvY2tldEV2ZW50TWFwPiA9IFRJbjtcblxuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRDb25uZWN0aW9uPFxuICBUT3V0IGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcCxcbiAgVEluIGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcCxcbj4gZXh0ZW5kcyBNYW5hZ2VkV2ViU29ja2V0Q29ubmVjdGlvbiB7XG4gIHRyYW5zcG9ydDogXCJ3c1wiO1xuICBvbkNsb3NlKGNhbGxiYWNrOiBDbG9zZUhhbmRsZXIpOiB2b2lkO1xuICBvbk1lc3NhZ2U8SyBleHRlbmRzIGtleW9mIFdlYlNvY2tldEluRXZlbnRzPFRJbj4+KFxuICAgIGV2ZW50OiBLLFxuICAgIGhhbmRsZXI6IE1lc3NhZ2VIYW5kbGVyPFdlYlNvY2tldEluRXZlbnRzPFRJbj5bS10+LFxuICApOiB2b2lkO1xuICBwdWJsaXNoPEsgZXh0ZW5kcyBrZXlvZiBXZWJTb2NrZXRPdXRFdmVudHM8VE91dD4+KFxuICAgIGV2ZW50OiBLLFxuICAgIGRhdGE6IFdlYlNvY2tldE91dEV2ZW50czxUT3V0PltLXSxcbiAgKTogdm9pZDtcbiAgd2FpdEZvckNsb3NlKCk6IFByb21pc2U8dm9pZD47XG4gIGpvaW4ocm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkO1xuICBsZWF2ZShyb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IHZvaWQ7XG4gIHNldFVzZXJJZCh1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCk6IHZvaWQ7XG4gIGNsZWFyVXNlcklkKCk6IHZvaWQ7XG59XG5cbmV4cG9ydCB0eXBlIEFueVdlYlNvY2tldENvbm5lY3Rpb24gPSBXZWJTb2NrZXRDb25uZWN0aW9uPFdlYlNvY2tldEV2ZW50TWFwLCBXZWJTb2NrZXRFdmVudE1hcD47XG5cbnR5cGUgUGFyc2VkRW52ZWxvcGUgPSB6LmluZmVyPHR5cGVvZiBXZWJTb2NrZXRFbnZlbG9wZVNjaGVtYT47XG5cbnR5cGUgV2ViU29ja2V0Q29ubmVjdGlvbk9wdGlvbnM8VE91dCBleHRlbmRzIHouWm9kUmF3U2hhcGUsIFRJbiBleHRlbmRzIHouWm9kUmF3U2hhcGU+ID0ge1xuICBuYW1lc3BhY2U/OiBzdHJpbmc7XG4gIGhlYXJ0YmVhdD86IG51bWJlcjtcbiAgbWF4UGF5bG9hZD86IG51bWJlcjtcbiAgYWN0aXZlPzogYm9vbGVhbjtcbiAgb3V0RXZlbnRzOiB6LlpvZE9iamVjdDxUT3V0PjtcbiAgaW5FdmVudHM6IHouWm9kT2JqZWN0PFRJbj47XG4gIHJlZ2lzdHJ5OiBXZWJTb2NrZXRSZWdpc3RyeTtcbn07XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldFJ1bnRpbWVPcHRpb25zID0ge1xuICBub2RlSWQ/OiBzdHJpbmc7XG4gIHByZXNlbmNlU3RvcmU/OiBXZWJTb2NrZXRQcmVzZW5jZVN0b3JlO1xuICBjbHVzdGVyQnVzPzogV2ViU29ja2V0Q2x1c3RlckJ1cztcbn07XG5cbi8vIHJlZ2lzdHJ566W8IOyGjOycoO2VmOqzoCBjb25uZWN0aW9uIOyDneyEsS9zaHV0ZG93buydhCDri7Tri7ntlaguIFNvbmFtdSDslaDtlIzrpqzsvIDsnbTshZgg7IiY66qF7KO86riw7JmAIOqwmeydtCDsm4Dsp4HsnbTrj4TroZ0g7ISk6rOE7ZWoXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0UnVudGltZSB7XG4gIHJlYWRvbmx5IHJlZ2lzdHJ5OiBXZWJTb2NrZXRSZWdpc3RyeTtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBXZWJTb2NrZXRSdW50aW1lT3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgcmVnaXN0cnlPcHRpb25zOiBXZWJTb2NrZXRSZWdpc3RyeU9wdGlvbnMgPSB7XG4gICAgICBub2RlSWQ6IG9wdGlvbnMubm9kZUlkLFxuICAgICAgcHJlc2VuY2VTdG9yZTogb3B0aW9ucy5wcmVzZW5jZVN0b3JlLFxuICAgICAgY2x1c3RlckJ1czogb3B0aW9ucy5jbHVzdGVyQnVzLFxuICAgIH07XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBXZWJTb2NrZXRSZWdpc3RyeShyZWdpc3RyeU9wdGlvbnMpO1xuICB9XG5cbiAgcmVnaXN0ZXJDb25uZWN0aW9uPFRPdXRTY2hlbWEgZXh0ZW5kcyB6LlpvZFJhd1NoYXBlLCBUSW5TY2hlbWEgZXh0ZW5kcyB6LlpvZFJhd1NoYXBlPihcbiAgICBzb2NrZXQ6IFdlYlNvY2tldCxcbiAgICBvcHRpb25zOiBPbWl0PFdlYlNvY2tldENvbm5lY3Rpb25PcHRpb25zPFRPdXRTY2hlbWEsIFRJblNjaGVtYT4sIFwicmVnaXN0cnlcIj4sXG4gICk6IFdlYlNvY2tldENvbm5lY3Rpb248SW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUT3V0U2NoZW1hPiwgSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUSW5TY2hlbWE+PiB7XG4gICAgcmV0dXJuIG5ldyBXZWJTb2NrZXRDb25uZWN0aW9uSW1wbChzb2NrZXQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICByZWdpc3RyeTogdGhpcy5yZWdpc3RyeSxcbiAgICB9KTtcbiAgfVxuXG4gIGFjdGl2YXRlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVnaXN0cnkuYWN0aXZhdGUoY29ubmVjdGlvbklkKTtcbiAgfVxuXG4gIGJyb2FkY2FzdChldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duLCBuYW1lc3BhY2U/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lzdHJ5LmJyb2FkY2FzdChldmVudCwgZGF0YSwgbmFtZXNwYWNlKTtcbiAgfVxuXG4gIHB1Ymxpc2hUb1Jvb20ocm9vbUlkOiBXZWJTb2NrZXRSb29tSWQsIGV2ZW50OiBzdHJpbmcsIGRhdGE6IHVua25vd24sIG5hbWVzcGFjZT86IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVnaXN0cnkucHVibGlzaFRvUm9vbShyb29tSWQsIGV2ZW50LCBkYXRhLCBuYW1lc3BhY2UpO1xuICB9XG5cbiAgcHVibGlzaFRvVXNlcih1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCwgZXZlbnQ6IHN0cmluZywgZGF0YTogdW5rbm93biwgbmFtZXNwYWNlPzogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpc3RyeS5wdWJsaXNoVG9Vc2VyKHVzZXJJZCwgZXZlbnQsIGRhdGEsIG5hbWVzcGFjZSk7XG4gIH1cblxuICBwdWJsaXNoVG9BdWRpZW5jZShhdWRpZW5jZTogV2ViU29ja2V0QXVkaWVuY2UsIGV2ZW50OiBzdHJpbmcsIGRhdGE6IHVua25vd24pOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lzdHJ5LnB1Ymxpc2hUb0F1ZGllbmNlKGF1ZGllbmNlLCBldmVudCwgZGF0YSk7XG4gIH1cblxuICAvLyDtlITroZzshLjsiqQg7KKF66OMIOyLnCDsgrTslYTsnojripQg7Jew6rKw7J20IOuCqOyngCDslYrrj4TroZ0gcmVnaXN0cnnrpbwg7Iic7ZqM7ZW0IOydvOq0hCDsooXro4ztlahcbiAgYXN5bmMgc2h1dGRvd24oXG4gICAgY29kZTogbnVtYmVyID0gV1NfQ0xPU0VfQ09ERV9HT0lOR19BV0FZLFxuICAgIHJlYXNvbiA9IFwiU2VydmVyIHNodXR0aW5nIGRvd25cIixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5yZWdpc3RyeS5zaHV0ZG93bihjb2RlLCByZWFzb24pO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVXZWJTb2NrZXRSdW50aW1lKG9wdGlvbnM6IFdlYlNvY2tldFJ1bnRpbWVPcHRpb25zID0ge30pOiBXZWJTb2NrZXRSdW50aW1lIHtcbiAgcmV0dXJuIG5ldyBXZWJTb2NrZXRSdW50aW1lKG9wdGlvbnMpO1xufVxuXG5jbGFzcyBXZWJTb2NrZXRDb25uZWN0aW9uSW1wbDxcbiAgVE91dFNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGUsXG4gIFRJblNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGUsXG4+IGltcGxlbWVudHMgV2ViU29ja2V0Q29ubmVjdGlvbjxcbiAgSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUT3V0U2NoZW1hPixcbiAgSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUSW5TY2hlbWE+XG4+IHtcbiAgcmVhZG9ubHkgaWQgPSByYW5kb21VVUlEKCk7XG4gIHJlYWRvbmx5IHRyYW5zcG9ydCA9IFwid3NcIjtcbiAgcmVhZG9ubHkgbmFtZXNwYWNlOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjbG9zZUNhbGxiYWNrczogQ2xvc2VIYW5kbGVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBtZXNzYWdlSGFuZGxlcnMgPSBuZXcgTWFwPHN0cmluZywgQXJyYXk8TWVzc2FnZUhhbmRsZXI8dW5rbm93bj4+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdNZXNzYWdlczogUGFyc2VkRW52ZWxvcGVbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGNsb3NlUHJvbWlzZTogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSByZWFkb25seSByZXNvbHZlQ2xvc2VQcm9taXNlOiAoKSA9PiB2b2lkO1xuICBwcml2YXRlIHJlYWRvbmx5IGhlYXJ0YmVhdE1zOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWF4UGF5bG9hZD86IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBldmVudFNjaGVtYXNJbjogUmVjb3JkPHN0cmluZywgei5ab2RUeXBlQW55PjtcbiAgcHJpdmF0ZSByZWFkb25seSBldmVudFNjaGVtYXNPdXQ6IFJlY29yZDxzdHJpbmcsIHouWm9kVHlwZUFueT47XG5cbiAgcHJpdmF0ZSBjbG9zZWRJbnRlcm5hbCA9IGZhbHNlO1xuICBwcml2YXRlIGNsb3NlU3RhcnRlZCA9IGZhbHNlO1xuICBwcml2YXRlIGF3YWl0aW5nUG9uZyA9IGZhbHNlO1xuICBwcml2YXRlIGhlYXJ0YmVhdFRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRJbnRlcnZhbD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBtZXNzYWdlUXVldWU6IFByb21pc2U8dm9pZD4gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgcHJpdmF0ZSBvdXRib3VuZEZsdXNoU2NoZWR1bGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzb2NrZXQ6IFdlYlNvY2tldCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IFdlYlNvY2tldENvbm5lY3Rpb25PcHRpb25zPFRPdXRTY2hlbWEsIFRJblNjaGVtYT4sXG4gICkge1xuICAgIHRoaXMubmFtZXNwYWNlID0gb3B0aW9ucy5uYW1lc3BhY2UgPz8gXCJkZWZhdWx0XCI7XG4gICAgdGhpcy5oZWFydGJlYXRNcyA9IG9wdGlvbnMuaGVhcnRiZWF0ID8/IDMwMDAwO1xuICAgIHRoaXMubWF4UGF5bG9hZCA9IG9wdGlvbnMubWF4UGF5bG9hZDtcbiAgICB0aGlzLmV2ZW50U2NoZW1hc0luID0gb3B0aW9ucy5pbkV2ZW50cy5zaGFwZSBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHouWm9kVHlwZUFueT47XG4gICAgdGhpcy5ldmVudFNjaGVtYXNPdXQgPSBvcHRpb25zLm91dEV2ZW50cy5zaGFwZSBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHouWm9kVHlwZUFueT47XG5cbiAgICBsZXQgcmVzb2x2ZUNsb3NlUHJvbWlzZSE6ICgpID0+IHZvaWQ7XG4gICAgdGhpcy5jbG9zZVByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgcmVzb2x2ZUNsb3NlUHJvbWlzZSA9IHJlc29sdmU7XG4gICAgfSk7XG4gICAgdGhpcy5yZXNvbHZlQ2xvc2VQcm9taXNlID0gcmVzb2x2ZUNsb3NlUHJvbWlzZTtcblxuICAgIHRoaXMub3B0aW9ucy5yZWdpc3RyeS5yZWdpc3Rlcih0aGlzLCBvcHRpb25zLmFjdGl2ZSA/PyB0cnVlKTtcbiAgICB0aGlzLnNvY2tldC5vbihcIm1lc3NhZ2VcIiwgdGhpcy5oYW5kbGVNZXNzYWdlKTtcbiAgICB0aGlzLnNvY2tldC5vbihcImNsb3NlXCIsIHRoaXMuaGFuZGxlQ2xvc2UpO1xuICAgIHRoaXMuc29ja2V0Lm9uKFwiZXJyb3JcIiwgdGhpcy5oYW5kbGVFcnJvcik7XG4gICAgdGhpcy5zb2NrZXQub24oXCJwb25nXCIsIHRoaXMuaGFuZGxlUG9uZyk7XG4gICAgdGhpcy5zdGFydEhlYXJ0YmVhdCgpO1xuICB9XG5cbiAgZ2V0IGNsb3NlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jbG9zZWRJbnRlcm5hbDtcbiAgfVxuXG4gIG9uQ2xvc2UoY2FsbGJhY2s6IENsb3NlSGFuZGxlcik6IHZvaWQge1xuICAgIHRoaXMuY2xvc2VDYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gIH1cblxuICBvbk1lc3NhZ2U8SyBleHRlbmRzIGtleW9mIEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VEluU2NoZW1hPj4oXG4gICAgZXZlbnQ6IEssXG4gICAgaGFuZGxlcjogTWVzc2FnZUhhbmRsZXI8SW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUSW5TY2hlbWE+W0tdPixcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgZXZlbnRLZXkgPSBTdHJpbmcoZXZlbnQpO1xuICAgIGNvbnN0IGhhbmRsZXJzID0gdGhpcy5tZXNzYWdlSGFuZGxlcnMuZ2V0KGV2ZW50S2V5KSA/PyBbXTtcbiAgICBoYW5kbGVycy5wdXNoKGhhbmRsZXIgYXMgTWVzc2FnZUhhbmRsZXI8dW5rbm93bj4pO1xuICAgIHRoaXMubWVzc2FnZUhhbmRsZXJzLnNldChldmVudEtleSwgaGFuZGxlcnMpO1xuICAgIHRoaXMuZmx1c2hQZW5kaW5nTWVzc2FnZXMoZXZlbnRLZXkpO1xuICB9XG5cbiAgcHVibGlzaDxLIGV4dGVuZHMga2V5b2YgSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUT3V0U2NoZW1hPj4oXG4gICAgZXZlbnQ6IEssXG4gICAgZGF0YTogSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUT3V0U2NoZW1hPltLXSxcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5wdWJsaXNoVmFsaWRhdGVkKFN0cmluZyhldmVudCksIGRhdGEpO1xuICB9XG5cbiAgcHVibGlzaFVudHlwZWQoZXZlbnQ6IHN0cmluZywgZGF0YTogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMucHVibGlzaFZhbGlkYXRlZChldmVudCwgZGF0YSk7XG4gIH1cblxuICB3YWl0Rm9yQ2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuY2xvc2VQcm9taXNlO1xuICB9XG5cbiAgam9pbihyb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IHZvaWQge1xuICAgIHRoaXMub3B0aW9ucy5yZWdpc3RyeS5qb2luKHRoaXMuaWQsIHJvb21JZCk7XG4gIH1cblxuICBsZWF2ZShyb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IHZvaWQge1xuICAgIHRoaXMub3B0aW9ucy5yZWdpc3RyeS5sZWF2ZSh0aGlzLmlkLCByb29tSWQpO1xuICB9XG5cbiAgc2V0VXNlcklkKHVzZXJJZDogV2ViU29ja2V0VXNlcklkKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LnNldFVzZXJJZCh0aGlzLmlkLCB1c2VySWQpO1xuICB9XG5cbiAgY2xlYXJVc2VySWQoKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LmNsZWFyVXNlcklkKHRoaXMuaWQpO1xuICB9XG5cbiAgLy8gdHJhbnNwb3J0IOyiheujjCDrj4TspJEg7JiI7Jm46rCAIOuCmOuPhCBtYXJrQ2xvc2Vk6rCAIOuwmOuTnOyLnCDsi6TtlonrkJjrj4TroZ0gdHJ5L2ZpbmFsbHnroZwg6rCQ7IyIXG4gIGNsb3NlKGNvZGU/OiBudW1iZXIsIHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuY2xvc2VTdGFydGVkIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgPT09IFdTX0NMT1NFRCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2xvc2VTdGFydGVkID0gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5jbG9zZVRyYW5zcG9ydChjb2RlLCByZWFzb24pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm1hcmtDbG9zZWQoKTtcbiAgICB9XG4gIH1cblxuICAvLyDsnbjrsJTsmrTrk5wg66mU7Iuc7KeA66W8IOyInOywqCDsspjrpqwg7YGQ7JeQIOyYrOumvC4gcGF5bG9hZCBzaXplIOKGkiBlbnZlbG9wZSDtjIzsi7Eg7Iic7Jy866GcIHRyYW5zcG9ydCDroIjrsqgg6rKA7Kad7J2EIOyasOyEoCDsiJjtlontlahcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVNZXNzYWdlID0gKHJhdzogdW5rbm93bikgPT4ge1xuICAgIHRoaXMuZW5xdWV1ZU1lc3NhZ2VUYXNrKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRleHQgPSBub3JtYWxpemVNZXNzYWdlKHJhdyk7XG4gICAgICBpZiAodGhpcy5tYXhQYXlsb2FkICE9PSB1bmRlZmluZWQgJiYgQnVmZmVyLmJ5dGVMZW5ndGgodGV4dCkgPiB0aGlzLm1heFBheWxvYWQpIHtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX01FU1NBR0VfVE9PX0JJRywgXCJNZXNzYWdlIHRvbyBsYXJnZVwiKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJzZWRFbnZlbG9wZSA9IHNhZmVQYXJzZUVudmVsb3BlKHRleHQpO1xuICAgICAgaWYgKCFwYXJzZWRFbnZlbG9wZSkge1xuICAgICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfSU5WQUxJRF9GUkFNRV9QQVlMT0FEX0RBVEEsIFwiSW52YWxpZCBtZXNzYWdlIHBheWxvYWRcIik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LnRvdWNoKHRoaXMuaWQpO1xuICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaEVudmVsb3BlKHBhcnNlZEVudmVsb3BlKTtcbiAgICB9KTtcbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZUNsb3NlID0gKCkgPT4ge1xuICAgIHRoaXMubWFya0Nsb3NlZCgpO1xuICB9O1xuXG4gIC8vIOyGjOy8k+ydtCB0cmFuc3BvcnQgZXJyb3LrpbwgZW1pdO2VmOuptCDsponsi5wgMTAxMSBjbG9zZeuhnCDsiJjroLTsi5zsvJwg7IOB7YOcIOuIhOudveydhCDrp4nsnYxcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVFcnJvciA9ICgpID0+IHtcbiAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfSU5URVJOQUxfRVJST1IsIFwiV2ViU29ja2V0IHRyYW5zcG9ydCBlcnJvclwiKTtcbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZVBvbmcgPSAoKSA9PiB7XG4gICAgdGhpcy5hd2FpdGluZ1BvbmcgPSBmYWxzZTtcbiAgICB0aGlzLm9wdGlvbnMucmVnaXN0cnkudG91Y2godGhpcy5pZCk7XG4gIH07XG5cbiAgLy8gZXZlbnQg7KG07J6sIOyXrOu2gCDihpIgc2NoZW1hIOqygOymnSDihpIgaGFuZGxlciDsi6Ttlokg7Iic7Jy866GcIOu2hOq4sO2VqFxuICAvLyBoYW5kbGVy6rCAIOyVhOyngSDrk7HroZ3rkJjsp4Ag7JWK7J2AIOy0iOq4sCDrqZTsi5zsp4DripQg67KE7Y287JeQIOuztOq0gO2WiOuLpOqwgCBvbk1lc3NhZ2Ug65Ox66GdIOyLnCBmbHVzaO2VqFxuICAvLyBoYW5kbGVy64qUIGBhd2FpdGDsnLzroZwg7Iic7LCoIOyLpO2Wie2VtCDtlZwgY29ubmVjdGlvbiDslYjsnZgg66mU7Iuc7KeAIOyInOyEnOulvCDrs7TsnqXtlahcbiAgcHJpdmF0ZSBhc3luYyBkaXNwYXRjaEVudmVsb3BlKGVudmVsb3BlOiBQYXJzZWRFbnZlbG9wZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGhhbmRsZXJzID0gdGhpcy5tZXNzYWdlSGFuZGxlcnMuZ2V0KGVudmVsb3BlLmV2ZW50KTtcbiAgICBjb25zdCBzY2hlbWEgPSB0aGlzLmV2ZW50U2NoZW1hc0luW2VudmVsb3BlLmV2ZW50XTtcblxuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfUE9MSUNZX1ZJT0xBVElPTiwgXCJVbmtub3duIGV2ZW50XCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHNjaGVtYS5zYWZlUGFyc2UoZW52ZWxvcGUuZGF0YSk7XG4gICAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVkFMSURfRlJBTUVfUEFZTE9BRF9EQVRBLCBcIkludmFsaWQgZXZlbnQgZGF0YVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWhhbmRsZXJzIHx8IGhhbmRsZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKHRoaXMucGVuZGluZ01lc3NhZ2VzLmxlbmd0aCA+PSBNQVhfUEVORElOR19NRVNTQUdFUykge1xuICAgICAgICB0aGlzLnBlbmRpbmdNZXNzYWdlcy5zaGlmdCgpO1xuICAgICAgfVxuICAgICAgdGhpcy5wZW5kaW5nTWVzc2FnZXMucHVzaChlbnZlbG9wZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG4gICAgICBhd2FpdCBoYW5kbGVyKHBhcnNlZC5kYXRhKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZsdXNoUGVuZGluZ01lc3NhZ2VzKGV2ZW50OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByZW1haW5pbmc6IFBhcnNlZEVudmVsb3BlW10gPSBbXTtcbiAgICBjb25zdCB0b0ZsdXNoOiBQYXJzZWRFbnZlbG9wZVtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgdGhpcy5wZW5kaW5nTWVzc2FnZXMpIHtcbiAgICAgIGlmIChtZXNzYWdlLmV2ZW50ICE9PSBldmVudCkge1xuICAgICAgICByZW1haW5pbmcucHVzaChtZXNzYWdlKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRvRmx1c2gucHVzaChtZXNzYWdlKTtcbiAgICB9XG5cbiAgICB0aGlzLnBlbmRpbmdNZXNzYWdlcy5sZW5ndGggPSAwO1xuICAgIHRoaXMucGVuZGluZ01lc3NhZ2VzLnB1c2goLi4ucmVtYWluaW5nKTtcblxuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiB0b0ZsdXNoKSB7XG4gICAgICB0aGlzLmVucXVldWVNZXNzYWdlVGFzayhhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hFbnZlbG9wZShtZXNzYWdlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcHVibGlzaFZhbGlkYXRlZChldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duKTogdm9pZCB7XG4gICAgY29uc3Qgc2NoZW1hID0gdGhpcy5ldmVudFNjaGVtYXNPdXRbZXZlbnRdO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gd2Vic29ja2V0IGV2ZW50OiAke2V2ZW50fWApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHNjaGVtYS5zYWZlUGFyc2UoZGF0YSk7XG4gICAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHdlYnNvY2tldCBldmVudCBwYXlsb2FkOiAke2V2ZW50fWApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgIT09IFdTX09QRU4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmVucXVldWVPdXRib3VuZE1lc3NhZ2UoXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGV2ZW50LFxuICAgICAgICBkYXRhOiBwYXJzZWQuZGF0YSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICAvLyBsaXN0ZW5lciDtlbTsoJwgLyBoZWFydGJlYXQg7KSR64uoIC8gcGVuZGluZyBxdWV1ZSDruYTsm4AgLyByZWdpc3RyeSB1bnJlZ2lzdGVyIC8gb25DbG9zZSDsi6TtlokgLyB3YWl0Rm9yQ2xvc2UgcmVzb2x2ZSDsnYQg7ZWcIOqzs+yXkCDrqqjslYQg7JuQ7J6Q7KCB7Jy866GcIOyymOumrO2VqFxuICAvLyBhc3luYyBvbkNsb3Nl6rCAIHJlamVjdO2VtOuPhCB1bmhhbmRsZWQgcmVqZWN0aW9u7Jy866GcIOyDiOyngCDslYrrj4TroZ0gY2F0Y2jroZwg6rKp66as7ZWoXG4gIHByaXZhdGUgbWFya0Nsb3NlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jbG9zZWRJbnRlcm5hbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2xvc2VkSW50ZXJuYWwgPSB0cnVlO1xuICAgIHRoaXMuY2xvc2VTdGFydGVkID0gZmFsc2U7XG4gICAgdGhpcy5zdG9wSGVhcnRiZWF0KCk7XG4gICAgdGhpcy5zb2NrZXQub2ZmKFwibWVzc2FnZVwiLCB0aGlzLmhhbmRsZU1lc3NhZ2UpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcImNsb3NlXCIsIHRoaXMuaGFuZGxlQ2xvc2UpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcImVycm9yXCIsIHRoaXMuaGFuZGxlRXJyb3IpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcInBvbmdcIiwgdGhpcy5oYW5kbGVQb25nKTtcbiAgICB0aGlzLmF3YWl0aW5nUG9uZyA9IGZhbHNlO1xuICAgIHRoaXMucGVuZGluZ01lc3NhZ2VzLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcy5sZW5ndGggPSAwO1xuICAgIHRoaXMub3B0aW9ucy5yZWdpc3RyeS51bnJlZ2lzdGVyKHRoaXMuaWQpO1xuICAgIGZvciAoY29uc3QgY2FsbGJhY2sgb2YgdGhpcy5jbG9zZUNhbGxiYWNrcy5zcGxpY2UoMCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrKCk7XG4gICAgICAgIGlmIChpc1Byb21pc2VMaWtlKHJlc3VsdCkpIHtcbiAgICAgICAgICB2b2lkIHJlc3VsdC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAvLyBhc3luYyBjbG9zZSBjYWxsYmFja3MgbXVzdCBub3QgZXNjYXBlIGFzIHVuaGFuZGxlZCByZWplY3Rpb25zXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBjbG9zZSBjYWxsYmFja3MgbXVzdCBub3QgYmxvY2sgdHJhbnNwb3J0IGNsZWFudXBcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5yZXNvbHZlQ2xvc2VQcm9taXNlKCk7XG4gIH1cblxuICAvLyBwb25n7J20IOyYpOyngCDslYrsnYAg7IOB7YOc7JeQ7IScIOuLpOydjCB0aWNr7J20IOyYpOuptCB0aW1lb3V0IGNsb3Nl66GcIOyymOumrO2VtCB6b21iaWUgY29ubmVjdGlvbuydhCDsoJXrpqztlahcbiAgcHJpdmF0ZSBzdGFydEhlYXJ0YmVhdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5oZWFydGJlYXRNcyA8PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5oZWFydGJlYXRUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgIT09IFdTX09QRU4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5hd2FpdGluZ1BvbmcpIHtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0dPSU5HX0FXQVksIFwiSGVhcnRiZWF0IHRpbWVvdXRcIik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hd2FpdGluZ1BvbmcgPSB0cnVlO1xuICAgICAgdGhpcy5zb2NrZXQucGluZygpO1xuICAgIH0sIHRoaXMuaGVhcnRiZWF0TXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdG9wSGVhcnRiZWF0KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5oZWFydGJlYXRUaW1lcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNsZWFySW50ZXJ2YWwodGhpcy5oZWFydGJlYXRUaW1lcik7XG4gICAgdGhpcy5oZWFydGJlYXRUaW1lciA9IG51bGw7XG4gIH1cblxuICAvLyBjbG9zZeqwgCDsi6TtjKjtlbTrj4QgdGVybWluYXRlIO2PtOuwseq5jOyngCDsi5zrj4TtlZjqs6AsIOuBneuCtCDsi6TtjKjtlZjrqbQgbWFya0Nsb3NlZOyXkCDsg4Htg5wg7KCV66as66W8IOychOyehO2VqFxuICBwcml2YXRlIGNsb3NlVHJhbnNwb3J0KGNvZGU/OiBudW1iZXIsIHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5zb2NrZXQucmVhZHlTdGF0ZSA9PT0gV1NfT1BFTiB8fCB0aGlzLnNvY2tldC5yZWFkeVN0YXRlID09PSBXU19DT05ORUNUSU5HKSB7XG4gICAgICAgIHRoaXMuc29ja2V0LmNsb3NlKGNvZGUsIHRydW5jYXRlQ2xvc2VSZWFzb24ocmVhc29uKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zb2NrZXQudGVybWluYXRlKCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLnNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyB0cmFuc3BvcnQgaXMgYWxyZWFkeSBicm9rZW47IHN0YXRlIGNsZWFudXAgaXMgaGFuZGxlZCBieSBtYXJrQ2xvc2VkKClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyDsnbjrsJTsmrTrk5wgaGFuZGxlcuulvCBwcm9taXNlIGNoYWlu7Jy866GcIHNlcmlhbGl6ZSDtlZjqs6AsIGhhbmRsZXIg7JiI7Jm464qUIGNvbm5lY3Rpb24tbG9jYWwgMTAxMSBjbG9zZeuhnCDstpXshoztlahcbiAgcHJpdmF0ZSBlbnF1ZXVlTWVzc2FnZVRhc2sodGFzazogKCkgPT4gUHJvbWlzZTx2b2lkPik6IHZvaWQge1xuICAgIHRoaXMubWVzc2FnZVF1ZXVlID0gdGhpcy5tZXNzYWdlUXVldWVcbiAgICAgIC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VkSW50ZXJuYWwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0YXNrKCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVEVSTkFMX0VSUk9SLCBcIk1lc3NhZ2UgaGFuZGxpbmcgZmFpbGVkXCIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBxdWV1ZeqwgCDtlZzqs4Tsl5Ag64+E64us7ZWY66m0IDEwMTPsnLzroZwg64ur7JWEIOuKkOumsCDshozruYTsnpDqsIAg66mU66qo66as66W8IOuBneyXhuydtCDsnqHslYTrqLnsp4Ag66q77ZWY6rKMIO2VqFxuICBwcml2YXRlIGVucXVldWVPdXRib3VuZE1lc3NhZ2UocGF5bG9hZDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucGVuZGluZ091dGJvdW5kTWVzc2FnZXMubGVuZ3RoID49IE1BWF9QRU5ESU5HX09VVEJPVU5EX01FU1NBR0VTKSB7XG4gICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfVFJZX0FHQUlOX0xBVEVSLCBcIldlYlNvY2tldCBiYWNrcHJlc3N1cmUgb3ZlcmZsb3dcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcy5wdXNoKHBheWxvYWQpO1xuICAgIHRoaXMuc2NoZWR1bGVPdXRib3VuZEZsdXNoKCk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlT3V0Ym91bmRGbHVzaChkZWxheU1zOiBudW1iZXIgPSAwKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub3V0Ym91bmRGbHVzaFNjaGVkdWxlZCB8fCB0aGlzLmNsb3NlZEludGVybmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5vdXRib3VuZEZsdXNoU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICBjb25zdCBmbHVzaCA9ICgpID0+IHtcbiAgICAgIHRoaXMub3V0Ym91bmRGbHVzaFNjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5mbHVzaE91dGJvdW5kTWVzc2FnZXMoKTtcbiAgICB9O1xuXG4gICAgaWYgKGRlbGF5TXMgPiAwKSB7XG4gICAgICBzZXRUaW1lb3V0KGZsdXNoLCBkZWxheU1zKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzZXRJbW1lZGlhdGUoZmx1c2gpO1xuICB9XG5cbiAgLy8gYnVmZmVyZWRBbW91bnTqsIAg7J6E6rOE7LmY66W8IOuEmOycvOuptCBmbHVzaOulvCDrr7jrpIQgc29ja2V0IOuCtOu2gCDtgZDqsIAg7YSw7KeA7KeAIOyViuuPhOuhnSBiYWNrcHJlc3N1cmXrpbwg7KG07KSR7ZWoXG4gIC8vIO2VnCDrsojsl5Ag67Cw7LmYIOuLqOychOuhnOunjCBzZW5k7ZW0IOuPmeq4sCDro6jtlITqsIAg7J2067Kk7Yq4IOujqO2UhOulvCDsnqXsi5zqsIQg7KCQ7Jyg7ZWY7KeAIOyViuqyjCDtlahcbiAgcHJpdmF0ZSBmbHVzaE91dGJvdW5kTWVzc2FnZXMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY2xvc2VkSW50ZXJuYWwgfHwgdGhpcy5zb2NrZXQucmVhZHlTdGF0ZSAhPT0gV1NfT1BFTikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNvY2tldC5idWZmZXJlZEFtb3VudCA+IE1BWF9TT0NLRVRfQlVGRkVSRURfQU1PVU5UKSB7XG4gICAgICB0aGlzLnNjaGVkdWxlT3V0Ym91bmRGbHVzaChPVVRCT1VORF9SRVRSWV9ERUxBWV9NUyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNlbnQgPSAwO1xuICAgIHdoaWxlIChcbiAgICAgIHNlbnQgPCBPVVRCT1VORF9CQVRDSF9TSVpFICYmXG4gICAgICB0aGlzLnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzLmxlbmd0aCA+IDAgJiZcbiAgICAgIHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgPT09IFdTX09QRU5cbiAgICApIHtcbiAgICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzLnNoaWZ0KCk7XG4gICAgICBpZiAoIXBheWxvYWQpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuc29ja2V0LnNlbmQocGF5bG9hZCk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVEVSTkFMX0VSUk9SLCBcIk91dGJvdW5kIHB1Ymxpc2ggZmFpbGVkXCIpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHNlbnQgKz0gMTtcbiAgICAgIGlmICh0aGlzLnNvY2tldC5idWZmZXJlZEFtb3VudCA+IE1BWF9TT0NLRVRfQlVGRkVSRURfQU1PVU5UKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2NoZWR1bGVPdXRib3VuZEZsdXNoKFxuICAgICAgICB0aGlzLnNvY2tldC5idWZmZXJlZEFtb3VudCA+IE1BWF9TT0NLRVRfQlVGRkVSRURfQU1PVU5UID8gT1VUQk9VTkRfUkVUUllfREVMQVlfTVMgOiAwLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplTWVzc2FnZShyYXc6IHVua25vd24pOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIHJhdyA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiByYXc7XG4gIH1cblxuICBpZiAocmF3IGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgcmV0dXJuIHJhdy50b1N0cmluZyhcInV0Zi04XCIpO1xuICB9XG5cbiAgaWYgKHJhdyBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHJhdykudG9TdHJpbmcoXCJ1dGYtOFwiKTtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChyYXcuZmlsdGVyKChjaHVuayk6IGNodW5rIGlzIEJ1ZmZlciA9PiBjaHVuayBpbnN0YW5jZW9mIEJ1ZmZlcikpLnRvU3RyaW5nKFxuICAgICAgXCJ1dGYtOFwiLFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmF3KTtcbn1cblxuZnVuY3Rpb24gc2FmZVBhcnNlRW52ZWxvcGUocmF3OiBzdHJpbmcpOiBQYXJzZWRFbnZlbG9wZSB8IG51bGwge1xuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UocmF3KSBhcyB1bmtub3duO1xuICAgIGNvbnN0IHZhbGlkYXRlZCA9IFdlYlNvY2tldEVudmVsb3BlU2NoZW1hLnNhZmVQYXJzZShwYXJzZWQpO1xuICAgIHJldHVybiB2YWxpZGF0ZWQuc3VjY2VzcyA/IHZhbGlkYXRlZC5kYXRhIDogbnVsbDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLy8gUkZDIDY0NTXqsIAgY2xvc2UgZnJhbWUgcmVhc29u7J2EIDEyMyBieXRl66GcIOygnO2VnO2VmOuvgOuhnCDstIjqs7zrtoTsnYAg7J6Y6528IOyghOyGoSDsi6TtjKjrpbwg67Cp7KeA7ZWoXG5mdW5jdGlvbiB0cnVuY2F0ZUNsb3NlUmVhc29uKHJlYXNvbj86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghcmVhc29uKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBCdWZmZXIuYnl0ZUxlbmd0aChyZWFzb24sIFwidXRmLThcIikgPD0gMTIzXG4gICAgPyByZWFzb25cbiAgICA6IEJ1ZmZlci5mcm9tKHJlYXNvbikuc3ViYXJyYXkoMCwgMTIzKS50b1N0cmluZyhcInV0Zi04XCIpO1xufVxuXG5mdW5jdGlvbiBpc1Byb21pc2VMaWtlKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiYgdmFsdWUgIT09IG51bGwgJiYgXCJ0aGVuXCIgaW4gdmFsdWUgJiYgXCJjYXRjaFwiIGluIHZhbHVlO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUErSUEsU0FBZ0IsdUJBQXVCLFVBQW1DLEVBQUUsRUFBb0I7QUFDOUYsUUFBTyxJQUFJLGlCQUFpQixRQUFROztBQWladEMsU0FBUyxpQkFBaUIsS0FBc0I7QUFDOUMsS0FBSSxPQUFPLFFBQVEsVUFBVTtB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
676
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MuanMiLCJuYW1lcyI6WyJ6IiwicmVnaXN0cnlPcHRpb25zOiBXZWJTb2NrZXRSZWdpc3RyeU9wdGlvbnMiLCJzb2NrZXQ6IFdlYlNvY2tldCIsIm9wdGlvbnM6IFdlYlNvY2tldENvbm5lY3Rpb25PcHRpb25zPFRPdXRTY2hlbWEsIFRJblNjaGVtYT4iLCJyZXNvbHZlQ2xvc2VQcm9taXNlITogKCkgPT4gdm9pZCIsInJlbWFpbmluZzogUGFyc2VkRW52ZWxvcGVbXSIsInRvRmx1c2g6IFBhcnNlZEVudmVsb3BlW10iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWFtL3dzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IGhvc3RuYW1lIH0gZnJvbSBcIm5vZGU6b3NcIjtcblxuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0QXVkaWVuY2UgfSBmcm9tIFwiLi93cy1hdWRpZW5jZVwiO1xuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXRDbHVzdGVyQnVzIH0gZnJvbSBcIi4vd3MtY2x1c3Rlci1idXNcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0UHJlc2VuY2VTdG9yZSB9IGZyb20gXCIuL3dzLXByZXNlbmNlLXN0b3JlXCI7XG5pbXBvcnQge1xuICB0eXBlIE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uLFxuICBXZWJTb2NrZXRSZWdpc3RyeSxcbiAgdHlwZSBXZWJTb2NrZXRSZWdpc3RyeU9wdGlvbnMsXG4gIHR5cGUgV2ViU29ja2V0Um9vbUlkLFxuICB0eXBlIFdlYlNvY2tldFVzZXJJZCxcbn0gZnJvbSBcIi4vd3MtcmVnaXN0cnlcIjtcbmltcG9ydCB7XG4gIHR5cGUgVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyLFxuICB0eXBlIFdlYlNvY2tldFRlbGVtZXRyeUNvbm5lY3Rpb25TbmFwc2hvdCxcbiAgdHlwZSBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCxcbiAgdHlwZSBXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyLFxuICB0eXBlIFdlYlNvY2tldFRlbGVtZXRyeU9wdGlvbnMsXG4gIHR5cGUgVGVsZW1ldHJ5SW5zcGVjdGFibGVDb25uZWN0aW9uLFxuICBjcmVhdGVXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyLFxuICBpc1Byb21pc2VMaWtlLFxufSBmcm9tIFwiLi93cy10ZWxlbWV0cnlcIjtcbmltcG9ydCB7IHBhcnNlVHJhY2VQYXJlbnQsIGdlbmVyYXRlU3BhbklkIH0gZnJvbSBcIi4vd3MtdGVsZW1ldHJ5LXRyYWNlXCI7XG5cbi8vIHRyYW5zcG9ydC1sZXZlbCDsg4HsiJjsmYAgcXVldWUgdGhyZXNob2xk66W8IO2VnCDtjIzsnbzsl5Ag66qo7JWEIGxpZmVjeWNsZS9iYWNrcHJlc3N1cmUg7KCV7LGF7J2EIOykkeyVme2ZlO2VqFxuY29uc3QgV1NfQ09OTkVDVElORyA9IDA7XG5jb25zdCBXU19PUEVOID0gMTtcbmNvbnN0IFdTX0NMT1NFRCA9IDM7XG4vLyBSRkMgNjQ1NSBjbG9zZSBjb2RlcyB1c2VkIGJ5IFNvbmFtdSdzIFdlYlNvY2tldCBydW50aW1lLlxuY29uc3QgV1NfQ0xPU0VfQ09ERV9HT0lOR19BV0FZID0gMTAwMTtcbmNvbnN0IFdTX0NMT1NFX0NPREVfSU5WQUxJRF9GUkFNRV9QQVlMT0FEX0RBVEEgPSAxMDA3O1xuY29uc3QgV1NfQ0xPU0VfQ09ERV9QT0xJQ1lfVklPTEFUSU9OID0gMTAwODtcbmNvbnN0IFdTX0NMT1NFX0NPREVfSU5URVJOQUxfRVJST1IgPSAxMDExO1xuY29uc3QgV1NfQ0xPU0VfQ09ERV9UUllfQUdBSU5fTEFURVIgPSAxMDEzO1xuY29uc3QgTUFYX1BFTkRJTkdfTUVTU0FHRVMgPSAxMDA7XG5jb25zdCBNQVhfUEVORElOR19PVVRCT1VORF9NRVNTQUdFUyA9IDFfMDAwO1xuY29uc3QgTUFYX1NPQ0tFVF9CVUZGRVJFRF9BTU9VTlQgPSAxXzA0OF81NzY7XG5jb25zdCBPVVRCT1VORF9CQVRDSF9TSVpFID0gNTA7XG5jb25zdCBPVVRCT1VORF9SRVRSWV9ERUxBWV9NUyA9IDU7XG5cbi8vIGVudmVsb3Bl7J2EIGB7ZXZlbnQsIGRhdGF9YCDtmJXtg5zroZwg6rOg7KCV7ZW0IHNlcnZlciBoYW5kbGVy7JmAIGdlbmVyYXRlZCBjbGllbnTqsIAg6rCZ7J2AIGZyYW1pbmcgY29udHJhY3Trpbwg7JOw6rKMIO2VqFxuLy8gbWV0YeuKlCBvcHRpb25hbOydtOuvgOuhnCDquLDsobQgYHtldmVudCwgZGF0YX1gIOuplOyLnOyngOuPhCDqt7jrjIDroZwg7YyM7Iux65CoIChiYWNrd2FyZC1jb21wYXRpYmxlKVxuY29uc3QgV2ViU29ja2V0RW52ZWxvcGVTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGV2ZW50OiB6LnN0cmluZygpLFxuICBkYXRhOiB6LnVua25vd24oKSxcbiAgbWV0YTogelxuICAgIC5vYmplY3Qoe1xuICAgICAgdHJhY2VwYXJlbnQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICAgIHRyYWNlc3RhdGU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICB9KVxuICAgIC5vcHRpb25hbCgpLFxufSk7XG5cbnR5cGUgTWVzc2FnZUhhbmRsZXI8VD4gPSAoXG4gIGRhdGE6IFQsXG4gIHRlbGVtZXRyeUNvbnRleHQ/OiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCxcbikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG50eXBlIENsb3NlSGFuZGxlciA9ICgpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRFdmVudE1hcCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG50eXBlIEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VFNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGU+ID0gei5pbmZlcjx6LlpvZE9iamVjdDxUU2NoZW1hPj47XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldE91dEV2ZW50czxUT3V0IGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcD4gPSBUT3V0O1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRJbkV2ZW50czxUSW4gZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCA9IFdlYlNvY2tldEV2ZW50TWFwPiA9IFRJbjtcblxuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRDb25uZWN0aW9uPFxuICBUT3V0IGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcCxcbiAgVEluIGV4dGVuZHMgV2ViU29ja2V0RXZlbnRNYXAgPSBXZWJTb2NrZXRFdmVudE1hcCxcbj4gZXh0ZW5kcyBNYW5hZ2VkV2ViU29ja2V0Q29ubmVjdGlvbiB7XG4gIHRyYW5zcG9ydDogXCJ3c1wiO1xuICBvbkNsb3NlKGNhbGxiYWNrOiBDbG9zZUhhbmRsZXIpOiB2b2lkO1xuICBvbk1lc3NhZ2U8SyBleHRlbmRzIGtleW9mIFdlYlNvY2tldEluRXZlbnRzPFRJbj4+KFxuICAgIGV2ZW50OiBLLFxuICAgIGhhbmRsZXI6IE1lc3NhZ2VIYW5kbGVyPFdlYlNvY2tldEluRXZlbnRzPFRJbj5bS10+LFxuICApOiB2b2lkO1xuICBwdWJsaXNoPEsgZXh0ZW5kcyBrZXlvZiBXZWJTb2NrZXRPdXRFdmVudHM8VE91dD4+KFxuICAgIGV2ZW50OiBLLFxuICAgIGRhdGE6IFdlYlNvY2tldE91dEV2ZW50czxUT3V0PltLXSxcbiAgKTogdm9pZDtcbiAgd2FpdEZvckNsb3NlKCk6IFByb21pc2U8dm9pZD47XG4gIGpvaW4ocm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkO1xuICBsZWF2ZShyb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IHZvaWQ7XG4gIHNldFVzZXJJZCh1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCk6IHZvaWQ7XG4gIGNsZWFyVXNlcklkKCk6IHZvaWQ7XG59XG5cbmV4cG9ydCB0eXBlIEFueVdlYlNvY2tldENvbm5lY3Rpb24gPSBXZWJTb2NrZXRDb25uZWN0aW9uPFdlYlNvY2tldEV2ZW50TWFwLCBXZWJTb2NrZXRFdmVudE1hcD47XG5cbnR5cGUgUGFyc2VkRW52ZWxvcGUgPSB6LmluZmVyPHR5cGVvZiBXZWJTb2NrZXRFbnZlbG9wZVNjaGVtYT47XG5cbnR5cGUgV2ViU29ja2V0Q29ubmVjdGlvbk9wdGlvbnM8VE91dCBleHRlbmRzIHouWm9kUmF3U2hhcGUsIFRJbiBleHRlbmRzIHouWm9kUmF3U2hhcGU+ID0ge1xuICBuYW1lc3BhY2U/OiBzdHJpbmc7XG4gIGhlYXJ0YmVhdD86IG51bWJlcjtcbiAgYWN0aXZlPzogYm9vbGVhbjtcbiAgb3V0RXZlbnRzOiB6LlpvZE9iamVjdDxUT3V0PjtcbiAgaW5FdmVudHM6IHouWm9kT2JqZWN0PFRJbj47XG4gIHJlZ2lzdHJ5OiBXZWJTb2NrZXRSZWdpc3RyeTtcbiAgdGVsZW1ldHJ5Q29udHJvbGxlcjogV2ViU29ja2V0VGVsZW1ldHJ5Q29udHJvbGxlcjtcbiAgdHJhY2VJZD86IHN0cmluZztcbiAgc3BhbklkPzogc3RyaW5nO1xuICBwYXJlbnRTcGFuSWQ/OiBzdHJpbmc7XG4gIHNhbXBsZWQ/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgV2ViU29ja2V0UnVudGltZU9wdGlvbnMgPSB7XG4gIG5vZGVJZD86IHN0cmluZztcbiAgcHJlc2VuY2VTdG9yZT86IFdlYlNvY2tldFByZXNlbmNlU3RvcmU7XG4gIGNsdXN0ZXJCdXM/OiBXZWJTb2NrZXRDbHVzdGVyQnVzO1xuICB0ZWxlbWV0cnk/OiBib29sZWFuIHwgV2ViU29ja2V0VGVsZW1ldHJ5T3B0aW9ucztcbn07XG5cbi8vIHJlZ2lzdHJ566W8IOyGjOycoO2VmOqzoCBjb25uZWN0aW9uIOyDneyEsS9zaHV0ZG93buydhCDri7Tri7ntlaguIFNvbmFtdSDslaDtlIzrpqzsvIDsnbTshZgg7IiY66qF7KO86riw7JmAIOqwmeydtCDsm4Dsp4HsnbTrj4TroZ0g7ISk6rOE7ZWoXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0UnVudGltZSB7XG4gIHJlYWRvbmx5IHJlZ2lzdHJ5OiBXZWJTb2NrZXRSZWdpc3RyeTtcbiAgcmVhZG9ubHkgdGVsZW1ldHJ5Q29udHJvbGxlcjogV2ViU29ja2V0VGVsZW1ldHJ5Q29udHJvbGxlcjtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBXZWJTb2NrZXRSdW50aW1lT3B0aW9ucyA9IHt9KSB7XG4gICAgLy8g67aE7IKwIO2ZmOqyveyXkOyEnCDrhbjrk5wg6rCEIOy2qeuPjOydhCDrp4nquLAg7JyE7ZW0IGhvc3RuYW1lICsgcGlk66GcIOuUlO2PtO2KuCDsi53rs4TsnpDrpbwg66eM65Og64ukLlxuICAgIC8vIOqwmeydgCDtmLjsiqTtirjsl5Ag7Jes65+sIO2UhOuhnOyEuOyKpOqwgCDrlqAg7J6I7Ja064+EIHBpZOuhnCDqtazrtoTrkJjrqbAsIOuhnOq3uC/rqZTtirjrpq3sl5DshJzrj4Qg7Iud67OE7J20IOyJrOybgFxuICAgIGNvbnN0IHJlc29sdmVkTm9kZUlkID0gb3B0aW9ucy5ub2RlSWQgPz8gYCR7aG9zdG5hbWUoKX0tJHtwcm9jZXNzLnBpZH1gO1xuICAgIHRoaXMudGVsZW1ldHJ5Q29udHJvbGxlciA9IGNyZWF0ZVdlYlNvY2tldFRlbGVtZXRyeUNvbnRyb2xsZXIob3B0aW9ucy50ZWxlbWV0cnksIHtcbiAgICAgIHJ1bnRpbWVJZDogcmFuZG9tVVVJRCgpLFxuICAgICAgbm9kZUlkOiByZXNvbHZlZE5vZGVJZCxcbiAgICB9KTtcbiAgICBjb25zdCByZWdpc3RyeU9wdGlvbnM6IFdlYlNvY2tldFJlZ2lzdHJ5T3B0aW9ucyA9IHtcbiAgICAgIG5vZGVJZDogcmVzb2x2ZWROb2RlSWQsXG4gICAgICBwcmVzZW5jZVN0b3JlOiBvcHRpb25zLnByZXNlbmNlU3RvcmUsXG4gICAgICBjbHVzdGVyQnVzOiBvcHRpb25zLmNsdXN0ZXJCdXMsXG4gICAgICB0ZWxlbWV0cnlDb250cm9sbGVyOiB0aGlzLnRlbGVtZXRyeUNvbnRyb2xsZXIsXG4gICAgfTtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IFdlYlNvY2tldFJlZ2lzdHJ5KHJlZ2lzdHJ5T3B0aW9ucyk7XG4gIH1cblxuICByZWdpc3RlckNvbm5lY3Rpb248VE91dFNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGUsIFRJblNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGU+KFxuICAgIHNvY2tldDogV2ViU29ja2V0LFxuICAgIG9wdGlvbnM6IE9taXQ8XG4gICAgICBXZWJTb2NrZXRDb25uZWN0aW9uT3B0aW9uczxUT3V0U2NoZW1hLCBUSW5TY2hlbWE+LFxuICAgICAgXCJyZWdpc3RyeVwiIHwgXCJ0ZWxlbWV0cnlDb250cm9sbGVyXCJcbiAgICA+LFxuICApOiBXZWJTb2NrZXRDb25uZWN0aW9uPEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VE91dFNjaGVtYT4sIEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VEluU2NoZW1hPj4ge1xuICAgIHJldHVybiBuZXcgV2ViU29ja2V0Q29ubmVjdGlvbkltcGwoc29ja2V0LCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgcmVnaXN0cnk6IHRoaXMucmVnaXN0cnksXG4gICAgICB0ZWxlbWV0cnlDb250cm9sbGVyOiB0aGlzLnRlbGVtZXRyeUNvbnRyb2xsZXIsXG4gICAgfSk7XG4gIH1cblxuICBhY3RpdmF0ZUNvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lzdHJ5LmFjdGl2YXRlKGNvbm5lY3Rpb25JZCk7XG4gIH1cblxuICBicm9hZGNhc3QoZXZlbnQ6IHN0cmluZywgZGF0YTogdW5rbm93biwgbmFtZXNwYWNlPzogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpc3RyeS5icm9hZGNhc3QoZXZlbnQsIGRhdGEsIG5hbWVzcGFjZSk7XG4gIH1cblxuICBwdWJsaXNoVG9Sb29tKHJvb21JZDogV2ViU29ja2V0Um9vbUlkLCBldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duLCBuYW1lc3BhY2U/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lzdHJ5LnB1Ymxpc2hUb1Jvb20ocm9vbUlkLCBldmVudCwgZGF0YSwgbmFtZXNwYWNlKTtcbiAgfVxuXG4gIHB1Ymxpc2hUb1VzZXIodXNlcklkOiBXZWJTb2NrZXRVc2VySWQsIGV2ZW50OiBzdHJpbmcsIGRhdGE6IHVua25vd24sIG5hbWVzcGFjZT86IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVnaXN0cnkucHVibGlzaFRvVXNlcih1c2VySWQsIGV2ZW50LCBkYXRhLCBuYW1lc3BhY2UpO1xuICB9XG5cbiAgcHVibGlzaFRvQXVkaWVuY2UoYXVkaWVuY2U6IFdlYlNvY2tldEF1ZGllbmNlLCBldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpc3RyeS5wdWJsaXNoVG9BdWRpZW5jZShhdWRpZW5jZSwgZXZlbnQsIGRhdGEpO1xuICB9XG5cbiAgLy8g7ZSE66Gc7IS47IqkIOyiheujjCDsi5wg7IK07JWE7J6I64qUIOyXsOqysOydtCDrgqjsp4Ag7JWK64+E66GdIHJlZ2lzdHJ566W8IOyInO2ajO2VtCDsnbzqtIQg7KKF66OM7ZWoXG4gIGFzeW5jIHNodXRkb3duKFxuICAgIGNvZGU6IG51bWJlciA9IFdTX0NMT1NFX0NPREVfR09JTkdfQVdBWSxcbiAgICByZWFzb24gPSBcIlNlcnZlciBzaHV0dGluZyBkb3duXCIsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMucmVnaXN0cnkuc2h1dGRvd24oY29kZSwgcmVhc29uKTtcbiAgICBhd2FpdCB0aGlzLnRlbGVtZXRyeUNvbnRyb2xsZXIuc2h1dGRvd24oKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV2ViU29ja2V0UnVudGltZShvcHRpb25zOiBXZWJTb2NrZXRSdW50aW1lT3B0aW9ucyA9IHt9KTogV2ViU29ja2V0UnVudGltZSB7XG4gIHJldHVybiBuZXcgV2ViU29ja2V0UnVudGltZShvcHRpb25zKTtcbn1cblxuY2xhc3MgV2ViU29ja2V0Q29ubmVjdGlvbkltcGw8VE91dFNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGUsIFRJblNjaGVtYSBleHRlbmRzIHouWm9kUmF3U2hhcGU+XG4gIGltcGxlbWVudHNcbiAgICBXZWJTb2NrZXRDb25uZWN0aW9uPEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VE91dFNjaGVtYT4sIEluZmVyV2ViU29ja2V0RXZlbnRNYXA8VEluU2NoZW1hPj4sXG4gICAgVGVsZW1ldHJ5SW5zcGVjdGFibGVDb25uZWN0aW9uLFxuICAgIFRlbGVtZXRyeUNvbnRleHRQcm92aWRlclxue1xuICByZWFkb25seSBpZCA9IHJhbmRvbVVVSUQoKTtcbiAgcmVhZG9ubHkgdHJhbnNwb3J0ID0gXCJ3c1wiO1xuICByZWFkb25seSBuYW1lc3BhY2U6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNsb3NlQ2FsbGJhY2tzOiBDbG9zZUhhbmRsZXJbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IG1lc3NhZ2VIYW5kbGVycyA9IG5ldyBNYXA8c3RyaW5nLCBBcnJheTxNZXNzYWdlSGFuZGxlcjx1bmtub3duPj4+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZ01lc3NhZ2VzOiBQYXJzZWRFbnZlbG9wZVtdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZ091dGJvdW5kTWVzc2FnZXM6IEFycmF5PHsgcGF5bG9hZDogc3RyaW5nOyBldmVudDogc3RyaW5nIH0+ID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgY2xvc2VQcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmVDbG9zZVByb21pc2U6ICgpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgaGVhcnRiZWF0TXM6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBldmVudFNjaGVtYXNJbjogUmVjb3JkPHN0cmluZywgei5ab2RUeXBlQW55PjtcbiAgcHJpdmF0ZSByZWFkb25seSBldmVudFNjaGVtYXNPdXQ6IFJlY29yZDxzdHJpbmcsIHouWm9kVHlwZUFueT47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb25uZWN0aW9uVHJhY2VJZD86IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBjb25uZWN0aW9uU3BhbklkPzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbm5lY3Rpb25QYXJlbnRTcGFuSWQ/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29ubmVjdGlvblNhbXBsZWQ/OiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbm5lY3Rpb25TdGFydGVkQXQgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuICAvLyBjb25uZWN0aW9uIOyImOuqhSDrj5nslYgg7Jyg7KeA65CY64qUIOyLneuzhOyekC4gc2V0VXNlcklkL2NsZWFyVXNlcklk66GcIOyXheuNsOydtO2KuOuQmOupsCBlbWl0IGhvdCBwYXRo7JeQ7IScIOunpOuyiCByZWdpc3RyeSBsb29rdXDtlZjsp4Ag7JWK64+E66GdIOy6kOyLnO2VqFxuICBwcml2YXRlIF91c2VySWQ/OiBzdHJpbmc7XG5cbiAgZ2V0IHVzZXJJZCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl91c2VySWQ7XG4gIH1cblxuICBwcml2YXRlIGNsb3NlZEludGVybmFsID0gZmFsc2U7XG4gIHByaXZhdGUgY2xvc2VTdGFydGVkID0gZmFsc2U7XG4gIHByaXZhdGUgYXdhaXRpbmdQb25nID0gZmFsc2U7XG4gIHByaXZhdGUgaGVhcnRiZWF0VGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldEludGVydmFsPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG1lc3NhZ2VRdWV1ZTogUHJvbWlzZTx2b2lkPiA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBwcml2YXRlIG91dGJvdW5kRmx1c2hTY2hlZHVsZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNvY2tldDogV2ViU29ja2V0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogV2ViU29ja2V0Q29ubmVjdGlvbk9wdGlvbnM8VE91dFNjaGVtYSwgVEluU2NoZW1hPixcbiAgKSB7XG4gICAgdGhpcy5uYW1lc3BhY2UgPSBvcHRpb25zLm5hbWVzcGFjZSA/PyBcImRlZmF1bHRcIjtcbiAgICB0aGlzLmhlYXJ0YmVhdE1zID0gb3B0aW9ucy5oZWFydGJlYXQgPz8gMzAwMDA7XG4gICAgdGhpcy5jb25uZWN0aW9uVHJhY2VJZCA9IG9wdGlvbnMudHJhY2VJZDtcbiAgICB0aGlzLmNvbm5lY3Rpb25TcGFuSWQgPSBvcHRpb25zLnNwYW5JZDtcbiAgICB0aGlzLmNvbm5lY3Rpb25QYXJlbnRTcGFuSWQgPSBvcHRpb25zLnBhcmVudFNwYW5JZDtcbiAgICB0aGlzLmNvbm5lY3Rpb25TYW1wbGVkID0gb3B0aW9ucy5zYW1wbGVkO1xuICAgIHRoaXMuZXZlbnRTY2hlbWFzSW4gPSBvcHRpb25zLmluRXZlbnRzLnNoYXBlIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgei5ab2RUeXBlQW55PjtcbiAgICB0aGlzLmV2ZW50U2NoZW1hc091dCA9IG9wdGlvbnMub3V0RXZlbnRzLnNoYXBlIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgei5ab2RUeXBlQW55PjtcblxuICAgIGxldCByZXNvbHZlQ2xvc2VQcm9taXNlITogKCkgPT4gdm9pZDtcbiAgICB0aGlzLmNsb3NlUHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICByZXNvbHZlQ2xvc2VQcm9taXNlID0gcmVzb2x2ZTtcbiAgICB9KTtcbiAgICB0aGlzLnJlc29sdmVDbG9zZVByb21pc2UgPSByZXNvbHZlQ2xvc2VQcm9taXNlO1xuXG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LnJlZ2lzdGVyKHRoaXMsIG9wdGlvbnMuYWN0aXZlID8/IHRydWUpO1xuICAgIHRoaXMuc29ja2V0Lm9uKFwibWVzc2FnZVwiLCB0aGlzLmhhbmRsZU1lc3NhZ2UpO1xuICAgIHRoaXMuc29ja2V0Lm9uKFwiY2xvc2VcIiwgdGhpcy5oYW5kbGVDbG9zZSk7XG4gICAgdGhpcy5zb2NrZXQub24oXCJlcnJvclwiLCB0aGlzLmhhbmRsZUVycm9yKTtcbiAgICB0aGlzLnNvY2tldC5vbihcInBvbmdcIiwgdGhpcy5oYW5kbGVQb25nKTtcbiAgICB0aGlzLnN0YXJ0SGVhcnRiZWF0KCk7XG4gIH1cblxuICBnZXQgY2xvc2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsb3NlZEludGVybmFsO1xuICB9XG5cbiAgb25DbG9zZShjYWxsYmFjazogQ2xvc2VIYW5kbGVyKTogdm9pZCB7XG4gICAgdGhpcy5jbG9zZUNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbiAgfVxuXG4gIG9uTWVzc2FnZTxLIGV4dGVuZHMga2V5b2YgSW5mZXJXZWJTb2NrZXRFdmVudE1hcDxUSW5TY2hlbWE+PihcbiAgICBldmVudDogSyxcbiAgICBoYW5kbGVyOiBNZXNzYWdlSGFuZGxlcjxJbmZlcldlYlNvY2tldEV2ZW50TWFwPFRJblNjaGVtYT5bS10+LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBldmVudEtleSA9IFN0cmluZyhldmVudCk7XG4gICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLm1lc3NhZ2VIYW5kbGVycy5nZXQoZXZlbnRLZXkpID8/IFtdO1xuICAgIGhhbmRsZXJzLnB1c2goaGFuZGxlciBhcyBNZXNzYWdlSGFuZGxlcjx1bmtub3duPik7XG4gICAgdGhpcy5tZXNzYWdlSGFuZGxlcnMuc2V0KGV2ZW50S2V5LCBoYW5kbGVycyk7XG4gICAgdGhpcy5mbHVzaFBlbmRpbmdNZXNzYWdlcyhldmVudEtleSk7XG4gIH1cblxuICBwdWJsaXNoPEsgZXh0ZW5kcyBrZXlvZiBJbmZlcldlYlNvY2tldEV2ZW50TWFwPFRPdXRTY2hlbWE+PihcbiAgICBldmVudDogSyxcbiAgICBkYXRhOiBJbmZlcldlYlNvY2tldEV2ZW50TWFwPFRPdXRTY2hlbWE+W0tdLFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnB1Ymxpc2hWYWxpZGF0ZWQoU3RyaW5nKGV2ZW50KSwgZGF0YSk7XG4gIH1cblxuICBwdWJsaXNoVW50eXBlZChldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duKTogdm9pZCB7XG4gICAgdGhpcy5wdWJsaXNoVmFsaWRhdGVkKGV2ZW50LCBkYXRhKTtcbiAgfVxuXG4gIHdhaXRGb3JDbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5jbG9zZVByb21pc2U7XG4gIH1cblxuICBqb2luKHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LmpvaW4odGhpcy5pZCwgcm9vbUlkKTtcbiAgfVxuXG4gIGxlYXZlKHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LmxlYXZlKHRoaXMuaWQsIHJvb21JZCk7XG4gIH1cblxuICBzZXRVc2VySWQodXNlcklkOiBXZWJTb2NrZXRVc2VySWQpOiB2b2lkIHtcbiAgICB0aGlzLl91c2VySWQgPSBTdHJpbmcodXNlcklkKTtcbiAgICB0aGlzLm9wdGlvbnMucmVnaXN0cnkuc2V0VXNlcklkKHRoaXMuaWQsIHVzZXJJZCk7XG4gIH1cblxuICBjbGVhclVzZXJJZCgpOiB2b2lkIHtcbiAgICB0aGlzLl91c2VySWQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5vcHRpb25zLnJlZ2lzdHJ5LmNsZWFyVXNlcklkKHRoaXMuaWQpO1xuICB9XG5cbiAgZ2V0VGVsZW1ldHJ5U25hcHNob3QoKTogV2ViU29ja2V0VGVsZW1ldHJ5Q29ubmVjdGlvblNuYXBzaG90IHtcbiAgICByZXR1cm4ge1xuICAgICAgcGVuZGluZ0luYm91bmRNZXNzYWdlczogdGhpcy5wZW5kaW5nTWVzc2FnZXMubGVuZ3RoLFxuICAgICAgcGVuZGluZ091dGJvdW5kTWVzc2FnZXM6IHRoaXMucGVuZGluZ091dGJvdW5kTWVzc2FnZXMubGVuZ3RoLFxuICAgICAgc29ja2V0QnVmZmVyZWRCeXRlczogdGhpcy5zb2NrZXQucmVhZHlTdGF0ZSA9PT0gV1NfT1BFTiA/IHRoaXMuc29ja2V0LmJ1ZmZlcmVkQW1vdW50IDogMCxcbiAgICB9O1xuICB9XG5cbiAgZ2V0VGVsZW1ldHJ5Q29udGV4dCgpOiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRyYWNlSWQ6IHRoaXMuY29ubmVjdGlvblRyYWNlSWQsXG4gICAgICBzcGFuSWQ6IHRoaXMuY29ubmVjdGlvblNwYW5JZCxcbiAgICAgIHBhcmVudFNwYW5JZDogdGhpcy5jb25uZWN0aW9uUGFyZW50U3BhbklkLFxuICAgICAgc2FtcGxlZDogdGhpcy5jb25uZWN0aW9uU2FtcGxlZCxcbiAgICB9O1xuICB9XG5cbiAgLy8g66qo65OgIHRlbGVtZXRyeSBlbWl0IHNpdGXqsIAg6rO17Jyg7ZWY64qUIGNvbm5lY3Rpb24tbGV2ZWwgZmllbGQg66y27J2MLlxuICAvLyDtlqXtm4QgY29ubmVjdGlvbi1zY29wZWQg7Iud67OE7J6QKGUuZy4gdGVuYW50SWQp6rCAIOy2lOqwgOuQoCDrlYwg7ZWcIOqzs+unjCDshpDrjIDrqbQg65CoXG4gIHByaXZhdGUgdGVsZW1ldHJ5RmllbGRzKCkge1xuICAgIHJldHVybiB7XG4gICAgICBjb25uZWN0aW9uSWQ6IHRoaXMuaWQsXG4gICAgICBuYW1lc3BhY2U6IHRoaXMubmFtZXNwYWNlLFxuICAgICAgdXNlcklkOiB0aGlzLl91c2VySWQsXG4gICAgICB0cmFjZUlkOiB0aGlzLmNvbm5lY3Rpb25UcmFjZUlkLFxuICAgICAgc3BhbklkOiB0aGlzLmNvbm5lY3Rpb25TcGFuSWQsXG4gICAgICBwYXJlbnRTcGFuSWQ6IHRoaXMuY29ubmVjdGlvblBhcmVudFNwYW5JZCxcbiAgICAgIHNhbXBsZWQ6IHRoaXMuY29ubmVjdGlvblNhbXBsZWQsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdEluYm91bmRSZWplY3RlZChyZWFzb246IHN0cmluZywgZXZlbnQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBmaWVsZHMgPSB0aGlzLnRlbGVtZXRyeUZpZWxkcygpO1xuICAgIHRoaXMub3B0aW9ucy50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgbmFtZTogXCJ3cy5tZXNzYWdlLnJlamVjdGVkXCIsXG4gICAgICBsZXZlbDogXCJ3YXJuXCIsXG4gICAgICAuLi5maWVsZHMsXG4gICAgICBkZXRhaWw6IGV2ZW50ICE9PSB1bmRlZmluZWQgPyB7IHJlYXNvbiwgZXZlbnQgfSA6IHsgcmVhc29uIH0sXG4gICAgfSk7XG4gICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIucmVjb3JkTWV0cmljKHtcbiAgICAgIG5hbWU6IFwic29uYW11LndzLm1lc3NhZ2VzXCIsXG4gICAgICBraW5kOiBcImNvdW50ZXJcIixcbiAgICAgIHZhbHVlOiAxLFxuICAgICAgdW5pdDogXCIxXCIsXG4gICAgICB0YWdzOiB7IGRpcmVjdGlvbjogXCJpbmJvdW5kXCIsIG91dGNvbWU6IFwicmVqZWN0ZWRcIiB9LFxuICAgICAgLi4uZmllbGRzLFxuICAgIH0pO1xuICB9XG5cbiAgLy8gdHJhbnNwb3J0IOyiheujjCDrj4TspJEg7JiI7Jm46rCAIOuCmOuPhCBtYXJrQ2xvc2Vk6rCAIOuwmOuTnOyLnCDsi6TtlonrkJjrj4TroZ0gdHJ5L2ZpbmFsbHnroZwg6rCQ7IyIXG4gIGNsb3NlKGNvZGU/OiBudW1iZXIsIHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuY2xvc2VTdGFydGVkIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgPT09IFdTX0NMT1NFRCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2xvc2VTdGFydGVkID0gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5jbG9zZVRyYW5zcG9ydChjb2RlLCByZWFzb24pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm1hcmtDbG9zZWQoY29kZSwgcmVhc29uKTtcbiAgICB9XG4gIH1cblxuICAvLyDsnbjrsJTsmrTrk5wg66mU7Iuc7KeA66W8IOyInOywqCDsspjrpqwg7YGQ7JeQIOyYrOumvC4gU29uYW11IGVudmVsb3BlIOqygOymnSDsiJjtlolcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVNZXNzYWdlID0gKHJhdzogdW5rbm93bikgPT4ge1xuICAgIHRoaXMuZW5xdWV1ZU1lc3NhZ2VUYXNrKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRleHQgPSBub3JtYWxpemVNZXNzYWdlKHJhdyk7XG4gICAgICBjb25zdCBwYXJzZWRFbnZlbG9wZSA9IHNhZmVQYXJzZUVudmVsb3BlKHRleHQpO1xuICAgICAgaWYgKCFwYXJzZWRFbnZlbG9wZSkge1xuICAgICAgICB0aGlzLmVtaXRJbmJvdW5kUmVqZWN0ZWQoXCJpbnZhbGlkUGF5bG9hZFwiKTtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVkFMSURfRlJBTUVfUEFZTE9BRF9EQVRBLCBcIkludmFsaWQgbWVzc2FnZSBwYXlsb2FkXCIpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMub3B0aW9ucy50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLm1lc3NhZ2UucmVjZWl2ZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgICAgLi4udGhpcy50ZWxlbWV0cnlGaWVsZHMoKSxcbiAgICAgICAgZGV0YWlsOiB7IGV2ZW50OiBwYXJzZWRFbnZlbG9wZS5ldmVudCB9LFxuICAgICAgICBwYXlsb2FkOiBwYXJzZWRFbnZlbG9wZS5kYXRhLFxuICAgICAgfSk7XG4gICAgICB0aGlzLm9wdGlvbnMucmVnaXN0cnkudG91Y2godGhpcy5pZCk7XG4gICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoRW52ZWxvcGUocGFyc2VkRW52ZWxvcGUpO1xuICAgIH0pO1xuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaGFuZGxlQ2xvc2UgPSAoY29kZT86IG51bWJlciwgcmVhc29uPzogQnVmZmVyIHwgc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgcmVhc29uVGV4dCA9IHR5cGVvZiByZWFzb24gPT09IFwic3RyaW5nXCIgPyByZWFzb24gOiByZWFzb24/LnRvU3RyaW5nKCk7XG4gICAgdGhpcy5tYXJrQ2xvc2VkKGNvZGUsIHJlYXNvblRleHQpO1xuICB9O1xuXG4gIC8vIOyGjOy8k+ydtCB0cmFuc3BvcnQgZXJyb3LrpbwgZW1pdO2VmOuptCDsponsi5wgMTAxMSBjbG9zZeuhnCDsiJjroLTsi5zsvJwg7IOB7YOcIOuIhOudveydhCDrp4nsnYxcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVFcnJvciA9ICgpID0+IHtcbiAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfSU5URVJOQUxfRVJST1IsIFwiV2ViU29ja2V0IHRyYW5zcG9ydCBlcnJvclwiKTtcbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZVBvbmcgPSAoKSA9PiB7XG4gICAgdGhpcy5hd2FpdGluZ1BvbmcgPSBmYWxzZTtcbiAgICB0aGlzLm9wdGlvbnMucmVnaXN0cnkudG91Y2godGhpcy5pZCk7XG4gIH07XG5cbiAgLy8gZW52ZWxvcGXsnZggbWV0YS50cmFjZXBhcmVudOuhnOu2gO2EsCB0cmFjZSBjb250ZXh066W8IOy2lOy2nO2VqFxuICAvLyBpbnZhbGlkIHRyYWNlcGFyZW5064qUIOyXsOqysOydhCDqsbDrtoDtlZjsp4Ag7JWK6rOgIGRlYnVnIOugiOuyqCDqsr3qs6Drp4wgZW1pdO2VqFxuICBwcml2YXRlIHJlc29sdmVNZXNzYWdlVHJhY2VDb250ZXh0KFxuICAgIGVudmVsb3BlOiBQYXJzZWRFbnZlbG9wZSxcbiAgKTogV2ViU29ja2V0VGVsZW1ldHJ5Q29ubmVjdGlvbkNvbnRleHQge1xuICAgIGNvbnN0IG1lc3NhZ2VTcGFuSWQgPSBnZW5lcmF0ZVNwYW5JZCgpO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZ2V0VHJhY2VPcHRpb25zKCkucHJvcGFnYXRlTWVzc2FnZVRyYWNlICYmXG4gICAgICBlbnZlbG9wZS5tZXRhPy50cmFjZXBhcmVudFxuICAgICkge1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VUcmFjZVBhcmVudChlbnZlbG9wZS5tZXRhLnRyYWNlcGFyZW50KTtcbiAgICAgIGlmIChwYXJzZWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0cmFjZUlkOiBwYXJzZWQudHJhY2VJZCxcbiAgICAgICAgICBzcGFuSWQ6IG1lc3NhZ2VTcGFuSWQsXG4gICAgICAgICAgcGFyZW50U3BhbklkOiBwYXJzZWQucGFyZW50SWQsXG4gICAgICAgICAgc2FtcGxlZDogcGFyc2VkLnNhbXBsZWQsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICAvLyBpbnZhbGlkIHRyYWNlcGFyZW50OiB3YXJuIGJ1dCBkbyBub3QgcmVqZWN0XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy50cmFjZS5pbnZhbGlkXCIsXG4gICAgICAgIGxldmVsOiBcImRlYnVnXCIsXG4gICAgICAgIC4uLnRoaXMudGVsZW1ldHJ5RmllbGRzKCksXG4gICAgICAgIGRldGFpbDogeyBzb3VyY2U6IFwibWVzc2FnZVwiLCB0cmFjZXBhcmVudDogZW52ZWxvcGUubWV0YS50cmFjZXBhcmVudCB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRyYWNlSWQ6IHRoaXMuY29ubmVjdGlvblRyYWNlSWQsXG4gICAgICBzcGFuSWQ6IG1lc3NhZ2VTcGFuSWQsXG4gICAgICBwYXJlbnRTcGFuSWQ6IHRoaXMuY29ubmVjdGlvblNwYW5JZCA/PyB0aGlzLmNvbm5lY3Rpb25QYXJlbnRTcGFuSWQsXG4gICAgICBzYW1wbGVkOiB0aGlzLmNvbm5lY3Rpb25TYW1wbGVkLFxuICAgIH07XG4gIH1cblxuICAvLyBldmVudCDsobTsnqwg7Jes67aAIOKGkiBzY2hlbWEg6rKA7KadIOKGkiBoYW5kbGVyIOyLpO2WiSDsiJzsnLzroZwg67aE6riw7ZWoXG4gIC8vIGhhbmRsZXLqsIAg7JWE7KeBIOuTseuhneuQmOyngCDslYrsnYAg7LSI6riwIOuplOyLnOyngOuKlCDrsoTtjbzsl5Ag67O06rSA7ZaI64uk6rCAIG9uTWVzc2FnZSDrk7HroZ0g7IucIGZsdXNo7ZWoXG4gIC8vIGhhbmRsZXLripQgYGF3YWl0YOycvOuhnCDsiJzssKgg7Iuk7ZaJ7ZW0IO2VnCBjb25uZWN0aW9uIOyViOydmCDrqZTsi5zsp4Ag7Iic7ISc66W8IOuztOyepe2VqFxuICBwcml2YXRlIGFzeW5jIGRpc3BhdGNoRW52ZWxvcGUoZW52ZWxvcGU6IFBhcnNlZEVudmVsb3BlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLm1lc3NhZ2VIYW5kbGVycy5nZXQoZW52ZWxvcGUuZXZlbnQpO1xuICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMuZXZlbnRTY2hlbWFzSW5bZW52ZWxvcGUuZXZlbnRdO1xuXG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRoaXMuZW1pdEluYm91bmRSZWplY3RlZChcInVua25vd25FdmVudFwiLCBlbnZlbG9wZS5ldmVudCk7XG4gICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfUE9MSUNZX1ZJT0xBVElPTiwgXCJVbmtub3duIGV2ZW50XCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHNjaGVtYS5zYWZlUGFyc2UoZW52ZWxvcGUuZGF0YSk7XG4gICAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgICAgdGhpcy5lbWl0SW5ib3VuZFJlamVjdGVkKFwiaW52YWxpZERhdGFcIiwgZW52ZWxvcGUuZXZlbnQpO1xuICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVkFMSURfRlJBTUVfUEFZTE9BRF9EQVRBLCBcIkludmFsaWQgZXZlbnQgZGF0YVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWhhbmRsZXJzIHx8IGhhbmRsZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKHRoaXMucGVuZGluZ01lc3NhZ2VzLmxlbmd0aCA+PSBNQVhfUEVORElOR19NRVNTQUdFUykge1xuICAgICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgICBuYW1lOiBcIndzLm1lc3NhZ2UuYnVmZmVyLmRyb3BwZWRcIixcbiAgICAgICAgICBsZXZlbDogXCJ3YXJuXCIsXG4gICAgICAgICAgLi4udGhpcy50ZWxlbWV0cnlGaWVsZHMoKSxcbiAgICAgICAgICBkZXRhaWw6IHsgZXZlbnQ6IGVudmVsb3BlLmV2ZW50IH0sXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnBlbmRpbmdNZXNzYWdlcy5zaGlmdCgpO1xuICAgICAgfVxuICAgICAgdGhpcy5wZW5kaW5nTWVzc2FnZXMucHVzaChlbnZlbG9wZSk7XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5tZXNzYWdlLmJ1ZmZlcmVkXCIsXG4gICAgICAgIGxldmVsOiBcImRlYnVnXCIsXG4gICAgICAgIC4uLnRoaXMudGVsZW1ldHJ5RmllbGRzKCksXG4gICAgICAgIGRldGFpbDogeyBldmVudDogZW52ZWxvcGUuZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRyYWNlQ3R4ID0gdGhpcy5yZXNvbHZlTWVzc2FnZVRyYWNlQ29udGV4dChlbnZlbG9wZSk7XG4gICAgLy8gbWVzc2FnZS1sZXZlbCB0cmFjZeuKlCBjb25uZWN0aW9uLWxldmVsIHRyYWNl66W8IG92ZXJyaWRl7ZWoLiB1c2VySWQgLyBjb25uZWN0aW9uSWQgLyBuYW1lc3BhY2XripQg6re464yA66GcIOycoOyngFxuICAgIGNvbnN0IG1lc3NhZ2VUcmFjZUZpZWxkcyA9IHtcbiAgICAgIGNvbm5lY3Rpb25JZDogdGhpcy5pZCxcbiAgICAgIG5hbWVzcGFjZTogdGhpcy5uYW1lc3BhY2UsXG4gICAgICB1c2VySWQ6IHRoaXMuX3VzZXJJZCxcbiAgICAgIHRyYWNlSWQ6IHRyYWNlQ3R4LnRyYWNlSWQsXG4gICAgICBzcGFuSWQ6IHRyYWNlQ3R4LnNwYW5JZCxcbiAgICAgIHBhcmVudFNwYW5JZDogdHJhY2VDdHgucGFyZW50U3BhbklkLFxuICAgICAgc2FtcGxlZDogdHJhY2VDdHguc2FtcGxlZCxcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IGhhbmRsZXIgb2YgaGFuZGxlcnMpIHtcbiAgICAgICAgYXdhaXQgaGFuZGxlcihwYXJzZWQuZGF0YSwgdHJhY2VDdHgpO1xuICAgICAgfVxuICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgIG5hbWU6IFwid3MubWVzc2FnZS5kaXNwYXRjaGVkXCIsXG4gICAgICAgIGxldmVsOiBcImRlYnVnXCIsXG4gICAgICAgIC4uLm1lc3NhZ2VUcmFjZUZpZWxkcyxcbiAgICAgICAgZGV0YWlsOiB7IGV2ZW50OiBlbnZlbG9wZS5ldmVudCB9LFxuICAgICAgfSk7XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5yZWNvcmRNZXRyaWMoe1xuICAgICAgICBuYW1lOiBcInNvbmFtdS53cy5tZXNzYWdlc1wiLFxuICAgICAgICBraW5kOiBcImNvdW50ZXJcIixcbiAgICAgICAgdmFsdWU6IDEsXG4gICAgICAgIHVuaXQ6IFwiMVwiLFxuICAgICAgICB0YWdzOiB7IGRpcmVjdGlvbjogXCJpbmJvdW5kXCIsIGV2ZW50OiBlbnZlbG9wZS5ldmVudCwgb3V0Y29tZTogXCJhY2NlcHRlZFwiIH0sXG4gICAgICAgIC4uLm1lc3NhZ2VUcmFjZUZpZWxkcyxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5tZXNzYWdlLmZhaWxlZFwiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICAuLi5tZXNzYWdlVHJhY2VGaWVsZHMsXG4gICAgICAgIGRldGFpbDogeyBldmVudDogZW52ZWxvcGUuZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmbHVzaFBlbmRpbmdNZXNzYWdlcyhldmVudDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgcmVtYWluaW5nOiBQYXJzZWRFbnZlbG9wZVtdID0gW107XG4gICAgY29uc3QgdG9GbHVzaDogUGFyc2VkRW52ZWxvcGVbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBtZXNzYWdlIG9mIHRoaXMucGVuZGluZ01lc3NhZ2VzKSB7XG4gICAgICBpZiAobWVzc2FnZS5ldmVudCAhPT0gZXZlbnQpIHtcbiAgICAgICAgcmVtYWluaW5nLnB1c2gobWVzc2FnZSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0b0ZsdXNoLnB1c2gobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nTWVzc2FnZXMubGVuZ3RoID0gMDtcbiAgICB0aGlzLnBlbmRpbmdNZXNzYWdlcy5wdXNoKC4uLnJlbWFpbmluZyk7XG5cbiAgICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgdG9GbHVzaCkge1xuICAgICAgdGhpcy5lbnF1ZXVlTWVzc2FnZVRhc2soYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoRW52ZWxvcGUobWVzc2FnZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHB1Ymxpc2hWYWxpZGF0ZWQoZXZlbnQ6IHN0cmluZywgZGF0YTogdW5rbm93bik6IHZvaWQge1xuICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMuZXZlbnRTY2hlbWFzT3V0W2V2ZW50XTtcbiAgICBpZiAoIXNjaGVtYSkge1xuICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgIG5hbWU6IFwid3MucHVibGlzaC5yZWplY3RlZFwiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICAuLi50aGlzLnRlbGVtZXRyeUZpZWxkcygpLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQsIHJlYXNvbjogXCJ1bmtub3duRXZlbnRcIiB9LFxuICAgICAgfSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gd2Vic29ja2V0IGV2ZW50OiAke2V2ZW50fWApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHNjaGVtYS5zYWZlUGFyc2UoZGF0YSk7XG4gICAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgIG5hbWU6IFwid3MucHVibGlzaC5yZWplY3RlZFwiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICAuLi50aGlzLnRlbGVtZXRyeUZpZWxkcygpLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQsIHJlYXNvbjogXCJpbnZhbGlkUGF5bG9hZFwiIH0sXG4gICAgICB9KTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB3ZWJzb2NrZXQgZXZlbnQgcGF5bG9hZDogJHtldmVudH1gKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jbG9zZWRJbnRlcm5hbCB8fCB0aGlzLnNvY2tldC5yZWFkeVN0YXRlICE9PSBXU19PUEVOKSB7XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5wdWJsaXNoLmRyb3BwZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgICAgLi4udGhpcy50ZWxlbWV0cnlGaWVsZHMoKSxcbiAgICAgICAgZGV0YWlsOiB7IGV2ZW50LCByZWFzb246IFwiY29ubmVjdGlvbkNsb3NlZFwiIH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmVucXVldWVPdXRib3VuZE1lc3NhZ2UoXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGV2ZW50LFxuICAgICAgICBkYXRhOiBwYXJzZWQuZGF0YSxcbiAgICAgIH0pLFxuICAgICAgZXZlbnQsXG4gICAgICBwYXJzZWQuZGF0YSxcbiAgICApO1xuICB9XG5cbiAgLy8gbGlzdGVuZXIg7ZW07KCcIC8gaGVhcnRiZWF0IOykkeuLqCAvIHBlbmRpbmcgcXVldWUg67mE7JuAIC8gcmVnaXN0cnkgdW5yZWdpc3RlciAvIG9uQ2xvc2Ug7Iuk7ZaJIC8gd2FpdEZvckNsb3NlIHJlc29sdmUg7J2EIO2VnCDqs7Psl5Ag66qo7JWEIOybkOyekOyggeycvOuhnCDsspjrpqztlahcbiAgLy8gYXN5bmMgb25DbG9zZeqwgCByZWplY3TtlbTrj4QgdW5oYW5kbGVkIHJlamVjdGlvbuycvOuhnCDsg4jsp4Ag7JWK64+E66GdIGNhdGNo66GcIOqyqeumrO2VqFxuICBwcml2YXRlIG1hcmtDbG9zZWQoY29kZT86IG51bWJlciwgX3JlYXNvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZWRJbnRlcm5hbCA9IHRydWU7XG4gICAgdGhpcy5jbG9zZVN0YXJ0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLnN0b3BIZWFydGJlYXQoKTtcbiAgICBjb25zdCBmaWVsZHMgPSB0aGlzLnRlbGVtZXRyeUZpZWxkcygpO1xuICAgIHRoaXMub3B0aW9ucy50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgbmFtZTogXCJ3cy5jb25uZWN0aW9uLmNsb3NlZFwiLFxuICAgICAgbGV2ZWw6IFwiaW5mb1wiLFxuICAgICAgLi4uZmllbGRzLFxuICAgIH0pO1xuICAgIGlmICh0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5nZXRUcmFjZU9wdGlvbnMoKS5yZWNvcmRDb25uZWN0aW9uTGlmZXRpbWVTcGFuKSB7XG4gICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5yZWNvcmRTcGFuKHtcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5jb25uZWN0aW9uLmxpZmV0aW1lXCIsXG4gICAgICAgIGtpbmQ6IFwic2VydmVyXCIsXG4gICAgICAgIGR1cmF0aW9uTXM6IHBlcmZvcm1hbmNlLm5vdygpIC0gdGhpcy5jb25uZWN0aW9uU3RhcnRlZEF0LFxuICAgICAgICBzdGF0dXM6IGRlcml2ZUxpZmV0aW1lU3RhdHVzKGNvZGUpLFxuICAgICAgICAuLi5maWVsZHMsXG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhpcy5zb2NrZXQub2ZmKFwibWVzc2FnZVwiLCB0aGlzLmhhbmRsZU1lc3NhZ2UpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcImNsb3NlXCIsIHRoaXMuaGFuZGxlQ2xvc2UpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcImVycm9yXCIsIHRoaXMuaGFuZGxlRXJyb3IpO1xuICAgIHRoaXMuc29ja2V0Lm9mZihcInBvbmdcIiwgdGhpcy5oYW5kbGVQb25nKTtcbiAgICB0aGlzLmF3YWl0aW5nUG9uZyA9IGZhbHNlO1xuICAgIHRoaXMucGVuZGluZ01lc3NhZ2VzLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcy5sZW5ndGggPSAwO1xuICAgIHRoaXMub3B0aW9ucy5yZWdpc3RyeS51bnJlZ2lzdGVyKHRoaXMuaWQpO1xuICAgIGZvciAoY29uc3QgY2FsbGJhY2sgb2YgdGhpcy5jbG9zZUNhbGxiYWNrcy5zcGxpY2UoMCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrKCk7XG4gICAgICAgIGlmIChpc1Byb21pc2VMaWtlKHJlc3VsdCkpIHtcbiAgICAgICAgICB2b2lkIHJlc3VsdC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAvLyBhc3luYyBjbG9zZSBjYWxsYmFja3MgbXVzdCBub3QgZXNjYXBlIGFzIHVuaGFuZGxlZCByZWplY3Rpb25zXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBjbG9zZSBjYWxsYmFja3MgbXVzdCBub3QgYmxvY2sgdHJhbnNwb3J0IGNsZWFudXBcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5yZXNvbHZlQ2xvc2VQcm9taXNlKCk7XG4gIH1cblxuICAvLyBwb25n7J20IOyYpOyngCDslYrsnYAg7IOB7YOc7JeQ7IScIOuLpOydjCB0aWNr7J20IOyYpOuptCB0aW1lb3V0IGNsb3Nl66GcIOyymOumrO2VtCB6b21iaWUgY29ubmVjdGlvbuydhCDsoJXrpqztlahcbiAgcHJpdmF0ZSBzdGFydEhlYXJ0YmVhdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5oZWFydGJlYXRNcyA8PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5oZWFydGJlYXRUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgIT09IFdTX09QRU4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5hd2FpdGluZ1BvbmcpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgICAgbmFtZTogXCJ3cy5oZWFydGJlYXQudGltZW91dFwiLFxuICAgICAgICAgIGxldmVsOiBcIndhcm5cIixcbiAgICAgICAgICAuLi50aGlzLnRlbGVtZXRyeUZpZWxkcygpLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0dPSU5HX0FXQVksIFwiSGVhcnRiZWF0IHRpbWVvdXRcIik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hd2FpdGluZ1BvbmcgPSB0cnVlO1xuICAgICAgdGhpcy5zb2NrZXQucGluZygpO1xuICAgIH0sIHRoaXMuaGVhcnRiZWF0TXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdG9wSGVhcnRiZWF0KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5oZWFydGJlYXRUaW1lcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNsZWFySW50ZXJ2YWwodGhpcy5oZWFydGJlYXRUaW1lcik7XG4gICAgdGhpcy5oZWFydGJlYXRUaW1lciA9IG51bGw7XG4gIH1cblxuICAvLyBjbG9zZeqwgCDsi6TtjKjtlbTrj4QgdGVybWluYXRlIO2PtOuwseq5jOyngCDsi5zrj4TtlZjqs6AsIOuBneuCtCDsi6TtjKjtlZjrqbQgbWFya0Nsb3NlZOyXkCDsg4Htg5wg7KCV66as66W8IOychOyehO2VqFxuICBwcml2YXRlIGNsb3NlVHJhbnNwb3J0KGNvZGU/OiBudW1iZXIsIHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5zb2NrZXQucmVhZHlTdGF0ZSA9PT0gV1NfT1BFTiB8fCB0aGlzLnNvY2tldC5yZWFkeVN0YXRlID09PSBXU19DT05ORUNUSU5HKSB7XG4gICAgICAgIHRoaXMuc29ja2V0LmNsb3NlKGNvZGUsIHRydW5jYXRlQ2xvc2VSZWFzb24ocmVhc29uKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zb2NrZXQudGVybWluYXRlKCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLnNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyB0cmFuc3BvcnQgaXMgYWxyZWFkeSBicm9rZW47IHN0YXRlIGNsZWFudXAgaXMgaGFuZGxlZCBieSBtYXJrQ2xvc2VkKClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyDsnbjrsJTsmrTrk5wgaGFuZGxlcuulvCBwcm9taXNlIGNoYWlu7Jy866GcIHNlcmlhbGl6ZSDtlZjqs6AsIGhhbmRsZXIg7JiI7Jm464qUIGNvbm5lY3Rpb24tbG9jYWwgMTAxMSBjbG9zZeuhnCDstpXshoztlahcbiAgcHJpdmF0ZSBlbnF1ZXVlTWVzc2FnZVRhc2sodGFzazogKCkgPT4gUHJvbWlzZTx2b2lkPik6IHZvaWQge1xuICAgIHRoaXMubWVzc2FnZVF1ZXVlID0gdGhpcy5tZXNzYWdlUXVldWVcbiAgICAgIC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VkSW50ZXJuYWwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0YXNrKCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgdGhpcy5jbG9zZShXU19DTE9TRV9DT0RFX0lOVEVSTkFMX0VSUk9SLCBcIk1lc3NhZ2UgaGFuZGxpbmcgZmFpbGVkXCIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBxdWV1ZeqwgCDtlZzqs4Tsl5Ag64+E64us7ZWY66m0IDEwMTPsnLzroZwg64ur7JWEIOuKkOumsCDshozruYTsnpDqsIAg66mU66qo66as66W8IOuBneyXhuydtCDsnqHslYTrqLnsp4Ag66q77ZWY6rKMIO2VqFxuICAvLyBkYXRhIOyduOyekOuKlCB0ZWxlbWV0cnkgcGF5bG9hZCBwcmV2aWV3IOyaqeuPhOuhnOunjCDsgqzsmqntlZjrqbAgcGVuZGluZ091dGJvdW5kTWVzc2FnZXPsl5DripQg7KCA7J6l7ZWY7KeAIOyViuydjCAo7YGQIOuplOuqqOumrCDrs7TtmLgpXG4gIHByaXZhdGUgZW5xdWV1ZU91dGJvdW5kTWVzc2FnZShwYXlsb2FkOiBzdHJpbmcsIGV2ZW50OiBzdHJpbmcsIGRhdGE6IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcy5sZW5ndGggPj0gTUFYX1BFTkRJTkdfT1VUQk9VTkRfTUVTU0FHRVMpIHtcbiAgICAgIHRoaXMub3B0aW9ucy50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLmJhY2twcmVzc3VyZS5vdmVyZmxvd1wiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICAuLi50aGlzLnRlbGVtZXRyeUZpZWxkcygpLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfVFJZX0FHQUlOX0xBVEVSLCBcIldlYlNvY2tldCBiYWNrcHJlc3N1cmUgb3ZlcmZsb3dcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcy5wdXNoKHsgcGF5bG9hZCwgZXZlbnQgfSk7XG4gICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICBuYW1lOiBcIndzLnB1Ymxpc2gucXVldWVkXCIsXG4gICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgLi4udGhpcy50ZWxlbWV0cnlGaWVsZHMoKSxcbiAgICAgIGRldGFpbDogeyBldmVudCB9LFxuICAgICAgcGF5bG9hZDogZGF0YSxcbiAgICB9KTtcbiAgICB0aGlzLnNjaGVkdWxlT3V0Ym91bmRGbHVzaCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBzY2hlZHVsZU91dGJvdW5kRmx1c2goZGVsYXlNczogbnVtYmVyID0gMCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm91dGJvdW5kRmx1c2hTY2hlZHVsZWQgfHwgdGhpcy5jbG9zZWRJbnRlcm5hbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMub3V0Ym91bmRGbHVzaFNjaGVkdWxlZCA9IHRydWU7XG4gICAgY29uc3QgZmx1c2ggPSAoKSA9PiB7XG4gICAgICB0aGlzLm91dGJvdW5kRmx1c2hTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZmx1c2hPdXRib3VuZE1lc3NhZ2VzKCk7XG4gICAgfTtcblxuICAgIGlmIChkZWxheU1zID4gMCkge1xuICAgICAgc2V0VGltZW91dChmbHVzaCwgZGVsYXlNcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc2V0SW1tZWRpYXRlKGZsdXNoKTtcbiAgfVxuXG4gIC8vIGJ1ZmZlcmVkQW1vdW506rCAIOyehOqzhOy5mOulvCDrhJjsnLzrqbQgZmx1c2jrpbwg66+466SEIHNvY2tldCDrgrTrtoAg7YGQ6rCAIO2EsOyngOyngCDslYrrj4TroZ0gYmFja3ByZXNzdXJl66W8IOyhtOykke2VqFxuICAvLyDtlZwg67KI7JeQIOuwsOy5mCDri6jsnITroZzrp4wgc2VuZO2VtCDrj5nquLAg66Oo7ZSE6rCAIOydtOuypO2KuCDro6jtlITrpbwg7J6l7Iuc6rCEIOygkOycoO2VmOyngCDslYrqsowg7ZWoXG4gIHByaXZhdGUgZmx1c2hPdXRib3VuZE1lc3NhZ2VzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNsb3NlZEludGVybmFsIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgIT09IFdTX09QRU4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zb2NrZXQuYnVmZmVyZWRBbW91bnQgPiBNQVhfU09DS0VUX0JVRkZFUkVEX0FNT1VOVCkge1xuICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgIG5hbWU6IFwid3MuYmFja3ByZXNzdXJlLmRlbGF5ZWRcIixcbiAgICAgICAgbGV2ZWw6IFwid2FyblwiLFxuICAgICAgICAuLi50aGlzLnRlbGVtZXRyeUZpZWxkcygpLFxuICAgICAgfSk7XG4gICAgICB0aGlzLnNjaGVkdWxlT3V0Ym91bmRGbHVzaChPVVRCT1VORF9SRVRSWV9ERUxBWV9NUyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNlbnQgPSAwO1xuICAgIHdoaWxlIChcbiAgICAgIHNlbnQgPCBPVVRCT1VORF9CQVRDSF9TSVpFICYmXG4gICAgICB0aGlzLnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzLmxlbmd0aCA+IDAgJiZcbiAgICAgIHRoaXMuc29ja2V0LnJlYWR5U3RhdGUgPT09IFdTX09QRU5cbiAgICApIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzLnNoaWZ0KCk7XG4gICAgICBpZiAoIW5leHQpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjb25zdCB7IHBheWxvYWQsIGV2ZW50IH0gPSBuZXh0O1xuXG4gICAgICBjb25zdCBzdGFydGVkQXQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgIGNvbnN0IGZpZWxkcyA9IHRoaXMudGVsZW1ldHJ5RmllbGRzKCk7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKHBheWxvYWQpO1xuICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgICAgIHRoaXMub3B0aW9ucy50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICAgIG5hbWU6IFwid3MucHVibGlzaC5zZW50XCIsXG4gICAgICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgZGV0YWlsOiB7IGV2ZW50IH0sXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5yZWNvcmRTcGFuKHtcbiAgICAgICAgICBvcGVyYXRpb25OYW1lOiBcIndzLnB1Ymxpc2guc2VuZFwiLFxuICAgICAgICAgIGtpbmQ6IFwicHJvZHVjZXJcIixcbiAgICAgICAgICBkdXJhdGlvbk1zLFxuICAgICAgICAgIHN0YXR1czogXCJ1bnNldFwiLFxuICAgICAgICAgIC4uLmZpZWxkcyxcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7IGV2ZW50IH0sXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlci5yZWNvcmRNZXRyaWMoe1xuICAgICAgICAgIG5hbWU6IFwic29uYW11LndzLnB1Ymxpc2hlc1wiLFxuICAgICAgICAgIGtpbmQ6IFwiY291bnRlclwiLFxuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIHVuaXQ6IFwiMVwiLFxuICAgICAgICAgIHRhZ3M6IHsgb3V0Y29tZTogXCJzZW50XCIsIGV2ZW50IH0sXG4gICAgICAgICAgLi4uZmllbGRzLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWRBdDtcbiAgICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIuZW1pdCh7XG4gICAgICAgICAgbmFtZTogXCJ3cy5wdWJsaXNoLmZhaWxlZFwiLFxuICAgICAgICAgIGxldmVsOiBcImVycm9yXCIsXG4gICAgICAgICAgLi4uZmllbGRzLFxuICAgICAgICAgIGRldGFpbDogeyBldmVudCB9LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIucmVjb3JkU3Bhbih7XG4gICAgICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5wdWJsaXNoLnNlbmRcIixcbiAgICAgICAgICBraW5kOiBcInByb2R1Y2VyXCIsXG4gICAgICAgICAgZHVyYXRpb25NcyxcbiAgICAgICAgICBzdGF0dXM6IFwiZXJyb3JcIixcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgYXR0cmlidXRlczogeyBldmVudCB9LFxuICAgICAgICAgIGVycm9yVHlwZTogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm5hbWUgOiB0eXBlb2YgZXJyb3IsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNsb3NlKFdTX0NMT1NFX0NPREVfSU5URVJOQUxfRVJST1IsIFwiT3V0Ym91bmQgcHVibGlzaCBmYWlsZWRcIik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc2VudCArPSAxO1xuICAgICAgaWYgKHRoaXMuc29ja2V0LmJ1ZmZlcmVkQW1vdW50ID4gTUFYX1NPQ0tFVF9CVUZGRVJFRF9BTU9VTlQpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucGVuZGluZ091dGJvdW5kTWVzc2FnZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zY2hlZHVsZU91dGJvdW5kRmx1c2goXG4gICAgICAgIHRoaXMuc29ja2V0LmJ1ZmZlcmVkQW1vdW50ID4gTUFYX1NPQ0tFVF9CVUZGRVJFRF9BTU9VTlQgPyBPVVRCT1VORF9SRVRSWV9ERUxBWV9NUyA6IDAsXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVNZXNzYWdlKHJhdzogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgcmF3ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIHJhdztcbiAgfVxuXG4gIGlmIChyYXcgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICByZXR1cm4gcmF3LnRvU3RyaW5nKFwidXRmLThcIik7XG4gIH1cblxuICBpZiAocmF3IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20ocmF3KS50b1N0cmluZyhcInV0Zi04XCIpO1xuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkocmF3KSkge1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KHJhdy5maWx0ZXIoKGNodW5rKTogY2h1bmsgaXMgQnVmZmVyID0+IGNodW5rIGluc3RhbmNlb2YgQnVmZmVyKSkudG9TdHJpbmcoXG4gICAgICBcInV0Zi04XCIsXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShyYXcpO1xufVxuXG5mdW5jdGlvbiBzYWZlUGFyc2VFbnZlbG9wZShyYXc6IHN0cmluZyk6IFBhcnNlZEVudmVsb3BlIHwgbnVsbCB7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpIGFzIHVua25vd247XG4gICAgY29uc3QgdmFsaWRhdGVkID0gV2ViU29ja2V0RW52ZWxvcGVTY2hlbWEuc2FmZVBhcnNlKHBhcnNlZCk7XG4gICAgcmV0dXJuIHZhbGlkYXRlZC5zdWNjZXNzID8gdmFsaWRhdGVkLmRhdGEgOiBudWxsO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vLyBSRkMgNjQ1NeqwgCBjbG9zZSBmcmFtZSByZWFzb27snYQgMTIzIGJ5dGXroZwg7KCc7ZWc7ZWY66+A66GcIOy0iOqzvOu2hOydgCDsnpjrnbwg7KCE7IahIOyLpO2MqOulvCDrsKnsp4DtlahcbmZ1bmN0aW9uIHRydW5jYXRlQ2xvc2VSZWFzb24ocmVhc29uPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFyZWFzb24pIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIEJ1ZmZlci5ieXRlTGVuZ3RoKHJlYXNvbiwgXCJ1dGYtOFwiKSA8PSAxMjNcbiAgICA/IHJlYXNvblxuICAgIDogQnVmZmVyLmZyb20ocmVhc29uKS5zdWJhcnJheSgwLCAxMjMpLnRvU3RyaW5nKFwidXRmLThcIik7XG59XG5cbi8vIGNvbm5lY3Rpb24gbGlmZXRpbWUgc3BhbuydmCBzdGF0dXPrpbwgY2xvc2UgY29kZSDquLDspIDsnLzroZwg67aE6riw7ZWoICgxMDAwLzEwMDEg7KCV7IOBIOyiheujjCwg6re4IOyZuCBrbm93biBjb2RlIGVycm9yLCBjb2RlIOuvuOyDgeydgCB1bnNldClcbmZ1bmN0aW9uIGRlcml2ZUxpZmV0aW1lU3RhdHVzKGNvZGU6IG51bWJlciB8IHVuZGVmaW5lZCk6IFwib2tcIiB8IFwiZXJyb3JcIiB8IFwidW5zZXRcIiB7XG4gIGlmIChjb2RlID09PSB1bmRlZmluZWQpIHJldHVybiBcInVuc2V0XCI7XG4gIGlmIChjb2RlID09PSAxMDAwIHx8IGNvZGUgPT09IDEwMDEpIHJldHVybiBcIm9rXCI7XG4gIHJldHVybiBcImVycm9yXCI7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQXVMQSxTQUFnQix1QkFBdUIsVUFBbUMsRUFBRSxFQUFvQjtBQUM5RixRQUFPLElBQUksaUJBQWlCLFFBQVE7O0FBZ3BCdEMsU0FBUyxpQkFBaUIsS0FBc0I7QUFDOUMsS0FBSSxPQUFPLFFBQVEsVUFBVTtBQUMzQixTQUFPOztBQUdULEtBQUksZUFBZSxRQUFRO0FBQ3pCLFNBQU8sSUFBSSxTQUFTLFFBQVE7O0FBRzlCLEtBQUksZUFBZSxhQUFhO0FBQzlCLFNBQU8sT0FBTyxLQUFLLElBQUksQ0FBQyxTQUFTLFFBQVE7O0FBRzNDLEtBQUksTUFBTSxRQUFRLElBQUksRUFBRTtBQUN0QixTQUFPLE9BQU8sT0FBTyxJQUFJLFFBQVEsVUFBMkIsaUJBQWlCLE9BQU8sQ0FBQyxDQUFDLFNBQ3BGLFFBQ0Q7O0FBR0gsUUFBTyxLQUFLLFVBQVUsSUFBSTs7QUFHNUIsU0FBUyxrQkFBa0IsS0FBb0M7QUFDN0QsS0FBSTtFQUNGLE1BQU0sU0FBUyxLQUFLLE1BQU0sSUFBSTtFQUM5QixNQUFNLFlBQVksd0JBQXdCLFVBQVUsT0FBTztBQUMzRCxTQUFPLFVBQVUsVUFBVSxVQUFVLE9BQU87U0FDdEM7QUFDTixTQUFPOzs7QUFLWCxTQUFTLG9CQUFvQixRQUFxQztBQUNoRSxLQUFJLENBQUMsUUFBUTtBQUNYLFNBQU87O0FBR1QsUUFBTyxPQUFPLFdBQVcsUUFBUSxRQUFRLElBQUksTUFDekMsU0FDQSxPQUFPLEtBQUssT0FBTyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxRQUFROztBQUk1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