@dollhousemcp/mcp-server 2.0.11 → 2.0.12-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/config/ConfigManager.d.ts +34 -0
- package/dist/config/ConfigManager.d.ts.map +1 -1
- package/dist/config/ConfigManager.js +46 -1
- package/dist/config/env.d.ts +18 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +89 -2
- package/dist/di/Container.d.ts +1 -0
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +38 -2
- package/dist/elements/agents/AgentManager.js +2 -2
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +3 -3
- package/dist/handlers/mcp-aql/GatekeeperSession.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/GatekeeperSession.js +3 -2
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/MCPAQLHandler.js +11 -3
- package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/OperationSchema.js +11 -6
- package/dist/handlers/mcp-aql/policies/ToolClassification.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/policies/ToolClassification.js +8 -1
- package/dist/index.js +53 -3
- package/dist/security/InputNormalizer.d.ts +4 -6
- package/dist/security/InputNormalizer.d.ts.map +1 -1
- package/dist/security/InputNormalizer.js +10 -16
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +26 -1
- package/dist/security/constants.d.ts +7 -0
- package/dist/security/constants.d.ts.map +1 -1
- package/dist/security/constants.js +10 -1
- package/dist/security/contentValidator.d.ts.map +1 -1
- package/dist/security/contentValidator.js +14 -6
- package/dist/security/encryption/PatternEncryptor.d.ts.map +1 -1
- package/dist/security/encryption/PatternEncryptor.js +18 -10
- package/dist/security/securityMonitor.d.ts +1 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +1 -1
- package/dist/security/tokenManager.d.ts +18 -2
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +47 -15
- package/dist/security/validators/unicodeValidator.d.ts +4 -5
- package/dist/security/validators/unicodeValidator.d.ts.map +1 -1
- package/dist/security/validators/unicodeValidator.js +19 -20
- package/dist/services/VerificationNotifier.d.ts.map +1 -1
- package/dist/services/VerificationNotifier.js +15 -13
- package/dist/services/validation/GenericElementValidator.js +5 -5
- package/dist/web/console/IngestRoutes.d.ts +14 -2
- package/dist/web/console/IngestRoutes.d.ts.map +1 -1
- package/dist/web/console/IngestRoutes.js +69 -5
- package/dist/web/console/LeaderElection.d.ts +37 -3
- package/dist/web/console/LeaderElection.d.ts.map +1 -1
- package/dist/web/console/LeaderElection.js +67 -7
- package/dist/web/console/LeaderForwardingSink.d.ts +19 -3
- package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -1
- package/dist/web/console/LeaderForwardingSink.js +44 -9
- package/dist/web/console/PromotionManager.d.ts +29 -0
- package/dist/web/console/PromotionManager.d.ts.map +1 -0
- package/dist/web/console/PromotionManager.js +94 -0
- package/dist/web/console/SessionNames.d.ts +7 -0
- package/dist/web/console/SessionNames.d.ts.map +1 -1
- package/dist/web/console/SessionNames.js +10 -1
- package/dist/web/console/UnifiedConsole.d.ts +26 -1
- package/dist/web/console/UnifiedConsole.d.ts.map +1 -1
- package/dist/web/console/UnifiedConsole.js +143 -20
- package/dist/web/portDiscovery.d.ts +4 -3
- package/dist/web/portDiscovery.d.ts.map +1 -1
- package/dist/web/portDiscovery.js +7 -5
- package/dist/web/public/app.js +35 -18
- package/dist/web/public/consoleAuth.js +152 -0
- package/dist/web/public/index.html +243 -9
- package/dist/web/public/logs.js +1 -1
- package/dist/web/public/metrics.js +3 -3
- package/dist/web/public/permissions.js +1 -1
- package/dist/web/public/security.css +396 -0
- package/dist/web/public/security.js +393 -0
- package/dist/web/public/sessions.css +54 -4
- package/dist/web/public/sessions.js +46 -6
- package/dist/web/public/setup.css +439 -0
- package/dist/web/public/setup.js +490 -18
- package/dist/web/public/styles.css +10 -0
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +8 -3
- package/dist/web/routes/setupRoutes.d.ts +4 -0
- package/dist/web/routes/setupRoutes.d.ts.map +1 -1
- package/dist/web/routes/setupRoutes.js +418 -7
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +9 -5
- package/dist/web/server.d.ts +49 -3
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +282 -82
- package/package.json +11 -2
- package/server.json +2 -2
package/dist/web/server.js
CHANGED
|
@@ -15,15 +15,40 @@ import { join, dirname, extname } from 'node:path';
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import { execFile } from 'node:child_process';
|
|
17
17
|
import { platform } from 'node:os';
|
|
18
|
-
import { mkdir, readdir } from 'node:fs/promises';
|
|
18
|
+
import { mkdir, readdir, readFile as readFileFs } from 'node:fs/promises';
|
|
19
19
|
import { createApiRoutes, createGatewayApiRoutes } from './routes.js';
|
|
20
20
|
import { createLogRoutes } from './routes/logRoutes.js';
|
|
21
21
|
import { createMetricsRoutes } from './routes/metricsRoutes.js';
|
|
22
22
|
import { createHealthRoutes } from './routes/healthRoutes.js';
|
|
23
23
|
import { createSetupRoutes } from './routes/setupRoutes.js';
|
|
24
|
+
import { createTotpRoutes } from './routes/totpRoutes.js';
|
|
25
|
+
import { createTokenRoutes } from './routes/tokenRoutes.js';
|
|
24
26
|
import { logger } from '../utils/logger.js';
|
|
27
|
+
import { env } from '../config/env.js';
|
|
28
|
+
import { createAuthMiddleware } from './middleware/authMiddleware.js';
|
|
29
|
+
/**
|
|
30
|
+
* Public path prefixes that never require authentication (#1780).
|
|
31
|
+
* These endpoints return safe metadata or act as health probes — requiring
|
|
32
|
+
* tokens on them would break monitoring and client detection without adding
|
|
33
|
+
* real security value.
|
|
34
|
+
*/
|
|
35
|
+
const PUBLIC_PATH_PREFIXES = [
|
|
36
|
+
'/api/health',
|
|
37
|
+
'/api/setup/version',
|
|
38
|
+
'/api/setup/mcpb',
|
|
39
|
+
'/api/setup/detect',
|
|
40
|
+
'/api/setup/license',
|
|
41
|
+
];
|
|
42
|
+
/** Placeholder in index.html that is replaced with the current console token. */
|
|
43
|
+
const TOKEN_META_PLACEHOLDER = '{{CONSOLE_TOKEN}}';
|
|
25
44
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Default port for standalone `startWebServer` calls. Reads from the
|
|
47
|
+
* `DOLLHOUSE_WEB_CONSOLE_PORT` env var so there is a single source of
|
|
48
|
+
* truth (see `src/config/env.ts`). Callers passing an explicit `port` in
|
|
49
|
+
* `WebServerOptions` override this default.
|
|
50
|
+
*/
|
|
51
|
+
const DEFAULT_PORT = env.DOLLHOUSE_WEB_CONSOLE_PORT;
|
|
27
52
|
const CONSOLE_HOST = 'dollhouse.localhost';
|
|
28
53
|
const ALLOWED_PAGE_EXTENSIONS = new Set(['.html', '.htm']);
|
|
29
54
|
/** Max JSON body for setup routes (install/open-config). Ingest routes use their own 1mb limit. */
|
|
@@ -31,10 +56,29 @@ const SETUP_BODY_LIMIT = '1kb';
|
|
|
31
56
|
/** Track whether the web server is already running in-process. */
|
|
32
57
|
let serverRunning = false;
|
|
33
58
|
let serverPort = DEFAULT_PORT;
|
|
59
|
+
/** Active HTTP server instance — tracked so _resetServerState can close it. */
|
|
60
|
+
let activeHttpServer = null;
|
|
61
|
+
/** Cached token store for openPortfolioBrowser — prevents duplicate instances on the same file. */
|
|
62
|
+
let cachedTokenStore = null;
|
|
34
63
|
/** Check whether the web server has been started in this process. */
|
|
35
64
|
export function isWebServerRunning() {
|
|
36
65
|
return serverRunning;
|
|
37
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Reset module-level server state. Exported for testing only —
|
|
69
|
+
* allows tests to exercise startWebServer/bindAndListen without
|
|
70
|
+
* interference from prior runs in the same process.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export function _resetServerState() {
|
|
74
|
+
if (activeHttpServer) {
|
|
75
|
+
activeHttpServer.close();
|
|
76
|
+
activeHttpServer = null;
|
|
77
|
+
}
|
|
78
|
+
serverRunning = false;
|
|
79
|
+
serverPort = DEFAULT_PORT;
|
|
80
|
+
cachedTokenStore = null;
|
|
81
|
+
}
|
|
38
82
|
/**
|
|
39
83
|
* Open a URL in the system's default browser.
|
|
40
84
|
*
|
|
@@ -105,20 +149,52 @@ export async function startWebServer(options) {
|
|
|
105
149
|
"default-src 'self'",
|
|
106
150
|
"script-src 'self' cdn.jsdelivr.net cdnjs.cloudflare.com",
|
|
107
151
|
"style-src 'self' 'unsafe-inline' cdnjs.cloudflare.com cdn.jsdelivr.net",
|
|
152
|
+
"img-src 'self' data:",
|
|
108
153
|
"connect-src 'self' raw.githubusercontent.com",
|
|
109
154
|
"font-src 'self'",
|
|
110
155
|
].join('; '));
|
|
111
156
|
next();
|
|
112
157
|
});
|
|
158
|
+
// Console token authentication middleware (#1780). Mounted before any /api
|
|
159
|
+
// routes so every protected endpoint goes through it. When the feature flag
|
|
160
|
+
// DOLLHOUSE_WEB_AUTH_ENABLED is false (Phase 1 default) this is a pass-through.
|
|
161
|
+
// Public endpoints in PUBLIC_PATH_PREFIXES always bypass auth regardless of flag.
|
|
162
|
+
if (options.tokenStore) {
|
|
163
|
+
const authMiddleware = createAuthMiddleware({
|
|
164
|
+
store: options.tokenStore,
|
|
165
|
+
enabled: env.DOLLHOUSE_WEB_AUTH_ENABLED,
|
|
166
|
+
publicPathPrefixes: PUBLIC_PATH_PREFIXES,
|
|
167
|
+
label: 'api',
|
|
168
|
+
});
|
|
169
|
+
app.use('/api', authMiddleware);
|
|
170
|
+
logger.info(`[WebUI] Console auth middleware mounted ${env.DOLLHOUSE_WEB_AUTH_ENABLED ? 'ENFORCING' : 'pass-through (flag off)'}`);
|
|
171
|
+
// TOTP enrollment routes (#1794). Mounted AFTER the /api auth middleware
|
|
172
|
+
// because the router adds its own always-on auth guard — the global auth
|
|
173
|
+
// middleware at /api is a pass-through during Phase 1 rollout, but the
|
|
174
|
+
// TOTP router enforces regardless of DOLLHOUSE_WEB_AUTH_ENABLED so an
|
|
175
|
+
// attacker with local port access cannot pre-enroll a second factor and
|
|
176
|
+
// lock the legitimate user out.
|
|
177
|
+
app.use('/api/console/totp', createTotpRoutes({ store: options.tokenStore }));
|
|
178
|
+
logger.info('[WebUI] TOTP routes mounted at /api/console/totp (always-on auth)');
|
|
179
|
+
// Token management routes (#1795). Mounted alongside the TOTP router with
|
|
180
|
+
// the same always-on auth pattern. Currently hosts the rotation endpoint;
|
|
181
|
+
// future token management operations (list, revoke) go here too.
|
|
182
|
+
app.use('/api/console/token', createTokenRoutes({ store: options.tokenStore }));
|
|
183
|
+
logger.info('[WebUI] Token routes mounted at /api/console/token (always-on auth)');
|
|
184
|
+
}
|
|
113
185
|
// Setup routes: auto-install DollhouseMCP to MCP clients (mount BEFORE API routes)
|
|
114
186
|
// Body limit scoped to setup routes only — ingest routes need 1mb for follower log forwarding
|
|
115
187
|
const setupJsonParser = express.json({ limit: SETUP_BODY_LIMIT, type: 'application/json' });
|
|
116
|
-
const { installHandler, openConfigHandler, versionHandler, mcpbRedirectHandler, detectHandler } = createSetupRoutes();
|
|
188
|
+
const { installHandler, openConfigHandler, versionHandler, mcpbRedirectHandler, detectHandler, getLicenseHandler, setLicenseHandler, verifyLicenseHandler, resendVerificationHandler } = createSetupRoutes();
|
|
117
189
|
app.post('/api/setup/install', setupJsonParser, installHandler);
|
|
118
190
|
app.post('/api/setup/open-config', setupJsonParser, openConfigHandler);
|
|
119
191
|
app.get('/api/setup/version', versionHandler);
|
|
120
192
|
app.get('/api/setup/mcpb', mcpbRedirectHandler);
|
|
121
193
|
app.get('/api/setup/detect', detectHandler);
|
|
194
|
+
app.get('/api/setup/license', getLicenseHandler);
|
|
195
|
+
app.post('/api/setup/license', setupJsonParser, setLicenseHandler);
|
|
196
|
+
app.post('/api/setup/license/verify', setupJsonParser, verifyLicenseHandler);
|
|
197
|
+
app.post('/api/setup/license/resend', setupJsonParser, resendVerificationHandler);
|
|
122
198
|
logger.info('[WebUI] Setup routes mounted at /api/setup');
|
|
123
199
|
// API routes — use MCP-AQL gateway when handler is available (Issue #796)
|
|
124
200
|
if (options.mcpAqlHandler) {
|
|
@@ -134,30 +210,9 @@ export async function startWebServer(options) {
|
|
|
134
210
|
app.use('/api', createApiRoutes(options.portfolioDir));
|
|
135
211
|
logger.warn('[WebUI] API routes using direct filesystem access (no MCP-AQL handler available)');
|
|
136
212
|
}
|
|
137
|
-
// Console routes: logs, metrics, health
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (options.memorySink) {
|
|
141
|
-
logRoutes = createLogRoutes(options.memorySink);
|
|
142
|
-
app.use('/api', logRoutes.router);
|
|
143
|
-
result.logBroadcast = logRoutes.broadcast;
|
|
144
|
-
logger.info('[WebUI] Log viewer routes mounted at /api/logs');
|
|
145
|
-
}
|
|
146
|
-
if (options.metricsSink) {
|
|
147
|
-
metricsRoutes = createMetricsRoutes(options.metricsSink);
|
|
148
|
-
app.use('/api', metricsRoutes.router);
|
|
149
|
-
result.metricsOnSnapshot = metricsRoutes.onSnapshot;
|
|
150
|
-
logger.info('[WebUI] Metrics routes mounted at /api/metrics');
|
|
151
|
-
}
|
|
152
|
-
if (options.memorySink) {
|
|
153
|
-
const healthRouter = createHealthRoutes({
|
|
154
|
-
memorySink: options.memorySink,
|
|
155
|
-
metricsSink: options.metricsSink,
|
|
156
|
-
logClientCount: logRoutes ? logRoutes.clientCount : () => 0,
|
|
157
|
-
metricsClientCount: metricsRoutes ? metricsRoutes.clientCount : () => 0,
|
|
158
|
-
});
|
|
159
|
-
app.use('/api', healthRouter);
|
|
160
|
-
}
|
|
213
|
+
// Console routes: logs, metrics, health — extracted to keep cognitive
|
|
214
|
+
// complexity of startWebServer manageable.
|
|
215
|
+
mountConsoleRoutes(app, options, result);
|
|
161
216
|
// Serve ~/.dollhouse/pages/ at /pages/ — dashboards, generated content, stack views
|
|
162
217
|
const pagesDir = join(dirname(options.portfolioDir), 'pages');
|
|
163
218
|
mkdir(pagesDir, { recursive: true }).catch(err => {
|
|
@@ -185,9 +240,47 @@ export async function startWebServer(options) {
|
|
|
185
240
|
options.additionalRouters?.forEach(router => app.use(router));
|
|
186
241
|
// Static frontend files
|
|
187
242
|
const publicDir = join(__dirname, 'public');
|
|
188
|
-
|
|
189
|
-
//
|
|
190
|
-
|
|
243
|
+
// Serve static assets but skip index.html — the SPA fallback below
|
|
244
|
+
// handles it with token injection (replaces {{CONSOLE_TOKEN}} in the
|
|
245
|
+
// meta tag). Without this, express.static serves the raw template
|
|
246
|
+
// and the browser never gets the auth token (#1780).
|
|
247
|
+
const isDebug = Boolean(process.env.DOLLHOUSE_DEBUG || process.env.ENABLE_DEBUG);
|
|
248
|
+
app.use(express.static(publicDir, {
|
|
249
|
+
index: false,
|
|
250
|
+
// In debug mode, disable caching on all static assets (JS, CSS) so
|
|
251
|
+
// UI changes are picked up on normal reload without Cmd+Shift+R.
|
|
252
|
+
...(isDebug ? { etag: false, lastModified: false, maxAge: 0 } : {}),
|
|
253
|
+
}));
|
|
254
|
+
// SPA fallback with console token injection (#1780).
|
|
255
|
+
// Reads index.html on first request, substitutes the {{CONSOLE_TOKEN}} placeholder
|
|
256
|
+
// with the current token value, and caches the rendered string. The cache is
|
|
257
|
+
// auto-invalidated when the primary token changes (rotation), so a page reload
|
|
258
|
+
// after rotation picks up the new token without a server restart.
|
|
259
|
+
let cachedIndexHtml = null;
|
|
260
|
+
let cachedTokenValue = null;
|
|
261
|
+
const indexHtmlPath = join(publicDir, 'index.html');
|
|
262
|
+
const renderIndexHtml = async () => {
|
|
263
|
+
const tokenValue = options.tokenStore?.getPrimaryTokenValue() ?? '';
|
|
264
|
+
// Auto-invalidate cache when the token changes (rotation).
|
|
265
|
+
// In debug mode, always re-read from disk so UI changes are picked up on reload.
|
|
266
|
+
if (!isDebug && cachedIndexHtml !== null && cachedTokenValue === tokenValue) {
|
|
267
|
+
return cachedIndexHtml;
|
|
268
|
+
}
|
|
269
|
+
const template = await readFileFs(indexHtmlPath, 'utf8');
|
|
270
|
+
// Defensive HTML attribute escape. Tokens are strict 64-char lowercase hex
|
|
271
|
+
// today so no escaping is actually needed, but if the token format ever
|
|
272
|
+
// changes this prevents an HTML-injection regression from landing silently.
|
|
273
|
+
const escapedToken = tokenValue
|
|
274
|
+
.replaceAll('&', '&')
|
|
275
|
+
.replaceAll('"', '"')
|
|
276
|
+
.replaceAll("'", ''')
|
|
277
|
+
.replaceAll('<', '<')
|
|
278
|
+
.replaceAll('>', '>');
|
|
279
|
+
cachedIndexHtml = template.replaceAll(TOKEN_META_PLACEHOLDER, escapedToken);
|
|
280
|
+
cachedTokenValue = tokenValue;
|
|
281
|
+
return cachedIndexHtml;
|
|
282
|
+
};
|
|
283
|
+
app.get('/{*path}', async (req, res) => {
|
|
191
284
|
const normalizedPath = req.path.normalize('NFC');
|
|
192
285
|
if (normalizedPath.startsWith('/api/')) {
|
|
193
286
|
res.status(404).json({ error: `API route not found: ${normalizedPath}` });
|
|
@@ -197,7 +290,21 @@ export async function startWebServer(options) {
|
|
|
197
290
|
res.status(404).json({ error: `Page not found: ${normalizedPath}` });
|
|
198
291
|
return;
|
|
199
292
|
}
|
|
200
|
-
|
|
293
|
+
try {
|
|
294
|
+
const html = await renderIndexHtml();
|
|
295
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
296
|
+
// In debug mode, prevent browser caching so UI changes are picked up
|
|
297
|
+
// immediately. In production, allow short caching for performance.
|
|
298
|
+
const isDebug = Boolean(process.env.DOLLHOUSE_DEBUG || process.env.ENABLE_DEBUG);
|
|
299
|
+
res.setHeader('Cache-Control', isDebug
|
|
300
|
+
? 'no-cache, no-store, must-revalidate'
|
|
301
|
+
: 'private, max-age=60');
|
|
302
|
+
res.send(html);
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
logger.error(`[WebUI] Failed to render index.html: ${err.message}`);
|
|
306
|
+
res.status(500).send('Failed to load console');
|
|
307
|
+
}
|
|
201
308
|
});
|
|
202
309
|
// Global error handler — catch Express errors and route to logger instead of terminal.
|
|
203
310
|
// Without this, Express dumps stack traces to stderr (visible in --web terminal).
|
|
@@ -210,76 +317,169 @@ export async function startWebServer(options) {
|
|
|
210
317
|
res.status(status).json({ error: err.message });
|
|
211
318
|
}
|
|
212
319
|
});
|
|
213
|
-
// Bind to localhost only — handle port conflicts gracefully
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
320
|
+
// Bind to localhost only — handle port conflicts gracefully.
|
|
321
|
+
// Extracted to a helper to keep startWebServer's cognitive complexity manageable.
|
|
322
|
+
result.bindResult = await bindAndListen(app, port, options);
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Mount the logs, metrics, and health routes. These are only mounted when the
|
|
327
|
+
* corresponding sinks are provided (memory log sink for logs+health, metrics
|
|
328
|
+
* sink for the metrics tab). Extracted from startWebServer to cap the main
|
|
329
|
+
* function's cognitive complexity.
|
|
330
|
+
*/
|
|
331
|
+
function mountConsoleRoutes(app, options, result) {
|
|
332
|
+
let logRoutes;
|
|
333
|
+
let metricsRoutes;
|
|
334
|
+
if (options.memorySink) {
|
|
335
|
+
logRoutes = createLogRoutes(options.memorySink);
|
|
336
|
+
app.use('/api', logRoutes.router);
|
|
337
|
+
result.logBroadcast = logRoutes.broadcast;
|
|
338
|
+
logger.info('[WebUI] Log viewer routes mounted at /api/logs');
|
|
339
|
+
}
|
|
340
|
+
if (options.metricsSink) {
|
|
341
|
+
metricsRoutes = createMetricsRoutes(options.metricsSink);
|
|
342
|
+
app.use('/api', metricsRoutes.router);
|
|
343
|
+
result.metricsOnSnapshot = metricsRoutes.onSnapshot;
|
|
344
|
+
logger.info('[WebUI] Metrics routes mounted at /api/metrics');
|
|
345
|
+
}
|
|
346
|
+
if (options.memorySink) {
|
|
347
|
+
const healthRouter = createHealthRoutes({
|
|
348
|
+
memorySink: options.memorySink,
|
|
349
|
+
metricsSink: options.metricsSink,
|
|
350
|
+
logClientCount: logRoutes ? logRoutes.clientCount : () => 0,
|
|
351
|
+
metricsClientCount: metricsRoutes ? metricsRoutes.clientCount : () => 0,
|
|
352
|
+
});
|
|
353
|
+
app.use('/api', healthRouter);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Print the startup banner to stderr.
|
|
358
|
+
*
|
|
359
|
+
* NOTE: Use stderr for terminal output, not stdout. In MCP stdio mode, stdout
|
|
360
|
+
* is reserved for JSON-RPC messages — any non-JSON output corrupts the protocol.
|
|
361
|
+
* stderr is safe for human-readable messages in both MCP and standalone modes.
|
|
362
|
+
*/
|
|
363
|
+
function printStartupBanner(port, tokenStore) {
|
|
364
|
+
const url = `http://${CONSOLE_HOST}:${port}`;
|
|
365
|
+
const fallbackUrl = `http://127.0.0.1:${port}`;
|
|
366
|
+
logger.info(`[WebUI] Management console running at ${url}`);
|
|
367
|
+
console.error(`\n DollhouseMCP Management Console\n ${url}\n ${fallbackUrl} (fallback)\n`);
|
|
368
|
+
if (tokenStore) {
|
|
369
|
+
console.error(` Session token: ${tokenStore.getFilePath()}\n`);
|
|
370
|
+
}
|
|
371
|
+
console.error(` Type "q" or "quit" to exit.\n`);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Retry binding an already-configured Express app to a port.
|
|
375
|
+
* Used by UnifiedConsole when EADDRINUSE occurs — avoids recreating
|
|
376
|
+
* the Express app and all its routes on each retry attempt.
|
|
377
|
+
*/
|
|
378
|
+
export async function retryBind(app, port, options) {
|
|
379
|
+
return bindAndListen(app, port, options);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Bind the Express app to 127.0.0.1:port and handle success/conflict paths.
|
|
383
|
+
* Returns a BindResult so the caller can detect and handle port conflicts
|
|
384
|
+
* (e.g., retry after killing a stale process).
|
|
385
|
+
*/
|
|
386
|
+
async function bindAndListen(app, port, options) {
|
|
387
|
+
return new Promise((resolve) => {
|
|
218
388
|
const httpServer = app.listen(port, '127.0.0.1', () => {
|
|
219
389
|
serverRunning = true;
|
|
220
390
|
serverPort = port;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
logger.info(`[WebUI] Management console running at ${url}`);
|
|
224
|
-
console.error(`\n DollhouseMCP Management Console\n ${url}\n ${fallbackUrl} (fallback)\n`);
|
|
225
|
-
console.error(` Type "q" or "quit" to exit.\n`);
|
|
391
|
+
activeHttpServer = httpServer;
|
|
392
|
+
printStartupBanner(port, options.tokenStore);
|
|
226
393
|
if (options.openBrowser) {
|
|
227
|
-
openInBrowser(
|
|
394
|
+
openInBrowser(`http://${CONSOLE_HOST}:${port}`);
|
|
228
395
|
}
|
|
229
|
-
resolve();
|
|
396
|
+
resolve({ success: true });
|
|
230
397
|
});
|
|
231
398
|
httpServer.on('error', (err) => {
|
|
232
|
-
|
|
233
|
-
const url = `http://${CONSOLE_HOST}:${port}`;
|
|
234
|
-
logger.info(`[WebUI] Port ${port} already in use — opening existing console`);
|
|
235
|
-
console.error(`\n DollhouseMCP Management Console (existing instance)\n ${url}\n`);
|
|
236
|
-
if (options.openBrowser) {
|
|
237
|
-
openInBrowser(url);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
logger.error(`[WebUI] Failed to bind port ${port}: ${err.message}`);
|
|
242
|
-
}
|
|
243
|
-
resolve(); // Web console is optional — don't block startup
|
|
399
|
+
resolve(handleListenError(err, port, options.openBrowser));
|
|
244
400
|
});
|
|
245
401
|
});
|
|
246
|
-
return result;
|
|
247
402
|
}
|
|
248
403
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
404
|
+
* Handle errors from app.listen(). Returns a BindResult describing the failure.
|
|
405
|
+
* EADDRINUSE is logged at WARN (not INFO) so it's visible in production logs.
|
|
406
|
+
*/
|
|
407
|
+
function handleListenError(err, port, openBrowser) {
|
|
408
|
+
if (err.code === 'EADDRINUSE') {
|
|
409
|
+
const url = `http://${CONSOLE_HOST}:${port}`;
|
|
410
|
+
logger.warn(`[WebUI] Port ${port} already in use — another process holds this port`);
|
|
411
|
+
console.error(`\n DollhouseMCP Management Console (existing instance)\n ${url}\n`);
|
|
412
|
+
if (openBrowser) {
|
|
413
|
+
openInBrowser(url);
|
|
414
|
+
}
|
|
415
|
+
return { success: false, error: 'EADDRINUSE', detail: `Port ${port} already in use` };
|
|
416
|
+
}
|
|
417
|
+
logger.error(`[WebUI] Failed to bind port ${port}: ${err.message}`);
|
|
418
|
+
return { success: false, error: 'OTHER', detail: err.message };
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Self-provision sinks, token store, and ingest routes, then start the web
|
|
422
|
+
* server. Extracted from openPortfolioBrowser to keep cognitive complexity
|
|
423
|
+
* manageable (SonarCloud S3776).
|
|
260
424
|
*/
|
|
261
|
-
|
|
262
|
-
|
|
425
|
+
async function startFallbackServer(options, port) {
|
|
426
|
+
let memorySink = options.memorySink;
|
|
427
|
+
let metricsSink = options.metricsSink;
|
|
428
|
+
if (!memorySink) {
|
|
429
|
+
const { MemoryLogSink: LogSink } = await import('../logging/sinks/MemoryLogSink.js');
|
|
430
|
+
memorySink = new LogSink({ appCapacity: 10000, securityCapacity: 5000, perfCapacity: 2000, telemetryCapacity: 1000 });
|
|
431
|
+
}
|
|
432
|
+
if (!metricsSink) {
|
|
433
|
+
const { MemoryMetricsSink: MetricsSink } = await import('../metrics/sinks/MemoryMetricsSink.js');
|
|
434
|
+
metricsSink = new MetricsSink(240);
|
|
435
|
+
}
|
|
436
|
+
// Reuse cached token store — two instances on the same file can race on writes.
|
|
437
|
+
if (!cachedTokenStore) {
|
|
438
|
+
const { ConsoleTokenStore: TokenStore } = await import('./console/consoleToken.js');
|
|
439
|
+
const { pickRandomPuppetName } = await import('./console/SessionNames.js');
|
|
440
|
+
cachedTokenStore = new TokenStore(env.DOLLHOUSE_CONSOLE_TOKEN_FILE);
|
|
441
|
+
try {
|
|
442
|
+
await cachedTokenStore.ensureInitialized(pickRandomPuppetName());
|
|
443
|
+
}
|
|
444
|
+
catch (err) {
|
|
445
|
+
logger.warn('[WebUI] Failed to init token store for browser open', err);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
// logBroadcast is deferred — wired after startWebServer returns the real broadcast fn.
|
|
449
|
+
let liveBroadcast;
|
|
450
|
+
const { createIngestRoutes } = await import('./console/IngestRoutes.js');
|
|
451
|
+
const ingestResult = createIngestRoutes({
|
|
452
|
+
logBroadcast: (entry) => liveBroadcast?.(entry),
|
|
453
|
+
});
|
|
454
|
+
ingestResult.registerConsoleSession();
|
|
455
|
+
const webResult = await startWebServer({
|
|
456
|
+
portfolioDir: options.portfolioDir,
|
|
457
|
+
port,
|
|
458
|
+
openBrowser: false,
|
|
459
|
+
mcpAqlHandler: options.mcpAqlHandler,
|
|
460
|
+
memorySink,
|
|
461
|
+
metricsSink,
|
|
462
|
+
tokenStore: cachedTokenStore,
|
|
463
|
+
additionalRouters: [ingestResult.router],
|
|
464
|
+
});
|
|
465
|
+
liveBroadcast = webResult.logBroadcast;
|
|
466
|
+
}
|
|
467
|
+
export async function openPortfolioBrowser(options) {
|
|
468
|
+
const targetPort = options.port || DEFAULT_PORT;
|
|
263
469
|
const baseUrl = `http://${CONSOLE_HOST}:${targetPort}`;
|
|
264
470
|
// Build URL with optional tab hash and query parameters
|
|
265
|
-
// Format: http://host:port/#tab?key=value&key=value
|
|
266
471
|
let url = baseUrl;
|
|
267
|
-
if (tab) {
|
|
268
|
-
const qs = urlParams ? new URLSearchParams(urlParams).toString() : '';
|
|
269
|
-
url = `${baseUrl}/#${tab}${qs ? '?' + qs : ''}`;
|
|
472
|
+
if (options.tab) {
|
|
473
|
+
const qs = options.urlParams ? new URLSearchParams(options.urlParams).toString() : '';
|
|
474
|
+
url = `${baseUrl}/#${options.tab}${qs ? '?' + qs : ''}`;
|
|
270
475
|
}
|
|
271
|
-
else if (urlParams && Object.keys(urlParams).length > 0) {
|
|
272
|
-
const qs = new URLSearchParams(urlParams).toString();
|
|
476
|
+
else if (options.urlParams && Object.keys(options.urlParams).length > 0) {
|
|
477
|
+
const qs = new URLSearchParams(options.urlParams).toString();
|
|
273
478
|
url = `${baseUrl}/#portfolio?${qs}`;
|
|
274
479
|
}
|
|
275
480
|
const alreadyRunning = serverRunning;
|
|
276
481
|
if (!serverRunning) {
|
|
277
|
-
await
|
|
278
|
-
portfolioDir,
|
|
279
|
-
port: targetPort,
|
|
280
|
-
openBrowser: false, // We'll open manually below to capture the result
|
|
281
|
-
mcpAqlHandler,
|
|
282
|
-
});
|
|
482
|
+
await startFallbackServer(options, targetPort);
|
|
283
483
|
}
|
|
284
484
|
const browserResult = await openInBrowser(url);
|
|
285
485
|
return {
|
|
@@ -289,4 +489,4 @@ export async function openPortfolioBrowser(portfolioDir, port, mcpAqlHandler, ta
|
|
|
289
489
|
...(browserResult.error ? { warning: `Browser could not be opened automatically: ${browserResult.error}. Open ${url} manually.` } : {}),
|
|
290
490
|
};
|
|
291
491
|
}
|
|
292
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3dlYi9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ25ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDbkMsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxlQUFlLEVBQXdCLE1BQU0sdUJBQXVCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG1CQUFtQixFQUE0QixNQUFNLDJCQUEyQixDQUFDO0FBQzFGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzVELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUs1QyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUMxRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUM7QUFDMUIsTUFBTSxZQUFZLEdBQUcscUJBQXFCLENBQUM7QUFDM0MsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQzNELG1H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ckQsR0FBRyxHQUFHLEdBQUcsT0FBTyxlQUFlLEVBQUUsRUFBRSxDQUFDO0lBQ3RDLENBQUM7SUFFRCxNQUFNLGNBQWMsR0FBRyxhQUFhLENBQUM7SUFFckMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ25CLE1BQU0sY0FBYyxDQUFDO1lBQ25CLFlBQVk7WUFDWixJQUFJLEVBQUUsVUFBVTtZQUNoQixXQUFXLEVBQUUsS0FBSyxFQUFFLGtEQUFrRDtZQUN0RSxhQUFhO1NBQ2QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELE1BQU0sYUFBYSxHQUFHLE1BQU0sYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRS9DLE9BQU87UUFDTCxHQUFHO1FBQ0gsY0FBYztRQUNkLGFBQWEsRUFBRSxhQUFhLENBQUMsT0FBTztRQUNwQyxHQUFHLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsOENBQThDLGFBQWEsQ0FBQyxLQUFLLFVBQVUsR0FBRyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ3hJLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEb2xsaG91c2VNQ1AgV2ViIFVJIFNlcnZlclxuICpcbiAqIExpZ2h0d2VpZ2h0IEV4cHJlc3Mgc2VydmVyIGZvciBicm93c2luZyBwb3J0Zm9saW8gZWxlbWVudHMgaW4gYSBicm93c2VyLlxuICogQm91bmQgdG8gMTI3LjAuMC4xIG9ubHkgKGxvY2FsaG9zdCkuIFJlYWQtb25seSBmb3IgVjEuXG4gKlxuICogQ2FuIGJlIHN0YXJ0ZWQgc3RhbmRhbG9uZSAoYC0td2ViYCBmbGFnKSBvciBmcm9tIHdpdGhpbiB0aGUgTUNQIHNlcnZlclxuICogcHJvY2VzcyB2aWEgYG9wZW5Qb3J0Zm9saW9Ccm93c2VyKClgLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL0RvbGxob3VzZU1DUC9tY3Atc2VydmVyLXYyLXJlZmFjdG9yL2lzc3Vlcy83MDRcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL0RvbGxob3VzZU1DUC9tY3Atc2VydmVyLXYyLXJlZmFjdG9yL2lzc3Vlcy83NzRcbiAqL1xuXG5pbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGpvaW4sIGRpcm5hbWUsIGV4dG5hbWUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCB7IGV4ZWNGaWxlIH0gZnJvbSAnbm9kZTpjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IHBsYXRmb3JtIH0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgeyBta2RpciwgcmVhZGRpciB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgY3JlYXRlQXBpUm91dGVzLCBjcmVhdGVHYXRld2F5QXBpUm91dGVzIH0gZnJvbSAnLi9yb3V0ZXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nUm91dGVzLCB0eXBlIExvZ1JvdXRlc1Jlc3VsdCB9IGZyb20gJy4vcm91dGVzL2xvZ1JvdXRlcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVNZXRyaWNzUm91dGVzLCB0eXBlIE1ldHJpY3NSb3V0ZXNSZXN1bHQgfSBmcm9tICcuL3JvdXRlcy9tZXRyaWNzUm91dGVzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUhlYWx0aFJvdXRlcyB9IGZyb20gJy4vcm91dGVzL2hlYWx0aFJvdXRlcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTZXR1cFJvdXRlcyB9IGZyb20gJy4vcm91dGVzL3NldHVwUm91dGVzLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IE1DUEFRTEhhbmRsZXIgfSBmcm9tICcuLi9oYW5kbGVycy9tY3AtYXFsL01DUEFRTEhhbmRsZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBNZW1vcnlMb2dTaW5rIH0gZnJvbSAnLi4vbG9nZ2luZy9zaW5rcy9NZW1vcnlMb2dTaW5rLmpzJztcbmltcG9ydCB0eXBlIHsgTWVtb3J5TWV0cmljc1NpbmsgfSBmcm9tICcuLi9tZXRyaWNzL3NpbmtzL01lbW9yeU1ldHJpY3NTaW5rLmpzJztcblxuY29uc3QgX19kaXJuYW1lID0gZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuY29uc3QgREVGQVVMVF9QT1JUID0gMzkzOTtcbmNvbnN0IENPTlNPTEVfSE9TVCA9ICdkb2xsaG91c2UubG9jYWxob3N0JztcbmNvbnN0IEFMTE9XRURfUEFHRV9FWFRFTlNJT05TID0gbmV3IFNldChbJy5odG1sJywgJy5odG0nXSk7XG4vKiogTWF4IEpTT04gYm9keSBmb3Igc2V0dXAgcm91dGVzIChpbnN0YWxsL29wZW4tY29uZmlnKS4gSW5nZXN0IHJvdXRlcyB1c2UgdGhlaXIgb3duIDFtYiBsaW1pdC4gKi9cbmNvbnN0IFNFVFVQX0JPRFlfTElNSVQgPSAnMWtiJztcblxuLyoqIFRyYWNrIHdoZXRoZXIgdGhlIHdlYiBzZXJ2ZXIgaXMgYWxyZWFkeSBydW5uaW5nIGluLXByb2Nlc3MuICovXG5sZXQgc2VydmVyUnVubmluZyA9IGZhbHNlO1xubGV0IHNlcnZlclBvcnQgPSBERUZBVUxUX1BPUlQ7XG5cbi8qKiBDaGVjayB3aGV0aGVyIHRoZSB3ZWIgc2VydmVyIGhhcyBiZWVuIHN0YXJ0ZWQgaW4gdGhpcyBwcm9jZXNzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzV2ViU2VydmVyUnVubmluZygpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlcnZlclJ1bm5pbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3Igc3RhcnRpbmcgdGhlIHdlYiBzZXJ2ZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV2ViU2VydmVyT3B0aW9ucyB7XG4gIC8qKiBQb3J0IHRvIGJpbmQgdG8gKGRlZmF1bHQ6IDM5MzkpICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBQYXRoIHRvIHRoZSBwb3J0Zm9saW8gZGlyZWN0b3J5IChlLmcuLCB+Ly5kb2xsaG91c2UvcG9ydGZvbGlvKSAqL1xuICBwb3J0Zm9saW9EaXI6IHN0cmluZztcbiAgLyoqIE9wZW4gdGhlIGJyb3dzZXIgYXV0b21hdGljYWxseSBhZnRlciBzdGFydGluZyAoZGVmYXVsdDogZmFsc2UpICovXG4gIG9wZW5Ccm93c2VyPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIE1DUEFRTEhhbmRsZXIgZm9yIHJvdXRpbmcgdGhyb3VnaCB0aGUgTUNQLUFRTCBwaXBlbGluZS5cbiAgICogV2hlbiBwcm92aWRlZCwgQVBJIHJvdXRlcyB1c2UgdGhlIGdhdGV3YXkgKHZhbGlkYXRlZCwgY2FjaGVkLCBnYXRla2VlcGVyLWNoZWNrZWQpLlxuICAgKiBXaGVuIGFic2VudCwgZmFsbHMgYmFjayB0byBkaXJlY3QgZmlsZXN5c3RlbSBhY2Nlc3MgKGxlZ2FjeSBiZWhhdmlvcikuXG4gICAqIElzc3VlICM3OTY6IFdlYiBNQ1AtQVFMIEdhdGV3YXkuXG4gICAqL1xuICBtY3BBcWxIYW5kbGVyPzogTUNQQVFMSGFuZGxlcjtcbiAgLyoqIE1lbW9yeUxvZ1NpbmsgZm9yIGxvZyByb3V0ZXMgKG9wdGlvbmFsIOKAlCBsb2dzIHRhYiBkaXNhYmxlZCBpZiBub3QgcHJvdmlkZWQpICovXG4gIG1lbW9yeVNpbms/OiBNZW1vcnlMb2dTaW5rO1xuICAvKiogTWVtb3J5TWV0cmljc1NpbmsgZm9yIG1ldHJpY3Mgcm91dGVzIChvcHRpb25hbCDigJQgbWV0cmljcyB0YWIgZGlzYWJsZWQgaWYgbm90IHByb3ZpZGVkKSAqL1xuICBtZXRyaWNzU2luaz86IE1lbW9yeU1ldHJpY3NTaW5rO1xuICAvKiogQWRkaXRpb25hbCByb3V0ZXJzIHRvIG1vdW50IGJlZm9yZSB0aGUgU1BBIGZhbGxiYWNrIChlLmcuLCBpbmdlc3Qgcm91dGVzKSAqL1xuICBhZGRpdGlvbmFsUm91dGVycz86IGltcG9ydCgnZXhwcmVzcycpLlJvdXRlcltdO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBzdGFydGluZyB0aGUgd2ViIHNlcnZlciwgaW5jbHVkaW5nIGhvb2tzIGZvciBESSB3aXJpbmcuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV2ViU2VydmVyUmVzdWx0IHtcbiAgLyoqIEV4cHJlc3MgYXBwIGluc3RhbmNlIOKAlCBmb3IgbW91bnRpbmcgYWRkaXRpb25hbCByb3V0ZXMgKGUuZy4sIGluZ2VzdCByb3V0ZXMpICovXG4gIGFwcD86IGltcG9ydCgnZXhwcmVzcycpLkV4cHJlc3M7XG4gIC8qKiBMb2cgYnJvYWRjYXN0IGZ1bmN0aW9uIOKAlCBjYWxsIHdpdGggZWFjaCBlbnRyeSB0byBwdXNoIHRvIFNTRSBjbGllbnRzICovXG4gIGxvZ0Jyb2FkY2FzdD86IChlbnRyeTogaW1wb3J0KCcuLi9sb2dnaW5nL3R5cGVzLmpzJykuVW5pZmllZExvZ0VudHJ5KSA9PiB2b2lkO1xuICAvKiogTWV0cmljcyBzbmFwc2hvdCBmdW5jdGlvbiDigJQgY2FsbCB3aXRoIGVhY2ggc25hcHNob3QgdG8gcHVzaCB0byBTU0UgY2xpZW50cyAqL1xuICBtZXRyaWNzT25TbmFwc2hvdD86IChzbmFwc2hvdDogaW1wb3J0KCcuLi9tZXRyaWNzL3R5cGVzLmpzJykuTWV0cmljU25hcHNob3QpID0+IHZvaWQ7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGF0dGVtcHRpbmcgdG8gb3BlbiB0aGUgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCcm93c2VyT3BlblJlc3VsdCB7XG4gIC8qKiBUaGUgVVJMIHRoZSBzZXJ2ZXIgaXMgcnVubmluZyBvbiAqL1xuICB1cmw6IHN0cmluZztcbiAgLyoqIFdoZXRoZXIgdGhlIHNlcnZlciB3YXMgYWxyZWFkeSBydW5uaW5nICh0cnVlKSBvciBqdXN0IHN0YXJ0ZWQgKGZhbHNlKSAqL1xuICBhbHJlYWR5UnVubmluZzogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhlIGJyb3dzZXIgd2FzIHN1Y2Nlc3NmdWxseSBvcGVuZWQgKi9cbiAgYnJvd3Nlck9wZW5lZDogYm9vbGVhbjtcbiAgLyoqIFdhcm5pbmcgbWVzc2FnZSBpZiB0aGUgYnJvd3NlciBjb3VsZCBub3QgYmUgb3BlbmVkICovXG4gIHdhcm5pbmc/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3BlbiBhIFVSTCBpbiB0aGUgc3lzdGVtJ3MgZGVmYXVsdCBicm93c2VyLlxuICpcbiAqIFBsYXRmb3JtLWF3YXJlOlxuICogLSBtYWNPUzogYG9wZW5gXG4gKiAtIExpbnV4OiBgeGRnLW9wZW5gXG4gKiAtIFdpbmRvd3M6IGBzdGFydGBcbiAqXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCB0byBvcGVuXG4gKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdHJ1ZSBpZiB0aGUgYnJvd3NlciBvcGVuZWQsIGZhbHNlIHdpdGggZXJyb3IgbWVzc2FnZSBpZiBub3RcbiAqL1xuZnVuY3Rpb24gb3BlbkluQnJvd3Nlcih1cmw6IHN0cmluZyk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcj86IHN0cmluZyB9PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IHBsYXQgPSBwbGF0Zm9ybSgpO1xuICAgIGNvbnN0IGNtZCA9IHBsYXQgPT09ICdkYXJ3aW4nID8gJ29wZW4nXG4gICAgICA6IHBsYXQgPT09ICd3aW4zMicgPyAnc3RhcnQnXG4gICAgICA6ICd4ZGctb3Blbic7XG5cbiAgICAvLyBTZWN1cml0eTogdXNlIGV4ZWNGaWxlIHdpdGggVVJMIGFzIGFyZ3VtZW50IGFycmF5LCBub3Qgc3RyaW5nIGludGVycG9sYXRpb25cbiAgICBjb25zdCB1cmxTdHIgPSBTdHJpbmcodXJsKTtcbiAgICAvLyBBY2NlcHQgbG9jYWxob3N0LCAxMjcuMC4wLjEsIGFuZCAqLmxvY2FsaG9zdCBzdWJkb21haW5zIChSRkMgNjc2MSlcbiAgICBpZiAoIS9eaHR0cHM/OlxcL1xcLyhsb2NhbGhvc3R8MTI3XFwuMFxcLjBcXC4xfFtcXHctXStcXC5sb2NhbGhvc3QpWzovXS8udGVzdCh1cmxTdHIpKSB7XG4gICAgICByZXNvbHZlKHsgc3VjY2VzczogZmFsc2UsIGVycm9yOiAnVVJMIG11c3QgYmUgYSBsb2NhbGhvc3QgSFRUUCBVUkwnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBleGVjRmlsZShjbWQsIFt1cmxTdHJdLCAoZXJyKSA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbV2ViVUldIENvdWxkIG5vdCBhdXRvLW9wZW4gYnJvd3NlcjogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgICAgcmVzb2x2ZSh7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogZXJyLm1lc3NhZ2UgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKHsgc3VjY2VzczogdHJ1ZSB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogU3RhcnQgdGhlIHBvcnRmb2xpbyB3ZWIgc2VydmVyLlxuICpcbiAqIEJpbmRzIHRvIDEyNy4wLjAuMSBvbmx5IChsb2NhbGhvc3QpLiBTZXJ2ZXMgdGhlIHBvcnRmb2xpbyBicm93c2VyXG4gKiBmcm9udGVuZCBhbmQgQVBJIHJvdXRlcyBmb3IgcmVhZGluZyBlbGVtZW50cy5cbiAqXG4gKiBJZGVtcG90ZW50OiBpZiB0aGUgc2VydmVyIGlzIGFscmVhZHkgcnVubmluZywgb3B0aW9uYWxseSBvcGVucyB0aGVcbiAqIGJyb3dzZXIgd2l0aG91dCBzdGFydGluZyBhIHNlY29uZCBpbnN0YW5jZS5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFNlcnZlciBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBIb29rcyBmb3IgREkgd2lyaW5nIChsb2cgYnJvYWRjYXN0LCBtZXRyaWNzIG9uU25hcHNob3QpXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFdlYlNlcnZlcihvcHRpb25zOiBXZWJTZXJ2ZXJPcHRpb25zKTogUHJvbWlzZTxXZWJTZXJ2ZXJSZXN1bHQ+IHtcbiAgY29uc3QgcG9ydCA9IG9wdGlvbnMucG9ydCB8fCBERUZBVUxUX1BPUlQ7XG4gIGNvbnN0IHJlc3VsdDogV2ViU2VydmVyUmVzdWx0ID0ge307XG5cbiAgaWYgKHNlcnZlclJ1bm5pbmcpIHtcbiAgICBpZiAob3B0aW9ucy5vcGVuQnJvd3Nlcikge1xuICAgICAgb3BlbkluQnJvd3NlcihgaHR0cDovLyR7Q09OU09MRV9IT1NUfToke3NlcnZlclBvcnR9YCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gIHJlc3VsdC5hcHAgPSBhcHA7XG4gIGFwcC5kaXNhYmxlKCd4LXBvd2VyZWQtYnknKTtcblxuICAvLyBTZWN1cml0eSBoZWFkZXJzXG4gIGFwcC51c2UoKF9yZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtQ29udGVudC1UeXBlLU9wdGlvbnMnLCAnbm9zbmlmZicpO1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtRnJhbWUtT3B0aW9ucycsICdERU5ZJyk7XG4gICAgcmVzLnNldEhlYWRlcignWC1YU1MtUHJvdGVjdGlvbicsICcxOyBtb2RlPWJsb2NrJyk7XG4gICAgcmVzLnNldEhlYWRlcignUmVmZXJyZXItUG9saWN5JywgJ25vLXJlZmVycmVyJyk7XG4gICAgcmVzLnNldEhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgYGh0dHA6Ly8ke0NPTlNPTEVfSE9TVH06JHtwb3J0fWApO1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtU2VjdXJpdHktUG9saWN5JywgW1xuICAgICAgXCJkZWZhdWx0LXNyYyAnc2VsZidcIixcbiAgICAgIFwic2NyaXB0LXNyYyAnc2VsZicgY2RuLmpzZGVsaXZyLm5ldCBjZG5qcy5jbG91ZGZsYXJlLmNvbVwiLFxuICAgICAgXCJzdHlsZS1zcmMgJ3NlbGYnICd1bnNhZmUtaW5saW5lJyBjZG5qcy5jbG91ZGZsYXJlLmNvbSBjZG4uanNkZWxpdnIubmV0XCIsXG4gICAgICBcImNvbm5lY3Qtc3JjICdzZWxmJyByYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tXCIsXG4gICAgICBcImZvbnQtc3JjICdzZWxmJ1wiLFxuICAgIF0uam9pbignOyAnKSk7XG4gICAgbmV4dCgpO1xuICB9KTtcblxuICAvLyBTZXR1cCByb3V0ZXM6IGF1dG8taW5zdGFsbCBEb2xsaG91c2VNQ1AgdG8gTUNQIGNsaWVudHMgKG1vdW50IEJFRk9SRSBBUEkgcm91dGVzKVxuICAvLyBCb2R5IGxpbWl0IHNjb3BlZCB0byBzZXR1cCByb3V0ZXMgb25seSDigJQgaW5nZXN0IHJvdXRlcyBuZWVkIDFtYiBmb3IgZm9sbG93ZXIgbG9nIGZvcndhcmRpbmdcbiAgY29uc3Qgc2V0dXBKc29uUGFyc2VyID0gZXhwcmVzcy5qc29uKHsgbGltaXQ6IFNFVFVQX0JPRFlfTElNSVQsIHR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyB9KTtcbiAgY29uc3QgeyBpbnN0YWxsSGFuZGxlciwgb3BlbkNvbmZpZ0hhbmRsZXIsIHZlcnNpb25IYW5kbGVyLCBtY3BiUmVkaXJlY3RIYW5kbGVyLCBkZXRlY3RIYW5kbGVyIH0gPSBjcmVhdGVTZXR1cFJvdXRlcygpO1xuICBhcHAucG9zdCgnL2FwaS9zZXR1cC9pbnN0YWxsJywgc2V0dXBKc29uUGFyc2VyLCBpbnN0YWxsSGFuZGxlcik7XG4gIGFwcC5wb3N0KCcvYXBpL3NldHVwL29wZW4tY29uZmlnJywgc2V0dXBKc29uUGFyc2VyLCBvcGVuQ29uZmlnSGFuZGxlcik7XG4gIGFwcC5nZXQoJy9hcGkvc2V0dXAvdmVyc2lvbicsIHZlcnNpb25IYW5kbGVyKTtcbiAgYXBwLmdldCgnL2FwaS9zZXR1cC9tY3BiJywgbWNwYlJlZGlyZWN0SGFuZGxlcik7XG4gIGFwcC5nZXQoJy9hcGkvc2V0dXAvZGV0ZWN0JywgZGV0ZWN0SGFuZGxlcik7XG4gIGxvZ2dlci5pbmZvKCdbV2ViVUldIFNldHVwIHJvdXRlcyBtb3VudGVkIGF0IC9hcGkvc2V0dXAnKTtcblxuICAvLyBBUEkgcm91dGVzIOKAlCB1c2UgTUNQLUFRTCBnYXRld2F5IHdoZW4gaGFuZGxlciBpcyBhdmFpbGFibGUgKElzc3VlICM3OTYpXG4gIGlmIChvcHRpb25zLm1jcEFxbEhhbmRsZXIpIHtcbiAgICBhcHAudXNlKCcvYXBpJywgY3JlYXRlR2F0ZXdheUFwaVJvdXRlcyhvcHRpb25zLm1jcEFxbEhhbmRsZXIsIG9wdGlvbnMucG9ydGZvbGlvRGlyKSk7XG5cbiAgICAvLyBQZXJtaXNzaW9uIGV2YWx1YXRpb24gcm91dGVzIChQT1NUIC9ldmFsdWF0ZV9wZXJtaXNzaW9uLCBHRVQgL3Blcm1pc3Npb25zL3N0YXR1cylcbiAgICBjb25zdCB7IHJlZ2lzdGVyUGVybWlzc2lvblJvdXRlcyB9ID0gYXdhaXQgaW1wb3J0KCcuL3JvdXRlcy9wZXJtaXNzaW9uUm91dGVzLmpzJyk7XG4gICAgY29uc3QgcGVybVJvdXRlciA9IChhd2FpdCBpbXBvcnQoJ2V4cHJlc3MnKSkuUm91dGVyKCk7XG4gICAgcmVnaXN0ZXJQZXJtaXNzaW9uUm91dGVzKHBlcm1Sb3V0ZXIsIG9wdGlvbnMubWNwQXFsSGFuZGxlcik7XG4gICAgYXBwLnVzZSgnL2FwaScsIHBlcm1Sb3V0ZXIpO1xuXG4gICAgbG9nZ2VyLmluZm8oJ1tXZWJVSV0gQVBJIHJvdXRlcyB1c2luZyBNQ1AtQVFMIEdhdGV3YXkgKyBwZXJtaXNzaW9uIHJvdXRlcycpO1xuICB9IGVsc2Uge1xuICAgIGFwcC51c2UoJy9hcGknLCBjcmVhdGVBcGlSb3V0ZXMob3B0aW9ucy5wb3J0Zm9saW9EaXIpKTtcbiAgICBsb2dnZXIud2FybignW1dlYlVJXSBBUEkgcm91dGVzIHVzaW5nIGRpcmVjdCBmaWxlc3lzdGVtIGFjY2VzcyAobm8gTUNQLUFRTCBoYW5kbGVyIGF2YWlsYWJsZSknKTtcbiAgfVxuXG4gIC8vIENvbnNvbGUgcm91dGVzOiBsb2dzLCBtZXRyaWNzLCBoZWFsdGhcbiAgbGV0IGxvZ1JvdXRlczogTG9nUm91dGVzUmVzdWx0IHwgdW5kZWZpbmVkO1xuICBsZXQgbWV0cmljc1JvdXRlczogTWV0cmljc1JvdXRlc1Jlc3VsdCB8IHVuZGVmaW5lZDtcblxuICBpZiAob3B0aW9ucy5tZW1vcnlTaW5rKSB7XG4gICAgbG9nUm91dGVzID0gY3JlYXRlTG9nUm91dGVzKG9wdGlvbnMubWVtb3J5U2luayk7XG4gICAgYXBwLnVzZSgnL2FwaScsIGxvZ1JvdXRlcy5yb3V0ZXIpO1xuICAgIHJlc3VsdC5sb2dCcm9hZGNhc3QgPSBsb2dSb3V0ZXMuYnJvYWRjYXN0O1xuICAgIGxvZ2dlci5pbmZvKCdbV2ViVUldIExvZyB2aWV3ZXIgcm91dGVzIG1vdW50ZWQgYXQgL2FwaS9sb2dzJyk7XG4gIH1cblxuICBpZiAob3B0aW9ucy5tZXRyaWNzU2luaykge1xuICAgIG1ldHJpY3NSb3V0ZXMgPSBjcmVhdGVNZXRyaWNzUm91dGVzKG9wdGlvbnMubWV0cmljc1NpbmspO1xuICAgIGFwcC51c2UoJy9hcGknLCBtZXRyaWNzUm91dGVzLnJvdXRlcik7XG4gICAgcmVzdWx0Lm1ldHJpY3NPblNuYXBzaG90ID0gbWV0cmljc1JvdXRlcy5vblNuYXBzaG90O1xuICAgIGxvZ2dlci5pbmZvKCdbV2ViVUldIE1ldHJpY3Mgcm91dGVzIG1vdW50ZWQgYXQgL2FwaS9tZXRyaWNzJyk7XG4gIH1cblxuICBpZiAob3B0aW9ucy5tZW1vcnlTaW5rKSB7XG4gICAgY29uc3QgaGVhbHRoUm91dGVyID0gY3JlYXRlSGVhbHRoUm91dGVzKHtcbiAgICAgIG1lbW9yeVNpbms6IG9wdGlvbnMubWVtb3J5U2luayxcbiAgICAgIG1ldHJpY3NTaW5rOiBvcHRpb25zLm1ldHJpY3NTaW5rLFxuICAgICAgbG9nQ2xpZW50Q291bnQ6IGxvZ1JvdXRlcyA/IGxvZ1JvdXRlcy5jbGllbnRDb3VudCA6ICgpID0+IDAsXG4gICAgICBtZXRyaWNzQ2xpZW50Q291bnQ6IG1ldHJpY3NSb3V0ZXMgPyBtZXRyaWNzUm91dGVzLmNsaWVudENvdW50IDogKCkgPT4gMCxcbiAgICB9KTtcbiAgICBhcHAudXNlKCcvYXBpJywgaGVhbHRoUm91dGVyKTtcbiAgfVxuXG4gIC8vIFNlcnZlIH4vLmRvbGxob3VzZS9wYWdlcy8gYXQgL3BhZ2VzLyDigJQgZGFzaGJvYXJkcywgZ2VuZXJhdGVkIGNvbnRlbnQsIHN0YWNrIHZpZXdzXG4gIGNvbnN0IHBhZ2VzRGlyID0gam9pbihkaXJuYW1lKG9wdGlvbnMucG9ydGZvbGlvRGlyKSwgJ3BhZ2VzJyk7XG4gIG1rZGlyKHBhZ2VzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KS5jYXRjaChlcnIgPT4ge1xuICAgIGxvZ2dlci53YXJuKGBbV2ViVUldIENvdWxkIG5vdCBjcmVhdGUgcGFnZXMgZGlyZWN0b3J5OiAkeyhlcnIgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gIH0pO1xuICBhcHAudXNlKCcvcGFnZXMnLCBleHByZXNzLnN0YXRpYyhwYWdlc0RpcikpO1xuXG4gIC8qKlxuICAgKiBHRVQgL2FwaS9wYWdlc1xuICAgKiBMaXN0cyBhdmFpbGFibGUgSFRNTCBwYWdlcyBpbiB+Ly5kb2xsaG91c2UvcGFnZXMvLlxuICAgKiBSZXR1cm5zIHBhZ2UgbmFtZXMgYW5kIHRoZWlyIFVSTHMgZm9yIHRoZSBtYW5hZ2VtZW50IGNvbnNvbGUuXG4gICAqL1xuICBhcHAuZ2V0KCcvYXBpL3BhZ2VzJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlYWRkaXIocGFnZXNEaXIpO1xuICAgICAgY29uc3QgcGFnZXMgPSBmaWxlc1xuICAgICAgICAuZmlsdGVyKGYgPT4gIWYuc3RhcnRzV2l0aCgnLicpICYmIEFMTE9XRURfUEFHRV9FWFRFTlNJT05TLmhhcyhleHRuYW1lKGYpKSlcbiAgICAgICAgLm1hcChmID0+ICh7IG5hbWU6IGYsIHVybDogYC9wYWdlcy8ke2Z9YCB9KSk7XG4gICAgICByZXMuanNvbih7IHBhZ2VzLCBkaXJlY3Rvcnk6IHBhZ2VzRGlyIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmVzLmpzb24oeyBwYWdlczogW10sIGRpcmVjdG9yeTogcGFnZXNEaXIgfSk7XG4gICAgfVxuICB9KTtcblxuICAvLyBBZGRpdGlvbmFsIHJvdXRlcnMgKGUuZy4sIHVuaWZpZWQgY29uc29sZSBpbmdlc3Qgcm91dGVzKSDigJQgbXVzdCBtb3VudCBiZWZvcmUgU1BBIGZhbGxiYWNrXG4gIG9wdGlvbnMuYWRkaXRpb25hbFJvdXRlcnM/LmZvckVhY2gocm91dGVyID0+IGFwcC51c2Uocm91dGVyKSk7XG5cbiAgLy8gU3RhdGljIGZyb250ZW5kIGZpbGVzXG4gIGNvbnN0IHB1YmxpY0RpciA9IGpvaW4oX19kaXJuYW1lLCAncHVibGljJyk7XG4gIGFwcC51c2UoZXhwcmVzcy5zdGF0aWMocHVibGljRGlyKSk7XG5cbiAgLy8gU1BBIGZhbGxiYWNrXG4gIGFwcC5nZXQoJy97KnBhdGh9JywgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSByZXEucGF0aC5ub3JtYWxpemUoJ05GQycpO1xuICAgIGlmIChub3JtYWxpemVkUGF0aC5zdGFydHNXaXRoKCcvYXBpLycpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwNCkuanNvbih7IGVycm9yOiBgQVBJIHJvdXRlIG5vdCBmb3VuZDogJHtub3JtYWxpemVkUGF0aH1gIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobm9ybWFsaXplZFBhdGguc3RhcnRzV2l0aCgnL3BhZ2VzLycpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwNCkuanNvbih7IGVycm9yOiBgUGFnZSBub3QgZm91bmQ6ICR7bm9ybWFsaXplZFBhdGh9YCB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcmVzLnNlbmRGaWxlKGpvaW4ocHVibGljRGlyLCAnaW5kZXguaHRtbCcpKTtcbiAgfSk7XG5cbiAgLy8gR2xvYmFsIGVycm9yIGhhbmRsZXIg4oCUIGNhdGNoIEV4cHJlc3MgZXJyb3JzIGFuZCByb3V0ZSB0byBsb2dnZXIgaW5zdGVhZCBvZiB0ZXJtaW5hbC5cbiAgLy8gV2l0aG91dCB0aGlzLCBFeHByZXNzIGR1bXBzIHN0YWNrIHRyYWNlcyB0byBzdGRlcnIgKHZpc2libGUgaW4gLS13ZWIgdGVybWluYWwpLlxuICAvLyBBbGwgZXJyb3JzIHN0aWxsIGFwcGVhciBpbiB0aGUgbWFuYWdlbWVudCBjb25zb2xlJ3MgTG9ncyB0YWIgdmlhIE1lbW9yeUxvZ1NpbmsuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgYXBwLnVzZSgoZXJyOiBFcnJvciwgX3JlcTogaW1wb3J0KCdleHByZXNzJykuUmVxdWVzdCwgcmVzOiBpbXBvcnQoJ2V4cHJlc3MnKS5SZXNwb25zZSwgX25leHQ6IGltcG9ydCgnZXhwcmVzcycpLk5leHRGdW5jdGlvbikgPT4ge1xuICAgIGNvbnN0IHN0YXR1cyA9IChlcnIgYXMgYW55KS5zdGF0dXMgfHwgKGVyciBhcyBhbnkpLnN0YXR1c0NvZGUgfHwgNTAwO1xuICAgIGxvZ2dlci53YXJuKGBbV2ViVUldICR7ZXJyLm5hbWV9OiAke2Vyci5tZXNzYWdlfWApO1xuICAgIGlmICghcmVzLmhlYWRlcnNTZW50KSB7XG4gICAgICByZXMuc3RhdHVzKHN0YXR1cykuanNvbih7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIEJpbmQgdG8gbG9jYWxob3N0IG9ubHkg4oCUIGhhbmRsZSBwb3J0IGNvbmZsaWN0cyBncmFjZWZ1bGx5XG4gIC8vIE5PVEU6IFVzZSBzdGRlcnIgZm9yIHRlcm1pbmFsIG91dHB1dCwgbm90IHN0ZG91dC4gSW4gTUNQIHN0ZGlvIG1vZGUsIHN0ZG91dFxuICAvLyBpcyByZXNlcnZlZCBmb3IgSlNPTi1SUEMgbWVzc2FnZXMg4oCUIGFueSBub24tSlNPTiBvdXRwdXQgY29ycnVwdHMgdGhlIHByb3RvY29sLlxuICAvLyBzdGRlcnIgaXMgc2FmZSBmb3IgaHVtYW4tcmVhZGFibGUgbWVzc2FnZXMgaW4gYm90aCBNQ1AgYW5kIHN0YW5kYWxvbmUgbW9kZXMuXG4gIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgY29uc3QgaHR0cFNlcnZlciA9IGFwcC5saXN0ZW4ocG9ydCwgJzEyNy4wLjAuMScsICgpID0+IHtcbiAgICAgIHNlcnZlclJ1bm5pbmcgPSB0cnVlO1xuICAgICAgc2VydmVyUG9ydCA9IHBvcnQ7XG4gICAgICBjb25zdCB1cmwgPSBgaHR0cDovLyR7Q09OU09MRV9IT1NUfToke3BvcnR9YDtcbiAgICAgIGNvbnN0IGZhbGxiYWNrVXJsID0gYGh0dHA6Ly8xMjcuMC4wLjE6JHtwb3J0fWA7XG4gICAgICBsb2dnZXIuaW5mbyhgW1dlYlVJXSBNYW5hZ2VtZW50IGNvbnNvbGUgcnVubmluZyBhdCAke3VybH1gKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYFxcbiAgRG9sbGhvdXNlTUNQIE1hbmFnZW1lbnQgQ29uc29sZVxcbiAgJHt1cmx9XFxuICAke2ZhbGxiYWNrVXJsfSAoZmFsbGJhY2spXFxuYCk7XG4gICAgICBjb25zb2xlLmVycm9yKGAgIFR5cGUgXCJxXCIgb3IgXCJxdWl0XCIgdG8gZXhpdC5cXG5gKTtcblxuICAgICAgaWYgKG9wdGlvbnMub3BlbkJyb3dzZXIpIHtcbiAgICAgICAgb3BlbkluQnJvd3Nlcih1cmwpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuICAgIGh0dHBTZXJ2ZXIub24oJ2Vycm9yJywgKGVycjogTm9kZUpTLkVycm5vRXhjZXB0aW9uKSA9PiB7XG4gICAgICBpZiAoZXJyLmNvZGUgPT09ICdFQUREUklOVVNFJykge1xuICAgICAgICBjb25zdCB1cmwgPSBgaHR0cDovLyR7Q09OU09MRV9IT1NUfToke3BvcnR9YDtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtXZWJVSV0gUG9ydCAke3BvcnR9IGFscmVhZHkgaW4gdXNlIOKAlCBvcGVuaW5nIGV4aXN0aW5nIGNvbnNvbGVgKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihgXFxuICBEb2xsaG91c2VNQ1AgTWFuYWdlbWVudCBDb25zb2xlIChleGlzdGluZyBpbnN0YW5jZSlcXG4gICR7dXJsfVxcbmApO1xuICAgICAgICBpZiAob3B0aW9ucy5vcGVuQnJvd3Nlcikge1xuICAgICAgICAgIG9wZW5JbkJyb3dzZXIodXJsKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBbV2ViVUldIEZhaWxlZCB0byBiaW5kIHBvcnQgJHtwb3J0fTogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTsgLy8gV2ViIGNvbnNvbGUgaXMgb3B0aW9uYWwg4oCUIGRvbid0IGJsb2NrIHN0YXJ0dXBcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBPcGVuIHRoZSBwb3J0Zm9saW8gYnJvd3NlciBmcm9tIHdpdGhpbiB0aGUgTUNQIHNlcnZlciBwcm9jZXNzLlxuICpcbiAqIFN0YXJ0cyB0aGUgd2ViIHNlcnZlciBpZiBub3QgYWxyZWFkeSBydW5uaW5nLCB0aGVuIG9wZW5zIHRoZSBzeXN0ZW1cbiAqIGJyb3dzZXIgdG8gdGhlIHBvcnRmb2xpbyBVSS4gUmV0dXJucyBhIHJlc3VsdCBvYmplY3QgaW5kaWNhdGluZ1xuICogd2hldGhlciB0aGUgc2VydmVyIHN0YXJ0ZWQgYW5kIHRoZSBicm93c2VyIG9wZW5lZCBzdWNjZXNzZnVsbHkuXG4gKlxuICogQ2FsbGVkIGJ5IHRoZSBgb3Blbl9wb3J0Zm9saW9fYnJvd3NlcmAgTUNQLUFRTCBvcGVyYXRpb24gKElzc3VlICM3NzQpLlxuICpcbiAqIEBwYXJhbSBwb3J0Zm9saW9EaXIgLSBQYXRoIHRvIHRoZSBwb3J0Zm9saW8gZGlyZWN0b3J5IChlLmcuLCB+Ly5kb2xsaG91c2UvcG9ydGZvbGlvKVxuICogQHBhcmFtIHBvcnQgLSBQb3J0IHRvIGJpbmQgdG8gKGRlZmF1bHQ6IDM5MzkpXG4gKiBAcmV0dXJucyBSZXN1bHQgd2l0aCBVUkwsIHNlcnZlciBzdGF0dXMsIGFuZCBicm93c2VyIG9wZW4gc3RhdHVzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvcGVuUG9ydGZvbGlvQnJvd3Nlcihwb3J0Zm9saW9EaXI6IHN0cmluZywgcG9ydD86IG51bWJlciwgbWNwQXFsSGFuZGxlcj86IE1DUEFRTEhhbmRsZXIsIHRhYj86IHN0cmluZywgdXJsUGFyYW1zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IFByb21pc2U8QnJvd3Nlck9wZW5SZXN1bHQ+IHtcbiAgY29uc3QgdGFyZ2V0UG9ydCA9IHBvcnQgfHwgREVGQVVMVF9QT1JUO1xuICBjb25zdCBiYXNlVXJsID0gYGh0dHA6Ly8ke0NPTlNPTEVfSE9TVH06JHt0YXJnZXRQb3J0fWA7XG5cbiAgLy8gQnVpbGQgVVJMIHdpdGggb3B0aW9uYWwgdGFiIGhhc2ggYW5kIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgLy8gRm9ybWF0OiBodHRwOi8vaG9zdDpwb3J0LyN0YWI/a2V5PXZhbHVlJmtleT12YWx1ZVxuICBsZXQgdXJsID0gYmFzZVVybDtcbiAgaWYgKHRhYikge1xuICAgIGNvbnN0IHFzID0gdXJsUGFyYW1zID8gbmV3IFVSTFNlYXJjaFBhcmFtcyh1cmxQYXJhbXMpLnRvU3RyaW5nKCkgOiAnJztcbiAgICB1cmwgPSBgJHtiYXNlVXJsfS8jJHt0YWJ9JHtxcyA/ICc/JyArIHFzIDogJyd9YDtcbiAgfSBlbHNlIGlmICh1cmxQYXJhbXMgJiYgT2JqZWN0LmtleXModXJsUGFyYW1zKS5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgcXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHVybFBhcmFtcykudG9TdHJpbmcoKTtcbiAgICB1cmwgPSBgJHtiYXNlVXJsfS8jcG9ydGZvbGlvPyR7cXN9YDtcbiAgfVxuXG4gIGNvbnN0IGFscmVhZHlSdW5uaW5nID0gc2VydmVyUnVubmluZztcblxuICBpZiAoIXNlcnZlclJ1bm5pbmcpIHtcbiAgICBhd2FpdCBzdGFydFdlYlNlcnZlcih7XG4gICAgICBwb3J0Zm9saW9EaXIsXG4gICAgICBwb3J0OiB0YXJnZXRQb3J0LFxuICAgICAgb3BlbkJyb3dzZXI6IGZhbHNlLCAvLyBXZSdsbCBvcGVuIG1hbnVhbGx5IGJlbG93IHRvIGNhcHR1cmUgdGhlIHJlc3VsdFxuICAgICAgbWNwQXFsSGFuZGxlcixcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IGJyb3dzZXJSZXN1bHQgPSBhd2FpdCBvcGVuSW5Ccm93c2VyKHVybCk7XG5cbiAgcmV0dXJuIHtcbiAgICB1cmwsXG4gICAgYWxyZWFkeVJ1bm5pbmcsXG4gICAgYnJvd3Nlck9wZW5lZDogYnJvd3NlclJlc3VsdC5zdWNjZXNzLFxuICAgIC4uLihicm93c2VyUmVzdWx0LmVycm9yID8geyB3YXJuaW5nOiBgQnJvd3NlciBjb3VsZCBub3QgYmUgb3BlbmVkIGF1dG9tYXRpY2FsbHk6ICR7YnJvd3NlclJlc3VsdC5lcnJvcn0uIE9wZW4gJHt1cmx9IG1hbnVhbGx5LmAgfSA6IHt9KSxcbiAgfTtcbn1cbiJdfQ==
|
|
492
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3dlYi9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ25ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDbkMsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxJQUFJLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdEUsT0FBTyxFQUFFLGVBQWUsRUFBd0IsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RSxPQUFPLEVBQUUsbUJBQW1CLEVBQTRCLE1BQU0sMkJBQTJCLENBQUM7QUFDMUYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUt2QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUV0RTs7Ozs7R0FLRztBQUNILE1BQU0sb0JB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Q0FBQyxFQUFFLE9BQU8sRUFBRSw4Q0FBOEMsYUFBYSxDQUFDLEtBQUssVUFBVSxHQUFHLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDeEksQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERvbGxob3VzZU1DUCBXZWIgVUkgU2VydmVyXG4gKlxuICogTGlnaHR3ZWlnaHQgRXhwcmVzcyBzZXJ2ZXIgZm9yIGJyb3dzaW5nIHBvcnRmb2xpbyBlbGVtZW50cyBpbiBhIGJyb3dzZXIuXG4gKiBCb3VuZCB0byAxMjcuMC4wLjEgb25seSAobG9jYWxob3N0KS4gUmVhZC1vbmx5IGZvciBWMS5cbiAqXG4gKiBDYW4gYmUgc3RhcnRlZCBzdGFuZGFsb25lIChgLS13ZWJgIGZsYWcpIG9yIGZyb20gd2l0aGluIHRoZSBNQ1Agc2VydmVyXG4gKiBwcm9jZXNzIHZpYSBgb3BlblBvcnRmb2xpb0Jyb3dzZXIoKWAuXG4gKlxuICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vRG9sbGhvdXNlTUNQL21jcC1zZXJ2ZXItdjItcmVmYWN0b3IvaXNzdWVzLzcwNFxuICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vRG9sbGhvdXNlTUNQL21jcC1zZXJ2ZXItdjItcmVmYWN0b3IvaXNzdWVzLzc3NFxuICovXG5cbmltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgam9pbiwgZGlybmFtZSwgZXh0bmFtZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHsgZXhlY0ZpbGUgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgcGxhdGZvcm0gfSBmcm9tICdub2RlOm9zJztcbmltcG9ydCB7IG1rZGlyLCByZWFkZGlyLCByZWFkRmlsZSBhcyByZWFkRmlsZUZzIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgeyBjcmVhdGVBcGlSb3V0ZXMsIGNyZWF0ZUdhdGV3YXlBcGlSb3V0ZXMgfSBmcm9tICcuL3JvdXRlcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dSb3V0ZXMsIHR5cGUgTG9nUm91dGVzUmVzdWx0IH0gZnJvbSAnLi9yb3V0ZXMvbG9nUm91dGVzLmpzJztcbmltcG9ydCB7IGNyZWF0ZU1ldHJpY3NSb3V0ZXMsIHR5cGUgTWV0cmljc1JvdXRlc1Jlc3VsdCB9IGZyb20gJy4vcm91dGVzL21ldHJpY3NSb3V0ZXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlSGVhbHRoUm91dGVzIH0gZnJvbSAnLi9yb3V0ZXMvaGVhbHRoUm91dGVzLmpzJztcbmltcG9ydCB7IGNyZWF0ZVNldHVwUm91dGVzIH0gZnJvbSAnLi9yb3V0ZXMvc2V0dXBSb3V0ZXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlVG90cFJvdXRlcyB9IGZyb20gJy4vcm91dGVzL3RvdHBSb3V0ZXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlVG9rZW5Sb3V0ZXMgfSBmcm9tICcuL3JvdXRlcy90b2tlblJvdXRlcy5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZW52IH0gZnJvbSAnLi4vY29uZmlnL2Vudi5qcyc7XG5pbXBvcnQgdHlwZSB7IE1DUEFRTEhhbmRsZXIgfSBmcm9tICcuLi9oYW5kbGVycy9tY3AtYXFsL01DUEFRTEhhbmRsZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBNZW1vcnlMb2dTaW5rIH0gZnJvbSAnLi4vbG9nZ2luZy9zaW5rcy9NZW1vcnlMb2dTaW5rLmpzJztcbmltcG9ydCB0eXBlIHsgTWVtb3J5TWV0cmljc1NpbmsgfSBmcm9tICcuLi9tZXRyaWNzL3NpbmtzL01lbW9yeU1ldHJpY3NTaW5rLmpzJztcbmltcG9ydCB0eXBlIHsgQ29uc29sZVRva2VuU3RvcmUgfSBmcm9tICcuL2NvbnNvbGUvY29uc29sZVRva2VuLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhNaWRkbGV3YXJlIH0gZnJvbSAnLi9taWRkbGV3YXJlL2F1dGhNaWRkbGV3YXJlLmpzJztcblxuLyoqXG4gKiBQdWJsaWMgcGF0aCBwcmVmaXhlcyB0aGF0IG5ldmVyIHJlcXVpcmUgYXV0aGVudGljYXRpb24gKCMxNzgwKS5cbiAqIFRoZXNlIGVuZHBvaW50cyByZXR1cm4gc2FmZSBtZXRhZGF0YSBvciBhY3QgYXMgaGVhbHRoIHByb2JlcyDigJQgcmVxdWlyaW5nXG4gKiB0b2tlbnMgb24gdGhlbSB3b3VsZCBicmVhayBtb25pdG9yaW5nIGFuZCBjbGllbnQgZGV0ZWN0aW9uIHdpdGhvdXQgYWRkaW5nXG4gKiByZWFsIHNlY3VyaXR5IHZhbHVlLlxuICovXG5jb25zdCBQVUJMSUNfUEFUSF9QUkVGSVhFUyA9IFtcbiAgJy9hcGkvaGVhbHRoJyxcbiAgJy9hcGkvc2V0dXAvdmVyc2lvbicsXG4gICcvYXBpL3NldHVwL21jcGInLFxuICAnL2FwaS9zZXR1cC9kZXRlY3QnLFxuICAnL2FwaS9zZXR1cC9saWNlbnNlJyxcbl07XG5cbi8qKiBQbGFjZWhvbGRlciBpbiBpbmRleC5odG1sIHRoYXQgaXMgcmVwbGFjZWQgd2l0aCB0aGUgY3VycmVudCBjb25zb2xlIHRva2VuLiAqL1xuY29uc3QgVE9LRU5fTUVUQV9QTEFDRUhPTERFUiA9ICd7e0NPTlNPTEVfVE9LRU59fSc7XG5cbmNvbnN0IF9fZGlybmFtZSA9IGRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcbi8qKlxuICogRGVmYXVsdCBwb3J0IGZvciBzdGFuZGFsb25lIGBzdGFydFdlYlNlcnZlcmAgY2FsbHMuIFJlYWRzIGZyb20gdGhlXG4gKiBgRE9MTEhPVVNFX1dFQl9DT05TT0xFX1BPUlRgIGVudiB2YXIgc28gdGhlcmUgaXMgYSBzaW5nbGUgc291cmNlIG9mXG4gKiB0cnV0aCAoc2VlIGBzcmMvY29uZmlnL2Vudi50c2ApLiBDYWxsZXJzIHBhc3NpbmcgYW4gZXhwbGljaXQgYHBvcnRgIGluXG4gKiBgV2ViU2VydmVyT3B0aW9uc2Agb3ZlcnJpZGUgdGhpcyBkZWZhdWx0LlxuICovXG5jb25zdCBERUZBVUxUX1BPUlQgPSBlbnYuRE9MTEhPVVNFX1dFQl9DT05TT0xFX1BPUlQ7XG5jb25zdCBDT05TT0xFX0hPU1QgPSAnZG9sbGhvdXNlLmxvY2FsaG9zdCc7XG5jb25zdCBBTExPV0VEX1BBR0VfRVhURU5TSU9OUyA9IG5ldyBTZXQoWycuaHRtbCcsICcuaHRtJ10pO1xuLyoqIE1heCBKU09OIGJvZHkgZm9yIHNldHVwIHJvdXRlcyAoaW5zdGFsbC9vcGVuLWNvbmZpZykuIEluZ2VzdCByb3V0ZXMgdXNlIHRoZWlyIG93biAxbWIgbGltaXQuICovXG5jb25zdCBTRVRVUF9CT0RZX0xJTUlUID0gJzFrYic7XG5cbi8qKiBUcmFjayB3aGV0aGVyIHRoZSB3ZWIgc2VydmVyIGlzIGFscmVhZHkgcnVubmluZyBpbi1wcm9jZXNzLiAqL1xubGV0IHNlcnZlclJ1bm5pbmcgPSBmYWxzZTtcbmxldCBzZXJ2ZXJQb3J0ID0gREVGQVVMVF9QT1JUO1xuLyoqIEFjdGl2ZSBIVFRQIHNlcnZlciBpbnN0YW5jZSDigJQgdHJhY2tlZCBzbyBfcmVzZXRTZXJ2ZXJTdGF0ZSBjYW4gY2xvc2UgaXQuICovXG5sZXQgYWN0aXZlSHR0cFNlcnZlcjogaW1wb3J0KCdub2RlOmh0dHAnKS5TZXJ2ZXIgfCBudWxsID0gbnVsbDtcbi8qKiBDYWNoZWQgdG9rZW4gc3RvcmUgZm9yIG9wZW5Qb3J0Zm9saW9Ccm93c2VyIOKAlCBwcmV2ZW50cyBkdXBsaWNhdGUgaW5zdGFuY2VzIG9uIHRoZSBzYW1lIGZpbGUuICovXG5sZXQgY2FjaGVkVG9rZW5TdG9yZTogQ29uc29sZVRva2VuU3RvcmUgfCBudWxsID0gbnVsbDtcblxuLyoqIENoZWNrIHdoZXRoZXIgdGhlIHdlYiBzZXJ2ZXIgaGFzIGJlZW4gc3RhcnRlZCBpbiB0aGlzIHByb2Nlc3MuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXZWJTZXJ2ZXJSdW5uaW5nKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VydmVyUnVubmluZztcbn1cblxuLyoqXG4gKiBSZXNldCBtb2R1bGUtbGV2ZWwgc2VydmVyIHN0YXRlLiBFeHBvcnRlZCBmb3IgdGVzdGluZyBvbmx5IOKAlFxuICogYWxsb3dzIHRlc3RzIHRvIGV4ZXJjaXNlIHN0YXJ0V2ViU2VydmVyL2JpbmRBbmRMaXN0ZW4gd2l0aG91dFxuICogaW50ZXJmZXJlbmNlIGZyb20gcHJpb3IgcnVucyBpbiB0aGUgc2FtZSBwcm9jZXNzLlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfcmVzZXRTZXJ2ZXJTdGF0ZSgpOiB2b2lkIHtcbiAgaWYgKGFjdGl2ZUh0dHBTZXJ2ZXIpIHtcbiAgICBhY3RpdmVIdHRwU2VydmVyLmNsb3NlKCk7XG4gICAgYWN0aXZlSHR0cFNlcnZlciA9IG51bGw7XG4gIH1cbiAgc2VydmVyUnVubmluZyA9IGZhbHNlO1xuICBzZXJ2ZXJQb3J0ID0gREVGQVVMVF9QT1JUO1xuICBjYWNoZWRUb2tlblN0b3JlID0gbnVsbDtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBzdGFydGluZyB0aGUgd2ViIHNlcnZlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTZXJ2ZXJPcHRpb25zIHtcbiAgLyoqIFBvcnQgdG8gYmluZCB0byAoZGVmYXVsdHMgdG8gYERPTExIT1VTRV9XRUJfQ09OU09MRV9QT1JUYCwgc2VlIGBzcmMvY29uZmlnL2Vudi50c2ApICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBQYXRoIHRvIHRoZSBwb3J0Zm9saW8gZGlyZWN0b3J5IChlLmcuLCB+Ly5kb2xsaG91c2UvcG9ydGZvbGlvKSAqL1xuICBwb3J0Zm9saW9EaXI6IHN0cmluZztcbiAgLyoqIE9wZW4gdGhlIGJyb3dzZXIgYXV0b21hdGljYWxseSBhZnRlciBzdGFydGluZyAoZGVmYXVsdDogZmFsc2UpICovXG4gIG9wZW5Ccm93c2VyPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIE1DUEFRTEhhbmRsZXIgZm9yIHJvdXRpbmcgdGhyb3VnaCB0aGUgTUNQLUFRTCBwaXBlbGluZS5cbiAgICogV2hlbiBwcm92aWRlZCwgQVBJIHJvdXRlcyB1c2UgdGhlIGdhdGV3YXkgKHZhbGlkYXRlZCwgY2FjaGVkLCBnYXRla2VlcGVyLWNoZWNrZWQpLlxuICAgKiBXaGVuIGFic2VudCwgZmFsbHMgYmFjayB0byBkaXJlY3QgZmlsZXN5c3RlbSBhY2Nlc3MgKGxlZ2FjeSBiZWhhdmlvcikuXG4gICAqIElzc3VlICM3OTY6IFdlYiBNQ1AtQVFMIEdhdGV3YXkuXG4gICAqL1xuICBtY3BBcWxIYW5kbGVyPzogTUNQQVFMSGFuZGxlcjtcbiAgLyoqIE1lbW9yeUxvZ1NpbmsgZm9yIGxvZyByb3V0ZXMgKG9wdGlvbmFsIOKAlCBsb2dzIHRhYiBkaXNhYmxlZCBpZiBub3QgcHJvdmlkZWQpICovXG4gIG1lbW9yeVNpbms/OiBNZW1vcnlMb2dTaW5rO1xuICAvKiogTWVtb3J5TWV0cmljc1NpbmsgZm9yIG1ldHJpY3Mgcm91dGVzIChvcHRpb25hbCDigJQgbWV0cmljcyB0YWIgZGlzYWJsZWQgaWYgbm90IHByb3ZpZGVkKSAqL1xuICBtZXRyaWNzU2luaz86IE1lbW9yeU1ldHJpY3NTaW5rO1xuICAvKiogQWRkaXRpb25hbCByb3V0ZXJzIHRvIG1vdW50IGJlZm9yZSB0aGUgU1BBIGZhbGxiYWNrIChlLmcuLCBpbmdlc3Qgcm91dGVzKSAqL1xuICBhZGRpdGlvbmFsUm91dGVycz86IGltcG9ydCgnZXhwcmVzcycpLlJvdXRlcltdO1xuICAvKipcbiAgICogQ29uc29sZSB0b2tlbiBzdG9yZSAoIzE3ODApLiBXaGVuIHByb3ZpZGVkLCB0aGUgc2VydmVyIHdpbGw6XG4gICAqICAgMS4gTW91bnQgQmVhcmVyIHRva2VuIGF1dGggbWlkZGxld2FyZSBiZWZvcmUgcHJvdGVjdGVkIHJvdXRlcnMuXG4gICAqICAgMi4gSW5qZWN0IHRoZSBwcmltYXJ5IHRva2VuIGludG8gaW5kZXguaHRtbCBzbyB0aGUgYnJvd3NlciBjbGllbnRcbiAgICogICAgICBjYW4gYXR0YWNoIGl0IHRvIGZldGNoIGNhbGxzIGFuZCBFdmVudFNvdXJjZSBVUkxzLlxuICAgKiAgIDMuIEFwcGVuZCB0aGUgdG9rZW4gZmlsZSBsb2NhdGlvbiB0byB0aGUgc3RhcnR1cCBiYW5uZXIuXG4gICAqIEF1dGggZW5mb3JjZW1lbnQgaXMgc3RpbGwgZ2F0ZWQgb24gRE9MTEhPVVNFX1dFQl9BVVRIX0VOQUJMRUQg4oCUIHRoZVxuICAgKiBtaWRkbGV3YXJlIGlzIGEgcGFzcy10aHJvdWdoIHdoZW4gdGhlIGZsYWcgaXMgZmFsc2UgKHRoZSBQaGFzZSAxIGRlZmF1bHQpLlxuICAgKi9cbiAgdG9rZW5TdG9yZT86IENvbnNvbGVUb2tlblN0b3JlO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBhdHRlbXB0aW5nIHRvIGJpbmQgdGhlIEhUVFAgc2VydmVyIHRvIGEgcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCaW5kUmVzdWx0IHtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgZXJyb3I/OiAnRUFERFJJTlVTRScgfCAnT1RIRVInO1xuICBkZXRhaWw/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIHN0YXJ0aW5nIHRoZSB3ZWIgc2VydmVyLCBpbmNsdWRpbmcgaG9va3MgZm9yIERJIHdpcmluZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTZXJ2ZXJSZXN1bHQge1xuICAvKiogRXhwcmVzcyBhcHAgaW5zdGFuY2Ug4oCUIGZvciBtb3VudGluZyBhZGRpdGlvbmFsIHJvdXRlcyAoZS5nLiwgaW5nZXN0IHJvdXRlcykgKi9cbiAgYXBwPzogaW1wb3J0KCdleHByZXNzJykuRXhwcmVzcztcbiAgLyoqIExvZyBicm9hZGNhc3QgZnVuY3Rpb24g4oCUIGNhbGwgd2l0aCBlYWNoIGVudHJ5IHRvIHB1c2ggdG8gU1NFIGNsaWVudHMgKi9cbiAgbG9nQnJvYWRjYXN0PzogKGVudHJ5OiBpbXBvcnQoJy4uL2xvZ2dpbmcvdHlwZXMuanMnKS5VbmlmaWVkTG9nRW50cnkpID0+IHZvaWQ7XG4gIC8qKiBNZXRyaWNzIHNuYXBzaG90IGZ1bmN0aW9uIOKAlCBjYWxsIHdpdGggZWFjaCBzbmFwc2hvdCB0byBwdXNoIHRvIFNTRSBjbGllbnRzICovXG4gIG1ldHJpY3NPblNuYXBzaG90PzogKHNuYXBzaG90OiBpbXBvcnQoJy4uL21ldHJpY3MvdHlwZXMuanMnKS5NZXRyaWNTbmFwc2hvdCkgPT4gdm9pZDtcbiAgLyoqIFJlc3VsdCBvZiB0aGUgcG9ydCBiaW5kaW5nIGF0dGVtcHQgKi9cbiAgYmluZFJlc3VsdD86IEJpbmRSZXN1bHQ7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGF0dGVtcHRpbmcgdG8gb3BlbiB0aGUgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCcm93c2VyT3BlblJlc3VsdCB7XG4gIC8qKiBUaGUgVVJMIHRoZSBzZXJ2ZXIgaXMgcnVubmluZyBvbiAqL1xuICB1cmw6IHN0cmluZztcbiAgLyoqIFdoZXRoZXIgdGhlIHNlcnZlciB3YXMgYWxyZWFkeSBydW5uaW5nICh0cnVlKSBvciBqdXN0IHN0YXJ0ZWQgKGZhbHNlKSAqL1xuICBhbHJlYWR5UnVubmluZzogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhlIGJyb3dzZXIgd2FzIHN1Y2Nlc3NmdWxseSBvcGVuZWQgKi9cbiAgYnJvd3Nlck9wZW5lZDogYm9vbGVhbjtcbiAgLyoqIFdhcm5pbmcgbWVzc2FnZSBpZiB0aGUgYnJvd3NlciBjb3VsZCBub3QgYmUgb3BlbmVkICovXG4gIHdhcm5pbmc/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3BlbiBhIFVSTCBpbiB0aGUgc3lzdGVtJ3MgZGVmYXVsdCBicm93c2VyLlxuICpcbiAqIFBsYXRmb3JtLWF3YXJlOlxuICogLSBtYWNPUzogYG9wZW5gXG4gKiAtIExpbnV4OiBgeGRnLW9wZW5gXG4gKiAtIFdpbmRvd3M6IGBzdGFydGBcbiAqXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCB0byBvcGVuXG4gKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdHJ1ZSBpZiB0aGUgYnJvd3NlciBvcGVuZWQsIGZhbHNlIHdpdGggZXJyb3IgbWVzc2FnZSBpZiBub3RcbiAqL1xuZnVuY3Rpb24gb3BlbkluQnJvd3Nlcih1cmw6IHN0cmluZyk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcj86IHN0cmluZyB9PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IHBsYXQgPSBwbGF0Zm9ybSgpO1xuICAgIGNvbnN0IGNtZCA9IHBsYXQgPT09ICdkYXJ3aW4nID8gJ29wZW4nXG4gICAgICA6IHBsYXQgPT09ICd3aW4zMicgPyAnc3RhcnQnXG4gICAgICA6ICd4ZGctb3Blbic7XG5cbiAgICAvLyBTZWN1cml0eTogdXNlIGV4ZWNGaWxlIHdpdGggVVJMIGFzIGFyZ3VtZW50IGFycmF5LCBub3Qgc3RyaW5nIGludGVycG9sYXRpb25cbiAgICBjb25zdCB1cmxTdHIgPSBTdHJpbmcodXJsKTtcbiAgICAvLyBBY2NlcHQgbG9jYWxob3N0LCAxMjcuMC4wLjEsIGFuZCAqLmxvY2FsaG9zdCBzdWJkb21haW5zIChSRkMgNjc2MSlcbiAgICBpZiAoIS9eaHR0cHM/OlxcL1xcLyhsb2NhbGhvc3R8MTI3XFwuMFxcLjBcXC4xfFtcXHctXStcXC5sb2NhbGhvc3QpWzovXS8udGVzdCh1cmxTdHIpKSB7XG4gICAgICByZXNvbHZlKHsgc3VjY2VzczogZmFsc2UsIGVycm9yOiAnVVJMIG11c3QgYmUgYSBsb2NhbGhvc3QgSFRUUCBVUkwnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBleGVjRmlsZShjbWQsIFt1cmxTdHJdLCAoZXJyKSA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbV2ViVUldIENvdWxkIG5vdCBhdXRvLW9wZW4gYnJvd3NlcjogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgICAgcmVzb2x2ZSh7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogZXJyLm1lc3NhZ2UgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKHsgc3VjY2VzczogdHJ1ZSB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogU3RhcnQgdGhlIHBvcnRmb2xpbyB3ZWIgc2VydmVyLlxuICpcbiAqIEJpbmRzIHRvIDEyNy4wLjAuMSBvbmx5IChsb2NhbGhvc3QpLiBTZXJ2ZXMgdGhlIHBvcnRmb2xpbyBicm93c2VyXG4gKiBmcm9udGVuZCBhbmQgQVBJIHJvdXRlcyBmb3IgcmVhZGluZyBlbGVtZW50cy5cbiAqXG4gKiBJZGVtcG90ZW50OiBpZiB0aGUgc2VydmVyIGlzIGFscmVhZHkgcnVubmluZywgb3B0aW9uYWxseSBvcGVucyB0aGVcbiAqIGJyb3dzZXIgd2l0aG91dCBzdGFydGluZyBhIHNlY29uZCBpbnN0YW5jZS5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFNlcnZlciBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBIb29rcyBmb3IgREkgd2lyaW5nIChsb2cgYnJvYWRjYXN0LCBtZXRyaWNzIG9uU25hcHNob3QpXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFdlYlNlcnZlcihvcHRpb25zOiBXZWJTZXJ2ZXJPcHRpb25zKTogUHJvbWlzZTxXZWJTZXJ2ZXJSZXN1bHQ+IHtcbiAgY29uc3QgcG9ydCA9IG9wdGlvbnMucG9ydCB8fCBERUZBVUxUX1BPUlQ7XG4gIGNvbnN0IHJlc3VsdDogV2ViU2VydmVyUmVzdWx0ID0ge307XG5cbiAgaWYgKHNlcnZlclJ1bm5pbmcpIHtcbiAgICBpZiAob3B0aW9ucy5vcGVuQnJvd3Nlcikge1xuICAgICAgb3BlbkluQnJvd3NlcihgaHR0cDovLyR7Q09OU09MRV9IT1NUfToke3NlcnZlclBvcnR9YCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gIHJlc3VsdC5hcHAgPSBhcHA7XG4gIGFwcC5kaXNhYmxlKCd4LXBvd2VyZWQtYnknKTtcblxuICAvLyBTZWN1cml0eSBoZWFkZXJzXG4gIGFwcC51c2UoKF9yZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtQ29udGVudC1UeXBlLU9wdGlvbnMnLCAnbm9zbmlmZicpO1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtRnJhbWUtT3B0aW9ucycsICdERU5ZJyk7XG4gICAgcmVzLnNldEhlYWRlcignWC1YU1MtUHJvdGVjdGlvbicsICcxOyBtb2RlPWJsb2NrJyk7XG4gICAgcmVzLnNldEhlYWRlcignUmVmZXJyZXItUG9saWN5JywgJ25vLXJlZmVycmVyJyk7XG4gICAgcmVzLnNldEhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgYGh0dHA6Ly8ke0NPTlNPTEVfSE9TVH06JHtwb3J0fWApO1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtU2VjdXJpdHktUG9saWN5JywgW1xuICAgICAgXCJkZWZhdWx0LXNyYyAnc2VsZidcIixcbiAgICAgIFwic2NyaXB0LXNyYyAnc2VsZicgY2RuLmpzZGVsaXZyLm5ldCBjZG5qcy5jbG91ZGZsYXJlLmNvbVwiLFxuICAgICAgXCJzdHlsZS1zcmMgJ3NlbGYnICd1bnNhZmUtaW5saW5lJyBjZG5qcy5jbG91ZGZsYXJlLmNvbSBjZG4uanNkZWxpdnIubmV0XCIsXG4gICAgICBcImltZy1zcmMgJ3NlbGYnIGRhdGE6XCIsXG4gICAgICBcImNvbm5lY3Qtc3JjICdzZWxmJyByYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tXCIsXG4gICAgICBcImZvbnQtc3JjICdzZWxmJ1wiLFxuICAgIF0uam9pbignOyAnKSk7XG4gICAgbmV4dCgpO1xuICB9KTtcblxuICAvLyBDb25zb2xlIHRva2VuIGF1dGhlbnRpY2F0aW9uIG1pZGRsZXdhcmUgKCMxNzgwKS4gTW91bnRlZCBiZWZvcmUgYW55IC9hcGlcbiAgLy8gcm91dGVzIHNvIGV2ZXJ5IHByb3RlY3RlZCBlbmRwb2ludCBnb2VzIHRocm91Z2ggaXQuIFdoZW4gdGhlIGZlYXR1cmUgZmxhZ1xuICAvLyBET0xMSE9VU0VfV0VCX0FVVEhfRU5BQkxFRCBpcyBmYWxzZSAoUGhhc2UgMSBkZWZhdWx0KSB0aGlzIGlzIGEgcGFzcy10aHJvdWdoLlxuICAvLyBQdWJsaWMgZW5kcG9pbnRzIGluIFBVQkxJQ19QQVRIX1BSRUZJWEVTIGFsd2F5cyBieXBhc3MgYXV0aCByZWdhcmRsZXNzIG9mIGZsYWcuXG4gIGlmIChvcHRpb25zLnRva2VuU3RvcmUpIHtcbiAgICBjb25zdCBhdXRoTWlkZGxld2FyZSA9IGNyZWF0ZUF1dGhNaWRkbGV3YXJlKHtcbiAgICAgIHN0b3JlOiBvcHRpb25zLnRva2VuU3RvcmUsXG4gICAgICBlbmFibGVkOiBlbnYuRE9MTEhPVVNFX1dFQl9BVVRIX0VOQUJMRUQsXG4gICAgICBwdWJsaWNQYXRoUHJlZml4ZXM6IFBVQkxJQ19QQVRIX1BSRUZJWEVTLFxuICAgICAgbGFiZWw6ICdhcGknLFxuICAgIH0pO1xuICAgIGFwcC51c2UoJy9hcGknLCBhdXRoTWlkZGxld2FyZSk7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICBgW1dlYlVJXSBDb25zb2xlIGF1dGggbWlkZGxld2FyZSBtb3VudGVkICR7ZW52LkRPTExIT1VTRV9XRUJfQVVUSF9FTkFCTEVEID8gJ0VORk9SQ0lORycgOiAncGFzcy10aHJvdWdoIChmbGFnIG9mZiknfWAsXG4gICAgKTtcblxuICAgIC8vIFRPVFAgZW5yb2xsbWVudCByb3V0ZXMgKCMxNzk0KS4gTW91bnRlZCBBRlRFUiB0aGUgL2FwaSBhdXRoIG1pZGRsZXdhcmVcbiAgICAvLyBiZWNhdXNlIHRoZSByb3V0ZXIgYWRkcyBpdHMgb3duIGFsd2F5cy1vbiBhdXRoIGd1YXJkIOKAlCB0aGUgZ2xvYmFsIGF1dGhcbiAgICAvLyBtaWRkbGV3YXJlIGF0IC9hcGkgaXMgYSBwYXNzLXRocm91Z2ggZHVyaW5nIFBoYXNlIDEgcm9sbG91dCwgYnV0IHRoZVxuICAgIC8vIFRPVFAgcm91dGVyIGVuZm9yY2VzIHJlZ2FyZGxlc3Mgb2YgRE9MTEhPVVNFX1dFQl9BVVRIX0VOQUJMRUQgc28gYW5cbiAgICAvLyBhdHRhY2tlciB3aXRoIGxvY2FsIHBvcnQgYWNjZXNzIGNhbm5vdCBwcmUtZW5yb2xsIGEgc2Vjb25kIGZhY3RvciBhbmRcbiAgICAvLyBsb2NrIHRoZSBsZWdpdGltYXRlIHVzZXIgb3V0LlxuICAgIGFwcC51c2UoJy9hcGkvY29uc29sZS90b3RwJywgY3JlYXRlVG90cFJvdXRlcyh7IHN0b3JlOiBvcHRpb25zLnRva2VuU3RvcmUgfSkpO1xuICAgIGxvZ2dlci5pbmZvKCdbV2ViVUldIFRPVFAgcm91dGVzIG1vdW50ZWQgYXQgL2FwaS9jb25zb2xlL3RvdHAgKGFsd2F5cy1vbiBhdXRoKScpO1xuXG4gICAgLy8gVG9rZW4gbWFuYWdlbWVudCByb3V0ZXMgKCMxNzk1KS4gTW91bnRlZCBhbG9uZ3NpZGUgdGhlIFRPVFAgcm91dGVyIHdpdGhcbiAgICAvLyB0aGUgc2FtZSBhbHdheXMtb24gYXV0aCBwYXR0ZXJuLiBDdXJyZW50bHkgaG9zdHMgdGhlIHJvdGF0aW9uIGVuZHBvaW50O1xuICAgIC8vIGZ1dHVyZSB0b2tlbiBtYW5hZ2VtZW50IG9wZXJhdGlvbnMgKGxpc3QsIHJldm9rZSkgZ28gaGVyZSB0b28uXG4gICAgYXBwLnVzZSgnL2FwaS9jb25zb2xlL3Rva2VuJywgY3JlYXRlVG9rZW5Sb3V0ZXMoeyBzdG9yZTogb3B0aW9ucy50b2tlblN0b3JlIH0pKTtcbiAgICBsb2dnZXIuaW5mbygnW1dlYlVJXSBUb2tlbiByb3V0ZXMgbW91bnRlZCBhdCAvYXBpL2NvbnNvbGUvdG9rZW4gKGFsd2F5cy1vbiBhdXRoKScpO1xuICB9XG5cbiAgLy8gU2V0dXAgcm91dGVzOiBhdXRvLWluc3RhbGwgRG9sbGhvdXNlTUNQIHRvIE1DUCBjbGllbnRzIChtb3VudCBCRUZPUkUgQVBJIHJvdXRlcylcbiAgLy8gQm9keSBsaW1pdCBzY29wZWQgdG8gc2V0dXAgcm91dGVzIG9ubHkg4oCUIGluZ2VzdCByb3V0ZXMgbmVlZCAxbWIgZm9yIGZvbGxvd2VyIGxvZyBmb3J3YXJkaW5nXG4gIGNvbnN0IHNldHVwSnNvblBhcnNlciA9IGV4cHJlc3MuanNvbih7IGxpbWl0OiBTRVRVUF9CT0RZX0xJTUlULCB0eXBlOiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gIGNvbnN0IHsgaW5zdGFsbEhhbmRsZXIsIG9wZW5Db25maWdIYW5kbGVyLCB2ZXJzaW9uSGFuZGxlciwgbWNwYlJlZGlyZWN0SGFuZGxlciwgZGV0ZWN0SGFuZGxlciwgZ2V0TGljZW5zZUhhbmRsZXIsIHNldExpY2Vuc2VIYW5kbGVyLCB2ZXJpZnlMaWNlbnNlSGFuZGxlciwgcmVzZW5kVmVyaWZpY2F0aW9uSGFuZGxlciB9ID0gY3JlYXRlU2V0dXBSb3V0ZXMoKTtcbiAgYXBwLnBvc3QoJy9hcGkvc2V0dXAvaW5zdGFsbCcsIHNldHVwSnNvblBhcnNlciwgaW5zdGFsbEhhbmRsZXIpO1xuICBhcHAucG9zdCgnL2FwaS9zZXR1cC9vcGVuLWNvbmZpZycsIHNldHVwSnNvblBhcnNlciwgb3BlbkNvbmZpZ0hhbmRsZXIpO1xuICBhcHAuZ2V0KCcvYXBpL3NldHVwL3ZlcnNpb24nLCB2ZXJzaW9uSGFuZGxlcik7XG4gIGFwcC5nZXQoJy9hcGkvc2V0dXAvbWNwYicsIG1jcGJSZWRpcmVjdEhhbmRsZXIpO1xuICBhcHAuZ2V0KCcvYXBpL3NldHVwL2RldGVjdCcsIGRldGVjdEhhbmRsZXIpO1xuICBhcHAuZ2V0KCcvYXBpL3NldHVwL2xpY2Vuc2UnLCBnZXRMaWNlbnNlSGFuZGxlcik7XG4gIGFwcC5wb3N0KCcvYXBpL3NldHVwL2xpY2Vuc2UnLCBzZXR1cEpzb25QYXJzZXIsIHNldExpY2Vuc2VIYW5kbGVyKTtcbiAgYXBwLnBvc3QoJy9hcGkvc2V0dXAvbGljZW5zZS92ZXJpZnknLCBzZXR1cEpzb25QYXJzZXIsIHZlcmlmeUxpY2Vuc2VIYW5kbGVyKTtcbiAgYXBwLnBvc3QoJy9hcGkvc2V0dXAvbGljZW5zZS9yZXNlbmQnLCBzZXR1cEpzb25QYXJzZXIsIHJlc2VuZFZlcmlmaWNhdGlvbkhhbmRsZXIpO1xuICBsb2dnZXIuaW5mbygnW1dlYlVJXSBTZXR1cCByb3V0ZXMgbW91bnRlZCBhdCAvYXBpL3NldHVwJyk7XG5cbiAgLy8gQVBJIHJvdXRlcyDigJQgdXNlIE1DUC1BUUwgZ2F0ZXdheSB3aGVuIGhhbmRsZXIgaXMgYXZhaWxhYmxlIChJc3N1ZSAjNzk2KVxuICBpZiAob3B0aW9ucy5tY3BBcWxIYW5kbGVyKSB7XG4gICAgYXBwLnVzZSgnL2FwaScsIGNyZWF0ZUdhdGV3YXlBcGlSb3V0ZXMob3B0aW9ucy5tY3BBcWxIYW5kbGVyLCBvcHRpb25zLnBvcnRmb2xpb0RpcikpO1xuXG4gICAgLy8gUGVybWlzc2lvbiBldmFsdWF0aW9uIHJvdXRlcyAoUE9TVCAvZXZhbHVhdGVfcGVybWlzc2lvbiwgR0VUIC9wZXJtaXNzaW9ucy9zdGF0dXMpXG4gICAgY29uc3QgeyByZWdpc3RlclBlcm1pc3Npb25Sb3V0ZXMgfSA9IGF3YWl0IGltcG9ydCgnLi9yb3V0ZXMvcGVybWlzc2lvblJvdXRlcy5qcycpO1xuICAgIGNvbnN0IHBlcm1Sb3V0ZXIgPSAoYXdhaXQgaW1wb3J0KCdleHByZXNzJykpLlJvdXRlcigpO1xuICAgIHJlZ2lzdGVyUGVybWlzc2lvblJvdXRlcyhwZXJtUm91dGVyLCBvcHRpb25zLm1jcEFxbEhhbmRsZXIpO1xuICAgIGFwcC51c2UoJy9hcGknLCBwZXJtUm91dGVyKTtcblxuICAgIGxvZ2dlci5pbmZvKCdbV2ViVUldIEFQSSByb3V0ZXMgdXNpbmcgTUNQLUFRTCBHYXRld2F5ICsgcGVybWlzc2lvbiByb3V0ZXMnKTtcbiAgfSBlbHNlIHtcbiAgICBhcHAudXNlKCcvYXBpJywgY3JlYXRlQXBpUm91dGVzKG9wdGlvbnMucG9ydGZvbGlvRGlyKSk7XG4gICAgbG9nZ2VyLndhcm4oJ1tXZWJVSV0gQVBJIHJvdXRlcyB1c2luZyBkaXJlY3QgZmlsZXN5c3RlbSBhY2Nlc3MgKG5vIE1DUC1BUUwgaGFuZGxlciBhdmFpbGFibGUpJyk7XG4gIH1cblxuICAvLyBDb25zb2xlIHJvdXRlczogbG9ncywgbWV0cmljcywgaGVhbHRoIOKAlCBleHRyYWN0ZWQgdG8ga2VlcCBjb2duaXRpdmVcbiAgLy8gY29tcGxleGl0eSBvZiBzdGFydFdlYlNlcnZlciBtYW5hZ2VhYmxlLlxuICBtb3VudENvbnNvbGVSb3V0ZXMoYXBwLCBvcHRpb25zLCByZXN1bHQpO1xuXG4gIC8vIFNlcnZlIH4vLmRvbGxob3VzZS9wYWdlcy8gYXQgL3BhZ2VzLyDigJQgZGFzaGJvYXJkcywgZ2VuZXJhdGVkIGNvbnRlbnQsIHN0YWNrIHZpZXdzXG4gIGNvbnN0IHBhZ2VzRGlyID0gam9pbihkaXJuYW1lKG9wdGlvbnMucG9ydGZvbGlvRGlyKSwgJ3BhZ2VzJyk7XG4gIG1rZGlyKHBhZ2VzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KS5jYXRjaChlcnIgPT4ge1xuICAgIGxvZ2dlci53YXJuKGBbV2ViVUldIENvdWxkIG5vdCBjcmVhdGUgcGFnZXMgZGlyZWN0b3J5OiAkeyhlcnIgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gIH0pO1xuICBhcHAudXNlKCcvcGFnZXMnLCBleHByZXNzLnN0YXRpYyhwYWdlc0RpcikpO1xuXG4gIC8qKlxuICAgKiBHRVQgL2FwaS9wYWdlc1xuICAgKiBMaXN0cyBhdmFpbGFibGUgSFRNTCBwYWdlcyBpbiB+Ly5kb2xsaG91c2UvcGFnZXMvLlxuICAgKiBSZXR1cm5zIHBhZ2UgbmFtZXMgYW5kIHRoZWlyIFVSTHMgZm9yIHRoZSBtYW5hZ2VtZW50IGNvbnNvbGUuXG4gICAqL1xuICBhcHAuZ2V0KCcvYXBpL3BhZ2VzJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlYWRkaXIocGFnZXNEaXIpO1xuICAgICAgY29uc3QgcGFnZXMgPSBmaWxlc1xuICAgICAgICAuZmlsdGVyKGYgPT4gIWYuc3RhcnRzV2l0aCgnLicpICYmIEFMTE9XRURfUEFHRV9FWFRFTlNJT05TLmhhcyhleHRuYW1lKGYpKSlcbiAgICAgICAgLm1hcChmID0+ICh7IG5hbWU6IGYsIHVybDogYC9wYWdlcy8ke2Z9YCB9KSk7XG4gICAgICByZXMuanNvbih7IHBhZ2VzLCBkaXJlY3Rvcnk6IHBhZ2VzRGlyIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmVzLmpzb24oeyBwYWdlczogW10sIGRpcmVjdG9yeTogcGFnZXNEaXIgfSk7XG4gICAgfVxuICB9KTtcblxuICAvLyBBZGRpdGlvbmFsIHJvdXRlcnMgKGUuZy4sIHVuaWZpZWQgY29uc29sZSBpbmdlc3Qgcm91dGVzKSDigJQgbXVzdCBtb3VudCBiZWZvcmUgU1BBIGZhbGxiYWNrXG4gIG9wdGlvbnMuYWRkaXRpb25hbFJvdXRlcnM/LmZvckVhY2gocm91dGVyID0+IGFwcC51c2Uocm91dGVyKSk7XG5cbiAgLy8gU3RhdGljIGZyb250ZW5kIGZpbGVzXG4gIGNvbnN0IHB1YmxpY0RpciA9IGpvaW4oX19kaXJuYW1lLCAncHVibGljJyk7XG4gIC8vIFNlcnZlIHN0YXRpYyBhc3NldHMgYnV0IHNraXAgaW5kZXguaHRtbCDigJQgdGhlIFNQQSBmYWxsYmFjayBiZWxvd1xuICAvLyBoYW5kbGVzIGl0IHdpdGggdG9rZW4gaW5qZWN0aW9uIChyZXBsYWNlcyB7e0NPTlNPTEVfVE9LRU59fSBpbiB0aGVcbiAgLy8gbWV0YSB0YWcpLiBXaXRob3V0IHRoaXMsIGV4cHJlc3Muc3RhdGljIHNlcnZlcyB0aGUgcmF3IHRlbXBsYXRlXG4gIC8vIGFuZCB0aGUgYnJvd3NlciBuZXZlciBnZXRzIHRoZSBhdXRoIHRva2VuICgjMTc4MCkuXG4gIGNvbnN0IGlzRGVidWcgPSBCb29sZWFuKHByb2Nlc3MuZW52LkRPTExIT1VTRV9ERUJVRyB8fCBwcm9jZXNzLmVudi5FTkFCTEVfREVCVUcpO1xuICBhcHAudXNlKGV4cHJlc3Muc3RhdGljKHB1YmxpY0Rpciwge1xuICAgIGluZGV4OiBmYWxzZSxcbiAgICAvLyBJbiBkZWJ1ZyBtb2RlLCBkaXNhYmxlIGNhY2hpbmcgb24gYWxsIHN0YXRpYyBhc3NldHMgKEpTLCBDU1MpIHNvXG4gICAgLy8gVUkgY2hhbmdlcyBhcmUgcGlja2VkIHVwIG9uIG5vcm1hbCByZWxvYWQgd2l0aG91dCBDbWQrU2hpZnQrUi5cbiAgICAuLi4oaXNEZWJ1ZyA/IHsgZXRhZzogZmFsc2UsIGxhc3RNb2RpZmllZDogZmFsc2UsIG1heEFnZTogMCB9IDoge30pLFxuICB9KSk7XG5cbiAgLy8gU1BBIGZhbGxiYWNrIHdpdGggY29uc29sZSB0b2tlbiBpbmplY3Rpb24gKCMxNzgwKS5cbiAgLy8gUmVhZHMgaW5kZXguaHRtbCBvbiBmaXJzdCByZXF1ZXN0LCBzdWJzdGl0dXRlcyB0aGUge3tDT05TT0xFX1RPS0VOfX0gcGxhY2Vob2xkZXJcbiAgLy8gd2l0aCB0aGUgY3VycmVudCB0b2tlbiB2YWx1ZSwgYW5kIGNhY2hlcyB0aGUgcmVuZGVyZWQgc3RyaW5nLiBUaGUgY2FjaGUgaXNcbiAgLy8gYXV0by1pbnZhbGlkYXRlZCB3aGVuIHRoZSBwcmltYXJ5IHRva2VuIGNoYW5nZXMgKHJvdGF0aW9uKSwgc28gYSBwYWdlIHJlbG9hZFxuICAvLyBhZnRlciByb3RhdGlvbiBwaWNrcyB1cCB0aGUgbmV3IHRva2VuIHdpdGhvdXQgYSBzZXJ2ZXIgcmVzdGFydC5cbiAgbGV0IGNhY2hlZEluZGV4SHRtbDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGxldCBjYWNoZWRUb2tlblZhbHVlOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgY29uc3QgaW5kZXhIdG1sUGF0aCA9IGpvaW4ocHVibGljRGlyLCAnaW5kZXguaHRtbCcpO1xuXG4gIGNvbnN0IHJlbmRlckluZGV4SHRtbCA9IGFzeW5jICgpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgIGNvbnN0IHRva2VuVmFsdWUgPSBvcHRpb25zLnRva2VuU3RvcmU/LmdldFByaW1hcnlUb2tlblZhbHVlKCkgPz8gJyc7XG4gICAgLy8gQXV0by1pbnZhbGlkYXRlIGNhY2hlIHdoZW4gdGhlIHRva2VuIGNoYW5nZXMgKHJvdGF0aW9uKS5cbiAgICAvLyBJbiBkZWJ1ZyBtb2RlLCBhbHdheXMgcmUtcmVhZCBmcm9tIGRpc2sgc28gVUkgY2hhbmdlcyBhcmUgcGlja2VkIHVwIG9uIHJlbG9hZC5cbiAgICBpZiAoIWlzRGVidWcgJiYgY2FjaGVkSW5kZXhIdG1sICE9PSBudWxsICYmIGNhY2hlZFRva2VuVmFsdWUgPT09IHRva2VuVmFsdWUpIHtcbiAgICAgIHJldHVybiBjYWNoZWRJbmRleEh0bWw7XG4gICAgfVxuICAgIGNvbnN0IHRlbXBsYXRlID0gYXdhaXQgcmVhZEZpbGVGcyhpbmRleEh0bWxQYXRoLCAndXRmOCcpO1xuICAgIC8vIERlZmVuc2l2ZSBIVE1MIGF0dHJpYnV0ZSBlc2NhcGUuIFRva2VucyBhcmUgc3RyaWN0IDY0LWNoYXIgbG93ZXJjYXNlIGhleFxuICAgIC8vIHRvZGF5IHNvIG5vIGVzY2FwaW5nIGlzIGFjdHVhbGx5IG5lZWRlZCwgYnV0IGlmIHRoZSB0b2tlbiBmb3JtYXQgZXZlclxuICAgIC8vIGNoYW5nZXMgdGhpcyBwcmV2ZW50cyBhbiBIVE1MLWluamVjdGlvbiByZWdyZXNzaW9uIGZyb20gbGFuZGluZyBzaWxlbnRseS5cbiAgICBjb25zdCBlc2NhcGVkVG9rZW4gPSB0b2tlblZhbHVlXG4gICAgICAucmVwbGFjZUFsbCgnJicsICcmYW1wOycpXG4gICAgICAucmVwbGFjZUFsbCgnXCInLCAnJnF1b3Q7JylcbiAgICAgIC5yZXBsYWNlQWxsKFwiJ1wiLCAnJiMzOTsnKVxuICAgICAgLnJlcGxhY2VBbGwoJzwnLCAnJmx0OycpXG4gICAgICAucmVwbGFjZUFsbCgnPicsICcmZ3Q7Jyk7XG4gICAgY2FjaGVkSW5kZXhIdG1sID0gdGVtcGxhdGUucmVwbGFjZUFsbChUT0tFTl9NRVRBX1BMQUNFSE9MREVSLCBlc2NhcGVkVG9rZW4pO1xuICAgIGNhY2hlZFRva2VuVmFsdWUgPSB0b2tlblZhbHVlO1xuICAgIHJldHVybiBjYWNoZWRJbmRleEh0bWw7XG4gIH07XG5cbiAgYXBwLmdldCgnL3sqcGF0aH0nLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IHJlcS5wYXRoLm5vcm1hbGl6ZSgnTkZDJyk7XG4gICAgaWYgKG5vcm1hbGl6ZWRQYXRoLnN0YXJ0c1dpdGgoJy9hcGkvJykpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IGBBUEkgcm91dGUgbm90IGZvdW5kOiAke25vcm1hbGl6ZWRQYXRofWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChub3JtYWxpemVkUGF0aC5zdGFydHNXaXRoKCcvcGFnZXMvJykpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IGBQYWdlIG5vdCBmb3VuZDogJHtub3JtYWxpemVkUGF0aH1gIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlbmRlckluZGV4SHRtbCgpO1xuICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvaHRtbDsgY2hhcnNldD11dGYtOCcpO1xuICAgICAgLy8gSW4gZGVidWcgbW9kZSwgcHJldmVudCBicm93c2VyIGNhY2hpbmcgc28gVUkgY2hhbmdlcyBhcmUgcGlja2VkIHVwXG4gICAgICAvLyBpbW1lZGlhdGVseS4gSW4gcHJvZHVjdGlvbiwgYWxsb3cgc2hvcnQgY2FjaGluZyBmb3IgcGVyZm9ybWFuY2UuXG4gICAgICBjb25zdCBpc0RlYnVnID0gQm9vbGVhbihwcm9jZXNzLmVudi5ET0xMSE9VU0VfREVCVUcgfHwgcHJvY2Vzcy5lbnYuRU5BQkxFX0RFQlVHKTtcbiAgICAgIHJlcy5zZXRIZWFkZXIoJ0NhY2hlLUNvbnRyb2wnLCBpc0RlYnVnXG4gICAgICAgID8gJ25vLWNhY2hlLCBuby1zdG9yZSwgbXVzdC1yZXZhbGlkYXRlJ1xuICAgICAgICA6ICdwcml2YXRlLCBtYXgtYWdlPTYwJyk7XG4gICAgICByZXMuc2VuZChodG1sKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgW1dlYlVJXSBGYWlsZWQgdG8gcmVuZGVyIGluZGV4Lmh0bWw6ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5zZW5kKCdGYWlsZWQgdG8gbG9hZCBjb25zb2xlJyk7XG4gICAgfVxuICB9KTtcblxuICAvLyBHbG9iYWwgZXJyb3IgaGFuZGxlciDigJQgY2F0Y2ggRXhwcmVzcyBlcnJvcnMgYW5kIHJvdXRlIHRvIGxvZ2dlciBpbnN0ZWFkIG9mIHRlcm1pbmFsLlxuICAvLyBXaXRob3V0IHRoaXMsIEV4cHJlc3MgZHVtcHMgc3RhY2sgdHJhY2VzIHRvIHN0ZGVyciAodmlzaWJsZSBpbiAtLXdlYiB0ZXJtaW5hbCkuXG4gIC8vIEFsbCBlcnJvcnMgc3RpbGwgYXBwZWFyIGluIHRoZSBtYW5hZ2VtZW50IGNvbnNvbGUncyBMb2dzIHRhYiB2aWEgTWVtb3J5TG9nU2luay5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBhcHAudXNlKChlcnI6IEVycm9yLCBfcmVxOiBpbXBvcnQoJ2V4cHJlc3MnKS5SZXF1ZXN0LCByZXM6IGltcG9ydCgnZXhwcmVzcycpLlJlc3BvbnNlLCBfbmV4dDogaW1wb3J0KCdleHByZXNzJykuTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3Qgc3RhdHVzID0gKGVyciBhcyBhbnkpLnN0YXR1cyB8fCAoZXJyIGFzIGFueSkuc3RhdHVzQ29kZSB8fCA1MDA7XG4gICAgbG9nZ2VyLndhcm4oYFtXZWJVSV0gJHtlcnIubmFtZX06ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgaWYgKCFyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICAgIHJlcy5zdGF0dXMoc3RhdHVzKS5qc29uKHsgZXJyb3I6IGVyci5tZXNzYWdlIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gQmluZCB0byBsb2NhbGhvc3Qgb25seSDigJQgaGFuZGxlIHBvcnQgY29uZmxpY3RzIGdyYWNlZnVsbHkuXG4gIC8vIEV4dHJhY3RlZCB0byBhIGhlbHBlciB0byBrZWVwIHN0YXJ0V2ViU2VydmVyJ3MgY29nbml0aXZlIGNvbXBsZXhpdHkgbWFuYWdlYWJsZS5cbiAgcmVzdWx0LmJpbmRSZXN1bHQgPSBhd2FpdCBiaW5kQW5kTGlzdGVuKGFwcCwgcG9ydCwgb3B0aW9ucyk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBNb3VudCB0aGUgbG9ncywgbWV0cmljcywgYW5kIGhlYWx0aCByb3V0ZXMuIFRoZXNlIGFyZSBvbmx5IG1vdW50ZWQgd2hlbiB0aGVcbiAqIGNvcnJlc3BvbmRpbmcgc2lua3MgYXJlIHByb3ZpZGVkIChtZW1vcnkgbG9nIHNpbmsgZm9yIGxvZ3MraGVhbHRoLCBtZXRyaWNzXG4gKiBzaW5rIGZvciB0aGUgbWV0cmljcyB0YWIpLiBFeHRyYWN0ZWQgZnJvbSBzdGFydFdlYlNlcnZlciB0byBjYXAgdGhlIG1haW5cbiAqIGZ1bmN0aW9uJ3MgY29nbml0aXZlIGNvbXBsZXhpdHkuXG4gKi9cbmZ1bmN0aW9uIG1vdW50Q29uc29sZVJvdXRlcyhcbiAgYXBwOiBpbXBvcnQoJ2V4cHJlc3MnKS5FeHByZXNzLFxuICBvcHRpb25zOiBXZWJTZXJ2ZXJPcHRpb25zLFxuICByZXN1bHQ6IFdlYlNlcnZlclJlc3VsdCxcbik6IHZvaWQge1xuICBsZXQgbG9nUm91dGVzOiBMb2dSb3V0ZXNSZXN1bHQgfCB1bmRlZmluZWQ7XG4gIGxldCBtZXRyaWNzUm91dGVzOiBNZXRyaWNzUm91dGVzUmVzdWx0IHwgdW5kZWZpbmVkO1xuXG4gIGlmIChvcHRpb25zLm1lbW9yeVNpbmspIHtcbiAgICBsb2dSb3V0ZXMgPSBjcmVhdGVMb2dSb3V0ZXMob3B0aW9ucy5tZW1vcnlTaW5rKTtcbiAgICBhcHAudXNlKCcvYXBpJywgbG9nUm91dGVzLnJvdXRlcik7XG4gICAgcmVzdWx0LmxvZ0Jyb2FkY2FzdCA9IGxvZ1JvdXRlcy5icm9hZGNhc3Q7XG4gICAgbG9nZ2VyLmluZm8oJ1tXZWJVSV0gTG9nIHZpZXdlciByb3V0ZXMgbW91bnRlZCBhdCAvYXBpL2xvZ3MnKTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLm1ldHJpY3NTaW5rKSB7XG4gICAgbWV0cmljc1JvdXRlcyA9IGNyZWF0ZU1ldHJpY3NSb3V0ZXMob3B0aW9ucy5tZXRyaWNzU2luayk7XG4gICAgYXBwLnVzZSgnL2FwaScsIG1ldHJpY3NSb3V0ZXMucm91dGVyKTtcbiAgICByZXN1bHQubWV0cmljc09uU25hcHNob3QgPSBtZXRyaWNzUm91dGVzLm9uU25hcHNob3Q7XG4gICAgbG9nZ2VyLmluZm8oJ1tXZWJVSV0gTWV0cmljcyByb3V0ZXMgbW91bnRlZCBhdCAvYXBpL21ldHJpY3MnKTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLm1lbW9yeVNpbmspIHtcbiAgICBjb25zdCBoZWFsdGhSb3V0ZXIgPSBjcmVhdGVIZWFsdGhSb3V0ZXMoe1xuICAgICAgbWVtb3J5U2luazogb3B0aW9ucy5tZW1vcnlTaW5rLFxuICAgICAgbWV0cmljc1Npbms6IG9wdGlvbnMubWV0cmljc1NpbmssXG4gICAgICBsb2dDbGllbnRDb3VudDogbG9nUm91dGVzID8gbG9nUm91dGVzLmNsaWVudENvdW50IDogKCkgPT4gMCxcbiAgICAgIG1ldHJpY3NDbGllbnRDb3VudDogbWV0cmljc1JvdXRlcyA/IG1ldHJpY3NSb3V0ZXMuY2xpZW50Q291bnQgOiAoKSA9PiAwLFxuICAgIH0pO1xuICAgIGFwcC51c2UoJy9hcGknLCBoZWFsdGhSb3V0ZXIpO1xuICB9XG59XG5cbi8qKlxuICogUHJpbnQgdGhlIHN0YXJ0dXAgYmFubmVyIHRvIHN0ZGVyci5cbiAqXG4gKiBOT1RFOiBVc2Ugc3RkZXJyIGZvciB0ZXJtaW5hbCBvdXRwdXQsIG5vdCBzdGRvdXQuIEluIE1DUCBzdGRpbyBtb2RlLCBzdGRvdXRcbiAqIGlzIHJlc2VydmVkIGZvciBKU09OLVJQQyBtZXNzYWdlcyDigJQgYW55IG5vbi1KU09OIG91dHB1dCBjb3JydXB0cyB0aGUgcHJvdG9jb2wuXG4gKiBzdGRlcnIgaXMgc2FmZSBmb3IgaHVtYW4tcmVhZGFibGUgbWVzc2FnZXMgaW4gYm90aCBNQ1AgYW5kIHN0YW5kYWxvbmUgbW9kZXMuXG4gKi9cbmZ1bmN0aW9uIHByaW50U3RhcnR1cEJhbm5lcihwb3J0OiBudW1iZXIsIHRva2VuU3RvcmU6IENvbnNvbGVUb2tlblN0b3JlIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gIGNvbnN0IHVybCA9IGBodHRwOi8vJHtDT05TT0xFX0hPU1R9OiR7cG9ydH1gO1xuICBjb25zdCBmYWxsYmFja1VybCA9IGBodHRwOi8vMTI3LjAuMC4xOiR7cG9ydH1gO1xuICBsb2dnZXIuaW5mbyhgW1dlYlVJXSBNYW5hZ2VtZW50IGNvbnNvbGUgcnVubmluZyBhdCAke3VybH1gKTtcbiAgY29uc29sZS5lcnJvcihgXFxuICBEb2xsaG91c2VNQ1AgTWFuYWdlbWVudCBDb25zb2xlXFxuICAke3VybH1cXG4gICR7ZmFsbGJhY2tVcmx9IChmYWxsYmFjaylcXG5gKTtcbiAgaWYgKHRva2VuU3RvcmUpIHtcbiAgICBjb25zb2xlLmVycm9yKGAgIFNlc3Npb24gdG9rZW46ICR7dG9rZW5TdG9yZS5nZXRGaWxlUGF0aCgpfVxcbmApO1xuICB9XG4gIGNvbnNvbGUuZXJyb3IoYCAgVHlwZSBcInFcIiBvciBcInF1aXRcIiB0byBleGl0LlxcbmApO1xufVxuXG4vKipcbiAqIFJldHJ5IGJpbmRpbmcgYW4gYWxyZWFkeS1jb25maWd1cmVkIEV4cHJlc3MgYXBwIHRvIGEgcG9ydC5cbiAqIFVzZWQgYnkgVW5pZmllZENvbnNvbGUgd2hlbiBFQUREUklOVVNFIG9jY3VycyDigJQgYXZvaWRzIHJlY3JlYXRpbmdcbiAqIHRoZSBFeHByZXNzIGFwcCBhbmQgYWxsIGl0cyByb3V0ZXMgb24gZWFjaCByZXRyeSBhdHRlbXB0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV0cnlCaW5kKFxuICBhcHA6IGltcG9ydCgnZXhwcmVzcycpLkV4cHJlc3MsXG4gIHBvcnQ6IG51bWJlcixcbiAgb3B0aW9uczogV2ViU2VydmVyT3B0aW9ucyxcbik6IFByb21pc2U8QmluZFJlc3VsdD4ge1xuICByZXR1cm4gYmluZEFuZExpc3RlbihhcHAsIHBvcnQsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIEJpbmQgdGhlIEV4cHJlc3MgYXBwIHRvIDEyNy4wLjAuMTpwb3J0IGFuZCBoYW5kbGUgc3VjY2Vzcy9jb25mbGljdCBwYXRocy5cbiAqIFJldHVybnMgYSBCaW5kUmVzdWx0IHNvIHRoZSBjYWxsZXIgY2FuIGRldGVjdCBhbmQgaGFuZGxlIHBvcnQgY29uZmxpY3RzXG4gKiAoZS5nLiwgcmV0cnkgYWZ0ZXIga2lsbGluZyBhIHN0YWxlIHByb2Nlc3MpLlxuICovXG5hc3luYyBmdW5jdGlvbiBiaW5kQW5kTGlzdGVuKFxuICBhcHA6IGltcG9ydCgnZXhwcmVzcycpLkV4cHJlc3MsXG4gIHBvcnQ6IG51bWJlcixcbiAgb3B0aW9uczogV2ViU2VydmVyT3B0aW9ucyxcbik6IFByb21pc2U8QmluZFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8QmluZFJlc3VsdD4oKHJlc29sdmUpID0+IHtcbiAgICBjb25zdCBodHRwU2VydmVyID0gYXBwLmxpc3Rlbihwb3J0LCAnMTI3LjAuMC4xJywgKCkgPT4ge1xuICAgICAgc2VydmVyUnVubmluZyA9IHRydWU7XG4gICAgICBzZXJ2ZXJQb3J0ID0gcG9ydDtcbiAgICAgIGFjdGl2ZUh0dHBTZXJ2ZXIgPSBodHRwU2VydmVyO1xuICAgICAgcHJpbnRTdGFydHVwQmFubmVyKHBvcnQsIG9wdGlvbnMudG9rZW5TdG9yZSk7XG4gICAgICBpZiAob3B0aW9ucy5vcGVuQnJvd3Nlcikge1xuICAgICAgICBvcGVuSW5Ccm93c2VyKGBodHRwOi8vJHtDT05TT0xFX0hPU1R9OiR7cG9ydH1gKTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoeyBzdWNjZXNzOiB0cnVlIH0pO1xuICAgIH0pO1xuICAgIGh0dHBTZXJ2ZXIub24oJ2Vycm9yJywgKGVycjogTm9kZUpTLkVycm5vRXhjZXB0aW9uKSA9PiB7XG4gICAgICByZXNvbHZlKGhhbmRsZUxpc3RlbkVycm9yKGVyciwgcG9ydCwgb3B0aW9ucy5vcGVuQnJvd3NlcikpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgZXJyb3JzIGZyb20gYXBwLmxpc3RlbigpLiBSZXR1cm5zIGEgQmluZFJlc3VsdCBkZXNjcmliaW5nIHRoZSBmYWlsdXJlLlxuICogRUFERFJJTlVTRSBpcyBsb2dnZWQgYXQgV0FSTiAobm90IElORk8pIHNvIGl0J3MgdmlzaWJsZSBpbiBwcm9kdWN0aW9uIGxvZ3MuXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUxpc3RlbkVycm9yKFxuICBlcnI6IE5vZGVKUy5FcnJub0V4Y2VwdGlvbixcbiAgcG9ydDogbnVtYmVyLFxuICBvcGVuQnJvd3NlcjogYm9vbGVhbiB8IHVuZGVmaW5lZCxcbik6IEJpbmRSZXN1bHQge1xuICBpZiAoZXJyLmNvZGUgPT09ICdFQUREUklOVVNFJykge1xuICAgIGNvbnN0IHVybCA9IGBodHRwOi8vJHtDT05TT0xFX0hPU1R9OiR7cG9ydH1gO1xuICAgIGxvZ2dlci53YXJuKGBbV2ViVUldIFBvcnQgJHtwb3J0fSBhbHJlYWR5IGluIHVzZSDigJQgYW5vdGhlciBwcm9jZXNzIGhvbGRzIHRoaXMgcG9ydGApO1xuICAgIGNvbnNvbGUuZXJyb3IoYFxcbiAgRG9sbGhvdXNlTUNQIE1hbmFnZW1lbnQgQ29uc29sZSAoZXhpc3RpbmcgaW5zdGFuY2UpXFxuICAke3VybH1cXG5gKTtcbiAgICBpZiAob3BlbkJyb3dzZXIpIHtcbiAgICAgIG9wZW5JbkJyb3dzZXIodXJsKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIGVycm9yOiAnRUFERFJJTlVTRScsIGRldGFpbDogYFBvcnQgJHtwb3J0fSBhbHJlYWR5IGluIHVzZWAgfTtcbiAgfVxuICBsb2dnZXIuZXJyb3IoYFtXZWJVSV0gRmFpbGVkIHRvIGJpbmQgcG9ydCAke3BvcnR9OiAke2Vyci5tZXNzYWdlfWApO1xuICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdPVEhFUicsIGRldGFpbDogZXJyLm1lc3NhZ2UgfTtcbn1cblxuLyoqXG4gKiBPcGVuIHRoZSBwb3J0Zm9saW8gYnJvd3NlciBmcm9tIHdpdGhpbiB0aGUgTUNQIHNlcnZlciBwcm9jZXNzLlxuICpcbiAqIFN0YXJ0cyB0aGUgd2ViIHNlcnZlciBpZiBub3QgYWxyZWFkeSBydW5uaW5nLCB0aGVuIG9wZW5zIHRoZSBzeXN0ZW1cbiAqIGJyb3dzZXIgdG8gdGhlIHBvcnRmb2xpbyBVSS4gUmV0dXJucyBhIHJlc3VsdCBvYmplY3QgaW5kaWNhdGluZ1xuICogd2hldGhlciB0aGUgc2VydmVyIHN0YXJ0ZWQgYW5kIHRoZSBicm93c2VyIG9wZW5lZCBzdWNjZXNzZnVsbHkuXG4gKlxuICogQ2FsbGVkIGJ5IHRoZSBgb3Blbl9wb3J0Zm9saW9fYnJvd3NlcmAgTUNQLUFRTCBvcGVyYXRpb24gKElzc3VlICM3NzQpLlxuICpcbiAqIEBwYXJhbSBwb3J0Zm9saW9EaXIgLSBQYXRoIHRvIHRoZSBwb3J0Zm9saW8gZGlyZWN0b3J5IChlLmcuLCB+Ly5kb2xsaG91c2UvcG9ydGZvbGlvKVxuICogQHBhcmFtIHBvcnQgLSBQb3J0IHRvIGJpbmQgdG8gKGRlZmF1bHRzIHRvIGBET0xMSE9VU0VfV0VCX0NPTlNPTEVfUE9SVGApXG4gKiBAcmV0dXJucyBSZXN1bHQgd2l0aCBVUkwsIHNlcnZlciBzdGF0dXMsIGFuZCBicm93c2VyIG9wZW4gc3RhdHVzXG4gKi9cbi8qKlxuICogT3B0aW9ucyBmb3Igb3BlbmluZyB0aGUgcG9ydGZvbGlvIGJyb3dzZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkJyb3dzZXJPcHRpb25zIHtcbiAgcG9ydGZvbGlvRGlyOiBzdHJpbmc7XG4gIHBvcnQ/OiBudW1iZXI7XG4gIG1jcEFxbEhhbmRsZXI/OiBNQ1BBUUxIYW5kbGVyO1xuICB0YWI/OiBzdHJpbmc7XG4gIHVybFBhcmFtcz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIG1lbW9yeVNpbms/OiBNZW1vcnlMb2dTaW5rO1xuICBtZXRyaWNzU2luaz86IE1lbW9yeU1ldHJpY3NTaW5rO1xufVxuXG4vKipcbiAqIFNlbGYtcHJvdmlzaW9uIHNpbmtzLCB0b2tlbiBzdG9yZSwgYW5kIGluZ2VzdCByb3V0ZXMsIHRoZW4gc3RhcnQgdGhlIHdlYlxuICogc2VydmVyLiBFeHRyYWN0ZWQgZnJvbSBvcGVuUG9ydGZvbGlvQnJvd3NlciB0byBrZWVwIGNvZ25pdGl2ZSBjb21wbGV4aXR5XG4gKiBtYW5hZ2VhYmxlIChTb25hckNsb3VkIFMzNzc2KS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc3RhcnRGYWxsYmFja1NlcnZlcihvcHRpb25zOiBPcGVuQnJvd3Nlck9wdGlvbnMsIHBvcnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICBsZXQgbWVtb3J5U2luayA9IG9wdGlvbnMubWVtb3J5U2luaztcbiAgbGV0IG1ldHJpY3NTaW5rID0gb3B0aW9ucy5tZXRyaWNzU2luaztcblxuICBpZiAoIW1lbW9yeVNpbmspIHtcbiAgICBjb25zdCB7IE1lbW9yeUxvZ1Npbms6IExvZ1NpbmsgfSA9IGF3YWl0IGltcG9ydCgnLi4vbG9nZ2luZy9zaW5rcy9NZW1vcnlMb2dTaW5rLmpzJyk7XG4gICAgbWVtb3J5U2luayA9IG5ldyBMb2dTaW5rKHsgYXBwQ2FwYWNpdHk6IDEwMDAwLCBzZWN1cml0eUNhcGFjaXR5OiA1MDAwLCBwZXJmQ2FwYWNpdHk6IDIwMDAsIHRlbGVtZXRyeUNhcGFjaXR5OiAxMDAwIH0pO1xuICB9XG4gIGlmICghbWV0cmljc1NpbmspIHtcbiAgICBjb25zdCB7IE1lbW9yeU1ldHJpY3NTaW5rOiBNZXRyaWNzU2luayB9ID0gYXdhaXQgaW1wb3J0KCcuLi9tZXRyaWNzL3NpbmtzL01lbW9yeU1ldHJpY3NTaW5rLmpzJyk7XG4gICAgbWV0cmljc1NpbmsgPSBuZXcgTWV0cmljc1NpbmsoMjQwKTtcbiAgfVxuXG4gIC8vIFJldXNlIGNhY2hlZCB0b2tlbiBzdG9yZSDigJQgdHdvIGluc3RhbmNlcyBvbiB0aGUgc2FtZSBmaWxlIGNhbiByYWNlIG9uIHdyaXRlcy5cbiAgaWYgKCFjYWNoZWRUb2tlblN0b3JlKSB7XG4gICAgY29uc3QgeyBDb25zb2xlVG9rZW5TdG9yZTogVG9rZW5TdG9yZSB9ID0gYXdhaXQgaW1wb3J0KCcuL2NvbnNvbGUvY29uc29sZVRva2VuLmpzJyk7XG4gICAgY29uc3QgeyBwaWNrUmFuZG9tUHVwcGV0TmFtZSB9ID0gYXdhaXQgaW1wb3J0KCcuL2NvbnNvbGUvU2Vzc2lvbk5hbWVzLmpzJyk7XG4gICAgY2FjaGVkVG9rZW5TdG9yZSA9IG5ldyBUb2tlblN0b3JlKGVudi5ET0xMSE9VU0VfQ09OU09MRV9UT0tFTl9GSUxFKTtcbiAgICB0cnkgeyBhd2FpdCBjYWNoZWRUb2tlblN0b3JlLmVuc3VyZUluaXRpYWxpemVkKHBpY2tSYW5kb21QdXBwZXROYW1lKCkpOyB9XG4gICAgY2F0Y2ggKGVycikgeyBsb2dnZXIud2FybignW1dlYlVJXSBGYWlsZWQgdG8gaW5pdCB0b2tlbiBzdG9yZSBmb3IgYnJvd3NlciBvcGVuJywgZXJyKTsgfVxuICB9XG5cbiAgLy8gbG9nQnJvYWRjYXN0IGlzIGRlZmVycmVkIOKAlCB3aXJlZCBhZnRlciBzdGFydFdlYlNlcnZlciByZXR1cm5zIHRoZSByZWFsIGJyb2FkY2FzdCBmbi5cbiAgbGV0IGxpdmVCcm9hZGNhc3Q6ICgoZW50cnk6IGltcG9ydCgnLi4vbG9nZ2luZy90eXBlcy5qcycpLlVuaWZpZWRMb2dFbnRyeSkgPT4gdm9pZCkgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IHsgY3JlYXRlSW5nZXN0Um91dGVzIH0gPSBhd2FpdCBpbXBvcnQoJy4vY29uc29sZS9Jbmdlc3RSb3V0ZXMuanMnKTtcbiAgY29uc3QgaW5nZXN0UmVzdWx0ID0gY3JlYXRlSW5nZXN0Um91dGVzKHtcbiAgICBsb2dCcm9hZGNhc3Q6IChlbnRyeSkgPT4gbGl2ZUJyb2FkY2FzdD8uKGVudHJ5KSxcbiAgfSk7XG4gIGluZ2VzdFJlc3VsdC5yZWdpc3RlckNvbnNvbGVTZXNzaW9uKCk7XG5cbiAgY29uc3Qgd2ViUmVzdWx0ID0gYXdhaXQgc3RhcnRXZWJTZXJ2ZXIoe1xuICAgIHBvcnRmb2xpb0Rpcjogb3B0aW9ucy5wb3J0Zm9saW9EaXIsXG4gICAgcG9ydCxcbiAgICBvcGVuQnJvd3NlcjogZmFsc2UsXG4gICAgbWNwQXFsSGFuZGxlcjogb3B0aW9ucy5tY3BBcWxIYW5kbGVyLFxuICAgIG1lbW9yeVNpbmssXG4gICAgbWV0cmljc1NpbmssXG4gICAgdG9rZW5TdG9yZTogY2FjaGVkVG9rZW5TdG9yZSxcbiAgICBhZGRpdGlvbmFsUm91dGVyczogW2luZ2VzdFJlc3VsdC5yb3V0ZXJdLFxuICB9KTtcblxuICBsaXZlQnJvYWRjYXN0ID0gd2ViUmVzdWx0LmxvZ0Jyb2FkY2FzdDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9wZW5Qb3J0Zm9saW9Ccm93c2VyKG9wdGlvbnM6IE9wZW5Ccm93c2VyT3B0aW9ucyk6IFByb21pc2U8QnJvd3Nlck9wZW5SZXN1bHQ+IHtcbiAgY29uc3QgdGFyZ2V0UG9ydCA9IG9wdGlvbnMucG9ydCB8fCBERUZBVUxUX1BPUlQ7XG4gIGNvbnN0IGJhc2VVcmwgPSBgaHR0cDovLyR7Q09OU09MRV9IT1NUfToke3RhcmdldFBvcnR9YDtcblxuICAvLyBCdWlsZCBVUkwgd2l0aCBvcHRpb25hbCB0YWIgaGFzaCBhbmQgcXVlcnkgcGFyYW1ldGVyc1xuICBsZXQgdXJsID0gYmFzZVVybDtcbiAgaWYgKG9wdGlvbnMudGFiKSB7XG4gICAgY29uc3QgcXMgPSBvcHRpb25zLnVybFBhcmFtcyA/IG5ldyBVUkxTZWFyY2hQYXJhbXMob3B0aW9ucy51cmxQYXJhbXMpLnRvU3RyaW5nKCkgOiAnJztcbiAgICB1cmwgPSBgJHtiYXNlVXJsfS8jJHtvcHRpb25zLnRhYn0ke3FzID8gJz8nICsgcXMgOiAnJ31gO1xuICB9IGVsc2UgaWYgKG9wdGlvbnMudXJsUGFyYW1zICYmIE9iamVjdC5rZXlzKG9wdGlvbnMudXJsUGFyYW1zKS5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgcXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKG9wdGlvbnMudXJsUGFyYW1zKS50b1N0cmluZygpO1xuICAgIHVybCA9IGAke2Jhc2VVcmx9LyNwb3J0Zm9saW8/JHtxc31gO1xuICB9XG5cbiAgY29uc3QgYWxyZWFkeVJ1bm5pbmcgPSBzZXJ2ZXJSdW5uaW5nO1xuXG4gIGlmICghc2VydmVyUnVubmluZykge1xuICAgIGF3YWl0IHN0YXJ0RmFsbGJhY2tTZXJ2ZXIob3B0aW9ucywgdGFyZ2V0UG9ydCk7XG4gIH1cblxuICBjb25zdCBicm93c2VyUmVzdWx0ID0gYXdhaXQgb3BlbkluQnJvd3Nlcih1cmwpO1xuXG4gIHJldHVybiB7XG4gICAgdXJsLFxuICAgIGFscmVhZHlSdW5uaW5nLFxuICAgIGJyb3dzZXJPcGVuZWQ6IGJyb3dzZXJSZXN1bHQuc3VjY2VzcyxcbiAgICAuLi4oYnJvd3NlclJlc3VsdC5lcnJvciA/IHsgd2FybmluZzogYEJyb3dzZXIgY291bGQgbm90IGJlIG9wZW5lZCBhdXRvbWF0aWNhbGx5OiAke2Jyb3dzZXJSZXN1bHQuZXJyb3J9LiBPcGVuICR7dXJsfSBtYW51YWxseS5gIH0gOiB7fSksXG4gIH07XG59XG4iXX0=
|