@pipeline-builder/api-server 4.1.15 → 4.1.17

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.
@@ -22,81 +22,15 @@ import { createEnvRedisSSERelay } from '../http/sse-relay.js';
22
22
  // in metrics.ts), and lets api-core helpers like the quota client record
23
23
  // `quota_fail_open_total` without taking a hard dep on api-server.
24
24
  setCounterEmitter(incCounter);
25
- /**
26
- * Create and configure an Express application with common middleware
27
- *
28
- * Sets up:
29
- * - CORS with configured origins
30
- * - Helmet security headers
31
- * - Rate limiting
32
- * - JSON and URL-encoded body parsing
33
- * - Trust proxy settings
34
- * - Health check endpoint (/health)
35
- * - Metrics endpoint (/metrics)
36
- * - SSE logs endpoint (/logs/:requestId) — only with `logStream: true`
37
- *
38
- * @param options - Configuration options
39
- * @returns Configured Express app and SSE manager
40
- *
41
- * @example
42
- * ```typescript
43
- * const { app, sseManager } = createApp();
44
- *
45
- * app.post('/api/resource', requireAuth, async (req, res) => {
46
- * // Your route handler
47
- * });
48
- *
49
- * startServer(app, { name: 'My Service' });
50
- * ```
51
- */
52
- export function createApp(options = {}) {
53
- const { enableCors = true, enableHelmet = true, enableRateLimit = true, enableJsonBody = true, jsonLimit = '1mb', enableUrlEncoded = true, urlEncodedLimit = '1mb', logStream = false, checkDependencies, enableOpenApi = process.env.NODE_ENV !== 'production', openApiOptions, enableCompression = true, warmupHooks = [], idempotencyStore, } = options;
54
- const serviceName = process.env.SERVICE_NAME || 'api';
55
- // Default SSE manager. The relay (this service's own Redis channel) is built
56
- // only when something streams: the log stream turns it on here, and an
57
- // org-keyed channel turns it on when registered (registerSseTicketChannel).
58
- // The log ticket store exists only with the log stream. A caller-supplied
59
- // `sseManager` skips this entirely.
60
- const sseManager = options.sseManager ?? new SSEManager({
61
- logStream,
62
- relayFactory: () => createEnvRedisSSERelay(serviceName),
63
- ...(logStream && {
64
- ticketStore: createEnvSseTicketStore({
65
- ttlMs: SSE_TICKET_TTL_MS,
66
- maxTotal: parseInt(process.env.SSE_MAX_TOTAL_TICKETS || '1000', 10),
67
- maxPerOrg: parseInt(process.env.SSE_MAX_TICKETS_PER_ORG || '10', 10),
68
- keyPrefix: `logs:${serviceName}`,
69
- }),
70
- }),
71
- });
72
- if (logStream)
73
- sseManager.enableRelay();
74
- // Wire the idempotency replay-cache backend used by the post-auth route
75
- // factories (createProtectedRoute / createAuthenticatedWithOrgRoute). Prefer
76
- // an explicitly injected store; otherwise auto-construct from the shared env
77
- // Redis so keyed mutation retries dedupe across replicas. Falls back to the
78
- // in-memory default when no Redis is configured (single-replica correctness).
79
- const resolvedIdempotencyStore = idempotencyStore ?? createEnvRedisIdempotencyStore();
80
- if (resolvedIdempotencyStore) {
81
- setIdempotencyStore(resolvedIdempotencyStore);
82
- }
83
- // OpenTelemetry is NOT initialized here: by the time createApp runs, express
84
- // and http have already been required, so the auto-instrumentation hooks
85
- // would have nothing to patch (no inbound span → no trace id). Tracing is
86
- // started by the `otel-bootstrap.js` preload instead (node -r … — see each
87
- // service's Dockerfile CMD / start script), which runs before any
88
- // instrumented module loads. `currentTraceId()` then reads the active span.
89
- const serverConfig = Config.get('server');
90
- const app = express();
91
- // Security middleware.
92
- //
25
+ /** Helmet (strict CSP), CORS, compression and ETags. */
26
+ function applySecurityHeaders(app, options, enableOpenApi) {
27
+ const { enableCors = true, enableHelmet = true, enableCompression = true } = options;
93
28
  // Swagger UI needs unsafe-inline + unsafe-eval for its bundled scripts —
94
- // but we only relax CSP that far when (a) OpenAPI is enabled AND (b) we're
29
+ // but CSP is only relaxed that far when (a) OpenAPI is enabled AND (b) we're
95
30
  // not in production. In prod, Swagger should be served behind a separate
96
31
  // host or auth-gated route; the main app keeps the strict CSP so a Stored
97
32
  // XSS in any handler can't `eval()` arbitrary script.
98
- const isProduction = process.env.NODE_ENV === 'production';
99
- const allowSwaggerCsp = enableOpenApi && !isProduction;
33
+ const allowSwaggerCsp = enableOpenApi && process.env.NODE_ENV !== 'production';
100
34
  if (enableHelmet) {
101
35
  app.use(helmet({
102
36
  contentSecurityPolicy: {
@@ -118,15 +52,15 @@ export function createApp(options = {}) {
118
52
  }));
119
53
  }
120
54
  if (enableCors) {
121
- app.use(cors(serverConfig.cors));
55
+ app.use(cors(Config.get('server').cors));
122
56
  }
123
57
  // Response compression (gzip/deflate) — skip SSE streams
124
58
  if (enableCompression) {
125
59
  app.use(compression({
126
60
  filter: (req, res) => {
127
61
  // Don't compress SSE streams. Match by inclusion: the Accept header is
128
- // often a list (e.g. "text/event-stream, */*"), so exact equality missed
129
- // those and compressed/buffered the stream.
62
+ // often a list (e.g. "text/event-stream, */*"), which exact equality
63
+ // would miss, compressing/buffering the stream.
130
64
  if ((req.headers.accept || '').includes('text/event-stream'))
131
65
  return false;
132
66
  return compression.filter(req, res);
@@ -136,7 +70,10 @@ export function createApp(options = {}) {
136
70
  }
137
71
  // ETag support for conditional GET requests (304 Not Modified)
138
72
  app.use(etagMiddleware());
139
- // Body parsing
73
+ }
74
+ /** JSON + URL-encoded body parsers. */
75
+ function applyBodyParsing(app, options) {
76
+ const { enableJsonBody = true, jsonLimit = '1mb', enableUrlEncoded = true, urlEncodedLimit = '1mb' } = options;
140
77
  if (enableJsonBody) {
141
78
  const jsonParser = express.json({ limit: jsonLimit });
142
79
  const exclude = options.jsonBodyExclude ?? [];
@@ -152,17 +89,13 @@ export function createApp(options = {}) {
152
89
  if (enableUrlEncoded) {
153
90
  app.use(express.urlencoded({ extended: true, limit: urlEncodedLimit }));
154
91
  }
155
- // Trust proxy (must be set before rate limiter so req.ip resolves correctly)
156
- app.set('trust proxy', serverConfig.trustProxy);
157
- // Request ID — prefer existing header from nginx, otherwise generate one
158
- app.use((req, res, next) => {
159
- const hdr = req.headers['x-request-id'];
160
- const requestId = (Array.isArray(hdr) ? hdr[0] : hdr) || uuid();
161
- req.requestId = requestId;
162
- res.setHeader('X-Request-Id', requestId);
163
- next();
164
- });
165
- // Health check registered before rate limiter so it is never throttled
92
+ }
93
+ /**
94
+ * Health, readiness guard, `/warmup`, `/metrics` and the OpenAPI docs — all
95
+ * registered before the rate limiter so they are never throttled.
96
+ */
97
+ function mountInfraEndpoints(app, options, serviceName, enableOpenApi) {
98
+ const { checkDependencies, openApiOptions, warmupHooks = [] } = options;
166
99
  app.use(createHealthRouter({
167
100
  serviceName,
168
101
  checkDependencies,
@@ -179,9 +112,9 @@ export function createApp(options = {}) {
179
112
  // Mongo / Redis / SQS pass `warmupHooks` so those are warmed in parallel.
180
113
  //
181
114
  // GATED to verified service principals. Every hit runs a Postgres round-trip
182
- // plus all `warmupHooks` (Mongo/Redis/SQS), so while it was open an anonymous
183
- // loop amplified into datastore load on every service in the fleet — and
184
- // because it is registered above the rate limiter, nothing throttled it.
115
+ // plus all `warmupHooks` (Mongo/Redis/SQS), so an open endpoint would let an
116
+ // anonymous loop amplify into datastore load on every service in the fleet —
117
+ // and it is registered above the rate limiter, so nothing would throttle it.
185
118
  // `verifyServicePrincipal` checks the bearer token cryptographically, so it is
186
119
  // safe here, above `requireAuth`.
187
120
  app.get('/warmup', async (req, res) => {
@@ -205,9 +138,9 @@ export function createApp(options = {}) {
205
138
  // Optionally gated: when `METRICS_SCRAPE_TOKEN` is set, the scraper must send
206
139
  // it as a bearer token (Prometheus `bearer_token` / `bearer_token_file` in the
207
140
  // scrape config). Left ungated when unset so enabling it is a deliberate,
208
- // coordinated change rather than a silent monitoring outage — the tenant
209
- // disclosure that made gating urgent is closed independently by defaulting the
210
- // per-org label OFF (see HTTP_METRICS_ORG_SAMPLE_RATE in metrics.ts).
141
+ // coordinated change rather than a silent monitoring outage — tenant ids stay
142
+ // out of the output regardless, because the per-org label defaults OFF (see
143
+ // HTTP_METRICS_ORG_SAMPLE_RATE in metrics.ts).
211
144
  const metricsToken = process.env.METRICS_SCRAPE_TOKEN;
212
145
  app.get('/metrics', (req, res, next) => {
213
146
  if (!metricsToken) {
@@ -224,7 +157,6 @@ export function createApp(options = {}) {
224
157
  }
225
158
  next();
226
159
  }, metricsHandler());
227
- // OpenAPI spec and Swagger UI (registered before rate limiter)
228
160
  if (enableOpenApi) {
229
161
  const spec = generateOpenApiSpec(openApiOptions);
230
162
  app.get('/docs/openapi.json', (_req, res) => {
@@ -234,42 +166,44 @@ export function createApp(options = {}) {
234
166
  customSiteTitle: openApiOptions?.title ?? 'Pipeline Builder API Docs',
235
167
  }));
236
168
  }
237
- // Rate limiting — shared across replicas via the env Redis when configured
238
- if (enableRateLimit) {
239
- const rateLimitConfig = Config.get('rateLimit');
240
- const rateLimitOptions = {
241
- max: rateLimitConfig.max,
242
- windowMs: rateLimitConfig.windowMs,
243
- standardHeaders: true,
244
- legacyHeaders: false,
245
- // Skip rate limiting only for CRYPTOGRAPHICALLY-VERIFIED internal service
246
- // callers. The limiter runs before requireAuth, so the previously-trusted
247
- // plaintext `x-internal-service` header was spoofable by any external
248
- // client → total bypass. verifyServicePrincipal verifies the signed
249
- // service JWT instead; inter-service callers all send one
250
- // (getServiceAuthHeader).
251
- skip: (req) => verifyServicePrincipal(req),
252
- // Key on client IP only. The limiter runs pre-auth, so `req.user` is unset
253
- // and any org id would come from the caller-supplied `x-org-id` header —
254
- // spoofable, letting an attacker rotate values to evade the bucket or
255
- // flood a victim org's bucket. ipKeyGenerator normalizes IPv6 to a /64
256
- // prefix (also required by express-rate-limit 8.x's validator).
257
- keyGenerator: (req) => ipKeyGenerator(req.ip || 'anon', 64),
258
- // A store failure (Redis down / failing over) must degrade to "not rate
259
- // limited", never to a 500 on every request of every service.
260
- passOnStoreError: true,
261
- handler: (_req, res) => {
262
- sendError(res, 429, 'Too many requests, please try again later.', ErrorCode.RATE_LIMIT_EXCEEDED);
263
- },
264
- };
169
+ }
170
+ /** Global rate limiter — shared across replicas via the env Redis when configured. */
171
+ function mountRateLimiter(app, serviceName) {
172
+ const rateLimitConfig = Config.get('rateLimit');
173
+ const rateLimitOptions = {
174
+ max: rateLimitConfig.max,
175
+ windowMs: rateLimitConfig.windowMs,
176
+ standardHeaders: true,
177
+ legacyHeaders: false,
178
+ // Skip rate limiting only for CRYPTOGRAPHICALLY-VERIFIED internal service
179
+ // callers. The limiter runs before requireAuth, so a plaintext header
180
+ // would be spoofable by any external client → total bypass.
181
+ // verifyServicePrincipal verifies the signed service JWT instead;
182
+ // inter-service callers all send one (getServiceAuthHeader).
183
+ skip: (req) => verifyServicePrincipal(req),
184
+ // Key on client IP only. The limiter runs pre-auth, so `req.user` is unset
185
+ // and any org id would come from the caller-supplied `x-org-id` header —
186
+ // spoofable, letting an attacker rotate values to evade the bucket or
187
+ // flood a victim org's bucket. ipKeyGenerator normalizes IPv6 to a /64
188
+ // prefix (also required by express-rate-limit 8.x's validator).
189
+ keyGenerator: (req) => ipKeyGenerator(req.ip || 'anon', 64),
190
+ // A store failure (Redis down / failing over) must degrade to "not rate
191
+ // limited", never to a 500 on every request of every service.
192
+ passOnStoreError: true,
193
+ handler: (_req, res) => {
194
+ sendError(res, 429, 'Too many requests, please try again later.', ErrorCode.RATE_LIMIT_EXCEEDED);
195
+ },
265
196
  // Shared state across replicas (the process-wide rate-limit Redis connection;
266
197
  // undefined without Redis → per-process memory store, right for one replica).
267
- // Namespaced per SERVICE: every service shares one Redis, and the old
268
- // unprefixed `rl:<ip>` key let one client's traffic to ANY service drain its
198
+ // Namespaced per SERVICE: every service shares one Redis, and an unprefixed
199
+ // `rl:<ip>` key would let one client's traffic to ANY service drain its
269
200
  // budget on EVERY service.
270
- rateLimitOptions.store = createSharedRateLimitStore(`${serviceName}:global`);
271
- app.use(rateLimit(rateLimitOptions));
272
- }
201
+ store: createSharedRateLimitStore(`${serviceName}:global`),
202
+ };
203
+ app.use(rateLimit(rateLimitOptions));
204
+ }
205
+ /** Request timeout, duration logging and HTTP metrics. */
206
+ function applyRequestTelemetry(app) {
273
207
  // Express request timeout — uses CoreConstants to share the same default as Lambda handlers
274
208
  const timeoutMs = CoreConstants.HANDLER_TIMEOUT_MS;
275
209
  app.use((_req, res, next) => {
@@ -300,57 +234,149 @@ export function createApp(options = {}) {
300
234
  });
301
235
  // Prometheus metrics middleware — records request duration and count
302
236
  app.use(metricsMiddleware());
237
+ }
238
+ /**
239
+ * The default SSE manager. The relay (this service's own Redis channel) is
240
+ * built only when something streams: the log stream turns it on here, and an
241
+ * org-keyed channel turns it on when registered (registerSseTicketChannel).
242
+ * The log ticket store exists only with the log stream.
243
+ */
244
+ function createDefaultSseManager(serviceName, logStream) {
245
+ const sseManager = new SSEManager({
246
+ logStream,
247
+ relayFactory: () => createEnvRedisSSERelay(serviceName),
248
+ ...(logStream && {
249
+ ticketStore: createEnvSseTicketStore({
250
+ ttlMs: SSE_TICKET_TTL_MS,
251
+ keyPrefix: `logs:${serviceName}`,
252
+ }),
253
+ }),
254
+ });
255
+ if (logStream)
256
+ sseManager.enableRelay();
257
+ return sseManager;
258
+ }
259
+ /**
260
+ * The per-request build-log stream: `POST /logs/ticket` + `GET /logs/:requestId`.
261
+ *
262
+ * Ticket-gated — the stream carries per-org build logs, so it must not be
263
+ * world-readable. Clients first POST /logs/ticket (JWT-authenticated) to mint a
264
+ * short-lived, single-use ticket bound to their org AND to the specific
265
+ * `requestId` stream they intend to open, then open the EventSource with
266
+ * ?ticket=<t>. This keeps the JWT out of query strings / access logs while
267
+ * enforcing org ownership, per-subject authorization, and the per-org
268
+ * connection cap on the stream. Mirrors the message-service notifications SSE
269
+ * ticket exchange.
270
+ */
271
+ function wireSse(app, sseManager) {
272
+ app.post('/logs/ticket', requireAuth, async (req, res) => {
273
+ const orgId = req.user?.organizationId?.toLowerCase();
274
+ if (!orgId) {
275
+ sendError(res, 400, 'Token missing organization', ErrorCode.VALIDATION_ERROR);
276
+ return;
277
+ }
278
+ // The caller must name the stream subject up front so the ticket is bound to
279
+ // it. Without this, a ticket could be replayed against ANY requestId the
280
+ // org could guess, letting it attach to another org's log stream. Strictly
281
+ // format-validated so it can't carry an injection payload into the subject.
282
+ const requestId = req.body?.requestId;
283
+ if (typeof requestId !== 'string' || !SSE_REQUEST_ID_RE.test(requestId)) {
284
+ sendError(res, 400, 'Missing or invalid requestId', ErrorCode.VALIDATION_ERROR);
285
+ return;
286
+ }
287
+ const result = await sseManager.createTicket(orgId, requestId);
288
+ if (!result.ok) {
289
+ if (result.reason === 'forbidden') {
290
+ // The subject is owned by another org — do not confirm it exists; a plain
291
+ // 403 is enough and leaks nothing about which requestIds are live.
292
+ sendError(res, 403, 'Not authorized for this log stream', ErrorCode.INSUFFICIENT_PERMISSIONS);
293
+ }
294
+ else if (result.reason === 'org-limit') {
295
+ sendError(res, 429, 'Too many log stream tickets issued', ErrorCode.QUOTA_EXCEEDED);
296
+ }
297
+ else {
298
+ sendError(res, 503, 'Log streaming subsystem at capacity', ErrorCode.QUOTA_EXCEEDED);
299
+ }
300
+ return;
301
+ }
302
+ sendSuccess(res, 200, { ticket: result.ticket });
303
+ });
304
+ // The stream itself resolves + consumes the ticket inside middleware() and
305
+ // rejects any anonymous / invalid / expired / already-used ticket with 401.
306
+ app.get('/logs/:requestId', sseManager.middleware());
307
+ }
308
+ /**
309
+ * Create and configure an Express application with common middleware
310
+ *
311
+ * Sets up:
312
+ * - CORS with configured origins
313
+ * - Helmet security headers
314
+ * - Rate limiting
315
+ * - JSON and URL-encoded body parsing
316
+ * - Trust proxy settings
317
+ * - Health check endpoint (/health)
318
+ * - Metrics endpoint (/metrics)
319
+ * - SSE logs endpoint (/logs/:requestId) — only with `logStream: true`
320
+ *
321
+ * @param options - Configuration options
322
+ * @returns Configured Express app and SSE manager
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * const { app, sseManager } = createApp();
327
+ *
328
+ * app.post('/api/resource', requireAuth, async (req, res) => {
329
+ * // Your route handler
330
+ * });
331
+ *
332
+ * startServer(app, { name: 'My Service' });
333
+ * ```
334
+ */
335
+ export function createApp(options = {}) {
336
+ const { enableRateLimit = true, logStream = false, enableOpenApi = process.env.NODE_ENV !== 'production', } = options;
337
+ const serviceName = process.env.SERVICE_NAME || 'api';
338
+ // A caller-supplied `sseManager` skips the default construction entirely.
339
+ const sseManager = options.sseManager ?? createDefaultSseManager(serviceName, logStream);
340
+ // Wire the idempotency replay-cache backend used by the post-auth route
341
+ // factories (createProtectedRoute / createAuthenticatedWithOrgRoute). Prefer
342
+ // an explicitly injected store; otherwise auto-construct from the shared env
343
+ // Redis so keyed mutation retries dedupe across replicas. Falls back to the
344
+ // in-memory default when no Redis is configured (single-replica correctness).
345
+ const resolvedIdempotencyStore = options.idempotencyStore ?? createEnvRedisIdempotencyStore();
346
+ if (resolvedIdempotencyStore) {
347
+ setIdempotencyStore(resolvedIdempotencyStore);
348
+ }
349
+ // OpenTelemetry is NOT initialized here: by the time createApp runs, express
350
+ // and http have already been required, so the auto-instrumentation hooks
351
+ // would have nothing to patch (no inbound span → no trace id). Tracing is
352
+ // started by the `otel-bootstrap.js` preload instead (node -r … — see each
353
+ // service's Dockerfile CMD / start script), which runs before any
354
+ // instrumented module loads. `currentTraceId()` then reads the active span.
355
+ const app = express();
356
+ applySecurityHeaders(app, options, enableOpenApi);
357
+ applyBodyParsing(app, options);
358
+ // Trust proxy (must be set before rate limiter so req.ip resolves correctly)
359
+ app.set('trust proxy', Config.get('server').trustProxy);
360
+ // Request ID — prefer existing header from nginx, otherwise generate one
361
+ app.use((req, res, next) => {
362
+ const hdr = req.headers['x-request-id'];
363
+ const requestId = (Array.isArray(hdr) ? hdr[0] : hdr) || uuid();
364
+ req.requestId = requestId;
365
+ res.setHeader('X-Request-Id', requestId);
366
+ next();
367
+ });
368
+ mountInfraEndpoints(app, options, serviceName, enableOpenApi);
369
+ if (enableRateLimit)
370
+ mountRateLimiter(app, serviceName);
371
+ applyRequestTelemetry(app);
303
372
  // NOTE: idempotency is intentionally NOT mounted here. It needs the VERIFIED
304
373
  // org id to namespace its replay cache, but this pre-auth position runs before
305
374
  // `requireAuth`/`attachRequestContext` populate identity, so a global mount
306
375
  // here is a permanent no-op (org always undefined → skip). It is instead wired
307
376
  // into the post-auth route chains — see `createProtectedRoute` /
308
377
  // `createAuthenticatedWithOrgRoute` in middleware-factory.ts.
309
- if (logStream) {
310
- // SSE logs endpoint — ticket-gated (Wave 2b).
311
- // The stream carries per-org build logs, so it must not be world-readable.
312
- // Clients first POST /logs/ticket (JWT-authenticated) to mint a short-lived,
313
- // single-use ticket bound to their org AND to the specific `requestId` stream
314
- // they intend to open, then open the EventSource with ?ticket=<t>. This keeps
315
- // the JWT out of query strings / access logs while enforcing org ownership,
316
- // per-subject authorization, and the per-org connection cap on the stream.
317
- // Mirrors the message-service notifications SSE ticket exchange.
318
- app.post('/logs/ticket', requireAuth, async (req, res) => {
319
- const orgId = req.user?.organizationId?.toLowerCase();
320
- if (!orgId) {
321
- sendError(res, 400, 'Token missing organization', ErrorCode.VALIDATION_ERROR);
322
- return;
323
- }
324
- // The caller must name the stream subject up front so the ticket is bound to
325
- // it. Without this, a ticket could be replayed against ANY requestId the
326
- // org could guess, letting it attach to another org's log stream. Strictly
327
- // format-validated so it can't carry an injection payload into the subject.
328
- const requestId = req.body?.requestId;
329
- if (typeof requestId !== 'string' || !SSE_REQUEST_ID_RE.test(requestId)) {
330
- sendError(res, 400, 'Missing or invalid requestId', ErrorCode.VALIDATION_ERROR);
331
- return;
332
- }
333
- const result = await sseManager.createTicket(orgId, requestId);
334
- if (!result.ok) {
335
- if (result.reason === 'forbidden') {
336
- // The subject is owned by another org — do not confirm it exists; a plain
337
- // 403 is enough and leaks nothing about which requestIds are live.
338
- sendError(res, 403, 'Not authorized for this log stream', ErrorCode.INSUFFICIENT_PERMISSIONS);
339
- }
340
- else if (result.reason === 'org-limit') {
341
- sendError(res, 429, 'Too many log stream tickets issued', ErrorCode.QUOTA_EXCEEDED);
342
- }
343
- else {
344
- sendError(res, 503, 'Log streaming subsystem at capacity', ErrorCode.QUOTA_EXCEEDED);
345
- }
346
- return;
347
- }
348
- sendSuccess(res, 200, { ticket: result.ticket });
349
- });
350
- // The stream itself resolves + consumes the ticket inside middleware() and
351
- // rejects any anonymous / invalid / expired / already-used ticket with 401.
352
- app.get('/logs/:requestId', sseManager.middleware());
353
- }
378
+ if (logStream)
379
+ wireSse(app, sseManager);
354
380
  return { app, sseManager };
355
381
  }
356
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2FwcC1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFclAsT0FBTyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxXQUFXLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLE9BQU8sRUFBRSxFQUFnRSxNQUFNLFNBQVMsQ0FBQztBQUNoRyxPQUFPLFNBQVMsRUFBRSxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLG1CQUFtQixFQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBQ3pILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ25FLE9BQU8sRUFB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RUFBRSxTQUFTLENBQUMsd0JBQXdCLENBQUMsQ0FBQztnQkFDaEcsQ0FBQztxQkFBTSxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssV0FBVyxFQUFFLENBQUM7b0JBQ3pDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLG9DQUFvQyxFQUFFLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDdEYsQ0FBQztxQkFBTSxDQUFDO29CQUNOLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLHFDQUFxQyxFQUFFLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDdkYsQ0FBQztnQkFDRCxPQUFPO1lBQ1QsQ0FBQztZQUNELFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ25ELENBQUMsQ0FBQyxDQUFDO1FBRUgsMkVBQTJFO1FBQzNFLDRFQUE0RTtRQUM1RSxHQUFHLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxPQUFPLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQzdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgc2VuZFN1Y2Nlc3MsIHNlbmRFcnJvciwgZ2VuZXJhdGVPcGVuQXBpU3BlYywgRXJyb3JDb2RlLCBjcmVhdGVMb2dnZXIsIHZlcmlmeVNlcnZpY2VQcmluY2lwYWwsIGNyZWF0ZUhlYWx0aFJvdXRlciwgc2V0Q291bnRlckVtaXR0ZXIsIHJlcXVpcmVBdXRoLCBzYWZlRXF1YWwsIGNyZWF0ZUVudlNzZVRpY2tldFN0b3JlLCBTU0VfVElDS0VUX1RUTF9NUyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgT3BlbkFwaVNwZWNPcHRpb25zIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgQ29uZmlnLCBDb3JlQ29uc3RhbnRzIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtY29yZSc7XG5pbXBvcnQgeyBnZXRDb25uZWN0aW9uIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtZGF0YSc7XG5pbXBvcnQgY29tcHJlc3Npb24gZnJvbSAnY29tcHJlc3Npb24nO1xuaW1wb3J0IGNvcnMgZnJvbSAnY29ycyc7XG5pbXBvcnQgZXhwcmVzcywgeyB0eXBlIEV4cHJlc3MsIHR5cGUgTmV4dEZ1bmN0aW9uLCB0eXBlIFJlcXVlc3QsIHR5cGUgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCByYXRlTGltaXQsIHsgaXBLZXlHZW5lcmF0b3IgfSBmcm9tICdleHByZXNzLXJhdGUtbGltaXQnO1xuaW1wb3J0IGhlbG1ldCBmcm9tICdoZWxtZXQnO1xuaW1wb3J0IHN3YWdnZXJVaSBmcm9tICdzd2FnZ2VyLXVpLWV4cHJlc3MnO1xuaW1wb3J0IHsgdjcgYXMgdXVpZCB9IGZyb20gJ3V1aWQnO1xuaW1wb3J0IHsgZXRhZ01pZGRsZXdhcmUgfSBmcm9tICcuL2V0YWctbWlkZGxld2FyZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0lkZW1wb3RlbmN5U3RvcmUsIHNldElkZW1wb3RlbmN5U3RvcmUsIHR5cGUgSWRlbXBvdGVuY3lTdG9yZSB9IGZyb20gJy4vaWRlbXBvdGVuY3ktbWlkZGxld2FyZS5qcyc7XG5pbXBvcnQgeyBtZXRyaWNzTWlkZGxld2FyZSwgbWV0cmljc0hhbmRsZXIsIGluY0NvdW50ZXIgfSBmcm9tICcuL21ldHJpY3MuanMnO1xuaW1wb3J0IHsgY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUgfSBmcm9tICcuL3JhdGUtbGltaXQtc3RvcmUuanMnO1xuaW1wb3J0IHsgcmVhZGluZXNzR3VhcmQgfSBmcm9tICcuL3JlYWRpbmVzcy5qcyc7XG5pbXBvcnQgeyBTU0VNYW5hZ2VyLCBTU0VfUkVRVUVTVF9JRF9SRSB9IGZyb20gJy4uL2h0dHAvc3NlLWNvbm5lY3Rpb24tbWFuYWdlci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc1NTRVJlbGF5IH0gZnJvbSAnLi4vaHR0cC9zc2UtcmVsYXkuanMnO1xuXG4vLyBXaXJlIGFwaS1jb3JlJ3MgY291bnRlciBzaGltIHRvIHRoZSByZWFsIHByb20tY2xpZW50IHJlZ2lzdHJ5LiBUaGlzIGlzXG4vLyBhIG5vLW9wIHVudGlsIGluY0NvdW50ZXIgaXMgY2FsbGVkIGZvciB0aGUgZmlyc3QgdGltZSAobGF6eSByZWdpc3RyYXRpb25cbi8vIGluIG1ldHJpY3MudHMpLCBhbmQgbGV0cyBhcGktY29yZSBoZWxwZXJzIGxpa2UgdGhlIHF1b3RhIGNsaWVudCByZWNvcmRcbi8vIGBxdW90YV9mYWlsX29wZW5fdG90YWxgIHdpdGhvdXQgdGFraW5nIGEgaGFyZCBkZXAgb24gYXBpLXNlcnZlci5cbnNldENvdW50ZXJFbWl0dGVyKGluY0NvdW50ZXIpO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNyZWF0aW5nIGFuIEV4cHJlc3MgYXBwbGljYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBcHBPcHRpb25zIHtcbiAgLyoqIEVuYWJsZSBDT1JTIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVDb3JzPzogYm9vbGVhbjtcbiAgLyoqIEVuYWJsZSBIZWxtZXQgc2VjdXJpdHkgaGVhZGVycyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlSGVsbWV0PzogYm9vbGVhbjtcbiAgLyoqIEVuYWJsZSByYXRlIGxpbWl0aW5nIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVSYXRlTGltaXQ/OiBib29sZWFuO1xuICAvKiogRW5hYmxlIEpTT04gYm9keSBwYXJzaW5nIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVKc29uQm9keT86IGJvb2xlYW47XG4gIC8qKiBKU09OIGJvZHkgc2l6ZSBsaW1pdCAoZGVmYXVsdDogJzFtYicpICovXG4gIGpzb25MaW1pdD86IHN0cmluZztcbiAgLyoqXG4gICAqIFBhdGggcHJlZml4ZXMgdGhlIGdsb2JhbCBKU09OIGJvZHkgcGFyc2VyIG11c3QgTk9UIHRvdWNoIOKAlCBmb3Igcm91dGVzIHRoYXQgbmVlZFxuICAgKiB0aGUgcmF3IGJvZHkgKGUuZy4gYSBTdHJpcGUgd2ViaG9vayB3aG9zZSBITUFDIGlzIGNvbXB1dGVkIG92ZXIgdGhlIGV4YWN0IGJ5dGVzKS5cbiAgICogV2l0aG91dCB0aGlzIHRoZSBnbG9iYWwgcGFyc2VyIGNvbnN1bWVzIHRoZSBib2R5IGZpcnN0IGFuZCBhIGxhdGVyIGBleHByZXNzLnJhdygpYFxuICAgKiBvbiB0aGUgc2FtZSBwYXRoIGlzIGEgbm8tb3AsIGJyZWFraW5nIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24uXG4gICAqL1xuICBqc29uQm9keUV4Y2x1ZGU/OiBzdHJpbmdbXTtcbiAgLyoqIEVuYWJsZSBVUkwtZW5jb2RlZCBib2R5IHBhcnNpbmcgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZVVybEVuY29kZWQ/OiBib29sZWFuO1xuICAvKiogVVJMLWVuY29kZWQgYm9keSBzaXplIGxpbWl0IChkZWZhdWx0OiAnMW1iJykgKi9cbiAgdXJsRW5jb2RlZExpbWl0Pzogc3RyaW5nO1xuICAvKiogQ3VzdG9tIFNTRSBtYW5hZ2VyIGluc3RhbmNlICovXG4gIHNzZU1hbmFnZXI/OiBTU0VNYW5hZ2VyO1xuICAvKipcbiAgICogU2VydmUgdGhlIHBlci1yZXF1ZXN0IGJ1aWxkLWxvZyBzdHJlYW06IGBQT1NUIC9sb2dzL3RpY2tldGAgK1xuICAgKiBgR0VUIC9sb2dzLzpyZXF1ZXN0SWRgLCBhIGxvZyB0aWNrZXQgc3RvcmUsIHRoZSBjcm9zcy1wb2QgcmVsYXksIGFuZFxuICAgKiBgY3R4LmxvZ2AgZnJhbWVzIHB1c2hlZCB0byBTU0UuIERlZmF1bHQgZmFsc2Ug4oCUIGEgc2VydmljZSB3aXRob3V0IGl0IGhhcyBub1xuICAgKiBgL2xvZ3NgIHJvdXRlcyBhbmQgYGN0eC5sb2dgIG9ubHkgd3JpdGVzIHRvIHRoZSBsb2dnZXIuXG4gICAqL1xuICBsb2dTdHJlYW0/OiBib29sZWFuO1xuICAvKiogSGVhbHRoIGNoZWNrIGRlcGVuZGVuY3kgY2hlY2tlciDigJQgaWYgcHJvdmlkZWQsIC9oZWFsdGggcmVwb3J0cyBkZXBlbmRlbmN5IHN0YXR1cyAqL1xuICBjaGVja0RlcGVuZGVuY2llcz86ICgpID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgJ2Nvbm5lY3RlZCcgfCAnZGlzY29ubmVjdGVkJyB8ICd1bmtub3duJz4+O1xuICAvKiogRW5hYmxlIE9wZW5BUEkgc3BlYyBhdCAvZG9jcy9vcGVuYXBpLmpzb24gYW5kIFN3YWdnZXIgVUkgYXQgL2RvY3MgKGRlZmF1bHQ6IHRydWUpICovXG4gIC8qKlxuICAgKiBTZXJ2ZSB0aGUgT3BlbkFQSSBzcGVjIGF0IGAvZG9jcy9vcGVuYXBpLmpzb25gIGFuZCBTd2FnZ2VyIFVJIGF0IGAvZG9jc2AuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIE9GRiB1bmRlciBgTk9ERV9FTlY9cHJvZHVjdGlvbmA6IHRoZSByb3V0ZXMgYXJlIHJlZ2lzdGVyZWQgYWJvdmVcbiAgICogdGhlIHJhdGUgbGltaXRlciBhbmQgd2VyZSBuZXZlciBhdXRoLWdhdGVkLCBzbyBpbiBwcm9kdWN0aW9uIHRoZXkgcHVibGlzaGVkXG4gICAqIHRoZSBmdWxsIHJvdXRlICsgc2NoZW1hIGludmVudG9yeSBvZiBldmVyeSBzZXJ2aWNlIHRvIGFueW9uZSB3aG8gY291bGQgcmVhY2hcbiAgICogdGhlIHBvcnQuIE9ubHkgdGhlIENTUCB3YXMgdGlnaHRlbmVkIGZvciBwcm9kdWN0aW9uIGJlZm9yZSwgbm90IHRoZSByb3V0ZS5cbiAgICogUGFzcyBgdHJ1ZWAgZXhwbGljaXRseSB0byBzZXJ2ZSB0aGVtIGluIHByb2R1Y3Rpb24gYW55d2F5LlxuICAgKi9cbiAgZW5hYmxlT3BlbkFwaT86IGJvb2xlYW47XG4gIC8qKiBPcGVuQVBJIHNwZWMgY3VzdG9taXphdGlvbiBvcHRpb25zICovXG4gIG9wZW5BcGlPcHRpb25zPzogT3BlbkFwaVNwZWNPcHRpb25zO1xuICAvKiogRW5hYmxlIGd6aXAvZGVmbGF0ZSByZXNwb25zZSBjb21wcmVzc2lvbiAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlQ29tcHJlc3Npb24/OiBib29sZWFuO1xuICAvKipcbiAgICogSWRlbXBvdGVuY3kgcmVwbGF5LWNhY2hlIGJhY2tlbmQgZm9yIGtleWVkIG11dGF0aW9uIHJldHJpZXMuIFdoZW4gb21pdHRlZCxcbiAgICogY3JlYXRlQXBwIGF1dG8td2lyZXMgdGhlIHNoYXJlZCBlbnYgUmVkaXMgc3RvcmUgKG11bHRpLXJlcGxpY2EgZGVkdXApIGlmXG4gICAqIFJlZGlzIGlzIGNvbmZpZ3VyZWQsIGVsc2Uga2VlcHMgdGhlIGluLW1lbW9yeSBkZWZhdWx0IChzaW5nbGUtcmVwbGljYSkuXG4gICAqIFBhc3MgYW4gZXhwbGljaXQgc3RvcmUgdG8gaW5qZWN0IGEgYmVzcG9rZSBiYWNrZW5kIChlLmcuIGEgc2VydmljZSdzIG93blxuICAgKiBpb3JlZGlzIGNvbm5lY3Rpb24pLlxuICAgKi9cbiAgaWRlbXBvdGVuY3lTdG9yZT86IElkZW1wb3RlbmN5U3RvcmU7XG4gIC8qKlxuICAgKiBFeHRyYSB3YXJtdXAgY2FsbGJhY2tzIGludm9rZWQgYnkgYEdFVCAvd2FybXVwYCBpbiBhZGRpdGlvbiB0byB0aGVcbiAgICogZGVmYXVsdCBQb3N0Z3JlcyBwaW5nLiBVc2UgZm9yIHNlcnZpY2VzIHRoYXQgZGVwZW5kIG9uIE1vbmdvLCBSZWRpcyxcbiAgICogU1FTLCBldGMuIOKAlCBwcmUtd2FybWluZyBvcGVucyBjb25uZWN0aW9uIHBvb2xzIGJlZm9yZSByZWFsIHRyYWZmaWNcbiAgICogYXJyaXZlcy4gRWFjaCBjYWxsYmFjayBzaG91bGQgcmVzb2x2ZSB3aGVuIGl0cyBkZXBlbmRlbmN5IGlzIHJlYWR5O1xuICAgKiBhbnkgcmVqZWN0aW9uIGNhdXNlcyAvd2FybXVwIHRvIHJldHVybiA1MDMuXG4gICAqL1xuICB3YXJtdXBIb29rcz86IEFycmF5PCgpID0+IFByb21pc2U8dm9pZD4+O1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBjcmVhdGluZyBhbiBFeHByZXNzIGFwcGxpY2F0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlQXBwUmVzdWx0IHtcbiAgLyoqIENvbmZpZ3VyZWQgRXhwcmVzcyBhcHBsaWNhdGlvbiAqL1xuICBhcHA6IEV4cHJlc3M7XG4gIC8qKiBTU0UgbWFuYWdlciBpbnN0YW5jZSAqL1xuICBzc2VNYW5hZ2VyOiBTU0VNYW5hZ2VyO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhbmQgY29uZmlndXJlIGFuIEV4cHJlc3MgYXBwbGljYXRpb24gd2l0aCBjb21tb24gbWlkZGxld2FyZVxuICpcbiAqIFNldHMgdXA6XG4gKiAtIENPUlMgd2l0aCBjb25maWd1cmVkIG9yaWdpbnNcbiAqIC0gSGVsbWV0IHNlY3VyaXR5IGhlYWRlcnNcbiAqIC0gUmF0ZSBsaW1pdGluZ1xuICogLSBKU09OIGFuZCBVUkwtZW5jb2RlZCBib2R5IHBhcnNpbmdcbiAqIC0gVHJ1c3QgcHJveHkgc2V0dGluZ3NcbiAqIC0gSGVhbHRoIGNoZWNrIGVuZHBvaW50ICgvaGVhbHRoKVxuICogLSBNZXRyaWNzIGVuZHBvaW50ICgvbWV0cmljcylcbiAqIC0gU1NFIGxvZ3MgZW5kcG9pbnQgKC9sb2dzLzpyZXF1ZXN0SWQpIOKAlCBvbmx5IHdpdGggYGxvZ1N0cmVhbTogdHJ1ZWBcbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICogQHJldHVybnMgQ29uZmlndXJlZCBFeHByZXNzIGFwcCBhbmQgU1NFIG1hbmFnZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgeyBhcHAsIHNzZU1hbmFnZXIgfSA9IGNyZWF0ZUFwcCgpO1xuICpcbiAqIGFwcC5wb3N0KCcvYXBpL3Jlc291cmNlJywgcmVxdWlyZUF1dGgsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICogICAvLyBZb3VyIHJvdXRlIGhhbmRsZXJcbiAqIH0pO1xuICpcbiAqIHN0YXJ0U2VydmVyKGFwcCwgeyBuYW1lOiAnTXkgU2VydmljZScgfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwcChvcHRpb25zOiBDcmVhdGVBcHBPcHRpb25zID0ge30pOiBDcmVhdGVBcHBSZXN1bHQge1xuICBjb25zdCB7XG4gICAgZW5hYmxlQ29ycyA9IHRydWUsXG4gICAgZW5hYmxlSGVsbWV0ID0gdHJ1ZSxcbiAgICBlbmFibGVSYXRlTGltaXQgPSB0cnVlLFxuICAgIGVuYWJsZUpzb25Cb2R5ID0gdHJ1ZSxcbiAgICBqc29uTGltaXQgPSAnMW1iJyxcbiAgICBlbmFibGVVcmxFbmNvZGVkID0gdHJ1ZSxcbiAgICB1cmxFbmNvZGVkTGltaXQgPSAnMW1iJyxcbiAgICBsb2dTdHJlYW0gPSBmYWxzZSxcbiAgICBjaGVja0RlcGVuZGVuY2llcyxcbiAgICBlbmFibGVPcGVuQXBpID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJyxcbiAgICBvcGVuQXBpT3B0aW9ucyxcbiAgICBlbmFibGVDb21wcmVzc2lvbiA9IHRydWUsXG4gICAgd2FybXVwSG9va3MgPSBbXSxcbiAgICBpZGVtcG90ZW5jeVN0b3JlLFxuICB9ID0gb3B0aW9ucztcblxuICBjb25zdCBzZXJ2aWNlTmFtZSA9IHByb2Nlc3MuZW52LlNFUlZJQ0VfTkFNRSB8fCAnYXBpJztcblxuICAvLyBEZWZhdWx0IFNTRSBtYW5hZ2VyLiBUaGUgcmVsYXkgKHRoaXMgc2VydmljZSdzIG93biBSZWRpcyBjaGFubmVsKSBpcyBidWlsdFxuICAvLyBvbmx5IHdoZW4gc29tZXRoaW5nIHN0cmVhbXM6IHRoZSBsb2cgc3RyZWFtIHR1cm5zIGl0IG9uIGhlcmUsIGFuZCBhblxuICAvLyBvcmcta2V5ZWQgY2hhbm5lbCB0dXJucyBpdCBvbiB3aGVuIHJlZ2lzdGVyZWQgKHJlZ2lzdGVyU3NlVGlja2V0Q2hhbm5lbCkuXG4gIC8vIFRoZSBsb2cgdGlja2V0IHN0b3JlIGV4aXN0cyBvbmx5IHdpdGggdGhlIGxvZyBzdHJlYW0uIEEgY2FsbGVyLXN1cHBsaWVkXG4gIC8vIGBzc2VNYW5hZ2VyYCBza2lwcyB0aGlzIGVudGlyZWx5LlxuICBjb25zdCBzc2VNYW5hZ2VyID0gb3B0aW9ucy5zc2VNYW5hZ2VyID8/IG5ldyBTU0VNYW5hZ2VyKHtcbiAgICBsb2dTdHJlYW0sXG4gICAgcmVsYXlGYWN0b3J5OiAoKSA9PiBjcmVhdGVFbnZSZWRpc1NTRVJlbGF5KHNlcnZpY2VOYW1lKSxcbiAgICAuLi4obG9nU3RyZWFtICYmIHtcbiAgICAgIHRpY2tldFN0b3JlOiBjcmVhdGVFbnZTc2VUaWNrZXRTdG9yZSh7XG4gICAgICAgIHR0bE1zOiBTU0VfVElDS0VUX1RUTF9NUyxcbiAgICAgICAgbWF4VG90YWw6IHBhcnNlSW50KHByb2Nlc3MuZW52LlNTRV9NQVhfVE9UQUxfVElDS0VUUyB8fCAnMTAwMCcsIDEwKSxcbiAgICAgICAgbWF4UGVyT3JnOiBwYXJzZUludChwcm9jZXNzLmVudi5TU0VfTUFYX1RJQ0tFVFNfUEVSX09SRyB8fCAnMTAnLCAxMCksXG4gICAgICAgIGtleVByZWZpeDogYGxvZ3M6JHtzZXJ2aWNlTmFtZX1gLFxuICAgICAgfSksXG4gICAgfSksXG4gIH0pO1xuICBpZiAobG9nU3RyZWFtKSBzc2VNYW5hZ2VyLmVuYWJsZVJlbGF5KCk7XG5cbiAgLy8gV2lyZSB0aGUgaWRlbXBvdGVuY3kgcmVwbGF5LWNhY2hlIGJhY2tlbmQgdXNlZCBieSB0aGUgcG9zdC1hdXRoIHJvdXRlXG4gIC8vIGZhY3RvcmllcyAoY3JlYXRlUHJvdGVjdGVkUm91dGUgLyBjcmVhdGVBdXRoZW50aWNhdGVkV2l0aE9yZ1JvdXRlKS4gUHJlZmVyXG4gIC8vIGFuIGV4cGxpY2l0bHkgaW5qZWN0ZWQgc3RvcmU7IG90aGVyd2lzZSBhdXRvLWNvbnN0cnVjdCBmcm9tIHRoZSBzaGFyZWQgZW52XG4gIC8vIFJlZGlzIHNvIGtleWVkIG11dGF0aW9uIHJldHJpZXMgZGVkdXBlIGFjcm9zcyByZXBsaWNhcy4gRmFsbHMgYmFjayB0byB0aGVcbiAgLy8gaW4tbWVtb3J5IGRlZmF1bHQgd2hlbiBubyBSZWRpcyBpcyBjb25maWd1cmVkIChzaW5nbGUtcmVwbGljYSBjb3JyZWN0bmVzcykuXG4gIGNvbnN0IHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSA9IGlkZW1wb3RlbmN5U3RvcmUgPz8gY3JlYXRlRW52UmVkaXNJZGVtcG90ZW5jeVN0b3JlKCk7XG4gIGlmIChyZXNvbHZlZElkZW1wb3RlbmN5U3RvcmUpIHtcbiAgICBzZXRJZGVtcG90ZW5jeVN0b3JlKHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSk7XG4gIH1cblxuICAvLyBPcGVuVGVsZW1ldHJ5IGlzIE5PVCBpbml0aWFsaXplZCBoZXJlOiBieSB0aGUgdGltZSBjcmVhdGVBcHAgcnVucywgZXhwcmVzc1xuICAvLyBhbmQgaHR0cCBoYXZlIGFscmVhZHkgYmVlbiByZXF1aXJlZCwgc28gdGhlIGF1dG8taW5zdHJ1bWVudGF0aW9uIGhvb2tzXG4gIC8vIHdvdWxkIGhhdmUgbm90aGluZyB0byBwYXRjaCAobm8gaW5ib3VuZCBzcGFuIOKGkiBubyB0cmFjZSBpZCkuIFRyYWNpbmcgaXNcbiAgLy8gc3RhcnRlZCBieSB0aGUgYG90ZWwtYm9vdHN0cmFwLmpzYCBwcmVsb2FkIGluc3RlYWQgKG5vZGUgLXIg4oCmIOKAlCBzZWUgZWFjaFxuICAvLyBzZXJ2aWNlJ3MgRG9ja2VyZmlsZSBDTUQgLyBzdGFydCBzY3JpcHQpLCB3aGljaCBydW5zIGJlZm9yZSBhbnlcbiAgLy8gaW5zdHJ1bWVudGVkIG1vZHVsZSBsb2Fkcy4gYGN1cnJlbnRUcmFjZUlkKClgIHRoZW4gcmVhZHMgdGhlIGFjdGl2ZSBzcGFuLlxuXG4gIGNvbnN0IHNlcnZlckNvbmZpZyA9IENvbmZpZy5nZXQoJ3NlcnZlcicpO1xuICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG5cbiAgLy8gU2VjdXJpdHkgbWlkZGxld2FyZS5cbiAgLy9cbiAgLy8gU3dhZ2dlciBVSSBuZWVkcyB1bnNhZmUtaW5saW5lICsgdW5zYWZlLWV2YWwgZm9yIGl0cyBidW5kbGVkIHNjcmlwdHMg4oCUXG4gIC8vIGJ1dCB3ZSBvbmx5IHJlbGF4IENTUCB0aGF0IGZhciB3aGVuIChhKSBPcGVuQVBJIGlzIGVuYWJsZWQgQU5EIChiKSB3ZSdyZVxuICAvLyBub3QgaW4gcHJvZHVjdGlvbi4gSW4gcHJvZCwgU3dhZ2dlciBzaG91bGQgYmUgc2VydmVkIGJlaGluZCBhIHNlcGFyYXRlXG4gIC8vIGhvc3Qgb3IgYXV0aC1nYXRlZCByb3V0ZTsgdGhlIG1haW4gYXBwIGtlZXBzIHRoZSBzdHJpY3QgQ1NQIHNvIGEgU3RvcmVkXG4gIC8vIFhTUyBpbiBhbnkgaGFuZGxlciBjYW4ndCBgZXZhbCgpYCBhcmJpdHJhcnkgc2NyaXB0LlxuICBjb25zdCBpc1Byb2R1Y3Rpb24gPSBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ3Byb2R1Y3Rpb24nO1xuICBjb25zdCBhbGxvd1N3YWdnZXJDc3AgPSBlbmFibGVPcGVuQXBpICYmICFpc1Byb2R1Y3Rpb247XG4gIGlmIChlbmFibGVIZWxtZXQpIHtcbiAgICBhcHAudXNlKGhlbG1ldCh7XG4gICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IHtcbiAgICAgICAgZGlyZWN0aXZlczoge1xuICAgICAgICAgIGRlZmF1bHRTcmM6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBzY3JpcHRTcmM6IGFsbG93U3dhZ2dlckNzcFxuICAgICAgICAgICAgPyBbXCInc2VsZidcIiwgXCIndW5zYWZlLWlubGluZSdcIiwgXCIndW5zYWZlLWV2YWwnXCJdXG4gICAgICAgICAgICA6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBzdHlsZVNyYzogW1wiJ3NlbGYnXCIsIFwiJ3Vuc2FmZS1pbmxpbmUnXCJdLFxuICAgICAgICAgIGltZ1NyYzogW1wiJ3NlbGYnXCIsICdkYXRhOicsICdibG9iOiddLFxuICAgICAgICAgIGNvbm5lY3RTcmM6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBmb250U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgb2JqZWN0U3JjOiBbXCInbm9uZSdcIl0sXG4gICAgICAgICAgZnJhbWVBbmNlc3RvcnM6IFtcIidub25lJ1wiXSxcbiAgICAgICAgICBiYXNlVXJpOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgZm9ybUFjdGlvbjogW1wiJ3NlbGYnXCJdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KSk7XG4gIH1cblxuICBpZiAoZW5hYmxlQ29ycykge1xuICAgIGFwcC51c2UoY29ycyhzZXJ2ZXJDb25maWcuY29ycykpO1xuICB9XG5cbiAgLy8gUmVzcG9uc2UgY29tcHJlc3Npb24gKGd6aXAvZGVmbGF0ZSkg4oCUIHNraXAgU1NFIHN0cmVhbXNcbiAgaWYgKGVuYWJsZUNvbXByZXNzaW9uKSB7XG4gICAgYXBwLnVzZShjb21wcmVzc2lvbih7XG4gICAgICBmaWx0ZXI6IChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gRG9uJ3QgY29tcHJlc3MgU1NFIHN0cmVhbXMuIE1hdGNoIGJ5IGluY2x1c2lvbjogdGhlIEFjY2VwdCBoZWFkZXIgaXNcbiAgICAgICAgLy8gb2Z0ZW4gYSBsaXN0IChlLmcuIFwidGV4dC9ldmVudC1zdHJlYW0sICovKlwiKSwgc28gZXhhY3QgZXF1YWxpdHkgbWlzc2VkXG4gICAgICAgIC8vIHRob3NlIGFuZCBjb21wcmVzc2VkL2J1ZmZlcmVkIHRoZSBzdHJlYW0uXG4gICAgICAgIGlmICgocmVxLmhlYWRlcnMuYWNjZXB0IHx8ICcnKS5pbmNsdWRlcygndGV4dC9ldmVudC1zdHJlYW0nKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gY29tcHJlc3Npb24uZmlsdGVyKHJlcSwgcmVzKTtcbiAgICAgIH0sXG4gICAgICB0aHJlc2hvbGQ6IENvcmVDb25zdGFudHMuQ09NUFJFU1NJT05fVEhSRVNIT0xEX0JZVEVTLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEVUYWcgc3VwcG9ydCBmb3IgY29uZGl0aW9uYWwgR0VUIHJlcXVlc3RzICgzMDQgTm90IE1vZGlmaWVkKVxuICBhcHAudXNlKGV0YWdNaWRkbGV3YXJlKCkpO1xuXG4gIC8vIEJvZHkgcGFyc2luZ1xuICBpZiAoZW5hYmxlSnNvbkJvZHkpIHtcbiAgICBjb25zdCBqc29uUGFyc2VyID0gZXhwcmVzcy5qc29uKHsgbGltaXQ6IGpzb25MaW1pdCB9KTtcbiAgICBjb25zdCBleGNsdWRlID0gb3B0aW9ucy5qc29uQm9keUV4Y2x1ZGUgPz8gW107XG4gICAgaWYgKGV4Y2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgLy8gU2tpcCB0aGUgZ2xvYmFsIEpTT04gcGFyc2VyIGZvciByYXctYm9keSBwYXRocyBzbyBhIHBlci1wYXRoIGBleHByZXNzLnJhdygpYFxuICAgICAgLy8gY2FuIHJlYWQgdGhlIGV4YWN0IGJ5dGVzIChzZWUgYGpzb25Cb2R5RXhjbHVkZWApLlxuICAgICAgYXBwLnVzZSgocmVxLCByZXMsIG5leHQpID0+IChleGNsdWRlLnNvbWUoKHApID0+IHJlcS5wYXRoLnN0YXJ0c1dpdGgocCkpID8gbmV4dCgpIDoganNvblBhcnNlcihyZXEsIHJlcywgbmV4dCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXBwLnVzZShqc29uUGFyc2VyKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZW5hYmxlVXJsRW5jb2RlZCkge1xuICAgIGFwcC51c2UoZXhwcmVzcy51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IHRydWUsIGxpbWl0OiB1cmxFbmNvZGVkTGltaXQgfSkpO1xuICB9XG5cbiAgLy8gVHJ1c3QgcHJveHkgKG11c3QgYmUgc2V0IGJlZm9yZSByYXRlIGxpbWl0ZXIgc28gcmVxLmlwIHJlc29sdmVzIGNvcnJlY3RseSlcbiAgYXBwLnNldCgndHJ1c3QgcHJveHknLCBzZXJ2ZXJDb25maWcudHJ1c3RQcm94eSk7XG5cbiAgLy8gUmVxdWVzdCBJRCDigJQgcHJlZmVyIGV4aXN0aW5nIGhlYWRlciBmcm9tIG5naW54LCBvdGhlcndpc2UgZ2VuZXJhdGUgb25lXG4gIGFwcC51c2UoKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3QgaGRyID0gcmVxLmhlYWRlcnNbJ3gtcmVxdWVzdC1pZCddO1xuICAgIGNvbnN0IHJlcXVlc3RJZCA9IChBcnJheS5pc0FycmF5KGhkcikgPyBoZHJbMF0gOiBoZHIpIHx8IHV1aWQoKTtcbiAgICByZXEucmVxdWVzdElkID0gcmVxdWVzdElkO1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtUmVxdWVzdC1JZCcsIHJlcXVlc3RJZCk7XG4gICAgbmV4dCgpO1xuICB9KTtcblxuICAvLyBIZWFsdGggY2hlY2sgcmVnaXN0ZXJlZCBiZWZvcmUgcmF0ZSBsaW1pdGVyIHNvIGl0IGlzIG5ldmVyIHRocm90dGxlZFxuICBhcHAudXNlKGNyZWF0ZUhlYWx0aFJvdXRlcih7XG4gICAgc2VydmljZU5hbWUsXG4gICAgY2hlY2tEZXBlbmRlbmNpZXMsXG4gIH0pKTtcblxuICAvLyBSZWFkaW5lc3MgZ3VhcmQg4oCUIDUwM3MgYnVzaW5lc3MgdHJhZmZpYyB3aGlsZSB0aGUgc2VydmljZSBpcyBOb3RSZWFkeVxuICAvLyAoZGF0YXN0b3JlIHN0aWxsIGNvbm5lY3RpbmcgYXQgc3RhcnR1cCwgb3IgZHJvcHBlZCkuIE1vdW50ZWQgcmlnaHQgYWZ0ZXJcbiAgLy8gdGhlIGhlYWx0aCByb3V0ZXIgYW5kIGJlZm9yZSBldmVyeXRoaW5nIGVsc2Ugc28gYSBOb3RSZWFkeSByZXF1ZXN0IGlzXG4gIC8vIHJlamVjdGVkIGNoZWFwbHksIGJlZm9yZSByYXRlLWxpbWl0IC8gaWRlbXBvdGVuY3kgLyBidXNpbmVzcyBoYW5kbGVycyBldmVyXG4gIC8vIHRvdWNoIGEgZGlzY29ubmVjdGVkIGRhdGFzdG9yZS4gSXQgYWxsb3dsaXN0cyB0aGUgaW5mcmEgZW5kcG9pbnRzXG4gIC8vICgvbWV0cmljcywgL3dhcm11cCwgL2RvY3MsIC9sb2dzKSByZWdpc3RlcmVkIGJlbG93LCBwbHVzIC9oZWFsdGggKyAvcmVhZHkuXG4gIGFwcC51c2UocmVhZGluZXNzR3VhcmQoKSk7XG5cbiAgLy8gV2FybS11cCBlbmRwb2ludCDigJQgcHJlLW9wZW5zIGNvbm5lY3Rpb24gcG9vbHMgc28gdGhlIGZpcnN0IHJlYWwgcmVxdWVzdFxuICAvLyBkb2Vzbid0IHBheSBjb2xkLXN0YXJ0IGxhdGVuY3kuIEFsd2F5cyBwaW5ncyBQb3N0Z3Jlczsgc2VydmljZXMgdXNpbmdcbiAgLy8gTW9uZ28gLyBSZWRpcyAvIFNRUyBwYXNzIGB3YXJtdXBIb29rc2Agc28gdGhvc2UgYXJlIHdhcm1lZCBpbiBwYXJhbGxlbC5cbiAgLy9cbiAgLy8gR0FURUQgdG8gdmVyaWZpZWQgc2VydmljZSBwcmluY2lwYWxzLiBFdmVyeSBoaXQgcnVucyBhIFBvc3RncmVzIHJvdW5kLXRyaXBcbiAgLy8gcGx1cyBhbGwgYHdhcm11cEhvb2tzYCAoTW9uZ28vUmVkaXMvU1FTKSwgc28gd2hpbGUgaXQgd2FzIG9wZW4gYW4gYW5vbnltb3VzXG4gIC8vIGxvb3AgYW1wbGlmaWVkIGludG8gZGF0YXN0b3JlIGxvYWQgb24gZXZlcnkgc2VydmljZSBpbiB0aGUgZmxlZXQg4oCUIGFuZFxuICAvLyBiZWNhdXNlIGl0IGlzIHJlZ2lzdGVyZWQgYWJvdmUgdGhlIHJhdGUgbGltaXRlciwgbm90aGluZyB0aHJvdHRsZWQgaXQuXG4gIC8vIGB2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsYCBjaGVja3MgdGhlIGJlYXJlciB0b2tlbiBjcnlwdG9ncmFwaGljYWxseSwgc28gaXQgaXNcbiAgLy8gc2FmZSBoZXJlLCBhYm92ZSBgcmVxdWlyZUF1dGhgLlxuICBhcHAuZ2V0KCcvd2FybXVwJywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGlmICghdmVyaWZ5U2VydmljZVByaW5jaXBhbChyZXEpKSB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MDQsICdOb3QgZm91bmQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgZ2V0Q29ubmVjdGlvbigpLnRlc3RDb25uZWN0aW9uKCksXG4gICAgICAgIC4uLndhcm11cEhvb2tzLm1hcCgoaG9vaykgPT4gaG9vaygpKSxcbiAgICAgIF0pO1xuICAgICAgc2VuZFN1Y2Nlc3MocmVzLCAyMDAsIHsgd2FybWVkOiB0cnVlLCBob29rczogd2FybXVwSG9va3MubGVuZ3RoIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgc2VuZEVycm9yKHJlcywgNTAzLCAnV2FybXVwIGZhaWxlZCcpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gUHJvbWV0aGV1cyBtZXRyaWNzIGVuZHBvaW50IOKAlCBhbHdheXMgcmVnaXN0ZXJlZCAobmV2ZXIgdGhyb3R0bGVkKS5cbiAgLy9cbiAgLy8gT3B0aW9uYWxseSBnYXRlZDogd2hlbiBgTUVUUklDU19TQ1JBUEVfVE9LRU5gIGlzIHNldCwgdGhlIHNjcmFwZXIgbXVzdCBzZW5kXG4gIC8vIGl0IGFzIGEgYmVhcmVyIHRva2VuIChQcm9tZXRoZXVzIGBiZWFyZXJfdG9rZW5gIC8gYGJlYXJlcl90b2tlbl9maWxlYCBpbiB0aGVcbiAgLy8gc2NyYXBlIGNvbmZpZykuIExlZnQgdW5nYXRlZCB3aGVuIHVuc2V0IHNvIGVuYWJsaW5nIGl0IGlzIGEgZGVsaWJlcmF0ZSxcbiAgLy8gY29vcmRpbmF0ZWQgY2hhbmdlIHJhdGhlciB0aGFuIGEgc2lsZW50IG1vbml0b3Jpbmcgb3V0YWdlIOKAlCB0aGUgdGVuYW50XG4gIC8vIGRpc2Nsb3N1cmUgdGhhdCBtYWRlIGdhdGluZyB1cmdlbnQgaXMgY2xvc2VkIGluZGVwZW5kZW50bHkgYnkgZGVmYXVsdGluZyB0aGVcbiAgLy8gcGVyLW9yZyBsYWJlbCBPRkYgKHNlZSBIVFRQX01FVFJJQ1NfT1JHX1NBTVBMRV9SQVRFIGluIG1ldHJpY3MudHMpLlxuICBjb25zdCBtZXRyaWNzVG9rZW4gPSBwcm9jZXNzLmVudi5NRVRSSUNTX1NDUkFQRV9UT0tFTjtcbiAgYXBwLmdldCgnL21ldHJpY3MnLCAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICBpZiAoIW1ldHJpY3NUb2tlbikge1xuICAgICAgbmV4dCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBoZWFkZXIgPSByZXEuaGVhZGVycy5hdXRob3JpemF0aW9uO1xuICAgIGNvbnN0IHByZXNlbnRlZCA9IGhlYWRlcj8uc3RhcnRzV2l0aCgnQmVhcmVyICcpID8gaGVhZGVyLnNsaWNlKDcpIDogdW5kZWZpbmVkO1xuICAgIC8vIENvbnN0YW50LXRpbWUgY29tcGFyZSDigJQgYSBsZW5ndGgtaW5kZXBlbmRlbnQgZXF1YWxpdHkgY2hlY2sgaGVyZSB3b3VsZFxuICAgIC8vIGxlYWsgdGhlIHRva2VuIGEgYnl0ZSBhdCBhIHRpbWUuXG4gICAgaWYgKCFwcmVzZW50ZWQgfHwgIXNhZmVFcXVhbChwcmVzZW50ZWQsIG1ldHJpY3NUb2tlbikpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwNCwgJ05vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBuZXh0KCk7XG4gIH0sIG1ldHJpY3NIYW5kbGVyKCkpO1xuXG4gIC8vIE9wZW5BUEkgc3BlYyBhbmQgU3dhZ2dlciBVSSAocmVnaXN0ZXJlZCBiZWZvcmUgcmF0ZSBsaW1pdGVyKVxuICBpZiAoZW5hYmxlT3BlbkFwaSkge1xuICAgIGNvbnN0IHNwZWMgPSBnZW5lcmF0ZU9wZW5BcGlTcGVjKG9wZW5BcGlPcHRpb25zKTtcbiAgICBhcHAuZ2V0KCcvZG9jcy9vcGVuYXBpLmpzb24nLCAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgcmVzLmpzb24oc3BlYyk7XG4gICAgfSk7XG4gICAgYXBwLnVzZSgnL2RvY3MnLCBzd2FnZ2VyVWkuc2VydmUsIHN3YWdnZXJVaS5zZXR1cChzcGVjLCB7XG4gICAgICBjdXN0b21TaXRlVGl0bGU6IG9wZW5BcGlPcHRpb25zPy50aXRsZSA/PyAnUGlwZWxpbmUgQnVpbGRlciBBUEkgRG9jcycsXG4gICAgfSkpO1xuICB9XG5cbiAgLy8gUmF0ZSBsaW1pdGluZyDigJQgc2hhcmVkIGFjcm9zcyByZXBsaWNhcyB2aWEgdGhlIGVudiBSZWRpcyB3aGVuIGNvbmZpZ3VyZWRcbiAgaWYgKGVuYWJsZVJhdGVMaW1pdCkge1xuICAgIGNvbnN0IHJhdGVMaW1pdENvbmZpZyA9IENvbmZpZy5nZXQoJ3JhdGVMaW1pdCcpO1xuXG4gICAgY29uc3QgcmF0ZUxpbWl0T3B0aW9uczogUGFyYW1ldGVyczx0eXBlb2YgcmF0ZUxpbWl0PlswXSA9IHtcbiAgICAgIG1heDogcmF0ZUxpbWl0Q29uZmlnLm1heCxcbiAgICAgIHdpbmRvd01zOiByYXRlTGltaXRDb25maWcud2luZG93TXMsXG4gICAgICBzdGFuZGFyZEhlYWRlcnM6IHRydWUsXG4gICAgICBsZWdhY3lIZWFkZXJzOiBmYWxzZSxcbiAgICAgIC8vIFNraXAgcmF0ZSBsaW1pdGluZyBvbmx5IGZvciBDUllQVE9HUkFQSElDQUxMWS1WRVJJRklFRCBpbnRlcm5hbCBzZXJ2aWNlXG4gICAgICAvLyBjYWxsZXJzLiBUaGUgbGltaXRlciBydW5zIGJlZm9yZSByZXF1aXJlQXV0aCwgc28gdGhlIHByZXZpb3VzbHktdHJ1c3RlZFxuICAgICAgLy8gcGxhaW50ZXh0IGB4LWludGVybmFsLXNlcnZpY2VgIGhlYWRlciB3YXMgc3Bvb2ZhYmxlIGJ5IGFueSBleHRlcm5hbFxuICAgICAgLy8gY2xpZW50IOKGkiB0b3RhbCBieXBhc3MuIHZlcmlmeVNlcnZpY2VQcmluY2lwYWwgdmVyaWZpZXMgdGhlIHNpZ25lZFxuICAgICAgLy8gc2VydmljZSBKV1QgaW5zdGVhZDsgaW50ZXItc2VydmljZSBjYWxsZXJzIGFsbCBzZW5kIG9uZVxuICAgICAgLy8gKGdldFNlcnZpY2VBdXRoSGVhZGVyKS5cbiAgICAgIHNraXA6IChyZXE6IFJlcXVlc3QpID0+IHZlcmlmeVNlcnZpY2VQcmluY2lwYWwocmVxKSxcbiAgICAgIC8vIEtleSBvbiBjbGllbnQgSVAgb25seS4gVGhlIGxpbWl0ZXIgcnVucyBwcmUtYXV0aCwgc28gYHJlcS51c2VyYCBpcyB1bnNldFxuICAgICAgLy8gYW5kIGFueSBvcmcgaWQgd291bGQgY29tZSBmcm9tIHRoZSBjYWxsZXItc3VwcGxpZWQgYHgtb3JnLWlkYCBoZWFkZXIg4oCUXG4gICAgICAvLyBzcG9vZmFibGUsIGxldHRpbmcgYW4gYXR0YWNrZXIgcm90YXRlIHZhbHVlcyB0byBldmFkZSB0aGUgYnVja2V0IG9yXG4gICAgICAvLyBmbG9vZCBhIHZpY3RpbSBvcmcncyBidWNrZXQuIGlwS2V5R2VuZXJhdG9yIG5vcm1hbGl6ZXMgSVB2NiB0byBhIC82NFxuICAgICAgLy8gcHJlZml4IChhbHNvIHJlcXVpcmVkIGJ5IGV4cHJlc3MtcmF0ZS1saW1pdCA4LngncyB2YWxpZGF0b3IpLlxuICAgICAga2V5R2VuZXJhdG9yOiAocmVxOiBSZXF1ZXN0KSA9PiBpcEtleUdlbmVyYXRvcihyZXEuaXAgfHwgJ2Fub24nLCA2NCksXG4gICAgICAvLyBBIHN0b3JlIGZhaWx1cmUgKFJlZGlzIGRvd24gLyBmYWlsaW5nIG92ZXIpIG11c3QgZGVncmFkZSB0byBcIm5vdCByYXRlXG4gICAgICAvLyBsaW1pdGVkXCIsIG5ldmVyIHRvIGEgNTAwIG9uIGV2ZXJ5IHJlcXVlc3Qgb2YgZXZlcnkgc2VydmljZS5cbiAgICAgIHBhc3NPblN0b3JlRXJyb3I6IHRydWUsXG4gICAgICBoYW5kbGVyOiAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICBzZW5kRXJyb3IocmVzLCA0MjksICdUb28gbWFueSByZXF1ZXN0cywgcGxlYXNlIHRyeSBhZ2FpbiBsYXRlci4nLCBFcnJvckNvZGUuUkFURV9MSU1JVF9FWENFRURFRCk7XG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBTaGFyZWQgc3RhdGUgYWNyb3NzIHJlcGxpY2FzICh0aGUgcHJvY2Vzcy13aWRlIHJhdGUtbGltaXQgUmVkaXMgY29ubmVjdGlvbjtcbiAgICAvLyB1bmRlZmluZWQgd2l0aG91dCBSZWRpcyDihpIgcGVyLXByb2Nlc3MgbWVtb3J5IHN0b3JlLCByaWdodCBmb3Igb25lIHJlcGxpY2EpLlxuICAgIC8vIE5hbWVzcGFjZWQgcGVyIFNFUlZJQ0U6IGV2ZXJ5IHNlcnZpY2Ugc2hhcmVzIG9uZSBSZWRpcywgYW5kIHRoZSBvbGRcbiAgICAvLyB1bnByZWZpeGVkIGBybDo8aXA+YCBrZXkgbGV0IG9uZSBjbGllbnQncyB0cmFmZmljIHRvIEFOWSBzZXJ2aWNlIGRyYWluIGl0c1xuICAgIC8vIGJ1ZGdldCBvbiBFVkVSWSBzZXJ2aWNlLlxuICAgIHJhdGVMaW1pdE9wdGlvbnMuc3RvcmUgPSBjcmVhdGVTaGFyZWRSYXRlTGltaXRTdG9yZShgJHtzZXJ2aWNlTmFtZX06Z2xvYmFsYCk7XG5cbiAgICBhcHAudXNlKHJhdGVMaW1pdChyYXRlTGltaXRPcHRpb25zKSk7XG4gIH1cblxuICAvLyBFeHByZXNzIHJlcXVlc3QgdGltZW91dCDigJQgdXNlcyBDb3JlQ29uc3RhbnRzIHRvIHNoYXJlIHRoZSBzYW1lIGRlZmF1bHQgYXMgTGFtYmRhIGhhbmRsZXJzXG4gIGNvbnN0IHRpbWVvdXRNcyA9IENvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TO1xuICBhcHAudXNlKChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICByZXMuc2V0VGltZW91dCh0aW1lb3V0TXMsICgpID0+IHtcbiAgICAgIGlmICghcmVzLmhlYWRlcnNTZW50KSB7XG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ1JlcXVlc3QgdGltZW91dCcpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUmVxdWVzdCBkdXJhdGlvbiBsb2dnaW5nXG4gIGNvbnN0IGR1cmF0aW9uTG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdyZXF1ZXN0LWR1cmF0aW9uJyk7XG4gIGFwcC51c2UoKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBEYXRlLm5vdygpIC0gc3RhcnQ7XG4gICAgICAvLyBMb2cgYHJlcS5wYXRoYCAobm8gcXVlcnkgc3RyaW5nKSDigJQgYSBzdHJheSBgP3Rva2VuPWAvYD90aWNrZXQ9YCBtdXN0IG5vdCBiZVxuICAgICAgLy8gcGVyc2lzdGVkIHZlcmJhdGltIG9uIGV2ZXJ5IHJlcXVlc3QgKG1pcnJvcnMgdGhlIGF1dGh6LWRlbmlhbCBhdWRpdG9yJ3Mgc3RyaXApLlxuICAgICAgZHVyYXRpb25Mb2dnZXIuaW5mbyhgJHtyZXEubWV0aG9kfSAke3JlcS5wYXRofSAke3Jlcy5zdGF0dXNDb2RlfSAke2R1cmF0aW9ufW1zYCwge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHBhdGg6IHJlcS5wYXRoLFxuICAgICAgICBzdGF0dXNDb2RlOiByZXMuc3RhdHVzQ29kZSxcbiAgICAgICAgZHVyYXRpb25NczogZHVyYXRpb24sXG4gICAgICAgIHJlcXVlc3RJZDogcmVxLnJlcXVlc3RJZCxcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUHJvbWV0aGV1cyBtZXRyaWNzIG1pZGRsZXdhcmUg4oCUIHJlY29yZHMgcmVxdWVzdCBkdXJhdGlvbiBhbmQgY291bnRcbiAgYXBwLnVzZShtZXRyaWNzTWlkZGxld2FyZSgpKTtcblxuICAvLyBOT1RFOiBpZGVtcG90ZW5jeSBpcyBpbnRlbnRpb25hbGx5IE5PVCBtb3VudGVkIGhlcmUuIEl0IG5lZWRzIHRoZSBWRVJJRklFRFxuICAvLyBvcmcgaWQgdG8gbmFtZXNwYWNlIGl0cyByZXBsYXkgY2FjaGUsIGJ1dCB0aGlzIHByZS1hdXRoIHBvc2l0aW9uIHJ1bnMgYmVmb3JlXG4gIC8vIGByZXF1aXJlQXV0aGAvYGF0dGFjaFJlcXVlc3RDb250ZXh0YCBwb3B1bGF0ZSBpZGVudGl0eSwgc28gYSBnbG9iYWwgbW91bnRcbiAgLy8gaGVyZSBpcyBhIHBlcm1hbmVudCBuby1vcCAob3JnIGFsd2F5cyB1bmRlZmluZWQg4oaSIHNraXApLiBJdCBpcyBpbnN0ZWFkIHdpcmVkXG4gIC8vIGludG8gdGhlIHBvc3QtYXV0aCByb3V0ZSBjaGFpbnMg4oCUIHNlZSBgY3JlYXRlUHJvdGVjdGVkUm91dGVgIC9cbiAgLy8gYGNyZWF0ZUF1dGhlbnRpY2F0ZWRXaXRoT3JnUm91dGVgIGluIG1pZGRsZXdhcmUtZmFjdG9yeS50cy5cblxuICBpZiAobG9nU3RyZWFtKSB7XG4gICAgLy8gU1NFIGxvZ3MgZW5kcG9pbnQg4oCUIHRpY2tldC1nYXRlZCAoV2F2ZSAyYikuXG4gICAgLy8gVGhlIHN0cmVhbSBjYXJyaWVzIHBlci1vcmcgYnVpbGQgbG9ncywgc28gaXQgbXVzdCBub3QgYmUgd29ybGQtcmVhZGFibGUuXG4gICAgLy8gQ2xpZW50cyBmaXJzdCBQT1NUIC9sb2dzL3RpY2tldCAoSldULWF1dGhlbnRpY2F0ZWQpIHRvIG1pbnQgYSBzaG9ydC1saXZlZCxcbiAgICAvLyBzaW5nbGUtdXNlIHRpY2tldCBib3VuZCB0byB0aGVpciBvcmcgQU5EIHRvIHRoZSBzcGVjaWZpYyBgcmVxdWVzdElkYCBzdHJlYW1cbiAgICAvLyB0aGV5IGludGVuZCB0byBvcGVuLCB0aGVuIG9wZW4gdGhlIEV2ZW50U291cmNlIHdpdGggP3RpY2tldD08dD4uIFRoaXMga2VlcHNcbiAgICAvLyB0aGUgSldUIG91dCBvZiBxdWVyeSBzdHJpbmdzIC8gYWNjZXNzIGxvZ3Mgd2hpbGUgZW5mb3JjaW5nIG9yZyBvd25lcnNoaXAsXG4gICAgLy8gcGVyLXN1YmplY3QgYXV0aG9yaXphdGlvbiwgYW5kIHRoZSBwZXItb3JnIGNvbm5lY3Rpb24gY2FwIG9uIHRoZSBzdHJlYW0uXG4gICAgLy8gTWlycm9ycyB0aGUgbWVzc2FnZS1zZXJ2aWNlIG5vdGlmaWNhdGlvbnMgU1NFIHRpY2tldCBleGNoYW5nZS5cbiAgICBhcHAucG9zdCgnL2xvZ3MvdGlja2V0JywgcmVxdWlyZUF1dGgsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgIGNvbnN0IG9yZ0lkID0gcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkPy50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKCFvcmdJZCkge1xuICAgICAgICBzZW5kRXJyb3IocmVzLCA0MDAsICdUb2tlbiBtaXNzaW5nIG9yZ2FuaXphdGlvbicsIEVycm9yQ29kZS5WQUxJREFUSU9OX0VSUk9SKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gVGhlIGNhbGxlciBtdXN0IG5hbWUgdGhlIHN0cmVhbSBzdWJqZWN0IHVwIGZyb250IHNvIHRoZSB0aWNrZXQgaXMgYm91bmQgdG9cbiAgICAgIC8vIGl0LiBXaXRob3V0IHRoaXMsIGEgdGlja2V0IGNvdWxkIGJlIHJlcGxheWVkIGFnYWluc3QgQU5ZIHJlcXVlc3RJZCB0aGVcbiAgICAgIC8vIG9yZyBjb3VsZCBndWVzcywgbGV0dGluZyBpdCBhdHRhY2ggdG8gYW5vdGhlciBvcmcncyBsb2cgc3RyZWFtLiBTdHJpY3RseVxuICAgICAgLy8gZm9ybWF0LXZhbGlkYXRlZCBzbyBpdCBjYW4ndCBjYXJyeSBhbiBpbmplY3Rpb24gcGF5bG9hZCBpbnRvIHRoZSBzdWJqZWN0LlxuICAgICAgY29uc3QgcmVxdWVzdElkID0gKHJlcS5ib2R5IGFzIHsgcmVxdWVzdElkPzogdW5rbm93biB9IHwgdW5kZWZpbmVkKT8ucmVxdWVzdElkO1xuICAgICAgaWYgKHR5cGVvZiByZXF1ZXN0SWQgIT09ICdzdHJpbmcnIHx8ICFTU0VfUkVRVUVTVF9JRF9SRS50ZXN0KHJlcXVlc3RJZCkpIHtcbiAgICAgICAgc2VuZEVycm9yKHJlcywgNDAwLCAnTWlzc2luZyBvciBpbnZhbGlkIHJlcXVlc3RJZCcsIEVycm9yQ29kZS5WQUxJREFUSU9OX0VSUk9SKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3NlTWFuYWdlci5jcmVhdGVUaWNrZXQob3JnSWQsIHJlcXVlc3RJZCk7XG4gICAgICBpZiAoIXJlc3VsdC5vaykge1xuICAgICAgICBpZiAocmVzdWx0LnJlYXNvbiA9PT0gJ2ZvcmJpZGRlbicpIHtcbiAgICAgICAgICAvLyBUaGUgc3ViamVjdCBpcyBvd25lZCBieSBhbm90aGVyIG9yZyDigJQgZG8gbm90IGNvbmZpcm0gaXQgZXhpc3RzOyBhIHBsYWluXG4gICAgICAgICAgLy8gNDAzIGlzIGVub3VnaCBhbmQgbGVha3Mgbm90aGluZyBhYm91dCB3aGljaCByZXF1ZXN0SWRzIGFyZSBsaXZlLlxuICAgICAgICAgIHNlbmRFcnJvcihyZXMsIDQwMywgJ05vdCBhdXRob3JpemVkIGZvciB0aGlzIGxvZyBzdHJlYW0nLCBFcnJvckNvZGUuSU5TVUZGSUNJRU5UX1BFUk1JU1NJT05TKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQucmVhc29uID09PSAnb3JnLWxpbWl0Jykge1xuICAgICAgICAgIHNlbmRFcnJvcihyZXMsIDQyOSwgJ1RvbyBtYW55IGxvZyBzdHJlYW0gdGlja2V0cyBpc3N1ZWQnLCBFcnJvckNvZGUuUVVPVEFfRVhDRUVERUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ0xvZyBzdHJlYW1pbmcgc3Vic3lzdGVtIGF0IGNhcGFjaXR5JywgRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVEKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzZW5kU3VjY2VzcyhyZXMsIDIwMCwgeyB0aWNrZXQ6IHJlc3VsdC50aWNrZXQgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBUaGUgc3RyZWFtIGl0c2VsZiByZXNvbHZlcyArIGNvbnN1bWVzIHRoZSB0aWNrZXQgaW5zaWRlIG1pZGRsZXdhcmUoKSBhbmRcbiAgICAvLyByZWplY3RzIGFueSBhbm9ueW1vdXMgLyBpbnZhbGlkIC8gZXhwaXJlZCAvIGFscmVhZHktdXNlZCB0aWNrZXQgd2l0aCA0MDEuXG4gICAgYXBwLmdldCgnL2xvZ3MvOnJlcXVlc3RJZCcsIHNzZU1hbmFnZXIubWlkZGxld2FyZSgpKTtcbiAgfVxuXG4gIHJldHVybiB7IGFwcCwgc3NlTWFuYWdlciB9O1xufVxuIl19
382
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2FwcC1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFclAsT0FBTyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxXQUFXLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLE9BQU8sRUFBRSxFQUFnRSxNQUFNLFNBQVMsQ0FBQztBQUNoRyxPQUFPLFNBQVMsRUFBRSxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLG1CQUFtQixFQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBQ3pILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ25FLE9BQU8sRUFB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RSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBzZW5kU3VjY2Vzcywgc2VuZEVycm9yLCBnZW5lcmF0ZU9wZW5BcGlTcGVjLCBFcnJvckNvZGUsIGNyZWF0ZUxvZ2dlciwgdmVyaWZ5U2VydmljZVByaW5jaXBhbCwgY3JlYXRlSGVhbHRoUm91dGVyLCBzZXRDb3VudGVyRW1pdHRlciwgcmVxdWlyZUF1dGgsIHNhZmVFcXVhbCwgY3JlYXRlRW52U3NlVGlja2V0U3RvcmUsIFNTRV9USUNLRVRfVFRMX01TIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBPcGVuQXBpU3BlY09wdGlvbnMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgeyBDb25maWcsIENvcmVDb25zdGFudHMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCB7IGdldENvbm5lY3Rpb24gfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1kYXRhJztcbmltcG9ydCBjb21wcmVzc2lvbiBmcm9tICdjb21wcmVzc2lvbic7XG5pbXBvcnQgY29ycyBmcm9tICdjb3JzJztcbmltcG9ydCBleHByZXNzLCB7IHR5cGUgRXhwcmVzcywgdHlwZSBOZXh0RnVuY3Rpb24sIHR5cGUgUmVxdWVzdCwgdHlwZSBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHJhdGVMaW1pdCwgeyBpcEtleUdlbmVyYXRvciB9IGZyb20gJ2V4cHJlc3MtcmF0ZS1saW1pdCc7XG5pbXBvcnQgaGVsbWV0IGZyb20gJ2hlbG1ldCc7XG5pbXBvcnQgc3dhZ2dlclVpIGZyb20gJ3N3YWdnZXItdWktZXhwcmVzcyc7XG5pbXBvcnQgeyB2NyBhcyB1dWlkIH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBldGFnTWlkZGxld2FyZSB9IGZyb20gJy4vZXRhZy1taWRkbGV3YXJlLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzSWRlbXBvdGVuY3lTdG9yZSwgc2V0SWRlbXBvdGVuY3lTdG9yZSwgdHlwZSBJZGVtcG90ZW5jeVN0b3JlIH0gZnJvbSAnLi9pZGVtcG90ZW5jeS1taWRkbGV3YXJlLmpzJztcbmltcG9ydCB7IG1ldHJpY3NNaWRkbGV3YXJlLCBtZXRyaWNzSGFuZGxlciwgaW5jQ291bnRlciB9IGZyb20gJy4vbWV0cmljcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTaGFyZWRSYXRlTGltaXRTdG9yZSB9IGZyb20gJy4vcmF0ZS1saW1pdC1zdG9yZS5qcyc7XG5pbXBvcnQgeyByZWFkaW5lc3NHdWFyZCB9IGZyb20gJy4vcmVhZGluZXNzLmpzJztcbmltcG9ydCB7IFNTRU1hbmFnZXIsIFNTRV9SRVFVRVNUX0lEX1JFIH0gZnJvbSAnLi4vaHR0cC9zc2UtY29ubmVjdGlvbi1tYW5hZ2VyLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzU1NFUmVsYXkgfSBmcm9tICcuLi9odHRwL3NzZS1yZWxheS5qcyc7XG5cbi8vIFdpcmUgYXBpLWNvcmUncyBjb3VudGVyIHNoaW0gdG8gdGhlIHJlYWwgcHJvbS1jbGllbnQgcmVnaXN0cnkuIFRoaXMgaXNcbi8vIGEgbm8tb3AgdW50aWwgaW5jQ291bnRlciBpcyBjYWxsZWQgZm9yIHRoZSBmaXJzdCB0aW1lIChsYXp5IHJlZ2lzdHJhdGlvblxuLy8gaW4gbWV0cmljcy50cyksIGFuZCBsZXRzIGFwaS1jb3JlIGhlbHBlcnMgbGlrZSB0aGUgcXVvdGEgY2xpZW50IHJlY29yZFxuLy8gYHF1b3RhX2ZhaWxfb3Blbl90b3RhbGAgd2l0aG91dCB0YWtpbmcgYSBoYXJkIGRlcCBvbiBhcGktc2VydmVyLlxuc2V0Q291bnRlckVtaXR0ZXIoaW5jQ291bnRlcik7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY3JlYXRpbmcgYW4gRXhwcmVzcyBhcHBsaWNhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUFwcE9wdGlvbnMge1xuICAvKiogRW5hYmxlIENPUlMgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUNvcnM/OiBib29sZWFuO1xuICAvKiogRW5hYmxlIEhlbG1ldCBzZWN1cml0eSBoZWFkZXJzIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVIZWxtZXQ/OiBib29sZWFuO1xuICAvKiogRW5hYmxlIHJhdGUgbGltaXRpbmcgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZVJhdGVMaW1pdD86IGJvb2xlYW47XG4gIC8qKiBFbmFibGUgSlNPTiBib2R5IHBhcnNpbmcgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUpzb25Cb2R5PzogYm9vbGVhbjtcbiAgLyoqIEpTT04gYm9keSBzaXplIGxpbWl0IChkZWZhdWx0OiAnMW1iJykgKi9cbiAganNvbkxpbWl0Pzogc3RyaW5nO1xuICAvKipcbiAgICogUGF0aCBwcmVmaXhlcyB0aGUgZ2xvYmFsIEpTT04gYm9keSBwYXJzZXIgbXVzdCBOT1QgdG91Y2gg4oCUIGZvciByb3V0ZXMgdGhhdCBuZWVkXG4gICAqIHRoZSByYXcgYm9keSAoZS5nLiBhIFN0cmlwZSB3ZWJob29rIHdob3NlIEhNQUMgaXMgY29tcHV0ZWQgb3ZlciB0aGUgZXhhY3QgYnl0ZXMpLlxuICAgKiBXaXRob3V0IHRoaXMgdGhlIGdsb2JhbCBwYXJzZXIgY29uc3VtZXMgdGhlIGJvZHkgZmlyc3QgYW5kIGEgbGF0ZXIgYGV4cHJlc3MucmF3KClgXG4gICAqIG9uIHRoZSBzYW1lIHBhdGggaXMgYSBuby1vcCwgYnJlYWtpbmcgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbi5cbiAgICovXG4gIGpzb25Cb2R5RXhjbHVkZT86IHN0cmluZ1tdO1xuICAvKiogRW5hYmxlIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2luZyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlVXJsRW5jb2RlZD86IGJvb2xlYW47XG4gIC8qKiBVUkwtZW5jb2RlZCBib2R5IHNpemUgbGltaXQgKGRlZmF1bHQ6ICcxbWInKSAqL1xuICB1cmxFbmNvZGVkTGltaXQ/OiBzdHJpbmc7XG4gIC8qKiBDdXN0b20gU1NFIG1hbmFnZXIgaW5zdGFuY2UgKi9cbiAgc3NlTWFuYWdlcj86IFNTRU1hbmFnZXI7XG4gIC8qKlxuICAgKiBTZXJ2ZSB0aGUgcGVyLXJlcXVlc3QgYnVpbGQtbG9nIHN0cmVhbTogYFBPU1QgL2xvZ3MvdGlja2V0YCArXG4gICAqIGBHRVQgL2xvZ3MvOnJlcXVlc3RJZGAsIGEgbG9nIHRpY2tldCBzdG9yZSwgdGhlIGNyb3NzLXBvZCByZWxheSwgYW5kXG4gICAqIGBjdHgubG9nYCBmcmFtZXMgcHVzaGVkIHRvIFNTRS4gRGVmYXVsdCBmYWxzZSDigJQgYSBzZXJ2aWNlIHdpdGhvdXQgaXQgaGFzIG5vXG4gICAqIGAvbG9nc2Agcm91dGVzIGFuZCBgY3R4LmxvZ2Agb25seSB3cml0ZXMgdG8gdGhlIGxvZ2dlci5cbiAgICovXG4gIGxvZ1N0cmVhbT86IGJvb2xlYW47XG4gIC8qKiBIZWFsdGggY2hlY2sgZGVwZW5kZW5jeSBjaGVja2VyIOKAlCBpZiBwcm92aWRlZCwgL2hlYWx0aCByZXBvcnRzIGRlcGVuZGVuY3kgc3RhdHVzICovXG4gIGNoZWNrRGVwZW5kZW5jaWVzPzogKCkgPT4gUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCAnY29ubmVjdGVkJyB8ICdkaXNjb25uZWN0ZWQnIHwgJ3Vua25vd24nPj47XG4gIC8qKlxuICAgKiBTZXJ2ZSB0aGUgT3BlbkFQSSBzcGVjIGF0IGAvZG9jcy9vcGVuYXBpLmpzb25gIGFuZCBTd2FnZ2VyIFVJIGF0IGAvZG9jc2AuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIE9GRiB1bmRlciBgTk9ERV9FTlY9cHJvZHVjdGlvbmA6IHRoZSByb3V0ZXMgYXJlIHJlZ2lzdGVyZWQgYWJvdmVcbiAgICogdGhlIHJhdGUgbGltaXRlciBhbmQgYXJlIG5vdCBhdXRoLWdhdGVkLCBzbyBpbiBwcm9kdWN0aW9uIHRoZXkgd291bGQgcHVibGlzaFxuICAgKiB0aGUgZnVsbCByb3V0ZSArIHNjaGVtYSBpbnZlbnRvcnkgb2YgZXZlcnkgc2VydmljZSB0byBhbnlvbmUgd2hvIGNvdWxkIHJlYWNoXG4gICAqIHRoZSBwb3J0LiBQYXNzIGB0cnVlYCBleHBsaWNpdGx5IHRvIHNlcnZlIHRoZW0gaW4gcHJvZHVjdGlvbiBhbnl3YXkuXG4gICAqL1xuICBlbmFibGVPcGVuQXBpPzogYm9vbGVhbjtcbiAgLyoqIE9wZW5BUEkgc3BlYyBjdXN0b21pemF0aW9uIG9wdGlvbnMgKi9cbiAgb3BlbkFwaU9wdGlvbnM/OiBPcGVuQXBpU3BlY09wdGlvbnM7XG4gIC8qKiBFbmFibGUgZ3ppcC9kZWZsYXRlIHJlc3BvbnNlIGNvbXByZXNzaW9uIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVDb21wcmVzc2lvbj86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZGVtcG90ZW5jeSByZXBsYXktY2FjaGUgYmFja2VuZCBmb3Iga2V5ZWQgbXV0YXRpb24gcmV0cmllcy4gV2hlbiBvbWl0dGVkLFxuICAgKiBjcmVhdGVBcHAgYXV0by13aXJlcyB0aGUgc2hhcmVkIGVudiBSZWRpcyBzdG9yZSAobXVsdGktcmVwbGljYSBkZWR1cCkgaWZcbiAgICogUmVkaXMgaXMgY29uZmlndXJlZCwgZWxzZSBrZWVwcyB0aGUgaW4tbWVtb3J5IGRlZmF1bHQgKHNpbmdsZS1yZXBsaWNhKS5cbiAgICogUGFzcyBhbiBleHBsaWNpdCBzdG9yZSB0byBpbmplY3QgYSBiZXNwb2tlIGJhY2tlbmQgKGUuZy4gYSBzZXJ2aWNlJ3Mgb3duXG4gICAqIGlvcmVkaXMgY29ubmVjdGlvbikuXG4gICAqL1xuICBpZGVtcG90ZW5jeVN0b3JlPzogSWRlbXBvdGVuY3lTdG9yZTtcbiAgLyoqXG4gICAqIEV4dHJhIHdhcm11cCBjYWxsYmFja3MgaW52b2tlZCBieSBgR0VUIC93YXJtdXBgIGluIGFkZGl0aW9uIHRvIHRoZVxuICAgKiBkZWZhdWx0IFBvc3RncmVzIHBpbmcuIFVzZSBmb3Igc2VydmljZXMgdGhhdCBkZXBlbmQgb24gTW9uZ28sIFJlZGlzLFxuICAgKiBTUVMsIGV0Yy4g4oCUIHByZS13YXJtaW5nIG9wZW5zIGNvbm5lY3Rpb24gcG9vbHMgYmVmb3JlIHJlYWwgdHJhZmZpY1xuICAgKiBhcnJpdmVzLiBFYWNoIGNhbGxiYWNrIHNob3VsZCByZXNvbHZlIHdoZW4gaXRzIGRlcGVuZGVuY3kgaXMgcmVhZHk7XG4gICAqIGFueSByZWplY3Rpb24gY2F1c2VzIC93YXJtdXAgdG8gcmV0dXJuIDUwMy5cbiAgICovXG4gIHdhcm11cEhvb2tzPzogQXJyYXk8KCkgPT4gUHJvbWlzZTx2b2lkPj47XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGNyZWF0aW5nIGFuIEV4cHJlc3MgYXBwbGljYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBcHBSZXN1bHQge1xuICAvKiogQ29uZmlndXJlZCBFeHByZXNzIGFwcGxpY2F0aW9uICovXG4gIGFwcDogRXhwcmVzcztcbiAgLyoqIFNTRSBtYW5hZ2VyIGluc3RhbmNlICovXG4gIHNzZU1hbmFnZXI6IFNTRU1hbmFnZXI7XG59XG5cbi8qKiBIZWxtZXQgKHN0cmljdCBDU1ApLCBDT1JTLCBjb21wcmVzc2lvbiBhbmQgRVRhZ3MuICovXG5mdW5jdGlvbiBhcHBseVNlY3VyaXR5SGVhZGVycyhhcHA6IEV4cHJlc3MsIG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMsIGVuYWJsZU9wZW5BcGk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgeyBlbmFibGVDb3JzID0gdHJ1ZSwgZW5hYmxlSGVsbWV0ID0gdHJ1ZSwgZW5hYmxlQ29tcHJlc3Npb24gPSB0cnVlIH0gPSBvcHRpb25zO1xuICAvLyBTd2FnZ2VyIFVJIG5lZWRzIHVuc2FmZS1pbmxpbmUgKyB1bnNhZmUtZXZhbCBmb3IgaXRzIGJ1bmRsZWQgc2NyaXB0cyDigJRcbiAgLy8gYnV0IENTUCBpcyBvbmx5IHJlbGF4ZWQgdGhhdCBmYXIgd2hlbiAoYSkgT3BlbkFQSSBpcyBlbmFibGVkIEFORCAoYikgd2UncmVcbiAgLy8gbm90IGluIHByb2R1Y3Rpb24uIEluIHByb2QsIFN3YWdnZXIgc2hvdWxkIGJlIHNlcnZlZCBiZWhpbmQgYSBzZXBhcmF0ZVxuICAvLyBob3N0IG9yIGF1dGgtZ2F0ZWQgcm91dGU7IHRoZSBtYWluIGFwcCBrZWVwcyB0aGUgc3RyaWN0IENTUCBzbyBhIFN0b3JlZFxuICAvLyBYU1MgaW4gYW55IGhhbmRsZXIgY2FuJ3QgYGV2YWwoKWAgYXJiaXRyYXJ5IHNjcmlwdC5cbiAgY29uc3QgYWxsb3dTd2FnZ2VyQ3NwID0gZW5hYmxlT3BlbkFwaSAmJiBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nO1xuICBpZiAoZW5hYmxlSGVsbWV0KSB7XG4gICAgYXBwLnVzZShoZWxtZXQoe1xuICAgICAgY29udGVudFNlY3VyaXR5UG9saWN5OiB7XG4gICAgICAgIGRpcmVjdGl2ZXM6IHtcbiAgICAgICAgICBkZWZhdWx0U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgc2NyaXB0U3JjOiBhbGxvd1N3YWdnZXJDc3BcbiAgICAgICAgICAgID8gW1wiJ3NlbGYnXCIsIFwiJ3Vuc2FmZS1pbmxpbmUnXCIsIFwiJ3Vuc2FmZS1ldmFsJ1wiXVxuICAgICAgICAgICAgOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgc3R5bGVTcmM6IFtcIidzZWxmJ1wiLCBcIid1bnNhZmUtaW5saW5lJ1wiXSxcbiAgICAgICAgICBpbWdTcmM6IFtcIidzZWxmJ1wiLCAnZGF0YTonLCAnYmxvYjonXSxcbiAgICAgICAgICBjb25uZWN0U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgZm9udFNyYzogW1wiJ3NlbGYnXCJdLFxuICAgICAgICAgIG9iamVjdFNyYzogW1wiJ25vbmUnXCJdLFxuICAgICAgICAgIGZyYW1lQW5jZXN0b3JzOiBbXCInbm9uZSdcIl0sXG4gICAgICAgICAgYmFzZVVyaTogW1wiJ3NlbGYnXCJdLFxuICAgICAgICAgIGZvcm1BY3Rpb246IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSkpO1xuICB9XG5cbiAgaWYgKGVuYWJsZUNvcnMpIHtcbiAgICBhcHAudXNlKGNvcnMoQ29uZmlnLmdldCgnc2VydmVyJykuY29ycykpO1xuICB9XG5cbiAgLy8gUmVzcG9uc2UgY29tcHJlc3Npb24gKGd6aXAvZGVmbGF0ZSkg4oCUIHNraXAgU1NFIHN0cmVhbXNcbiAgaWYgKGVuYWJsZUNvbXByZXNzaW9uKSB7XG4gICAgYXBwLnVzZShjb21wcmVzc2lvbih7XG4gICAgICBmaWx0ZXI6IChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gRG9uJ3QgY29tcHJlc3MgU1NFIHN0cmVhbXMuIE1hdGNoIGJ5IGluY2x1c2lvbjogdGhlIEFjY2VwdCBoZWFkZXIgaXNcbiAgICAgICAgLy8gb2Z0ZW4gYSBsaXN0IChlLmcuIFwidGV4dC9ldmVudC1zdHJlYW0sICovKlwiKSwgd2hpY2ggZXhhY3QgZXF1YWxpdHlcbiAgICAgICAgLy8gd291bGQgbWlzcywgY29tcHJlc3NpbmcvYnVmZmVyaW5nIHRoZSBzdHJlYW0uXG4gICAgICAgIGlmICgocmVxLmhlYWRlcnMuYWNjZXB0IHx8ICcnKS5pbmNsdWRlcygndGV4dC9ldmVudC1zdHJlYW0nKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gY29tcHJlc3Npb24uZmlsdGVyKHJlcSwgcmVzKTtcbiAgICAgIH0sXG4gICAgICB0aHJlc2hvbGQ6IENvcmVDb25zdGFudHMuQ09NUFJFU1NJT05fVEhSRVNIT0xEX0JZVEVTLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEVUYWcgc3VwcG9ydCBmb3IgY29uZGl0aW9uYWwgR0VUIHJlcXVlc3RzICgzMDQgTm90IE1vZGlmaWVkKVxuICBhcHAudXNlKGV0YWdNaWRkbGV3YXJlKCkpO1xufVxuXG4vKiogSlNPTiArIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2Vycy4gKi9cbmZ1bmN0aW9uIGFwcGx5Qm9keVBhcnNpbmcoYXBwOiBFeHByZXNzLCBvcHRpb25zOiBDcmVhdGVBcHBPcHRpb25zKTogdm9pZCB7XG4gIGNvbnN0IHsgZW5hYmxlSnNvbkJvZHkgPSB0cnVlLCBqc29uTGltaXQgPSAnMW1iJywgZW5hYmxlVXJsRW5jb2RlZCA9IHRydWUsIHVybEVuY29kZWRMaW1pdCA9ICcxbWInIH0gPSBvcHRpb25zO1xuICBpZiAoZW5hYmxlSnNvbkJvZHkpIHtcbiAgICBjb25zdCBqc29uUGFyc2VyID0gZXhwcmVzcy5qc29uKHsgbGltaXQ6IGpzb25MaW1pdCB9KTtcbiAgICBjb25zdCBleGNsdWRlID0gb3B0aW9ucy5qc29uQm9keUV4Y2x1ZGUgPz8gW107XG4gICAgaWYgKGV4Y2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgLy8gU2tpcCB0aGUgZ2xvYmFsIEpTT04gcGFyc2VyIGZvciByYXctYm9keSBwYXRocyBzbyBhIHBlci1wYXRoIGBleHByZXNzLnJhdygpYFxuICAgICAgLy8gY2FuIHJlYWQgdGhlIGV4YWN0IGJ5dGVzIChzZWUgYGpzb25Cb2R5RXhjbHVkZWApLlxuICAgICAgYXBwLnVzZSgocmVxLCByZXMsIG5leHQpID0+IChleGNsdWRlLnNvbWUoKHApID0+IHJlcS5wYXRoLnN0YXJ0c1dpdGgocCkpID8gbmV4dCgpIDoganNvblBhcnNlcihyZXEsIHJlcywgbmV4dCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXBwLnVzZShqc29uUGFyc2VyKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZW5hYmxlVXJsRW5jb2RlZCkge1xuICAgIGFwcC51c2UoZXhwcmVzcy51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IHRydWUsIGxpbWl0OiB1cmxFbmNvZGVkTGltaXQgfSkpO1xuICB9XG59XG5cbi8qKlxuICogSGVhbHRoLCByZWFkaW5lc3MgZ3VhcmQsIGAvd2FybXVwYCwgYC9tZXRyaWNzYCBhbmQgdGhlIE9wZW5BUEkgZG9jcyDigJQgYWxsXG4gKiByZWdpc3RlcmVkIGJlZm9yZSB0aGUgcmF0ZSBsaW1pdGVyIHNvIHRoZXkgYXJlIG5ldmVyIHRocm90dGxlZC5cbiAqL1xuZnVuY3Rpb24gbW91bnRJbmZyYUVuZHBvaW50cyhhcHA6IEV4cHJlc3MsIG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMsIHNlcnZpY2VOYW1lOiBzdHJpbmcsIGVuYWJsZU9wZW5BcGk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgeyBjaGVja0RlcGVuZGVuY2llcywgb3BlbkFwaU9wdGlvbnMsIHdhcm11cEhvb2tzID0gW10gfSA9IG9wdGlvbnM7XG5cbiAgYXBwLnVzZShjcmVhdGVIZWFsdGhSb3V0ZXIoe1xuICAgIHNlcnZpY2VOYW1lLFxuICAgIGNoZWNrRGVwZW5kZW5jaWVzLFxuICB9KSk7XG5cbiAgLy8gUmVhZGluZXNzIGd1YXJkIOKAlCA1MDNzIGJ1c2luZXNzIHRyYWZmaWMgd2hpbGUgdGhlIHNlcnZpY2UgaXMgTm90UmVhZHlcbiAgLy8gKGRhdGFzdG9yZSBzdGlsbCBjb25uZWN0aW5nIGF0IHN0YXJ0dXAsIG9yIGRyb3BwZWQpLiBNb3VudGVkIHJpZ2h0IGFmdGVyXG4gIC8vIHRoZSBoZWFsdGggcm91dGVyIGFuZCBiZWZvcmUgZXZlcnl0aGluZyBlbHNlIHNvIGEgTm90UmVhZHkgcmVxdWVzdCBpc1xuICAvLyByZWplY3RlZCBjaGVhcGx5LCBiZWZvcmUgcmF0ZS1saW1pdCAvIGlkZW1wb3RlbmN5IC8gYnVzaW5lc3MgaGFuZGxlcnMgZXZlclxuICAvLyB0b3VjaCBhIGRpc2Nvbm5lY3RlZCBkYXRhc3RvcmUuIEl0IGFsbG93bGlzdHMgdGhlIGluZnJhIGVuZHBvaW50c1xuICAvLyAoL21ldHJpY3MsIC93YXJtdXAsIC9kb2NzLCAvbG9ncykgcmVnaXN0ZXJlZCBiZWxvdywgcGx1cyAvaGVhbHRoICsgL3JlYWR5LlxuICBhcHAudXNlKHJlYWRpbmVzc0d1YXJkKCkpO1xuXG4gIC8vIFdhcm0tdXAgZW5kcG9pbnQg4oCUIHByZS1vcGVucyBjb25uZWN0aW9uIHBvb2xzIHNvIHRoZSBmaXJzdCByZWFsIHJlcXVlc3RcbiAgLy8gZG9lc24ndCBwYXkgY29sZC1zdGFydCBsYXRlbmN5LiBBbHdheXMgcGluZ3MgUG9zdGdyZXM7IHNlcnZpY2VzIHVzaW5nXG4gIC8vIE1vbmdvIC8gUmVkaXMgLyBTUVMgcGFzcyBgd2FybXVwSG9va3NgIHNvIHRob3NlIGFyZSB3YXJtZWQgaW4gcGFyYWxsZWwuXG4gIC8vXG4gIC8vIEdBVEVEIHRvIHZlcmlmaWVkIHNlcnZpY2UgcHJpbmNpcGFscy4gRXZlcnkgaGl0IHJ1bnMgYSBQb3N0Z3JlcyByb3VuZC10cmlwXG4gIC8vIHBsdXMgYWxsIGB3YXJtdXBIb29rc2AgKE1vbmdvL1JlZGlzL1NRUyksIHNvIGFuIG9wZW4gZW5kcG9pbnQgd291bGQgbGV0IGFuXG4gIC8vIGFub255bW91cyBsb29wIGFtcGxpZnkgaW50byBkYXRhc3RvcmUgbG9hZCBvbiBldmVyeSBzZXJ2aWNlIGluIHRoZSBmbGVldCDigJRcbiAgLy8gYW5kIGl0IGlzIHJlZ2lzdGVyZWQgYWJvdmUgdGhlIHJhdGUgbGltaXRlciwgc28gbm90aGluZyB3b3VsZCB0aHJvdHRsZSBpdC5cbiAgLy8gYHZlcmlmeVNlcnZpY2VQcmluY2lwYWxgIGNoZWNrcyB0aGUgYmVhcmVyIHRva2VuIGNyeXB0b2dyYXBoaWNhbGx5LCBzbyBpdCBpc1xuICAvLyBzYWZlIGhlcmUsIGFib3ZlIGByZXF1aXJlQXV0aGAuXG4gIGFwcC5nZXQoJy93YXJtdXAnLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgaWYgKCF2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsKHJlcSkpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwNCwgJ05vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICBnZXRDb25uZWN0aW9uKCkudGVzdENvbm5lY3Rpb24oKSxcbiAgICAgICAgLi4ud2FybXVwSG9va3MubWFwKChob29rKSA9PiBob29rKCkpLFxuICAgICAgXSk7XG4gICAgICBzZW5kU3VjY2VzcyhyZXMsIDIwMCwgeyB3YXJtZWQ6IHRydWUsIGhvb2tzOiB3YXJtdXBIb29rcy5sZW5ndGggfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA1MDMsICdXYXJtdXAgZmFpbGVkJyk7XG4gICAgfVxuICB9KTtcblxuICAvLyBQcm9tZXRoZXVzIG1ldHJpY3MgZW5kcG9pbnQg4oCUIGFsd2F5cyByZWdpc3RlcmVkIChuZXZlciB0aHJvdHRsZWQpLlxuICAvL1xuICAvLyBPcHRpb25hbGx5IGdhdGVkOiB3aGVuIGBNRVRSSUNTX1NDUkFQRV9UT0tFTmAgaXMgc2V0LCB0aGUgc2NyYXBlciBtdXN0IHNlbmRcbiAgLy8gaXQgYXMgYSBiZWFyZXIgdG9rZW4gKFByb21ldGhldXMgYGJlYXJlcl90b2tlbmAgLyBgYmVhcmVyX3Rva2VuX2ZpbGVgIGluIHRoZVxuICAvLyBzY3JhcGUgY29uZmlnKS4gTGVmdCB1bmdhdGVkIHdoZW4gdW5zZXQgc28gZW5hYmxpbmcgaXQgaXMgYSBkZWxpYmVyYXRlLFxuICAvLyBjb29yZGluYXRlZCBjaGFuZ2UgcmF0aGVyIHRoYW4gYSBzaWxlbnQgbW9uaXRvcmluZyBvdXRhZ2Ug4oCUIHRlbmFudCBpZHMgc3RheVxuICAvLyBvdXQgb2YgdGhlIG91dHB1dCByZWdhcmRsZXNzLCBiZWNhdXNlIHRoZSBwZXItb3JnIGxhYmVsIGRlZmF1bHRzIE9GRiAoc2VlXG4gIC8vIEhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEUgaW4gbWV0cmljcy50cykuXG4gIGNvbnN0IG1ldHJpY3NUb2tlbiA9IHByb2Nlc3MuZW52Lk1FVFJJQ1NfU0NSQVBFX1RPS0VOO1xuICBhcHAuZ2V0KCcvbWV0cmljcycsIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIGlmICghbWV0cmljc1Rva2VuKSB7XG4gICAgICBuZXh0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhlYWRlciA9IHJlcS5oZWFkZXJzLmF1dGhvcml6YXRpb247XG4gICAgY29uc3QgcHJlc2VudGVkID0gaGVhZGVyPy5zdGFydHNXaXRoKCdCZWFyZXIgJykgPyBoZWFkZXIuc2xpY2UoNykgOiB1bmRlZmluZWQ7XG4gICAgLy8gQ29uc3RhbnQtdGltZSBjb21wYXJlIOKAlCBhIGxlbmd0aC1pbmRlcGVuZGVudCBlcXVhbGl0eSBjaGVjayBoZXJlIHdvdWxkXG4gICAgLy8gbGVhayB0aGUgdG9rZW4gYSBieXRlIGF0IGEgdGltZS5cbiAgICBpZiAoIXByZXNlbnRlZCB8fCAhc2FmZUVxdWFsKHByZXNlbnRlZCwgbWV0cmljc1Rva2VuKSkge1xuICAgICAgc2VuZEVycm9yKHJlcywgNDA0LCAnTm90IGZvdW5kJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIG5leHQoKTtcbiAgfSwgbWV0cmljc0hhbmRsZXIoKSk7XG5cbiAgaWYgKGVuYWJsZU9wZW5BcGkpIHtcbiAgICBjb25zdCBzcGVjID0gZ2VuZXJhdGVPcGVuQXBpU3BlYyhvcGVuQXBpT3B0aW9ucyk7XG4gICAgYXBwLmdldCgnL2RvY3Mvb3BlbmFwaS5qc29uJywgKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgIHJlcy5qc29uKHNwZWMpO1xuICAgIH0pO1xuICAgIGFwcC51c2UoJy9kb2NzJywgc3dhZ2dlclVpLnNlcnZlLCBzd2FnZ2VyVWkuc2V0dXAoc3BlYywge1xuICAgICAgY3VzdG9tU2l0ZVRpdGxlOiBvcGVuQXBpT3B0aW9ucz8udGl0bGUgPz8gJ1BpcGVsaW5lIEJ1aWxkZXIgQVBJIERvY3MnLFxuICAgIH0pKTtcbiAgfVxufVxuXG4vKiogR2xvYmFsIHJhdGUgbGltaXRlciDigJQgc2hhcmVkIGFjcm9zcyByZXBsaWNhcyB2aWEgdGhlIGVudiBSZWRpcyB3aGVuIGNvbmZpZ3VyZWQuICovXG5mdW5jdGlvbiBtb3VudFJhdGVMaW1pdGVyKGFwcDogRXhwcmVzcywgc2VydmljZU5hbWU6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCByYXRlTGltaXRDb25maWcgPSBDb25maWcuZ2V0KCdyYXRlTGltaXQnKTtcblxuICBjb25zdCByYXRlTGltaXRPcHRpb25zOiBQYXJhbWV0ZXJzPHR5cGVvZiByYXRlTGltaXQ+WzBdID0ge1xuICAgIG1heDogcmF0ZUxpbWl0Q29uZmlnLm1heCxcbiAgICB3aW5kb3dNczogcmF0ZUxpbWl0Q29uZmlnLndpbmRvd01zLFxuICAgIHN0YW5kYXJkSGVhZGVyczogdHJ1ZSxcbiAgICBsZWdhY3lIZWFkZXJzOiBmYWxzZSxcbiAgICAvLyBTa2lwIHJhdGUgbGltaXRpbmcgb25seSBmb3IgQ1JZUFRPR1JBUEhJQ0FMTFktVkVSSUZJRUQgaW50ZXJuYWwgc2VydmljZVxuICAgIC8vIGNhbGxlcnMuIFRoZSBsaW1pdGVyIHJ1bnMgYmVmb3JlIHJlcXVpcmVBdXRoLCBzbyBhIHBsYWludGV4dCBoZWFkZXJcbiAgICAvLyB3b3VsZCBiZSBzcG9vZmFibGUgYnkgYW55IGV4dGVybmFsIGNsaWVudCDihpIgdG90YWwgYnlwYXNzLlxuICAgIC8vIHZlcmlmeVNlcnZpY2VQcmluY2lwYWwgdmVyaWZpZXMgdGhlIHNpZ25lZCBzZXJ2aWNlIEpXVCBpbnN0ZWFkO1xuICAgIC8vIGludGVyLXNlcnZpY2UgY2FsbGVycyBhbGwgc2VuZCBvbmUgKGdldFNlcnZpY2VBdXRoSGVhZGVyKS5cbiAgICBza2lwOiAocmVxOiBSZXF1ZXN0KSA9PiB2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsKHJlcSksXG4gICAgLy8gS2V5IG9uIGNsaWVudCBJUCBvbmx5LiBUaGUgbGltaXRlciBydW5zIHByZS1hdXRoLCBzbyBgcmVxLnVzZXJgIGlzIHVuc2V0XG4gICAgLy8gYW5kIGFueSBvcmcgaWQgd291bGQgY29tZSBmcm9tIHRoZSBjYWxsZXItc3VwcGxpZWQgYHgtb3JnLWlkYCBoZWFkZXIg4oCUXG4gICAgLy8gc3Bvb2ZhYmxlLCBsZXR0aW5nIGFuIGF0dGFja2VyIHJvdGF0ZSB2YWx1ZXMgdG8gZXZhZGUgdGhlIGJ1Y2tldCBvclxuICAgIC8vIGZsb29kIGEgdmljdGltIG9yZydzIGJ1Y2tldC4gaXBLZXlHZW5lcmF0b3Igbm9ybWFsaXplcyBJUHY2IHRvIGEgLzY0XG4gICAgLy8gcHJlZml4IChhbHNvIHJlcXVpcmVkIGJ5IGV4cHJlc3MtcmF0ZS1saW1pdCA4LngncyB2YWxpZGF0b3IpLlxuICAgIGtleUdlbmVyYXRvcjogKHJlcTogUmVxdWVzdCkgPT4gaXBLZXlHZW5lcmF0b3IocmVxLmlwIHx8ICdhbm9uJywgNjQpLFxuICAgIC8vIEEgc3RvcmUgZmFpbHVyZSAoUmVkaXMgZG93biAvIGZhaWxpbmcgb3ZlcikgbXVzdCBkZWdyYWRlIHRvIFwibm90IHJhdGVcbiAgICAvLyBsaW1pdGVkXCIsIG5ldmVyIHRvIGEgNTAwIG9uIGV2ZXJ5IHJlcXVlc3Qgb2YgZXZlcnkgc2VydmljZS5cbiAgICBwYXNzT25TdG9yZUVycm9yOiB0cnVlLFxuICAgIGhhbmRsZXI6IChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MjksICdUb28gbWFueSByZXF1ZXN0cywgcGxlYXNlIHRyeSBhZ2FpbiBsYXRlci4nLCBFcnJvckNvZGUuUkFURV9MSU1JVF9FWENFRURFRCk7XG4gICAgfSxcbiAgICAvLyBTaGFyZWQgc3RhdGUgYWNyb3NzIHJlcGxpY2FzICh0aGUgcHJvY2Vzcy13aWRlIHJhdGUtbGltaXQgUmVkaXMgY29ubmVjdGlvbjtcbiAgICAvLyB1bmRlZmluZWQgd2l0aG91dCBSZWRpcyDihpIgcGVyLXByb2Nlc3MgbWVtb3J5IHN0b3JlLCByaWdodCBmb3Igb25lIHJlcGxpY2EpLlxuICAgIC8vIE5hbWVzcGFjZWQgcGVyIFNFUlZJQ0U6IGV2ZXJ5IHNlcnZpY2Ugc2hhcmVzIG9uZSBSZWRpcywgYW5kIGFuIHVucHJlZml4ZWRcbiAgICAvLyBgcmw6PGlwPmAga2V5IHdvdWxkIGxldCBvbmUgY2xpZW50J3MgdHJhZmZpYyB0byBBTlkgc2VydmljZSBkcmFpbiBpdHNcbiAgICAvLyBidWRnZXQgb24gRVZFUlkgc2VydmljZS5cbiAgICBzdG9yZTogY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUoYCR7c2VydmljZU5hbWV9Omdsb2JhbGApLFxuICB9O1xuXG4gIGFwcC51c2UocmF0ZUxpbWl0KHJhdGVMaW1pdE9wdGlvbnMpKTtcbn1cblxuLyoqIFJlcXVlc3QgdGltZW91dCwgZHVyYXRpb24gbG9nZ2luZyBhbmQgSFRUUCBtZXRyaWNzLiAqL1xuZnVuY3Rpb24gYXBwbHlSZXF1ZXN0VGVsZW1ldHJ5KGFwcDogRXhwcmVzcyk6IHZvaWQge1xuICAvLyBFeHByZXNzIHJlcXVlc3QgdGltZW91dCDigJQgdXNlcyBDb3JlQ29uc3RhbnRzIHRvIHNoYXJlIHRoZSBzYW1lIGRlZmF1bHQgYXMgTGFtYmRhIGhhbmRsZXJzXG4gIGNvbnN0IHRpbWVvdXRNcyA9IENvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TO1xuICBhcHAudXNlKChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICByZXMuc2V0VGltZW91dCh0aW1lb3V0TXMsICgpID0+IHtcbiAgICAgIGlmICghcmVzLmhlYWRlcnNTZW50KSB7XG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ1JlcXVlc3QgdGltZW91dCcpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUmVxdWVzdCBkdXJhdGlvbiBsb2dnaW5nXG4gIGNvbnN0IGR1cmF0aW9uTG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdyZXF1ZXN0LWR1cmF0aW9uJyk7XG4gIGFwcC51c2UoKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBEYXRlLm5vdygpIC0gc3RhcnQ7XG4gICAgICAvLyBMb2cgYHJlcS5wYXRoYCAobm8gcXVlcnkgc3RyaW5nKSDigJQgYSBzdHJheSBgP3Rva2VuPWAvYD90aWNrZXQ9YCBtdXN0IG5vdCBiZVxuICAgICAgLy8gcGVyc2lzdGVkIHZlcmJhdGltIG9uIGV2ZXJ5IHJlcXVlc3QgKG1pcnJvcnMgdGhlIGF1dGh6LWRlbmlhbCBhdWRpdG9yJ3Mgc3RyaXApLlxuICAgICAgZHVyYXRpb25Mb2dnZXIuaW5mbyhgJHtyZXEubWV0aG9kfSAke3JlcS5wYXRofSAke3Jlcy5zdGF0dXNDb2RlfSAke2R1cmF0aW9ufW1zYCwge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHBhdGg6IHJlcS5wYXRoLFxuICAgICAgICBzdGF0dXNDb2RlOiByZXMuc3RhdHVzQ29kZSxcbiAgICAgICAgZHVyYXRpb25NczogZHVyYXRpb24sXG4gICAgICAgIHJlcXVlc3RJZDogcmVxLnJlcXVlc3RJZCxcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUHJvbWV0aGV1cyBtZXRyaWNzIG1pZGRsZXdhcmUg4oCUIHJlY29yZHMgcmVxdWVzdCBkdXJhdGlvbiBhbmQgY291bnRcbiAgYXBwLnVzZShtZXRyaWNzTWlkZGxld2FyZSgpKTtcbn1cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBTU0UgbWFuYWdlci4gVGhlIHJlbGF5ICh0aGlzIHNlcnZpY2UncyBvd24gUmVkaXMgY2hhbm5lbCkgaXNcbiAqIGJ1aWx0IG9ubHkgd2hlbiBzb21ldGhpbmcgc3RyZWFtczogdGhlIGxvZyBzdHJlYW0gdHVybnMgaXQgb24gaGVyZSwgYW5kIGFuXG4gKiBvcmcta2V5ZWQgY2hhbm5lbCB0dXJucyBpdCBvbiB3aGVuIHJlZ2lzdGVyZWQgKHJlZ2lzdGVyU3NlVGlja2V0Q2hhbm5lbCkuXG4gKiBUaGUgbG9nIHRpY2tldCBzdG9yZSBleGlzdHMgb25seSB3aXRoIHRoZSBsb2cgc3RyZWFtLlxuICovXG5mdW5jdGlvbiBjcmVhdGVEZWZhdWx0U3NlTWFuYWdlcihzZXJ2aWNlTmFtZTogc3RyaW5nLCBsb2dTdHJlYW06IGJvb2xlYW4pOiBTU0VNYW5hZ2VyIHtcbiAgY29uc3Qgc3NlTWFuYWdlciA9IG5ldyBTU0VNYW5hZ2VyKHtcbiAgICBsb2dTdHJlYW0sXG4gICAgcmVsYXlGYWN0b3J5OiAoKSA9PiBjcmVhdGVFbnZSZWRpc1NTRVJlbGF5KHNlcnZpY2VOYW1lKSxcbiAgICAuLi4obG9nU3RyZWFtICYmIHtcbiAgICAgIHRpY2tldFN0b3JlOiBjcmVhdGVFbnZTc2VUaWNrZXRTdG9yZSh7XG4gICAgICAgIHR0bE1zOiBTU0VfVElDS0VUX1RUTF9NUyxcbiAgICAgICAga2V5UHJlZml4OiBgbG9nczoke3NlcnZpY2VOYW1lfWAsXG4gICAgICB9KSxcbiAgICB9KSxcbiAgfSk7XG4gIGlmIChsb2dTdHJlYW0pIHNzZU1hbmFnZXIuZW5hYmxlUmVsYXkoKTtcbiAgcmV0dXJuIHNzZU1hbmFnZXI7XG59XG5cbi8qKlxuICogVGhlIHBlci1yZXF1ZXN0IGJ1aWxkLWxvZyBzdHJlYW06IGBQT1NUIC9sb2dzL3RpY2tldGAgKyBgR0VUIC9sb2dzLzpyZXF1ZXN0SWRgLlxuICpcbiAqIFRpY2tldC1nYXRlZCDigJQgdGhlIHN0cmVhbSBjYXJyaWVzIHBlci1vcmcgYnVpbGQgbG9ncywgc28gaXQgbXVzdCBub3QgYmVcbiAqIHdvcmxkLXJlYWRhYmxlLiBDbGllbnRzIGZpcnN0IFBPU1QgL2xvZ3MvdGlja2V0IChKV1QtYXV0aGVudGljYXRlZCkgdG8gbWludCBhXG4gKiBzaG9ydC1saXZlZCwgc2luZ2xlLXVzZSB0aWNrZXQgYm91bmQgdG8gdGhlaXIgb3JnIEFORCB0byB0aGUgc3BlY2lmaWNcbiAqIGByZXF1ZXN0SWRgIHN0cmVhbSB0aGV5IGludGVuZCB0byBvcGVuLCB0aGVuIG9wZW4gdGhlIEV2ZW50U291cmNlIHdpdGhcbiAqID90aWNrZXQ9PHQ+LiBUaGlzIGtlZXBzIHRoZSBKV1Qgb3V0IG9mIHF1ZXJ5IHN0cmluZ3MgLyBhY2Nlc3MgbG9ncyB3aGlsZVxuICogZW5mb3JjaW5nIG9yZyBvd25lcnNoaXAsIHBlci1zdWJqZWN0IGF1dGhvcml6YXRpb24sIGFuZCB0aGUgcGVyLW9yZ1xuICogY29ubmVjdGlvbiBjYXAgb24gdGhlIHN0cmVhbS4gTWlycm9ycyB0aGUgbWVzc2FnZS1zZXJ2aWNlIG5vdGlmaWNhdGlvbnMgU1NFXG4gKiB0aWNrZXQgZXhjaGFuZ2UuXG4gKi9cbmZ1bmN0aW9uIHdpcmVTc2UoYXBwOiBFeHByZXNzLCBzc2VNYW5hZ2VyOiBTU0VNYW5hZ2VyKTogdm9pZCB7XG4gIGFwcC5wb3N0KCcvbG9ncy90aWNrZXQnLCByZXF1aXJlQXV0aCwgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGNvbnN0IG9yZ0lkID0gcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkPy50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghb3JnSWQpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwMCwgJ1Rva2VuIG1pc3Npbmcgb3JnYW5pemF0aW9uJywgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBUaGUgY2FsbGVyIG11c3QgbmFtZSB0aGUgc3RyZWFtIHN1YmplY3QgdXAgZnJvbnQgc28gdGhlIHRpY2tldCBpcyBib3VuZCB0b1xuICAgIC8vIGl0LiBXaXRob3V0IHRoaXMsIGEgdGlja2V0IGNvdWxkIGJlIHJlcGxheWVkIGFnYWluc3QgQU5ZIHJlcXVlc3RJZCB0aGVcbiAgICAvLyBvcmcgY291bGQgZ3Vlc3MsIGxldHRpbmcgaXQgYXR0YWNoIHRvIGFub3RoZXIgb3JnJ3MgbG9nIHN0cmVhbS4gU3RyaWN0bHlcbiAgICAvLyBmb3JtYXQtdmFsaWRhdGVkIHNvIGl0IGNhbid0IGNhcnJ5IGFuIGluamVjdGlvbiBwYXlsb2FkIGludG8gdGhlIHN1YmplY3QuXG4gICAgY29uc3QgcmVxdWVzdElkID0gKHJlcS5ib2R5IGFzIHsgcmVxdWVzdElkPzogdW5rbm93biB9IHwgdW5kZWZpbmVkKT8ucmVxdWVzdElkO1xuICAgIGlmICh0eXBlb2YgcmVxdWVzdElkICE9PSAnc3RyaW5nJyB8fCAhU1NFX1JFUVVFU1RfSURfUkUudGVzdChyZXF1ZXN0SWQpKSB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MDAsICdNaXNzaW5nIG9yIGludmFsaWQgcmVxdWVzdElkJywgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzc2VNYW5hZ2VyLmNyZWF0ZVRpY2tldChvcmdJZCwgcmVxdWVzdElkKTtcbiAgICBpZiAoIXJlc3VsdC5vaykge1xuICAgICAgaWYgKHJlc3VsdC5yZWFzb24gPT09ICdmb3JiaWRkZW4nKSB7XG4gICAgICAgIC8vIFRoZSBzdWJqZWN0IGlzIG93bmVkIGJ5IGFub3RoZXIgb3JnIOKAlCBkbyBub3QgY29uZmlybSBpdCBleGlzdHM7IGEgcGxhaW5cbiAgICAgICAgLy8gNDAzIGlzIGVub3VnaCBhbmQgbGVha3Mgbm90aGluZyBhYm91dCB3aGljaCByZXF1ZXN0SWRzIGFyZSBsaXZlLlxuICAgICAgICBzZW5kRXJyb3IocmVzLCA0MDMsICdOb3QgYXV0aG9yaXplZCBmb3IgdGhpcyBsb2cgc3RyZWFtJywgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdC5yZWFzb24gPT09ICdvcmctbGltaXQnKSB7XG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDQyOSwgJ1RvbyBtYW55IGxvZyBzdHJlYW0gdGlja2V0cyBpc3N1ZWQnLCBFcnJvckNvZGUuUVVPVEFfRVhDRUVERUQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VuZEVycm9yKHJlcywgNTAzLCAnTG9nIHN0cmVhbWluZyBzdWJzeXN0ZW0gYXQgY2FwYWNpdHknLCBFcnJvckNvZGUuUVVPVEFfRVhDRUVERUQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzZW5kU3VjY2VzcyhyZXMsIDIwMCwgeyB0aWNrZXQ6IHJlc3VsdC50aWNrZXQgfSk7XG4gIH0pO1xuXG4gIC8vIFRoZSBzdHJlYW0gaXRzZWxmIHJlc29sdmVzICsgY29uc3VtZXMgdGhlIHRpY2tldCBpbnNpZGUgbWlkZGxld2FyZSgpIGFuZFxuICAvLyByZWplY3RzIGFueSBhbm9ueW1vdXMgLyBpbnZhbGlkIC8gZXhwaXJlZCAvIGFscmVhZHktdXNlZCB0aWNrZXQgd2l0aCA0MDEuXG4gIGFwcC5nZXQoJy9sb2dzLzpyZXF1ZXN0SWQnLCBzc2VNYW5hZ2VyLm1pZGRsZXdhcmUoKSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGFuZCBjb25maWd1cmUgYW4gRXhwcmVzcyBhcHBsaWNhdGlvbiB3aXRoIGNvbW1vbiBtaWRkbGV3YXJlXG4gKlxuICogU2V0cyB1cDpcbiAqIC0gQ09SUyB3aXRoIGNvbmZpZ3VyZWQgb3JpZ2luc1xuICogLSBIZWxtZXQgc2VjdXJpdHkgaGVhZGVyc1xuICogLSBSYXRlIGxpbWl0aW5nXG4gKiAtIEpTT04gYW5kIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2luZ1xuICogLSBUcnVzdCBwcm94eSBzZXR0aW5nc1xuICogLSBIZWFsdGggY2hlY2sgZW5kcG9pbnQgKC9oZWFsdGgpXG4gKiAtIE1ldHJpY3MgZW5kcG9pbnQgKC9tZXRyaWNzKVxuICogLSBTU0UgbG9ncyBlbmRwb2ludCAoL2xvZ3MvOnJlcXVlc3RJZCkg4oCUIG9ubHkgd2l0aCBgbG9nU3RyZWFtOiB0cnVlYFxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zXG4gKiBAcmV0dXJucyBDb25maWd1cmVkIEV4cHJlc3MgYXBwIGFuZCBTU0UgbWFuYWdlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCB7IGFwcCwgc3NlTWFuYWdlciB9ID0gY3JlYXRlQXBwKCk7XG4gKlxuICogYXBwLnBvc3QoJy9hcGkvcmVzb3VyY2UnLCByZXF1aXJlQXV0aCwgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gKiAgIC8vIFlvdXIgcm91dGUgaGFuZGxlclxuICogfSk7XG4gKlxuICogc3RhcnRTZXJ2ZXIoYXBwLCB7IG5hbWU6ICdNeSBTZXJ2aWNlJyB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQXBwKG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMgPSB7fSk6IENyZWF0ZUFwcFJlc3VsdCB7XG4gIGNvbnN0IHtcbiAgICBlbmFibGVSYXRlTGltaXQgPSB0cnVlLFxuICAgIGxvZ1N0cmVhbSA9IGZhbHNlLFxuICAgIGVuYWJsZU9wZW5BcGkgPSBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nLFxuICB9ID0gb3B0aW9ucztcblxuICBjb25zdCBzZXJ2aWNlTmFtZSA9IHByb2Nlc3MuZW52LlNFUlZJQ0VfTkFNRSB8fCAnYXBpJztcblxuICAvLyBBIGNhbGxlci1zdXBwbGllZCBgc3NlTWFuYWdlcmAgc2tpcHMgdGhlIGRlZmF1bHQgY29uc3RydWN0aW9uIGVudGlyZWx5LlxuICBjb25zdCBzc2VNYW5hZ2VyID0gb3B0aW9ucy5zc2VNYW5hZ2VyID8/IGNyZWF0ZURlZmF1bHRTc2VNYW5hZ2VyKHNlcnZpY2VOYW1lLCBsb2dTdHJlYW0pO1xuXG4gIC8vIFdpcmUgdGhlIGlkZW1wb3RlbmN5IHJlcGxheS1jYWNoZSBiYWNrZW5kIHVzZWQgYnkgdGhlIHBvc3QtYXV0aCByb3V0ZVxuICAvLyBmYWN0b3JpZXMgKGNyZWF0ZVByb3RlY3RlZFJvdXRlIC8gY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZSkuIFByZWZlclxuICAvLyBhbiBleHBsaWNpdGx5IGluamVjdGVkIHN0b3JlOyBvdGhlcndpc2UgYXV0by1jb25zdHJ1Y3QgZnJvbSB0aGUgc2hhcmVkIGVudlxuICAvLyBSZWRpcyBzbyBrZXllZCBtdXRhdGlvbiByZXRyaWVzIGRlZHVwZSBhY3Jvc3MgcmVwbGljYXMuIEZhbGxzIGJhY2sgdG8gdGhlXG4gIC8vIGluLW1lbW9yeSBkZWZhdWx0IHdoZW4gbm8gUmVkaXMgaXMgY29uZmlndXJlZCAoc2luZ2xlLXJlcGxpY2EgY29ycmVjdG5lc3MpLlxuICBjb25zdCByZXNvbHZlZElkZW1wb3RlbmN5U3RvcmUgPSBvcHRpb25zLmlkZW1wb3RlbmN5U3RvcmUgPz8gY3JlYXRlRW52UmVkaXNJZGVtcG90ZW5jeVN0b3JlKCk7XG4gIGlmIChyZXNvbHZlZElkZW1wb3RlbmN5U3RvcmUpIHtcbiAgICBzZXRJZGVtcG90ZW5jeVN0b3JlKHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSk7XG4gIH1cblxuICAvLyBPcGVuVGVsZW1ldHJ5IGlzIE5PVCBpbml0aWFsaXplZCBoZXJlOiBieSB0aGUgdGltZSBjcmVhdGVBcHAgcnVucywgZXhwcmVzc1xuICAvLyBhbmQgaHR0cCBoYXZlIGFscmVhZHkgYmVlbiByZXF1aXJlZCwgc28gdGhlIGF1dG8taW5zdHJ1bWVudGF0aW9uIGhvb2tzXG4gIC8vIHdvdWxkIGhhdmUgbm90aGluZyB0byBwYXRjaCAobm8gaW5ib3VuZCBzcGFuIOKGkiBubyB0cmFjZSBpZCkuIFRyYWNpbmcgaXNcbiAgLy8gc3RhcnRlZCBieSB0aGUgYG90ZWwtYm9vdHN0cmFwLmpzYCBwcmVsb2FkIGluc3RlYWQgKG5vZGUgLXIg4oCmIOKAlCBzZWUgZWFjaFxuICAvLyBzZXJ2aWNlJ3MgRG9ja2VyZmlsZSBDTUQgLyBzdGFydCBzY3JpcHQpLCB3aGljaCBydW5zIGJlZm9yZSBhbnlcbiAgLy8gaW5zdHJ1bWVudGVkIG1vZHVsZSBsb2Fkcy4gYGN1cnJlbnRUcmFjZUlkKClgIHRoZW4gcmVhZHMgdGhlIGFjdGl2ZSBzcGFuLlxuXG4gIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcblxuICBhcHBseVNlY3VyaXR5SGVhZGVycyhhcHAsIG9wdGlvbnMsIGVuYWJsZU9wZW5BcGkpO1xuICBhcHBseUJvZHlQYXJzaW5nKGFwcCwgb3B0aW9ucyk7XG5cbiAgLy8gVHJ1c3QgcHJveHkgKG11c3QgYmUgc2V0IGJlZm9yZSByYXRlIGxpbWl0ZXIgc28gcmVxLmlwIHJlc29sdmVzIGNvcnJlY3RseSlcbiAgYXBwLnNldCgndHJ1c3QgcHJveHknLCBDb25maWcuZ2V0KCdzZXJ2ZXInKS50cnVzdFByb3h5KTtcblxuICAvLyBSZXF1ZXN0IElEIOKAlCBwcmVmZXIgZXhpc3RpbmcgaGVhZGVyIGZyb20gbmdpbngsIG90aGVyd2lzZSBnZW5lcmF0ZSBvbmVcbiAgYXBwLnVzZSgocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICBjb25zdCBoZHIgPSByZXEuaGVhZGVyc1sneC1yZXF1ZXN0LWlkJ107XG4gICAgY29uc3QgcmVxdWVzdElkID0gKEFycmF5LmlzQXJyYXkoaGRyKSA/IGhkclswXSA6IGhkcikgfHwgdXVpZCgpO1xuICAgIHJlcS5yZXF1ZXN0SWQgPSByZXF1ZXN0SWQ7XG4gICAgcmVzLnNldEhlYWRlcignWC1SZXF1ZXN0LUlkJywgcmVxdWVzdElkKTtcbiAgICBuZXh0KCk7XG4gIH0pO1xuXG4gIG1vdW50SW5mcmFFbmRwb2ludHMoYXBwLCBvcHRpb25zLCBzZXJ2aWNlTmFtZSwgZW5hYmxlT3BlbkFwaSk7XG4gIGlmIChlbmFibGVSYXRlTGltaXQpIG1vdW50UmF0ZUxpbWl0ZXIoYXBwLCBzZXJ2aWNlTmFtZSk7XG4gIGFwcGx5UmVxdWVzdFRlbGVtZXRyeShhcHApO1xuXG4gIC8vIE5PVEU6IGlkZW1wb3RlbmN5IGlzIGludGVudGlvbmFsbHkgTk9UIG1vdW50ZWQgaGVyZS4gSXQgbmVlZHMgdGhlIFZFUklGSUVEXG4gIC8vIG9yZyBpZCB0byBuYW1lc3BhY2UgaXRzIHJlcGxheSBjYWNoZSwgYnV0IHRoaXMgcHJlLWF1dGggcG9zaXRpb24gcnVucyBiZWZvcmVcbiAgLy8gYHJlcXVpcmVBdXRoYC9gYXR0YWNoUmVxdWVzdENvbnRleHRgIHBvcHVsYXRlIGlkZW50aXR5LCBzbyBhIGdsb2JhbCBtb3VudFxuICAvLyBoZXJlIGlzIGEgcGVybWFuZW50IG5vLW9wIChvcmcgYWx3YXlzIHVuZGVmaW5lZCDihpIgc2tpcCkuIEl0IGlzIGluc3RlYWQgd2lyZWRcbiAgLy8gaW50byB0aGUgcG9zdC1hdXRoIHJvdXRlIGNoYWlucyDigJQgc2VlIGBjcmVhdGVQcm90ZWN0ZWRSb3V0ZWAgL1xuICAvLyBgY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZWAgaW4gbWlkZGxld2FyZS1mYWN0b3J5LnRzLlxuXG4gIGlmIChsb2dTdHJlYW0pIHdpcmVTc2UoYXBwLCBzc2VNYW5hZ2VyKTtcblxuICByZXR1cm4geyBhcHAsIHNzZU1hbmFnZXIgfTtcbn1cbiJdfQ==