@nlabs/lex 1.49.4 → 1.50.0
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/.swcrc +35 -0
- package/README.md +43 -59
- package/__mocks__/chalk.js +19 -17
- package/config.json +32 -8
- package/examples/lex.config.js +110 -10
- package/index.cjs +1 -5
- package/lex.config.js +34 -7
- package/lib/Button.stories.js +99 -0
- package/lib/LexConfig.d.ts +60 -22
- package/lib/LexConfig.js +285 -244
- package/lib/commands/ai/ai.js +287 -288
- package/lib/commands/ai/index.js +8 -7
- package/lib/commands/build/build.d.ts +2 -2
- package/lib/commands/build/build.js +349 -458
- package/lib/commands/clean/clean.js +45 -33
- package/lib/commands/compile/compile.js +214 -227
- package/lib/commands/config/config.js +46 -42
- package/lib/commands/copy/copy.js +36 -35
- package/lib/commands/create/create.js +200 -121
- package/lib/commands/dev/dev.d.ts +2 -0
- package/lib/commands/dev/dev.js +259 -263
- package/lib/commands/init/init.js +108 -88
- package/lib/commands/link/link.js +18 -14
- package/lib/commands/lint/lint.js +735 -742
- package/lib/commands/migrate/migrate.js +49 -36
- package/lib/commands/publish/publish.js +116 -96
- package/lib/commands/serverless/serverless.js +611 -585
- package/lib/commands/storybook/storybook.js +242 -238
- package/lib/commands/test/test.d.ts +1 -1
- package/lib/commands/test/test.js +382 -394
- package/lib/commands/update/update.js +141 -120
- package/lib/commands/upgrade/upgrade.js +51 -44
- package/lib/commands/versions/versions.d.ts +1 -1
- package/lib/commands/versions/versions.js +36 -38
- package/lib/create/changelog.js +136 -125
- package/lib/index.js +40 -38
- package/lib/lex.js +95 -68
- package/lib/storybook/index.js +6 -1
- package/lib/test-react/index.js +7 -84
- package/lib/types.d.ts +1 -1
- package/lib/types.js +7 -1
- package/lib/utils/aiService.js +240 -227
- package/lib/utils/app.js +274 -273
- package/lib/utils/deepMerge.js +37 -23
- package/lib/utils/file.js +218 -215
- package/lib/utils/log.js +29 -27
- package/lib/utils/reactShim.js +7 -85
- package/lib/utils/translations.js +91 -65
- package/package.json +63 -64
- package/templates/typescript/DataLayer.js.txt +218 -0
- package/templates/typescript/DataLayer.test.js.txt +268 -0
- package/templates/typescript/DataLayer.test.ts.txt +269 -0
- package/templates/typescript/DataLayer.ts.txt +227 -0
- package/webpack.config.js +53 -26
- package/lib/commands/lint/autofix.d.ts +0 -2
|
@@ -1,630 +1,656 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const cachePath = getCachePath();
|
|
21
|
-
if (!existsSync(cachePath)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const cacheData = readFileSync(cachePath, "utf8");
|
|
26
|
-
const cache = JSON.parse(cacheData);
|
|
27
|
-
const oneWeekMs = 7 * 24 * 60 * 60 * 1e3;
|
|
28
|
-
if (Date.now() - cache.timestamp > oneWeekMs) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
return cache;
|
|
32
|
-
} catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
const writePublicIpCache = (ip) => {
|
|
37
|
-
const cachePath = getCachePath();
|
|
38
|
-
const cache = {
|
|
39
|
-
ip,
|
|
40
|
-
timestamp: Date.now()
|
|
41
|
-
};
|
|
42
|
-
writeFileSync(cachePath, JSON.stringify(cache, null, 2));
|
|
43
|
-
};
|
|
44
|
-
const fetchPublicIp = (forceRefresh = false) => new Promise((resolve) => {
|
|
45
|
-
if (!forceRefresh) {
|
|
46
|
-
const cached = readPublicIpCache();
|
|
47
|
-
if (cached) {
|
|
48
|
-
resolve(cached.ip);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
fetch("https://api.ipify.org").then((res) => res.text()).then((data) => {
|
|
53
|
-
const ip = data.trim();
|
|
54
|
-
if (ip) {
|
|
55
|
-
writePublicIpCache(ip);
|
|
56
|
-
}
|
|
57
|
-
resolve(ip);
|
|
58
|
-
}).catch(() => resolve(void 0));
|
|
59
|
-
});
|
|
60
|
-
const displayServerStatus = (httpPort, httpsPort, wsPort, host, quiet, publicIp) => {
|
|
61
|
-
if (quiet) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const httpUrl = `http://${host}:${httpPort}`;
|
|
65
|
-
const httpsUrl = `https://${host}:${httpsPort}`;
|
|
66
|
-
const wsUrl = `ws://${host}:${wsPort}`;
|
|
67
|
-
const wssUrl = `wss://${host}:${wsPort}`;
|
|
68
|
-
let urlLines = `${chalk.green("HTTP:")} ${chalk.underline(httpUrl)}
|
|
69
|
-
`;
|
|
70
|
-
urlLines += `${chalk.green("HTTPS:")} ${chalk.underline(httpsUrl)}
|
|
71
|
-
`;
|
|
72
|
-
urlLines += `${chalk.green("WebSocket:")} ${chalk.underline(wsUrl)}
|
|
73
|
-
`;
|
|
74
|
-
urlLines += `${chalk.green("WSS:")} ${chalk.underline(wssUrl)}
|
|
75
|
-
`;
|
|
76
|
-
if (publicIp) {
|
|
77
|
-
urlLines += `
|
|
78
|
-
${chalk.green("Public:")} ${chalk.underline(`http://${publicIp}:${httpPort}`)}
|
|
79
|
-
`;
|
|
80
|
-
}
|
|
81
|
-
const statusBox = boxen(
|
|
82
|
-
`${chalk.cyan.bold("\u{1F680} Serverless Development Server Running")}
|
|
83
|
-
|
|
84
|
-
${urlLines}
|
|
85
|
-
${chalk.yellow("Press Ctrl+C to stop the server")}`,
|
|
86
|
-
{
|
|
87
|
-
backgroundColor: "#1a1a1a",
|
|
88
|
-
borderColor: "cyan",
|
|
89
|
-
borderStyle: "round",
|
|
90
|
-
margin: 1,
|
|
91
|
-
padding: 1
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2018-Present, Nitrogen Labs, Inc.
|
|
3
|
+
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
+
*/ import boxen from 'boxen';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { resolve as pathResolve, join } from 'path';
|
|
10
|
+
import { WebSocketServer } from 'ws';
|
|
11
|
+
import { LexConfig } from '../../LexConfig.js';
|
|
12
|
+
import { createSpinner, removeFiles } from '../../utils/app.js';
|
|
13
|
+
import { log } from '../../utils/log.js';
|
|
14
|
+
const getCacheDir = ()=>{
|
|
15
|
+
const cacheDir = join(homedir(), '.lex-cache');
|
|
16
|
+
if (!existsSync(cacheDir)) {
|
|
17
|
+
mkdirSync(cacheDir, {
|
|
18
|
+
recursive: true
|
|
19
|
+
});
|
|
92
20
|
}
|
|
93
|
-
|
|
94
|
-
console.log(`
|
|
95
|
-
${statusBox}
|
|
96
|
-
`);
|
|
21
|
+
return cacheDir;
|
|
97
22
|
};
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
throw new Error(`Handler file not found: ${fullPath}`);
|
|
23
|
+
const getCachePath = ()=>join(getCacheDir(), 'public-ip.json');
|
|
24
|
+
const readPublicIpCache = ()=>{
|
|
25
|
+
const cachePath = getCachePath();
|
|
26
|
+
if (!existsSync(cachePath)) {
|
|
27
|
+
return null;
|
|
104
28
|
}
|
|
105
29
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
30
|
+
const cacheData = readFileSync(cachePath, 'utf8');
|
|
31
|
+
const cache = JSON.parse(cacheData);
|
|
32
|
+
// Check if cache is older than 1 week
|
|
33
|
+
const oneWeekMs = 7 * 24 * 60 * 60 * 1000;
|
|
34
|
+
if (Date.now() - cache.timestamp > oneWeekMs) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return cache;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
114
40
|
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
log(`Error loading handler ${handlerPath}: ${error.message}`, "error", false);
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
41
|
};
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const originalConsoleLog = console.log;
|
|
126
|
-
const originalConsoleError = console.error;
|
|
127
|
-
const originalConsoleWarn = console.warn;
|
|
128
|
-
const originalConsoleInfo = console.info;
|
|
129
|
-
const logs = [];
|
|
130
|
-
console.log = (...args) => {
|
|
131
|
-
logs.push(`[LOG] ${args.join(" ")}`);
|
|
132
|
-
originalConsoleLog(...args);
|
|
133
|
-
};
|
|
134
|
-
console.error = (...args) => {
|
|
135
|
-
logs.push(`[ERROR] ${args.join(" ")}`);
|
|
136
|
-
originalConsoleError(...args);
|
|
137
|
-
};
|
|
138
|
-
console.warn = (...args) => {
|
|
139
|
-
logs.push(`[WARN] ${args.join(" ")}`);
|
|
140
|
-
originalConsoleWarn(...args);
|
|
42
|
+
const writePublicIpCache = (ip)=>{
|
|
43
|
+
const cachePath = getCachePath();
|
|
44
|
+
const cache = {
|
|
45
|
+
ip,
|
|
46
|
+
timestamp: Date.now()
|
|
141
47
|
};
|
|
142
|
-
|
|
143
|
-
logs.push(`[INFO] ${args.join(" ")}`);
|
|
144
|
-
originalConsoleInfo(...args);
|
|
145
|
-
};
|
|
146
|
-
try {
|
|
147
|
-
const result = await handler(event, context);
|
|
148
|
-
if (logs.length > 0) {
|
|
149
|
-
console.log(chalk.gray("--- Handler Console Output ---"));
|
|
150
|
-
logs.forEach((log2) => console.log(chalk.gray(log2)));
|
|
151
|
-
console.log(chalk.gray("--- End Handler Console Output ---"));
|
|
152
|
-
}
|
|
153
|
-
return result;
|
|
154
|
-
} finally {
|
|
155
|
-
console.log = originalConsoleLog;
|
|
156
|
-
console.error = originalConsoleError;
|
|
157
|
-
console.warn = originalConsoleWarn;
|
|
158
|
-
console.info = originalConsoleInfo;
|
|
159
|
-
}
|
|
160
|
-
};
|
|
48
|
+
writeFileSync(cachePath, JSON.stringify(cache, null, 2));
|
|
161
49
|
};
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
res.header("Access-Control-Allow-Credentials", "true");
|
|
169
|
-
if (req.method === "OPTIONS") {
|
|
170
|
-
res.sendStatus(200);
|
|
171
|
-
} else {
|
|
172
|
-
next();
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
app.use(express.json());
|
|
176
|
-
const loadGraphQLSchema = async () => {
|
|
177
|
-
try {
|
|
178
|
-
let graphqlHandler = null;
|
|
179
|
-
if (config.functions) {
|
|
180
|
-
for (const [functionName, functionConfig] of Object.entries(config.functions)) {
|
|
181
|
-
if (functionConfig.events) {
|
|
182
|
-
for (const event of functionConfig.events) {
|
|
183
|
-
if (event.http && event.http.path) {
|
|
184
|
-
if (event.http.path === "/public" || event.http.path === "/graphql") {
|
|
185
|
-
graphqlHandler = await loadHandler(functionConfig.handler, outputDir);
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
50
|
+
const fetchPublicIp = (forceRefresh = false)=>new Promise((resolve)=>{
|
|
51
|
+
if (!forceRefresh) {
|
|
52
|
+
const cached = readPublicIpCache();
|
|
53
|
+
if (cached) {
|
|
54
|
+
resolve(cached.ip);
|
|
55
|
+
return;
|
|
189
56
|
}
|
|
190
|
-
}
|
|
191
|
-
if (graphqlHandler) {
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
57
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return null;
|
|
201
|
-
} catch (error) {
|
|
202
|
-
log(`Error loading GraphQL handler: ${error.message}`, "error", quiet);
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
try {
|
|
207
|
-
const graphqlHandler = await loadGraphQLSchema();
|
|
208
|
-
if (graphqlHandler) {
|
|
209
|
-
let graphqlPath = "/graphql";
|
|
210
|
-
if (config.functions) {
|
|
211
|
-
for (const [_functionName, functionConfig] of Object.entries(config.functions)) {
|
|
212
|
-
if (functionConfig.events) {
|
|
213
|
-
for (const event of functionConfig.events) {
|
|
214
|
-
if (event?.http?.path) {
|
|
215
|
-
graphqlPath = event.http.path;
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
58
|
+
// Use fetch instead of https
|
|
59
|
+
fetch('https://api.ipify.org').then((res)=>res.text()).then((data)=>{
|
|
60
|
+
const ip = data.trim();
|
|
61
|
+
if (ip) {
|
|
62
|
+
writePublicIpCache(ip);
|
|
218
63
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
64
|
+
resolve(ip);
|
|
65
|
+
}).catch(()=>resolve(undefined));
|
|
66
|
+
});
|
|
67
|
+
const displayServerStatus = (httpPort, httpsPort, wsPort, host, quiet, publicIp)=>{
|
|
68
|
+
if (quiet) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const httpUrl = `http://${host}:${httpPort}`;
|
|
72
|
+
const httpsUrl = `https://${host}:${httpsPort}`;
|
|
73
|
+
const wsUrl = `ws://${host}:${wsPort}`;
|
|
74
|
+
const wssUrl = `wss://${host}:${wsPort}`;
|
|
75
|
+
let urlLines = `${chalk.green('HTTP:')} ${chalk.underline(httpUrl)}\n`;
|
|
76
|
+
urlLines += `${chalk.green('HTTPS:')} ${chalk.underline(httpsUrl)}\n`;
|
|
77
|
+
urlLines += `${chalk.green('WebSocket:')} ${chalk.underline(wsUrl)}\n`;
|
|
78
|
+
urlLines += `${chalk.green('WSS:')} ${chalk.underline(wssUrl)}\n`;
|
|
79
|
+
if (publicIp) {
|
|
80
|
+
urlLines += `\n${chalk.green('Public:')} ${chalk.underline(`http://${publicIp}:${httpPort}`)}\n`;
|
|
81
|
+
}
|
|
82
|
+
const statusBox = boxen(`${chalk.cyan.bold('🚀 Serverless Development Server Running')}\n\n${urlLines}\n` + `${chalk.yellow('Press Ctrl+C to stop the server')}`, {
|
|
83
|
+
backgroundColor: '#1a1a1a',
|
|
84
|
+
borderColor: 'cyan',
|
|
85
|
+
borderStyle: 'round',
|
|
86
|
+
margin: 1,
|
|
87
|
+
padding: 1
|
|
88
|
+
});
|
|
89
|
+
console.log(`\n${statusBox}\n`);
|
|
90
|
+
};
|
|
91
|
+
const loadHandler = async (handlerPath, outputDir)=>{
|
|
92
|
+
try {
|
|
93
|
+
const fullPath = pathResolve(outputDir, handlerPath);
|
|
94
|
+
log(`Loading handler from: ${fullPath}`, 'info', false);
|
|
95
|
+
if (!existsSync(fullPath)) {
|
|
96
|
+
throw new Error(`Handler file not found: ${fullPath}`);
|
|
223
97
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
98
|
+
// Dynamic import of the handler with better error handling
|
|
99
|
+
try {
|
|
100
|
+
const handlerModule = await import(fullPath);
|
|
101
|
+
log(`Handler module loaded: ${Object.keys(handlerModule)}`, 'info', false);
|
|
102
|
+
const handler = handlerModule.default || handlerModule.handler || handlerModule;
|
|
103
|
+
log(`Handler found: ${typeof handler}`, 'info', false);
|
|
104
|
+
return handler;
|
|
105
|
+
} catch (importError) {
|
|
106
|
+
log(`Import error for handler ${handlerPath}: ${importError.message}`, 'error', false);
|
|
107
|
+
return null;
|
|
235
108
|
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
log(`Error loading handler ${handlerPath}: ${error.message}`, 'error', false);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const captureConsoleLogs = (handler, quiet)=>{
|
|
115
|
+
if (quiet) {
|
|
116
|
+
return handler;
|
|
117
|
+
}
|
|
118
|
+
return async (event, context)=>{
|
|
119
|
+
// Capture console.log, console.error, etc.
|
|
236
120
|
const originalConsoleLog = console.log;
|
|
121
|
+
const originalConsoleError = console.error;
|
|
122
|
+
const originalConsoleWarn = console.warn;
|
|
123
|
+
const originalConsoleInfo = console.info;
|
|
237
124
|
const logs = [];
|
|
238
|
-
console.log = (...args)
|
|
239
|
-
|
|
240
|
-
(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
125
|
+
console.log = (...args)=>{
|
|
126
|
+
logs.push(`[LOG] ${args.join(' ')}`);
|
|
127
|
+
originalConsoleLog(...args);
|
|
128
|
+
};
|
|
129
|
+
console.error = (...args)=>{
|
|
130
|
+
logs.push(`[ERROR] ${args.join(' ')}`);
|
|
131
|
+
originalConsoleError(...args);
|
|
132
|
+
};
|
|
133
|
+
console.warn = (...args)=>{
|
|
134
|
+
logs.push(`[WARN] ${args.join(' ')}`);
|
|
135
|
+
originalConsoleWarn(...args);
|
|
244
136
|
};
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
functionVersion: "$LATEST",
|
|
249
|
-
getRemainingTimeInMillis: () => 3e4,
|
|
250
|
-
invokedFunctionArn: "arn:aws:lambda:us-east-1:123456789012:function:graphql",
|
|
251
|
-
logGroupName: "/aws/lambda/graphql",
|
|
252
|
-
logStreamName: "test-log-stream",
|
|
253
|
-
req,
|
|
254
|
-
res
|
|
137
|
+
console.info = (...args)=>{
|
|
138
|
+
logs.push(`[INFO] ${args.join(' ')}`);
|
|
139
|
+
originalConsoleInfo(...args);
|
|
255
140
|
};
|
|
256
|
-
const wrappedHandler = captureConsoleLogs(graphqlHandler, quiet);
|
|
257
141
|
try {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}, context);
|
|
265
|
-
console.log = originalConsoleLog;
|
|
266
|
-
if (result && typeof result === "object" && result.statusCode) {
|
|
267
|
-
res.status(result.statusCode);
|
|
268
|
-
if (result.headers) {
|
|
269
|
-
Object.entries(result.headers).forEach(([key, value]) => {
|
|
270
|
-
res.setHeader(key, String(value));
|
|
271
|
-
});
|
|
142
|
+
const result = await handler(event, context);
|
|
143
|
+
// Output captured logs
|
|
144
|
+
if (logs.length > 0) {
|
|
145
|
+
console.log(chalk.gray('--- Handler Console Output ---'));
|
|
146
|
+
logs.forEach((log)=>console.log(chalk.gray(log)));
|
|
147
|
+
console.log(chalk.gray('--- End Handler Console Output ---'));
|
|
272
148
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
res.status(500).json({ error: error.message });
|
|
149
|
+
return result;
|
|
150
|
+
} finally{
|
|
151
|
+
// Restore original console methods
|
|
152
|
+
console.log = originalConsoleLog;
|
|
153
|
+
console.error = originalConsoleError;
|
|
154
|
+
console.warn = originalConsoleWarn;
|
|
155
|
+
console.info = originalConsoleInfo;
|
|
281
156
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
const createExpressServer = async (config, outputDir, httpPort, host, quiet, debug)=>{
|
|
160
|
+
const app = express();
|
|
161
|
+
// Enable CORS
|
|
162
|
+
app.use((req, res, next)=>{
|
|
163
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
164
|
+
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
|
|
165
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
166
|
+
res.header('Access-Control-Allow-Credentials', 'true');
|
|
167
|
+
if (req.method === 'OPTIONS') {
|
|
168
|
+
res.sendStatus(200);
|
|
169
|
+
} else {
|
|
170
|
+
next();
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// Parse JSON bodies
|
|
174
|
+
app.use(express.json());
|
|
175
|
+
// Load GraphQL handler
|
|
176
|
+
const loadGraphQLSchema = async ()=>{
|
|
177
|
+
try {
|
|
178
|
+
// Try to find a GraphQL handler
|
|
179
|
+
let graphqlHandler = null;
|
|
180
|
+
if (config.functions) {
|
|
181
|
+
for (const [functionName, functionConfig] of Object.entries(config.functions)){
|
|
182
|
+
if (functionConfig.events) {
|
|
183
|
+
for (const event of functionConfig.events){
|
|
184
|
+
if (event.http && event.http.path) {
|
|
185
|
+
// Look for GraphQL endpoints
|
|
186
|
+
if (event.http.path === '/public' || event.http.path === '/graphql') {
|
|
187
|
+
graphqlHandler = await loadHandler(functionConfig.handler, outputDir);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (graphqlHandler) {
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
305
196
|
}
|
|
306
|
-
}
|
|
307
197
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
198
|
+
if (graphqlHandler) {
|
|
199
|
+
log('Found GraphQL handler', 'info', quiet);
|
|
200
|
+
return graphqlHandler;
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
log(`Error loading GraphQL handler: ${error.message}`, 'error', quiet);
|
|
205
|
+
return null;
|
|
312
206
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
memoryLimitInMB: "128"
|
|
335
|
-
};
|
|
336
|
-
try {
|
|
337
|
-
const result = await wrappedHandler(event, context);
|
|
338
|
-
if (result && typeof result === "object" && result.statusCode) {
|
|
339
|
-
res.status(result.statusCode);
|
|
340
|
-
if (result.headers) {
|
|
341
|
-
Object.entries(result.headers).forEach(([key, value]) => {
|
|
342
|
-
res.setHeader(key, String(value));
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
res.send(result.body);
|
|
346
|
-
} else {
|
|
347
|
-
res.json(result);
|
|
207
|
+
};
|
|
208
|
+
// Set up GraphQL handler for GraphQL requests
|
|
209
|
+
try {
|
|
210
|
+
const graphqlHandler = await loadGraphQLSchema();
|
|
211
|
+
if (graphqlHandler) {
|
|
212
|
+
// Find the GraphQL path from the serverless config
|
|
213
|
+
let graphqlPath = '/graphql'; // default fallback
|
|
214
|
+
if (config.functions) {
|
|
215
|
+
for (const [_functionName, functionConfig] of Object.entries(config.functions)){
|
|
216
|
+
if (functionConfig.events) {
|
|
217
|
+
for (const event of functionConfig.events){
|
|
218
|
+
if (event?.http?.path) {
|
|
219
|
+
graphqlPath = event.http.path;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (graphqlPath !== '/graphql') {
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
348
228
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
229
|
+
// Set up GraphQL endpoint with enhanced console.log capture
|
|
230
|
+
app.use(graphqlPath, async (req, res)=>{
|
|
231
|
+
// GraphQL Debug Logging
|
|
232
|
+
if (debug && req.body && req.body.query) {
|
|
233
|
+
log('🔍 GraphQL Debug Mode: Analyzing request...', 'info', false);
|
|
234
|
+
log(`📝 GraphQL Query: ${req.body.query}`, 'info', false);
|
|
235
|
+
if (req.body.variables) {
|
|
236
|
+
log(`📊 GraphQL Variables: ${JSON.stringify(req.body.variables, null, 2)}`, 'info', false);
|
|
237
|
+
}
|
|
238
|
+
if (req.body.operationName) {
|
|
239
|
+
log(`🏷️ GraphQL Operation: ${req.body.operationName}`, 'info', false);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Enhanced console.log capture
|
|
243
|
+
const originalConsoleLog = console.log;
|
|
244
|
+
const logs = [];
|
|
245
|
+
console.log = (...args)=>{
|
|
246
|
+
const logMessage = args.map((arg)=>typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)).join(' ');
|
|
247
|
+
logs.push(logMessage);
|
|
248
|
+
originalConsoleLog(`[GraphQL] ${logMessage}`);
|
|
249
|
+
};
|
|
250
|
+
// Create context for the handler
|
|
251
|
+
const context = {
|
|
252
|
+
awsRequestId: 'test-request-id',
|
|
253
|
+
functionName: 'graphql',
|
|
254
|
+
functionVersion: '$LATEST',
|
|
255
|
+
getRemainingTimeInMillis: ()=>30000,
|
|
256
|
+
invokedFunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:graphql',
|
|
257
|
+
logGroupName: '/aws/lambda/graphql',
|
|
258
|
+
logStreamName: 'test-log-stream',
|
|
259
|
+
req,
|
|
260
|
+
res
|
|
261
|
+
};
|
|
262
|
+
// Wrap handler with console log capture
|
|
263
|
+
const wrappedHandler = captureConsoleLogs(graphqlHandler, quiet);
|
|
264
|
+
try {
|
|
265
|
+
// Call the handler with GraphQL parameters
|
|
266
|
+
const result = await wrappedHandler({
|
|
267
|
+
body: JSON.stringify(req.body),
|
|
268
|
+
headers: req.headers,
|
|
269
|
+
httpMethod: 'POST',
|
|
270
|
+
path: graphqlPath,
|
|
271
|
+
queryStringParameters: {}
|
|
272
|
+
}, context);
|
|
273
|
+
// Restore console.log
|
|
274
|
+
console.log = originalConsoleLog;
|
|
275
|
+
// Handle the result
|
|
276
|
+
if (result && typeof result === 'object' && result.statusCode) {
|
|
277
|
+
res.status(result.statusCode);
|
|
278
|
+
if (result.headers) {
|
|
279
|
+
Object.entries(result.headers).forEach(([key, value])=>{
|
|
280
|
+
res.setHeader(key, String(value));
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
res.send(result.body);
|
|
284
|
+
} else {
|
|
285
|
+
res.json(result);
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
// Restore console.log
|
|
289
|
+
console.log = originalConsoleLog;
|
|
290
|
+
log(`GraphQL handler error: ${error.message}`, 'error', false);
|
|
291
|
+
res.status(500).json({
|
|
292
|
+
error: error.message
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
log(`GraphQL endpoint available at http://${host}:${httpPort}${graphqlPath}`, 'info', quiet);
|
|
355
297
|
}
|
|
356
|
-
} else {
|
|
357
|
-
res.status(404).json({ error: "Function not found" });
|
|
358
|
-
}
|
|
359
298
|
} catch (error) {
|
|
360
|
-
|
|
361
|
-
res.status(500).json({ error: error.message });
|
|
299
|
+
log(`Error setting up GraphQL: ${error.message}`, 'error', quiet);
|
|
362
300
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
301
|
+
// Fallback for non-GraphQL routes - handle all remaining routes
|
|
302
|
+
app.use('/', async (req, res)=>{
|
|
303
|
+
try {
|
|
304
|
+
const url = req.url || '/';
|
|
305
|
+
const method = req.method || 'GET';
|
|
306
|
+
const pathname = req.path || url.split('?')[0]; // Extract pathname without query string
|
|
307
|
+
log(`${method} ${url} (pathname: ${pathname})`, 'info', false);
|
|
308
|
+
// Find matching function
|
|
309
|
+
let matchedFunction = null;
|
|
310
|
+
if (config.functions) {
|
|
311
|
+
for (const [functionName, functionConfig] of Object.entries(config.functions)){
|
|
312
|
+
if (functionConfig.events) {
|
|
313
|
+
for (const event of functionConfig.events){
|
|
314
|
+
if (event.http) {
|
|
315
|
+
const eventPath = event.http.path || '/';
|
|
316
|
+
const eventMethod = event.http.method || 'GET';
|
|
317
|
+
// Improved path matching - compare pathname without query string
|
|
318
|
+
if (eventPath && eventPath === pathname && eventMethod === method) {
|
|
319
|
+
matchedFunction = functionName;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (matchedFunction) {
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
384
328
|
}
|
|
385
|
-
}
|
|
386
329
|
}
|
|
387
|
-
if (matchedFunction) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
330
|
+
if (matchedFunction && config.functions[matchedFunction]) {
|
|
331
|
+
// Resolve handler path relative to output directory
|
|
332
|
+
const handlerPath = config.functions[matchedFunction].handler;
|
|
333
|
+
const handler = await loadHandler(handlerPath, outputDir);
|
|
334
|
+
if (handler) {
|
|
335
|
+
const wrappedHandler = captureConsoleLogs(handler, quiet);
|
|
336
|
+
const event = {
|
|
337
|
+
body: req.body,
|
|
338
|
+
headers: req.headers,
|
|
339
|
+
httpMethod: method,
|
|
340
|
+
path: url,
|
|
341
|
+
queryStringParameters: req.query
|
|
342
|
+
};
|
|
343
|
+
const context = {
|
|
344
|
+
awsRequestId: 'test-request-id',
|
|
345
|
+
functionName: matchedFunction,
|
|
346
|
+
functionVersion: '$LATEST',
|
|
347
|
+
getRemainingTimeInMillis: ()=>30000,
|
|
348
|
+
invokedFunctionArn: `arn:aws:lambda:us-east-1:123456789012:function:${matchedFunction}`,
|
|
349
|
+
logGroupName: `/aws/lambda/${matchedFunction}`,
|
|
350
|
+
logStreamName: 'test-log-stream',
|
|
351
|
+
memoryLimitInMB: '128'
|
|
352
|
+
};
|
|
353
|
+
try {
|
|
354
|
+
const result = await wrappedHandler(event, context);
|
|
355
|
+
if (result && typeof result === 'object' && result.statusCode) {
|
|
356
|
+
res.status(result.statusCode);
|
|
357
|
+
if (result.headers) {
|
|
358
|
+
Object.entries(result.headers).forEach(([key, value])=>{
|
|
359
|
+
res.setHeader(key, String(value));
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
res.send(result.body);
|
|
363
|
+
} else {
|
|
364
|
+
res.json(result);
|
|
365
|
+
}
|
|
366
|
+
} catch (error) {
|
|
367
|
+
log(`Handler error: ${error.message}`, 'error', false);
|
|
368
|
+
res.status(500).json({
|
|
369
|
+
error: error.message
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
res.status(404).json({
|
|
374
|
+
error: 'Handler not found'
|
|
375
|
+
});
|
|
376
|
+
}
|
|
420
377
|
} else {
|
|
421
|
-
|
|
378
|
+
res.status(404).json({
|
|
379
|
+
error: 'Function not found'
|
|
380
|
+
});
|
|
422
381
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
382
|
+
} catch (error) {
|
|
383
|
+
log(`Route handling error: ${error.message}`, 'error', false);
|
|
384
|
+
res.status(500).json({
|
|
385
|
+
error: error.message
|
|
386
|
+
});
|
|
428
387
|
}
|
|
429
|
-
} catch (error) {
|
|
430
|
-
log(`WebSocket error: ${error.message}`, "error", false);
|
|
431
|
-
ws.send(JSON.stringify({ error: error.message }));
|
|
432
|
-
}
|
|
433
388
|
});
|
|
434
|
-
|
|
435
|
-
|
|
389
|
+
return app;
|
|
390
|
+
};
|
|
391
|
+
const createWebSocketServer = (config, outputDir, wsPort, quiet, debug)=>{
|
|
392
|
+
const wss = new WebSocketServer({
|
|
393
|
+
port: wsPort
|
|
394
|
+
});
|
|
395
|
+
wss.on('connection', async (ws, req)=>{
|
|
396
|
+
log(`WebSocket connection established: ${req.url}`, 'info', false);
|
|
397
|
+
ws.on('message', async (message)=>{
|
|
398
|
+
try {
|
|
399
|
+
const data = JSON.parse(message.toString());
|
|
400
|
+
// Find matching WebSocket function
|
|
401
|
+
let matchedFunction = null;
|
|
402
|
+
if (config.functions) {
|
|
403
|
+
for (const [functionName, functionConfig] of Object.entries(config.functions)){
|
|
404
|
+
if (functionConfig.events) {
|
|
405
|
+
for (const event of functionConfig.events){
|
|
406
|
+
if (event.websocket) {
|
|
407
|
+
const route = event.websocket.route || '$connect';
|
|
408
|
+
if (route === '$default' || route === data.action) {
|
|
409
|
+
matchedFunction = functionName;
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (matchedFunction) {
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (matchedFunction && config.functions[matchedFunction]) {
|
|
421
|
+
const handler = await loadHandler(config.functions[matchedFunction].handler, outputDir);
|
|
422
|
+
if (handler) {
|
|
423
|
+
// Wrap handler with console log capture
|
|
424
|
+
const wrappedHandler = captureConsoleLogs(handler, quiet);
|
|
425
|
+
const event = {
|
|
426
|
+
body: data.body || null,
|
|
427
|
+
requestContext: {
|
|
428
|
+
apiGateway: {
|
|
429
|
+
endpoint: `ws://localhost:${wsPort}`
|
|
430
|
+
},
|
|
431
|
+
connectionId: 'test-connection-id',
|
|
432
|
+
routeKey: data.action || '$default'
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const context = {
|
|
436
|
+
awsRequestId: 'test-request-id',
|
|
437
|
+
functionName: matchedFunction,
|
|
438
|
+
functionVersion: '$LATEST',
|
|
439
|
+
getRemainingTimeInMillis: ()=>30000,
|
|
440
|
+
invokedFunctionArn: `arn:aws:lambda:us-east-1:123456789012:function:${matchedFunction}`,
|
|
441
|
+
logGroupName: `/aws/lambda/${matchedFunction}`,
|
|
442
|
+
logStreamName: 'test-log-stream',
|
|
443
|
+
memoryLimitInMB: '128'
|
|
444
|
+
};
|
|
445
|
+
const result = await wrappedHandler(event, context);
|
|
446
|
+
// Handle Lambda response format for WebSocket
|
|
447
|
+
if (result && typeof result === 'object' && result.statusCode) {
|
|
448
|
+
// This is a Lambda response object, extract the body
|
|
449
|
+
const body = result.body || '';
|
|
450
|
+
ws.send(body);
|
|
451
|
+
} else {
|
|
452
|
+
// This is a direct response, stringify it
|
|
453
|
+
ws.send(JSON.stringify(result));
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
ws.send(JSON.stringify({
|
|
457
|
+
error: 'Handler not found'
|
|
458
|
+
}));
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
ws.send(JSON.stringify({
|
|
462
|
+
error: 'WebSocket function not found'
|
|
463
|
+
}));
|
|
464
|
+
}
|
|
465
|
+
} catch (error) {
|
|
466
|
+
log(`WebSocket error: ${error.message}`, 'error', false);
|
|
467
|
+
ws.send(JSON.stringify({
|
|
468
|
+
error: error.message
|
|
469
|
+
}));
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
ws.on('close', ()=>{
|
|
473
|
+
log('WebSocket connection closed', 'info', false);
|
|
474
|
+
});
|
|
436
475
|
});
|
|
437
|
-
|
|
438
|
-
return wss;
|
|
476
|
+
return wss;
|
|
439
477
|
};
|
|
440
|
-
const loadEnvFile = (envPath)
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
478
|
+
const loadEnvFile = (envPath)=>{
|
|
479
|
+
const envVars = {};
|
|
480
|
+
if (!existsSync(envPath)) {
|
|
481
|
+
return envVars;
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
const envContent = readFileSync(envPath, 'utf8');
|
|
485
|
+
const lines = envContent.split('\n');
|
|
486
|
+
for (const line of lines){
|
|
487
|
+
const trimmedLine = line.trim();
|
|
488
|
+
// Skip empty lines and comments
|
|
489
|
+
if (!trimmedLine || trimmedLine.startsWith('#')) {
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
// Parse KEY=value format
|
|
493
|
+
const equalIndex = trimmedLine.indexOf('=');
|
|
494
|
+
if (equalIndex > 0) {
|
|
495
|
+
const key = trimmedLine.substring(0, equalIndex).trim();
|
|
496
|
+
const value = trimmedLine.substring(equalIndex + 1).trim();
|
|
497
|
+
// Remove quotes if present
|
|
498
|
+
const cleanValue = value.replace(/^["']|["']$/g, '');
|
|
499
|
+
if (key) {
|
|
500
|
+
envVars[key] = cleanValue;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
460
503
|
}
|
|
461
|
-
|
|
504
|
+
} catch (error) {
|
|
505
|
+
log(`Warning: Could not load .env file at ${envPath}: ${error.message}`, 'warn', false);
|
|
462
506
|
}
|
|
463
|
-
|
|
464
|
-
log(`Warning: Could not load .env file at ${envPath}: ${error.message}`, "warn", false);
|
|
465
|
-
}
|
|
466
|
-
return envVars;
|
|
507
|
+
return envVars;
|
|
467
508
|
};
|
|
468
|
-
const serverless = async (cmd, callback = ()
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
];
|
|
492
|
-
let envVars = {};
|
|
493
|
-
for (const envPath of envPaths) {
|
|
494
|
-
const fileEnvVars = loadEnvFile(envPath);
|
|
495
|
-
if (Object.keys(fileEnvVars).length > 0) {
|
|
496
|
-
log(`Loaded environment variables from: ${envPath}`, "info", quiet);
|
|
509
|
+
export const serverless = async (cmd, callback = ()=>({}))=>{
|
|
510
|
+
const { cliName = 'Lex', config, debug = false, host = 'localhost', httpPort = 3000, httpsPort = 3001, quiet = false, remove = false, test = false, usePublicIp, variables, wsPort = 3002 } = cmd;
|
|
511
|
+
const spinner = createSpinner(quiet);
|
|
512
|
+
log(`${cliName} starting serverless development server...`, 'info', quiet);
|
|
513
|
+
await LexConfig.parseConfig(cmd);
|
|
514
|
+
const { outputFullPath } = LexConfig.config;
|
|
515
|
+
// Load environment variables from .env files
|
|
516
|
+
const envPaths = [
|
|
517
|
+
pathResolve(process.cwd(), '.env'),
|
|
518
|
+
pathResolve(process.cwd(), '.env.local'),
|
|
519
|
+
pathResolve(process.cwd(), '.env.development')
|
|
520
|
+
];
|
|
521
|
+
let envVars = {};
|
|
522
|
+
// Load from .env files in order (later files override earlier ones)
|
|
523
|
+
for (const envPath of envPaths){
|
|
524
|
+
const fileEnvVars = loadEnvFile(envPath);
|
|
525
|
+
if (Object.keys(fileEnvVars).length > 0) {
|
|
526
|
+
log(`Loaded environment variables from: ${envPath}`, 'info', quiet);
|
|
527
|
+
}
|
|
528
|
+
envVars = {
|
|
529
|
+
...envVars,
|
|
530
|
+
...fileEnvVars
|
|
531
|
+
};
|
|
497
532
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
533
|
+
// Start with default NODE_ENV and loaded .env variables
|
|
534
|
+
let variablesObj = {
|
|
535
|
+
NODE_ENV: 'development',
|
|
536
|
+
...envVars
|
|
537
|
+
};
|
|
538
|
+
// Override with command line variables if provided
|
|
539
|
+
if (variables) {
|
|
540
|
+
try {
|
|
541
|
+
const cliVars = JSON.parse(variables);
|
|
542
|
+
variablesObj = {
|
|
543
|
+
...variablesObj,
|
|
544
|
+
...cliVars
|
|
545
|
+
};
|
|
546
|
+
} catch (_error) {
|
|
547
|
+
log(`\n${cliName} Error: Environment variables option is not a valid JSON object.`, 'error', quiet);
|
|
548
|
+
callback(1);
|
|
549
|
+
return 1;
|
|
550
|
+
}
|
|
510
551
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
await removeFiles(outputFullPath || "");
|
|
521
|
-
spinner.succeed("Successfully cleaned output directory!");
|
|
522
|
-
}
|
|
523
|
-
let serverlessConfig = {};
|
|
524
|
-
try {
|
|
525
|
-
const configPath = config || pathResolve(process.cwd(), "lex.config.mjs");
|
|
526
|
-
log(`Loading serverless config from: ${configPath}`, "info", quiet);
|
|
527
|
-
if (existsSync(configPath)) {
|
|
528
|
-
const configModule = await import(configPath);
|
|
529
|
-
serverlessConfig = configModule.default?.serverless || configModule.serverless || {};
|
|
530
|
-
log("Serverless config loaded successfully", "info", quiet);
|
|
531
|
-
log(`Loaded functions: ${Object.keys(serverlessConfig.functions || {}).join(", ")}`, "info", quiet);
|
|
532
|
-
} else {
|
|
533
|
-
log(`No serverless config found at ${configPath}, using defaults`, "warn", quiet);
|
|
552
|
+
process.env = {
|
|
553
|
+
...process.env,
|
|
554
|
+
...variablesObj
|
|
555
|
+
};
|
|
556
|
+
// If in test mode, exit early after loading environment variables
|
|
557
|
+
if (test) {
|
|
558
|
+
log('Test mode: Environment variables loaded, exiting', 'info', quiet);
|
|
559
|
+
callback(0);
|
|
560
|
+
return 0;
|
|
534
561
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
...serverlessConfig,
|
|
540
|
-
custom: {
|
|
541
|
-
"serverless-offline": {
|
|
542
|
-
cors: serverlessConfig.custom?.["serverless-offline"]?.cors !== false,
|
|
543
|
-
host: serverlessConfig.custom?.["serverless-offline"]?.host || host,
|
|
544
|
-
httpPort: serverlessConfig.custom?.["serverless-offline"]?.httpPort || httpPort,
|
|
545
|
-
httpsPort: serverlessConfig.custom?.["serverless-offline"]?.httpsPort || httpsPort,
|
|
546
|
-
wsPort: serverlessConfig.custom?.["serverless-offline"]?.wsPort || wsPort
|
|
547
|
-
}
|
|
562
|
+
if (remove) {
|
|
563
|
+
spinner.start('Cleaning output directory...');
|
|
564
|
+
await removeFiles(outputFullPath || '');
|
|
565
|
+
spinner.succeed('Successfully cleaned output directory!');
|
|
548
566
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
callback(1);
|
|
578
|
-
return;
|
|
579
|
-
});
|
|
580
|
-
const server = expressApp.listen(httpPort2, host2, () => {
|
|
581
|
-
spinner.succeed("Serverless development server started.");
|
|
582
|
-
displayServerStatus(
|
|
583
|
-
httpPort2,
|
|
584
|
-
finalConfig.custom["serverless-offline"].httpsPort,
|
|
585
|
-
wsPort2,
|
|
586
|
-
host2,
|
|
587
|
-
quiet
|
|
588
|
-
);
|
|
589
|
-
fetchPublicIp(usePublicIp).then((publicIp) => {
|
|
590
|
-
if (publicIp) {
|
|
591
|
-
displayServerStatus(
|
|
592
|
-
httpPort2,
|
|
593
|
-
finalConfig.custom["serverless-offline"].httpsPort,
|
|
594
|
-
wsPort2,
|
|
595
|
-
host2,
|
|
596
|
-
quiet,
|
|
597
|
-
publicIp
|
|
598
|
-
);
|
|
567
|
+
// Load serverless configuration
|
|
568
|
+
let serverlessConfig = {};
|
|
569
|
+
try {
|
|
570
|
+
const configPath = config || pathResolve(process.cwd(), 'lex.config.mjs');
|
|
571
|
+
log(`Loading serverless config from: ${configPath}`, 'info', quiet);
|
|
572
|
+
if (existsSync(configPath)) {
|
|
573
|
+
const configModule = await import(configPath);
|
|
574
|
+
serverlessConfig = configModule.default?.serverless || configModule.serverless || {};
|
|
575
|
+
log('Serverless config loaded successfully', 'info', quiet);
|
|
576
|
+
log(`Loaded functions: ${Object.keys(serverlessConfig.functions || {}).join(', ')}`, 'info', quiet);
|
|
577
|
+
} else {
|
|
578
|
+
log(`No serverless config found at ${configPath}, using defaults`, 'warn', quiet);
|
|
579
|
+
}
|
|
580
|
+
} catch (error) {
|
|
581
|
+
log(`Error loading serverless config: ${error.message}`, 'error', quiet);
|
|
582
|
+
// Don't exit, continue with empty config
|
|
583
|
+
}
|
|
584
|
+
// Merge config with command line options
|
|
585
|
+
const finalConfig = {
|
|
586
|
+
...serverlessConfig,
|
|
587
|
+
custom: {
|
|
588
|
+
'serverless-offline': {
|
|
589
|
+
cors: serverlessConfig.custom?.['serverless-offline']?.cors !== false,
|
|
590
|
+
host: serverlessConfig.custom?.['serverless-offline']?.host || host,
|
|
591
|
+
httpPort: serverlessConfig.custom?.['serverless-offline']?.httpPort || httpPort,
|
|
592
|
+
httpsPort: serverlessConfig.custom?.['serverless-offline']?.httpsPort || httpsPort,
|
|
593
|
+
wsPort: serverlessConfig.custom?.['serverless-offline']?.wsPort || wsPort
|
|
594
|
+
}
|
|
599
595
|
}
|
|
600
|
-
});
|
|
601
|
-
});
|
|
602
|
-
server.on("error", (error) => {
|
|
603
|
-
log(`Express server error: ${error.message}`, "error", quiet);
|
|
604
|
-
spinner.fail("Failed to start Express server.");
|
|
605
|
-
callback(1);
|
|
606
|
-
return;
|
|
607
|
-
});
|
|
608
|
-
const shutdown = () => {
|
|
609
|
-
log("\nShutting down serverless development server...", "info", quiet);
|
|
610
|
-
server.close();
|
|
611
|
-
wsServer.close();
|
|
612
|
-
callback(0);
|
|
613
596
|
};
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
597
|
+
const outputDir = outputFullPath || 'lib';
|
|
598
|
+
log(`Using output directory: ${outputDir}`, 'info', quiet);
|
|
599
|
+
try {
|
|
600
|
+
spinner.start('Starting serverless development server...');
|
|
601
|
+
const httpPort = finalConfig.custom['serverless-offline'].httpPort;
|
|
602
|
+
const wsPort = finalConfig.custom['serverless-offline'].wsPort;
|
|
603
|
+
const host = finalConfig.custom['serverless-offline'].host;
|
|
604
|
+
log(`Creating HTTP server on ${host}:${httpPort}`, 'info', quiet);
|
|
605
|
+
log(`Creating WebSocket server on port ${wsPort}`, 'info', quiet);
|
|
606
|
+
// Create Express server
|
|
607
|
+
const expressApp = await createExpressServer(finalConfig, outputDir, httpPort, host, quiet, debug);
|
|
608
|
+
// Create WebSocket server
|
|
609
|
+
const wsServer = createWebSocketServer(finalConfig, outputDir, wsPort, quiet, debug);
|
|
610
|
+
// Handle server errors
|
|
611
|
+
wsServer.on('error', (error)=>{
|
|
612
|
+
log(`WebSocket server error: ${error.message}`, 'error', quiet);
|
|
613
|
+
spinner.fail('Failed to start WebSocket server.');
|
|
614
|
+
callback(1);
|
|
615
|
+
return;
|
|
616
|
+
});
|
|
617
|
+
// Start Express server
|
|
618
|
+
const server = expressApp.listen(httpPort, host, ()=>{
|
|
619
|
+
spinner.succeed('Serverless development server started.');
|
|
620
|
+
displayServerStatus(httpPort, finalConfig.custom['serverless-offline'].httpsPort, wsPort, host, quiet);
|
|
621
|
+
fetchPublicIp(usePublicIp).then((publicIp)=>{
|
|
622
|
+
if (publicIp) {
|
|
623
|
+
displayServerStatus(httpPort, finalConfig.custom['serverless-offline'].httpsPort, wsPort, host, quiet, publicIp);
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
// Handle Express server errors
|
|
628
|
+
server.on('error', (error)=>{
|
|
629
|
+
log(`Express server error: ${error.message}`, 'error', quiet);
|
|
630
|
+
spinner.fail('Failed to start Express server.');
|
|
631
|
+
callback(1);
|
|
632
|
+
return;
|
|
633
|
+
});
|
|
634
|
+
// Handle graceful shutdown
|
|
635
|
+
const shutdown = ()=>{
|
|
636
|
+
log('\nShutting down serverless development server...', 'info', quiet);
|
|
637
|
+
server.close();
|
|
638
|
+
wsServer.close();
|
|
639
|
+
callback(0);
|
|
640
|
+
};
|
|
641
|
+
process.on('SIGINT', shutdown);
|
|
642
|
+
process.on('SIGTERM', shutdown);
|
|
643
|
+
// Keep the process alive
|
|
644
|
+
process.stdin.resume();
|
|
645
|
+
log('Serverless development server is running. Press Ctrl+C to stop.', 'info', quiet);
|
|
646
|
+
// Don't call callback here, let the process stay alive
|
|
647
|
+
return 0;
|
|
648
|
+
} catch (error) {
|
|
649
|
+
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
|
|
650
|
+
spinner.fail('Failed to start serverless development server.');
|
|
651
|
+
callback(1);
|
|
652
|
+
return 1;
|
|
653
|
+
}
|
|
629
654
|
};
|
|
630
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL3NlcnZlcmxlc3Mvc2VydmVybGVzcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCBib3hlbiBmcm9tICdib3hlbic7XG5pbXBvcnQgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQge3JlYWRGaWxlU3luYywgZXhpc3RzU3luYywgbWtkaXJTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2hvbWVkaXJ9IGZyb20gJ29zJztcbmltcG9ydCB7cmVzb2x2ZSBhcyBwYXRoUmVzb2x2ZSwgam9pbn0gZnJvbSAncGF0aCc7XG5pbXBvcnQge1dlYlNvY2tldFNlcnZlcn0gZnJvbSAnd3MnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lciwgcmVtb3ZlRmlsZXN9IGZyb20gJy4uLy4uL3V0aWxzL2FwcC5qcyc7XG5pbXBvcnQge2xvZ30gZnJvbSAnLi4vLi4vdXRpbHMvbG9nLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJsZXNzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNsaU5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgZGVidWc/OiBib29sZWFuO1xuICByZWFkb25seSBob3N0Pzogc3RyaW5nO1xuICByZWFkb25seSBodHRwUG9ydD86IG51bWJlcjtcbiAgcmVhZG9ubHkgaHR0cHNQb3J0PzogbnVtYmVyO1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJlbW92ZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHRlc3Q/OiBib29sZWFuO1xuICByZWFkb25seSB1c2VQdWJsaWNJcD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHZhcmlhYmxlcz86IHN0cmluZztcbiAgcmVhZG9ubHkgd3NQb3J0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgdHlwZSBTZXJ2ZXJsZXNzQ2FsbGJhY2sgPSAoc3RhdHVzOiBudW1iZXIpID0+IHZvaWQ7XG5cbmludGVyZmFjZSBQdWJsaWNJcENhY2hlIHtcbiAgaXA6IHN0cmluZztcbiAgdGltZXN0YW1wOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBTZXJ2ZXJsZXNzSGFuZGxlciB7XG4gIHJlYWRvbmx5IGhhbmRsZXI6IHN0cmluZztcbiAgcmVhZG9ubHkgZXZlbnRzPzogQXJyYXk8e1xuICAgIHJlYWRvbmx5IGh0dHA/OiB7XG4gICAgICByZWFkb25seSBjb3JzPzogYm9vbGVhbjtcbiAgICAgIHJlYWRvbmx5IG1ldGhvZD86IHN0cmluZztcbiAgICAgIHJlYWRvbmx5IHBhdGg/OiBzdHJpbmc7XG4gICAgfTtcbiAgICByZWFkb25seSB3ZWJzb2NrZXQ/OiB7XG4gICAgICByZWFkb25seSByb3V0ZT86IHN0cmluZztcbiAgICB9O1xuICB9Pjtcbn1cblxuaW50ZXJmYWNlIFNlcnZlcmxlc3NDb25maWcge1xuICByZWFkb25seSBjdXN0b20/OiB7XG4gICAgcmVhZG9ubHkgJ3NlcnZlcmxlc3Mtb2ZmbGluZSc/OiB7XG4gICAgICByZWFkb25seSBjb3JzPzogYm9vbGVhbjtcbiAgICAgIHJlYWRvbmx5IGhvc3Q/OiBzdHJpbmc7XG4gICAgICByZWFkb25seSBodHRwUG9ydD86IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IGh0dHBzUG9ydD86IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IHdzUG9ydD86IG51bWJlcjtcbiAgICB9O1xuICB9O1xuICByZWFkb25seSBmdW5jdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBTZXJ2ZXJsZXNzSGFuZGxlcj47XG59XG5cbmNvbnN0IGdldENhY2hlRGlyID0gKCk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNhY2hlRGlyID0gam9pbihob21lZGlyKCksICcubGV4LWNhY2hlJyk7XG4gIGlmKCFleGlzdHNTeW5jKGNhY2hlRGlyKSkge1xuICAgIG1rZGlyU3luYyhjYWNoZURpciwge3JlY3Vyc2l2ZTogdHJ1ZX0pO1xuICB9XG4gIHJldHVybiBjYWNoZURpcjtcbn07XG5cbmNvbnN0IGdldENhY2hlUGF0aCA9ICgpOiBzdHJpbmcgPT4gam9pbihnZXRDYWNoZURpcigpLCAncHVibGljLWlwLmpzb24nKTtcblxuY29uc3QgcmVhZFB1YmxpY0lwQ2FjaGUgPSAoKTogUHVibGljSXBDYWNoZSB8IG51bGwgPT4ge1xuICBjb25zdCBjYWNoZVBhdGggPSBnZXRDYWNoZVBhdGgoKTtcbiAgaWYoIWV4aXN0c1N5bmMoY2FjaGVQYXRoKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjYWNoZURhdGEgPSByZWFkRmlsZVN5bmMoY2FjaGVQYXRoLCAndXRmOCcpO1xuICAgIGNvbnN0IGNhY2hlOiBQdWJsaWNJcENhY2hlID0gSlNPTi5wYXJzZShjYWNoZURhdGEpO1xuXG4gICAgLy8gQ2hlY2sgaWYgY2FjaGUgaXMgb2xkZXIgdGhhbiAxIHdlZWtcbiAgICBjb25zdCBvbmVXZWVrTXMgPSA3ICogMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgICBpZihEYXRlLm5vdygpIC0gY2FjaGUudGltZXN0YW1wID4gb25lV2Vla01zKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FjaGU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59O1xuXG5jb25zdCB3cml0ZVB1YmxpY0lwQ2FjaGUgPSAoaXA6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBjb25zdCBjYWNoZVBhdGggPSBnZXRDYWNoZVBhdGgoKTtcbiAgY29uc3QgY2FjaGU6IFB1YmxpY0lwQ2FjaGUgPSB7XG4gICAgaXAsXG4gICAgdGltZXN0YW1wOiBEYXRlLm5vdygpXG4gIH07XG4gIHdyaXRlRmlsZVN5bmMoY2FjaGVQYXRoLCBKU09OLnN0cmluZ2lmeShjYWNoZSwgbnVsbCwgMikpO1xufTtcblxuY29uc3QgZmV0Y2hQdWJsaWNJcCA9IChmb3JjZVJlZnJlc2g6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiA9PiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICBpZighZm9yY2VSZWZyZXNoKSB7XG4gICAgY29uc3QgY2FjaGVkID0gcmVhZFB1YmxpY0lwQ2FjaGUoKTtcbiAgICBpZihjYWNoZWQpIHtcbiAgICAgIHJlc29sdmUoY2FjaGVkLmlwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICAvLyBVc2UgZmV0Y2ggaW5zdGVhZCBvZiBodHRwc1xuICBmZXRjaCgnaHR0cHM6Ly9hcGkuaXBpZnkub3JnJylcbiAgICAudGhlbigocmVzKSA9PiByZXMudGV4dCgpKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICBjb25zdCBpcCA9IGRhdGEudHJpbSgpO1xuICAgICAgaWYoaXApIHtcbiAgICAgICAgd3JpdGVQdWJsaWNJcENhY2hlKGlwKTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoaXApO1xuICAgIH0pXG4gICAgLmNhdGNoKCgpID0+IHJlc29sdmUodW5kZWZpbmVkKSk7XG59KTtcblxuY29uc3QgZGlzcGxheVNlcnZlclN0YXR1cyA9IChcbiAgaHR0cFBvcnQ6IG51bWJlcixcbiAgaHR0cHNQb3J0OiBudW1iZXIsXG4gIHdzUG9ydDogbnVtYmVyLFxuICBob3N0OiBzdHJpbmcsXG4gIHF1aWV0OiBib29sZWFuLFxuICBwdWJsaWNJcD86IHN0cmluZ1xuKSA9PiB7XG4gIGlmKHF1aWV0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaHR0cFVybCA9IGBodHRwOi8vJHtob3N0fToke2h0dHBQb3J0fWA7XG4gIGNvbnN0IGh0dHBzVXJsID0gYGh0dHBzOi8vJHtob3N0fToke2h0dHBzUG9ydH1gO1xuICBjb25zdCB3c1VybCA9IGB3czovLyR7aG9zdH06JHt3c1BvcnR9YDtcbiAgY29uc3Qgd3NzVXJsID0gYHdzczovLyR7aG9zdH06JHt3c1BvcnR9YDtcblxuICBsZXQgdXJsTGluZXMgPSBgJHtjaGFsay5ncmVlbignSFRUUDonKX0gICAgICAke2NoYWxrLnVuZGVybGluZShodHRwVXJsKX1cXG5gO1xuICB1cmxMaW5lcyArPSBgJHtjaGFsay5ncmVlbignSFRUUFM6Jyl9ICAgICAke2NoYWxrLnVuZGVybGluZShodHRwc1VybCl9XFxuYDtcbiAgdXJsTGluZXMgKz0gYCR7Y2hhbGsuZ3JlZW4oJ1dlYlNvY2tldDonKX0gJHtjaGFsay51bmRlcmxpbmUod3NVcmwpfVxcbmA7XG4gIHVybExpbmVzICs9IGAke2NoYWxrLmdyZWVuKCdXU1M6Jyl9ICAgICAgICR7Y2hhbGsudW5kZXJsaW5lKHdzc1VybCl9XFxuYDtcblxuICBpZihwdWJsaWNJcCkge1xuICAgIHVybExpbmVzICs9IGBcXG4ke2NoYWxrLmdyZWVuKCdQdWJsaWM6Jyl9ICAgICR7Y2hhbGsudW5kZXJsaW5lKGBodHRwOi8vJHtwdWJsaWNJcH06JHtodHRwUG9ydH1gKX1cXG5gO1xuICB9XG5cbiAgY29uc3Qgc3RhdHVzQm94ID0gYm94ZW4oXG4gICAgYCR7Y2hhbGsuY3lhbi5ib2xkKCdcdUQ4M0RcdURFODAgU2VydmVybGVzcyBEZXZlbG9wbWVudCBTZXJ2ZXIgUnVubmluZycpfVxcblxcbiR7dXJsTGluZXN9XFxuYCArXG4gICAgYCR7Y2hhbGsueWVsbG93KCdQcmVzcyBDdHJsK0MgdG8gc3RvcCB0aGUgc2VydmVyJyl9YCxcbiAgICB7XG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICcjMWExYTFhJyxcbiAgICAgIGJvcmRlckNvbG9yOiAnY3lhbicsXG4gICAgICBib3JkZXJTdHlsZTogJ3JvdW5kJyxcbiAgICAgIG1hcmdpbjogMSxcbiAgICAgIHBhZGRpbmc6IDFcbiAgICB9XG4gICk7XG5cbiAgY29uc29sZS5sb2coYFxcbiR7c3RhdHVzQm94fVxcbmApO1xufTtcblxuY29uc3QgbG9hZEhhbmRsZXIgPSBhc3luYyAoaGFuZGxlclBhdGg6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpID0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGhSZXNvbHZlKG91dHB1dERpciwgaGFuZGxlclBhdGgpO1xuICAgIGxvZyhgTG9hZGluZyBoYW5kbGVyIGZyb206ICR7ZnVsbFBhdGh9YCwgJ2luZm8nLCBmYWxzZSk7XG5cbiAgICBpZighZXhpc3RzU3luYyhmdWxsUGF0aCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSGFuZGxlciBmaWxlIG5vdCBmb3VuZDogJHtmdWxsUGF0aH1gKTtcbiAgICB9XG5cbiAgICAvLyBEeW5hbWljIGltcG9ydCBvZiB0aGUgaGFuZGxlciB3aXRoIGJldHRlciBlcnJvciBoYW5kbGluZ1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBoYW5kbGVyTW9kdWxlID0gYXdhaXQgaW1wb3J0KGZ1bGxQYXRoKTtcbiAgICAgIGxvZyhgSGFuZGxlciBtb2R1bGUgbG9hZGVkOiAke09iamVjdC5rZXlzKGhhbmRsZXJNb2R1bGUpfWAsICdpbmZvJywgZmFsc2UpO1xuXG4gICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlck1vZHVsZS5kZWZhdWx0IHx8IGhhbmRsZXJNb2R1bGUuaGFuZGxlciB8fCBoYW5kbGVyTW9kdWxlO1xuICAgICAgbG9nKGBIYW5kbGVyIGZvdW5kOiAke3R5cGVvZiBoYW5kbGVyfWAsICdpbmZvJywgZmFsc2UpO1xuXG4gICAgICByZXR1cm4gaGFuZGxlcjtcbiAgICB9IGNhdGNoIChpbXBvcnRFcnJvcikge1xuICAgICAgbG9nKGBJbXBvcnQgZXJyb3IgZm9yIGhhbmRsZXIgJHtoYW5kbGVyUGF0aH06ICR7aW1wb3J0RXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBmYWxzZSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nKGBFcnJvciBsb2FkaW5nIGhhbmRsZXIgJHtoYW5kbGVyUGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBmYWxzZSk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cbmNvbnN0IGNhcHR1cmVDb25zb2xlTG9ncyA9IChoYW5kbGVyOiAoZXZlbnQ6IGFueSwgY29udGV4dDogYW55KSA9PiBQcm9taXNlPGFueT4sIHF1aWV0OiBib29sZWFuKSA9PiB7XG4gIGlmKHF1aWV0KSB7XG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICByZXR1cm4gYXN5bmMgKGV2ZW50OiBhbnksIGNvbnRleHQ6IGFueSkgPT4ge1xuICAgIC8vIENhcHR1cmUgY29uc29sZS5sb2csIGNvbnNvbGUuZXJyb3IsIGV0Yy5cbiAgICBjb25zdCBvcmlnaW5hbENvbnNvbGVMb2cgPSBjb25zb2xlLmxvZztcbiAgICBjb25zdCBvcmlnaW5hbENvbnNvbGVFcnJvciA9IGNvbnNvbGUuZXJyb3I7XG4gICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlV2FybiA9IGNvbnNvbGUud2FybjtcbiAgICBjb25zdCBvcmlnaW5hbENvbnNvbGVJbmZvID0gY29uc29sZS5pbmZvO1xuXG4gICAgY29uc3QgbG9nczogc3RyaW5nW10gPSBbXTtcblxuICAgIGNvbnNvbGUubG9nID0gKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICBsb2dzLnB1c2goYFtMT0ddICR7YXJncy5qb2luKCcgJyl9YCk7XG4gICAgICBvcmlnaW5hbENvbnNvbGVMb2coLi4uYXJncyk7XG4gICAgfTtcblxuICAgIGNvbnNvbGUuZXJyb3IgPSAoLi4uYXJnczogYW55W10pID0+IHtcbiAgICAgIGxvZ3MucHVzaChgW0VSUk9SXSAke2FyZ3Muam9pbignICcpfWApO1xuICAgICAgb3JpZ2luYWxDb25zb2xlRXJyb3IoLi4uYXJncyk7XG4gICAgfTtcblxuICAgIGNvbnNvbGUud2FybiA9ICguLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgICAgbG9ncy5wdXNoKGBbV0FSTl0gJHthcmdzLmpvaW4oJyAnKX1gKTtcbiAgICAgIG9yaWdpbmFsQ29uc29sZVdhcm4oLi4uYXJncyk7XG4gICAgfTtcblxuICAgIGNvbnNvbGUuaW5mbyA9ICguLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgICAgbG9ncy5wdXNoKGBbSU5GT10gJHthcmdzLmpvaW4oJyAnKX1gKTtcbiAgICAgIG9yaWdpbmFsQ29uc29sZUluZm8oLi4uYXJncyk7XG4gICAgfTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKGV2ZW50LCBjb250ZXh0KTtcblxuICAgICAgLy8gT3V0cHV0IGNhcHR1cmVkIGxvZ3NcbiAgICAgIGlmKGxvZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmF5KCctLS0gSGFuZGxlciBDb25zb2xlIE91dHB1dCAtLS0nKSk7XG4gICAgICAgIGxvZ3MuZm9yRWFjaCgobG9nKSA9PiBjb25zb2xlLmxvZyhjaGFsay5ncmF5KGxvZykpKTtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JheSgnLS0tIEVuZCBIYW5kbGVyIENvbnNvbGUgT3V0cHV0IC0tLScpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gUmVzdG9yZSBvcmlnaW5hbCBjb25zb2xlIG1ldGhvZHNcbiAgICAgIGNvbnNvbGUubG9nID0gb3JpZ2luYWxDb25zb2xlTG9nO1xuICAgICAgY29uc29sZS5lcnJvciA9IG9yaWdpbmFsQ29uc29sZUVycm9yO1xuICAgICAgY29uc29sZS53YXJuID0gb3JpZ2luYWxDb25zb2xlV2FybjtcbiAgICAgIGNvbnNvbGUuaW5mbyA9IG9yaWdpbmFsQ29uc29sZUluZm87XG4gICAgfVxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlRXhwcmVzc1NlcnZlciA9IGFzeW5jIChcbiAgY29uZmlnOiBTZXJ2ZXJsZXNzQ29uZmlnLFxuICBvdXRwdXREaXI6IHN0cmluZyxcbiAgaHR0cFBvcnQ6IG51bWJlcixcbiAgaG9zdDogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhbixcbiAgZGVidWc6IGJvb2xlYW5cbikgPT4ge1xuICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG5cbiAgLy8gRW5hYmxlIENPUlNcbiAgYXBwLnVzZSgocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nLCAnKicpO1xuICAgIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnLCAnR0VULCBQT1NULCBQVVQsIERFTEVURSwgUEFUQ0gsIE9QVElPTlMnKTtcbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzJywgJyonKTtcbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1DcmVkZW50aWFscycsICd0cnVlJyk7XG5cbiAgICBpZihyZXEubWV0aG9kID09PSAnT1BUSU9OUycpIHtcbiAgICAgIHJlcy5zZW5kU3RhdHVzKDIwMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5leHQoKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIFBhcnNlIEpTT04gYm9kaWVzXG4gIGFwcC51c2UoZXhwcmVzcy5qc29uKCkpO1xuXG4gIC8vIExvYWQgR3JhcGhRTCBoYW5kbGVyXG4gIGNvbnN0IGxvYWRHcmFwaFFMU2NoZW1hID0gYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBUcnkgdG8gZmluZCBhIEdyYXBoUUwgaGFuZGxlclxuICAgICAgbGV0IGdyYXBocWxIYW5kbGVyID0gbnVsbDtcblxuICAgICAgaWYoY29uZmlnLmZ1bmN0aW9ucykge1xuICAgICAgICBmb3IoY29uc3QgW2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgaWYoZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICBmb3IoY29uc3QgZXZlbnQgb2YgZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICAgIGlmKGV2ZW50Lmh0dHAgJiYgZXZlbnQuaHR0cC5wYXRoKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9vayBmb3IgR3JhcGhRTCBlbmRwb2ludHNcbiAgICAgICAgICAgICAgICBpZihldmVudC5odHRwLnBhdGggPT09ICcvcHVibGljJyB8fCBldmVudC5odHRwLnBhdGggPT09ICcvZ3JhcGhxbCcpIHtcbiAgICAgICAgICAgICAgICAgIGdyYXBocWxIYW5kbGVyID0gYXdhaXQgbG9hZEhhbmRsZXIoZnVuY3Rpb25Db25maWcuaGFuZGxlciwgb3V0cHV0RGlyKTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZihncmFwaHFsSGFuZGxlcikge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmKGdyYXBocWxIYW5kbGVyKSB7XG4gICAgICAgIGxvZygnRm91bmQgR3JhcGhRTCBoYW5kbGVyJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIHJldHVybiBncmFwaHFsSGFuZGxlcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2coYEVycm9yIGxvYWRpbmcgR3JhcGhRTCBoYW5kbGVyOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9O1xuXG4gIC8vIFNldCB1cCBHcmFwaFFMIGhhbmRsZXIgZm9yIEdyYXBoUUwgcmVxdWVzdHNcbiAgdHJ5IHtcbiAgICBjb25zdCBncmFwaHFsSGFuZGxlciA9IGF3YWl0IGxvYWRHcmFwaFFMU2NoZW1hKCk7XG4gICAgaWYoZ3JhcGhxbEhhbmRsZXIpIHtcbiAgICAgIC8vIEZpbmQgdGhlIEdyYXBoUUwgcGF0aCBmcm9tIHRoZSBzZXJ2ZXJsZXNzIGNvbmZpZ1xuICAgICAgbGV0IGdyYXBocWxQYXRoID0gJy9ncmFwaHFsJzsgLy8gZGVmYXVsdCBmYWxsYmFja1xuXG4gICAgICBpZihjb25maWcuZnVuY3Rpb25zKSB7XG4gICAgICAgIGZvcihjb25zdCBbX2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgaWYoZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICBmb3IoY29uc3QgZXZlbnQgb2YgZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICAgIGlmKGV2ZW50Py5odHRwPy5wYXRoKSB7XG4gICAgICAgICAgICAgICAgZ3JhcGhxbFBhdGggPSBldmVudC5odHRwLnBhdGg7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoZ3JhcGhxbFBhdGggIT09ICcvZ3JhcGhxbCcpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBTZXQgdXAgR3JhcGhRTCBlbmRwb2ludCB3aXRoIGVuaGFuY2VkIGNvbnNvbGUubG9nIGNhcHR1cmVcbiAgICAgIGFwcC51c2UoZ3JhcGhxbFBhdGgsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgICAgICAvLyBHcmFwaFFMIERlYnVnIExvZ2dpbmdcbiAgICAgICAgaWYoZGVidWcgJiYgcmVxLmJvZHkgJiYgcmVxLmJvZHkucXVlcnkpIHtcbiAgICAgICAgICBsb2coJ1x1RDgzRFx1REQwRCBHcmFwaFFMIERlYnVnIE1vZGU6IEFuYWx5emluZyByZXF1ZXN0Li4uJywgJ2luZm8nLCBmYWxzZSk7XG4gICAgICAgICAgbG9nKGBcdUQ4M0RcdURDREQgR3JhcGhRTCBRdWVyeTogJHtyZXEuYm9keS5xdWVyeX1gLCAnaW5mbycsIGZhbHNlKTtcbiAgICAgICAgICBpZihyZXEuYm9keS52YXJpYWJsZXMpIHtcbiAgICAgICAgICAgIGxvZyhgXHVEODNEXHVEQ0NBIEdyYXBoUUwgVmFyaWFibGVzOiAke0pTT04uc3RyaW5naWZ5KHJlcS5ib2R5LnZhcmlhYmxlcywgbnVsbCwgMil9YCwgJ2luZm8nLCBmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHJlcS5ib2R5Lm9wZXJhdGlvbk5hbWUpIHtcbiAgICAgICAgICAgIGxvZyhgXHVEODNDXHVERkY3XHVGRTBGICBHcmFwaFFMIE9wZXJhdGlvbjogJHtyZXEuYm9keS5vcGVyYXRpb25OYW1lfWAsICdpbmZvJywgZmFsc2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVuaGFuY2VkIGNvbnNvbGUubG9nIGNhcHR1cmVcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlTG9nID0gY29uc29sZS5sb2c7XG4gICAgICAgIGNvbnN0IGxvZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgY29uc29sZS5sb2cgPSAoLi4uYXJncykgPT4ge1xuICAgICAgICAgIGNvbnN0IGxvZ01lc3NhZ2UgPSBhcmdzLm1hcCgoYXJnKSA9PlxuICAgICAgICAgICAgKHR5cGVvZiBhcmcgPT09ICdvYmplY3QnID8gSlNPTi5zdHJpbmdpZnkoYXJnLCBudWxsLCAyKSA6IFN0cmluZyhhcmcpKVxuICAgICAgICAgICkuam9pbignICcpO1xuICAgICAgICAgIGxvZ3MucHVzaChsb2dNZXNzYWdlKTtcbiAgICAgICAgICBvcmlnaW5hbENvbnNvbGVMb2coYFtHcmFwaFFMXSAke2xvZ01lc3NhZ2V9YCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gQ3JlYXRlIGNvbnRleHQgZm9yIHRoZSBoYW5kbGVyXG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgYXdzUmVxdWVzdElkOiAndGVzdC1yZXF1ZXN0LWlkJyxcbiAgICAgICAgICBmdW5jdGlvbk5hbWU6ICdncmFwaHFsJyxcbiAgICAgICAgICBmdW5jdGlvblZlcnNpb246ICckTEFURVNUJyxcbiAgICAgICAgICBnZXRSZW1haW5pbmdUaW1lSW5NaWxsaXM6ICgpID0+IDMwMDAwLFxuICAgICAgICAgIGludm9rZWRGdW5jdGlvbkFybjogJ2Fybjphd3M6bGFtYmRhOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6ZnVuY3Rpb246Z3JhcGhxbCcsXG4gICAgICAgICAgbG9nR3JvdXBOYW1lOiAnL2F3cy9sYW1iZGEvZ3JhcGhxbCcsXG4gICAgICAgICAgbG9nU3RyZWFtTmFtZTogJ3Rlc3QtbG9nLXN0cmVhbScsXG4gICAgICAgICAgcmVxLFxuICAgICAgICAgIHJlc1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFdyYXAgaGFuZGxlciB3aXRoIGNvbnNvbGUgbG9nIGNhcHR1cmVcbiAgICAgICAgY29uc3Qgd3JhcHBlZEhhbmRsZXIgPSBjYXB0dXJlQ29uc29sZUxvZ3MoZ3JhcGhxbEhhbmRsZXIsIHF1aWV0KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIENhbGwgdGhlIGhhbmRsZXIgd2l0aCBHcmFwaFFMIHBhcmFtZXRlcnNcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cmFwcGVkSGFuZGxlcih7XG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShyZXEuYm9keSksXG4gICAgICAgICAgICBoZWFkZXJzOiByZXEuaGVhZGVycyxcbiAgICAgICAgICAgIGh0dHBNZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIHBhdGg6IGdyYXBocWxQYXRoLFxuICAgICAgICAgICAgcXVlcnlTdHJpbmdQYXJhbWV0ZXJzOiB7fVxuICAgICAgICAgIH0sIGNvbnRleHQpO1xuXG4gICAgICAgICAgLy8gUmVzdG9yZSBjb25zb2xlLmxvZ1xuICAgICAgICAgIGNvbnNvbGUubG9nID0gb3JpZ2luYWxDb25zb2xlTG9nO1xuXG4gICAgICAgICAgLy8gSGFuZGxlIHRoZSByZXN1bHRcbiAgICAgICAgICBpZihyZXN1bHQgJiYgdHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0LnN0YXR1c0NvZGUpIHtcbiAgICAgICAgICAgIHJlcy5zdGF0dXMocmVzdWx0LnN0YXR1c0NvZGUpO1xuICAgICAgICAgICAgaWYocmVzdWx0LmhlYWRlcnMpIHtcbiAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocmVzdWx0LmhlYWRlcnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICAgICAgICAgIHJlcy5zZXRIZWFkZXIoa2V5LCBTdHJpbmcodmFsdWUpKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMuc2VuZChyZXN1bHQuYm9keSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5qc29uKHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIC8vIFJlc3RvcmUgY29uc29sZS5sb2dcbiAgICAgICAgICBjb25zb2xlLmxvZyA9IG9yaWdpbmFsQ29uc29sZUxvZztcbiAgICAgICAgICBsb2coYEdyYXBoUUwgaGFuZGxlciBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIGZhbHNlKTtcbiAgICAgICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7ZXJyb3I6IGVycm9yLm1lc3NhZ2V9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGxvZyhgR3JhcGhRTCBlbmRwb2ludCBhdmFpbGFibGUgYXQgaHR0cDovLyR7aG9zdH06JHtodHRwUG9ydH0ke2dyYXBocWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2coYEVycm9yIHNldHRpbmcgdXAgR3JhcGhRTDogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgfVxuXG4gIC8vIEZhbGxiYWNrIGZvciBub24tR3JhcGhRTCByb3V0ZXMgLSBoYW5kbGUgYWxsIHJlbWFpbmluZyByb3V0ZXNcbiAgYXBwLnVzZSgnLycsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSByZXEudXJsIHx8ICcvJztcbiAgICAgIGNvbnN0IG1ldGhvZCA9IHJlcS5tZXRob2QgfHwgJ0dFVCc7XG4gICAgICBjb25zdCBwYXRobmFtZSA9IHJlcS5wYXRoIHx8IHVybC5zcGxpdCgnPycpWzBdOyAvLyBFeHRyYWN0IHBhdGhuYW1lIHdpdGhvdXQgcXVlcnkgc3RyaW5nXG5cbiAgICAgIGxvZyhgJHttZXRob2R9ICR7dXJsfSAocGF0aG5hbWU6ICR7cGF0aG5hbWV9KWAsICdpbmZvJywgZmFsc2UpO1xuXG4gICAgICAvLyBGaW5kIG1hdGNoaW5nIGZ1bmN0aW9uXG4gICAgICBsZXQgbWF0Y2hlZEZ1bmN0aW9uID0gbnVsbDtcblxuICAgICAgaWYoY29uZmlnLmZ1bmN0aW9ucykge1xuICAgICAgICBmb3IoY29uc3QgW2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgaWYoZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICBmb3IoY29uc3QgZXZlbnQgb2YgZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICAgIGlmKGV2ZW50Lmh0dHApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBldmVudFBhdGggPSBldmVudC5odHRwLnBhdGggfHwgJy8nO1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50TWV0aG9kID0gZXZlbnQuaHR0cC5tZXRob2QgfHwgJ0dFVCc7XG5cbiAgICAgICAgICAgICAgICAvLyBJbXByb3ZlZCBwYXRoIG1hdGNoaW5nIC0gY29tcGFyZSBwYXRobmFtZSB3aXRob3V0IHF1ZXJ5IHN0cmluZ1xuICAgICAgICAgICAgICAgIGlmKGV2ZW50UGF0aCAmJiBldmVudFBhdGggPT09IHBhdGhuYW1lICYmIGV2ZW50TWV0aG9kID09PSBtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgIG1hdGNoZWRGdW5jdGlvbiA9IGZ1bmN0aW9uTmFtZTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZihtYXRjaGVkRnVuY3Rpb24pIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihtYXRjaGVkRnVuY3Rpb24gJiYgY29uZmlnLmZ1bmN0aW9uc1ttYXRjaGVkRnVuY3Rpb25dKSB7XG4gICAgICAgIC8vIFJlc29sdmUgaGFuZGxlciBwYXRoIHJlbGF0aXZlIHRvIG91dHB1dCBkaXJlY3RvcnlcbiAgICAgICAgY29uc3QgaGFuZGxlclBhdGggPSBjb25maWcuZnVuY3Rpb25zW21hdGNoZWRGdW5jdGlvbl0uaGFuZGxlcjtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IGF3YWl0IGxvYWRIYW5kbGVyKGhhbmRsZXJQYXRoLCBvdXRwdXREaXIpO1xuXG4gICAgICAgIGlmKGhhbmRsZXIpIHtcbiAgICAgICAgICBjb25zdCB3cmFwcGVkSGFuZGxlciA9IGNhcHR1cmVDb25zb2xlTG9ncyhoYW5kbGVyLCBxdWlldCk7XG5cbiAgICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgIGJvZHk6IHJlcS5ib2R5LFxuICAgICAgICAgICAgaGVhZGVyczogcmVxLmhlYWRlcnMsXG4gICAgICAgICAgICBodHRwTWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICBwYXRoOiB1cmwsXG4gICAgICAgICAgICBxdWVyeVN0cmluZ1BhcmFtZXRlcnM6IHJlcS5xdWVyeVxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjb25zdCBjb250ZXh0ID0ge1xuICAgICAgICAgICAgYXdzUmVxdWVzdElkOiAndGVzdC1yZXF1ZXN0LWlkJyxcbiAgICAgICAgICAgIGZ1bmN0aW9uTmFtZTogbWF0Y2hlZEZ1bmN0aW9uLFxuICAgICAgICAgICAgZnVuY3Rpb25WZXJzaW9uOiAnJExBVEVTVCcsXG4gICAgICAgICAgICBnZXRSZW1haW5pbmdUaW1lSW5NaWxsaXM6ICgpID0+IDMwMDAwLFxuICAgICAgICAgICAgaW52b2tlZEZ1bmN0aW9uQXJuOiBgYXJuOmF3czpsYW1iZGE6dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpmdW5jdGlvbjoke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgbG9nR3JvdXBOYW1lOiBgL2F3cy9sYW1iZGEvJHttYXRjaGVkRnVuY3Rpb259YCxcbiAgICAgICAgICAgIGxvZ1N0cmVhbU5hbWU6ICd0ZXN0LWxvZy1zdHJlYW0nLFxuICAgICAgICAgICAgbWVtb3J5TGltaXRJbk1COiAnMTI4J1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JhcHBlZEhhbmRsZXIoZXZlbnQsIGNvbnRleHQpO1xuXG4gICAgICAgICAgICBpZihyZXN1bHQgJiYgdHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0LnN0YXR1c0NvZGUpIHtcbiAgICAgICAgICAgICAgcmVzLnN0YXR1cyhyZXN1bHQuc3RhdHVzQ29kZSk7XG4gICAgICAgICAgICAgIGlmKHJlc3VsdC5oZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocmVzdWx0LmhlYWRlcnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgcmVzLnNldEhlYWRlcihrZXksIFN0cmluZyh2YWx1ZSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlcy5zZW5kKHJlc3VsdC5ib2R5KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlcy5qc29uKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZyhgSGFuZGxlciBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIGZhbHNlKTtcbiAgICAgICAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtlcnJvcjogZXJyb3IubWVzc2FnZX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXMuc3RhdHVzKDQwNCkuanNvbih7ZXJyb3I6ICdIYW5kbGVyIG5vdCBmb3VuZCd9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oe2Vycm9yOiAnRnVuY3Rpb24gbm90IGZvdW5kJ30pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2coYFJvdXRlIGhhbmRsaW5nIGVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgZmFsc2UpO1xuICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oe2Vycm9yOiBlcnJvci5tZXNzYWdlfSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gYXBwO1xufTtcblxuY29uc3QgY3JlYXRlV2ViU29ja2V0U2VydmVyID0gKFxuICBjb25maWc6IFNlcnZlcmxlc3NDb25maWcsXG4gIG91dHB1dERpcjogc3RyaW5nLFxuICB3c1BvcnQ6IG51bWJlcixcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuXG4pID0+IHtcbiAgY29uc3Qgd3NzID0gbmV3IFdlYlNvY2tldFNlcnZlcih7cG9ydDogd3NQb3J0fSk7XG5cbiAgd3NzLm9uKCdjb25uZWN0aW9uJywgYXN5bmMgKHdzLCByZXEpID0+IHtcbiAgICBsb2coYFdlYlNvY2tldCBjb25uZWN0aW9uIGVzdGFibGlzaGVkOiAke3JlcS51cmx9YCwgJ2luZm8nLCBmYWxzZSk7XG5cbiAgICB3cy5vbignbWVzc2FnZScsIGFzeW5jIChtZXNzYWdlKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZShtZXNzYWdlLnRvU3RyaW5nKCkpO1xuXG4gICAgICAgIC8vIEZpbmQgbWF0Y2hpbmcgV2ViU29ja2V0IGZ1bmN0aW9uXG4gICAgICAgIGxldCBtYXRjaGVkRnVuY3Rpb24gPSBudWxsO1xuXG4gICAgICAgIGlmKGNvbmZpZy5mdW5jdGlvbnMpIHtcbiAgICAgICAgICBmb3IoY29uc3QgW2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgICBpZihmdW5jdGlvbkNvbmZpZy5ldmVudHMpIHtcbiAgICAgICAgICAgICAgZm9yKGNvbnN0IGV2ZW50IG9mIGZ1bmN0aW9uQ29uZmlnLmV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmKGV2ZW50LndlYnNvY2tldCkge1xuICAgICAgICAgICAgICAgICAgY29uc3Qgcm91dGUgPSBldmVudC53ZWJzb2NrZXQucm91dGUgfHwgJyRjb25uZWN0JztcbiAgICAgICAgICAgICAgICAgIGlmKHJvdXRlID09PSAnJGRlZmF1bHQnIHx8IHJvdXRlID09PSBkYXRhLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGVkRnVuY3Rpb24gPSBmdW5jdGlvbk5hbWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYobWF0Y2hlZEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG1hdGNoZWRGdW5jdGlvbiAmJiBjb25maWcuZnVuY3Rpb25zW21hdGNoZWRGdW5jdGlvbl0pIHtcbiAgICAgICAgICBjb25zdCBoYW5kbGVyID0gYXdhaXQgbG9hZEhhbmRsZXIoY29uZmlnLmZ1bmN0aW9uc1ttYXRjaGVkRnVuY3Rpb25dLmhhbmRsZXIsIG91dHB1dERpcik7XG5cbiAgICAgICAgICBpZihoYW5kbGVyKSB7XG4gICAgICAgICAgICAvLyBXcmFwIGhhbmRsZXIgd2l0aCBjb25zb2xlIGxvZyBjYXB0dXJlXG4gICAgICAgICAgICBjb25zdCB3cmFwcGVkSGFuZGxlciA9IGNhcHR1cmVDb25zb2xlTG9ncyhoYW5kbGVyLCBxdWlldCk7XG4gICAgICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgICAgYm9keTogZGF0YS5ib2R5IHx8IG51bGwsXG4gICAgICAgICAgICAgIHJlcXVlc3RDb250ZXh0OiB7XG4gICAgICAgICAgICAgICAgYXBpR2F0ZXdheToge1xuICAgICAgICAgICAgICAgICAgZW5kcG9pbnQ6IGB3czovL2xvY2FsaG9zdDoke3dzUG9ydH1gXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWQ6ICd0ZXN0LWNvbm5lY3Rpb24taWQnLFxuICAgICAgICAgICAgICAgIHJvdXRlS2V5OiBkYXRhLmFjdGlvbiB8fCAnJGRlZmF1bHQnXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgICAgIGF3c1JlcXVlc3RJZDogJ3Rlc3QtcmVxdWVzdC1pZCcsXG4gICAgICAgICAgICAgIGZ1bmN0aW9uTmFtZTogbWF0Y2hlZEZ1bmN0aW9uLFxuICAgICAgICAgICAgICBmdW5jdGlvblZlcnNpb246ICckTEFURVNUJyxcbiAgICAgICAgICAgICAgZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzOiAoKSA9PiAzMDAwMCxcbiAgICAgICAgICAgICAgaW52b2tlZEZ1bmN0aW9uQXJuOiBgYXJuOmF3czpsYW1iZGE6dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpmdW5jdGlvbjoke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgICBsb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgICBsb2dTdHJlYW1OYW1lOiAndGVzdC1sb2ctc3RyZWFtJyxcbiAgICAgICAgICAgICAgbWVtb3J5TGltaXRJbk1COiAnMTI4J1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JhcHBlZEhhbmRsZXIoZXZlbnQsIGNvbnRleHQpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgTGFtYmRhIHJlc3BvbnNlIGZvcm1hdCBmb3IgV2ViU29ja2V0XG4gICAgICAgICAgICBpZihyZXN1bHQgJiYgdHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0LnN0YXR1c0NvZGUpIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIExhbWJkYSByZXNwb25zZSBvYmplY3QsIGV4dHJhY3QgdGhlIGJvZHlcbiAgICAgICAgICAgICAgY29uc3QgYm9keSA9IHJlc3VsdC5ib2R5IHx8ICcnO1xuICAgICAgICAgICAgICB3cy5zZW5kKGJvZHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIGRpcmVjdCByZXNwb25zZSwgc3RyaW5naWZ5IGl0XG4gICAgICAgICAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoe2Vycm9yOiAnSGFuZGxlciBub3QgZm91bmQnfSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KHtlcnJvcjogJ1dlYlNvY2tldCBmdW5jdGlvbiBub3QgZm91bmQnfSkpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2coYFdlYlNvY2tldCBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIGZhbHNlKTtcbiAgICAgICAgd3Muc2VuZChKU09OLnN0cmluZ2lmeSh7ZXJyb3I6IGVycm9yLm1lc3NhZ2V9KSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB3cy5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICBsb2coJ1dlYlNvY2tldCBjb25uZWN0aW9uIGNsb3NlZCcsICdpbmZvJywgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gd3NzO1xufTtcblxuY29uc3QgbG9hZEVudkZpbGUgPSAoZW52UGF0aDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9PiB7XG4gIGNvbnN0IGVudlZhcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBpZighZXhpc3RzU3luYyhlbnZQYXRoKSkge1xuICAgIHJldHVybiBlbnZWYXJzO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBlbnZDb250ZW50ID0gcmVhZEZpbGVTeW5jKGVudlBhdGgsICd1dGY4Jyk7XG4gICAgY29uc3QgbGluZXMgPSBlbnZDb250ZW50LnNwbGl0KCdcXG4nKTtcblxuICAgIGZvcihjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICBjb25zdCB0cmltbWVkTGluZSA9IGxpbmUudHJpbSgpO1xuXG4gICAgICAvLyBTa2lwIGVtcHR5IGxpbmVzIGFuZCBjb21tZW50c1xuICAgICAgaWYoIXRyaW1tZWRMaW5lIHx8IHRyaW1tZWRMaW5lLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gUGFyc2UgS0VZPXZhbHVlIGZvcm1hdFxuICAgICAgY29uc3QgZXF1YWxJbmRleCA9IHRyaW1tZWRMaW5lLmluZGV4T2YoJz0nKTtcbiAgICAgIGlmKGVxdWFsSW5kZXggPiAwKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IHRyaW1tZWRMaW5lLnN1YnN0cmluZygwLCBlcXVhbEluZGV4KS50cmltKCk7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdHJpbW1lZExpbmUuc3Vic3RyaW5nKGVxdWFsSW5kZXggKyAxKS50cmltKCk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHF1b3RlcyBpZiBwcmVzZW50XG4gICAgICAgIGNvbnN0IGNsZWFuVmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9eW1wiJ118W1wiJ10kL2csICcnKTtcblxuICAgICAgICBpZihrZXkpIHtcbiAgICAgICAgICBlbnZWYXJzW2tleV0gPSBjbGVhblZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZyhgV2FybmluZzogQ291bGQgbm90IGxvYWQgLmVudiBmaWxlIGF0ICR7ZW52UGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnd2FybicsIGZhbHNlKTtcbiAgfVxuXG4gIHJldHVybiBlbnZWYXJzO1xufTtcblxuZXhwb3J0IGNvbnN0IHNlcnZlcmxlc3MgPSBhc3luYyAoXG4gIGNtZDogU2VydmVybGVzc09wdGlvbnMsXG4gIGNhbGxiYWNrOiBTZXJ2ZXJsZXNzQ2FsbGJhY2sgPSAoKSA9PiAoe30pXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCB7XG4gICAgY2xpTmFtZSA9ICdMZXgnLFxuICAgIGNvbmZpZyxcbiAgICBkZWJ1ZyA9IGZhbHNlLFxuICAgIGhvc3QgPSAnbG9jYWxob3N0JyxcbiAgICBodHRwUG9ydCA9IDMwMDAsXG4gICAgaHR0cHNQb3J0ID0gMzAwMSxcbiAgICBxdWlldCA9IGZhbHNlLFxuICAgIHJlbW92ZSA9IGZhbHNlLFxuICAgIHRlc3QgPSBmYWxzZSxcbiAgICB1c2VQdWJsaWNJcCxcbiAgICB2YXJpYWJsZXMsXG4gICAgd3NQb3J0ID0gMzAwMlxuICB9ID0gY21kO1xuXG4gIGNvbnN0IHNwaW5uZXIgPSBjcmVhdGVTcGlubmVyKHF1aWV0KTtcblxuICBsb2coYCR7Y2xpTmFtZX0gc3RhcnRpbmcgc2VydmVybGVzcyBkZXZlbG9wbWVudCBzZXJ2ZXIuLi5gLCAnaW5mbycsIHF1aWV0KTtcblxuICBhd2FpdCBMZXhDb25maWcucGFyc2VDb25maWcoY21kKTtcblxuICBjb25zdCB7b3V0cHV0RnVsbFBhdGh9ID0gTGV4Q29uZmlnLmNvbmZpZztcblxuICAvLyBMb2FkIGVudmlyb25tZW50IHZhcmlhYmxlcyBmcm9tIC5lbnYgZmlsZXNcbiAgY29uc3QgZW52UGF0aHMgPSBbXG4gICAgcGF0aFJlc29sdmUocHJvY2Vzcy5jd2QoKSwgJy5lbnYnKSxcbiAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLmVudi5sb2NhbCcpLFxuICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICcuZW52LmRldmVsb3BtZW50JylcbiAgXTtcblxuICBsZXQgZW52VmFyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIC8vIExvYWQgZnJvbSAuZW52IGZpbGVzIGluIG9yZGVyIChsYXRlciBmaWxlcyBvdmVycmlkZSBlYXJsaWVyIG9uZXMpXG4gIGZvcihjb25zdCBlbnZQYXRoIG9mIGVudlBhdGhzKSB7XG4gICAgY29uc3QgZmlsZUVudlZhcnMgPSBsb2FkRW52RmlsZShlbnZQYXRoKTtcbiAgICBpZihPYmplY3Qua2V5cyhmaWxlRW52VmFycykubGVuZ3RoID4gMCkge1xuICAgICAgbG9nKGBMb2FkZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZyb206ICR7ZW52UGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG4gICAgZW52VmFycyA9IHsuLi5lbnZWYXJzLCAuLi5maWxlRW52VmFyc307XG4gIH1cblxuICAvLyBTdGFydCB3aXRoIGRlZmF1bHQgTk9ERV9FTlYgYW5kIGxvYWRlZCAuZW52IHZhcmlhYmxlc1xuICBsZXQgdmFyaWFibGVzT2JqOiBvYmplY3QgPSB7Tk9ERV9FTlY6ICdkZXZlbG9wbWVudCcsIC4uLmVudlZhcnN9O1xuXG4gIC8vIE92ZXJyaWRlIHdpdGggY29tbWFuZCBsaW5lIHZhcmlhYmxlcyBpZiBwcm92aWRlZFxuICBpZih2YXJpYWJsZXMpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2xpVmFycyA9IEpTT04ucGFyc2UodmFyaWFibGVzKTtcbiAgICAgIHZhcmlhYmxlc09iaiA9IHsuLi52YXJpYWJsZXNPYmosIC4uLmNsaVZhcnN9O1xuICAgIH0gY2F0Y2ggKF9lcnJvcikge1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgb3B0aW9uIGlzIG5vdCBhIHZhbGlkIEpTT04gb2JqZWN0LmAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIGNhbGxiYWNrKDEpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9XG5cbiAgcHJvY2Vzcy5lbnYgPSB7Li4ucHJvY2Vzcy5lbnYsIC4uLnZhcmlhYmxlc09ian07XG5cbiAgLy8gSWYgaW4gdGVzdCBtb2RlLCBleGl0IGVhcmx5IGFmdGVyIGxvYWRpbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gIGlmKHRlc3QpIHtcbiAgICBsb2coJ1Rlc3QgbW9kZTogRW52aXJvbm1lbnQgdmFyaWFibGVzIGxvYWRlZCwgZXhpdGluZycsICdpbmZvJywgcXVpZXQpO1xuICAgIGNhbGxiYWNrKDApO1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgaWYocmVtb3ZlKSB7XG4gICAgc3Bpbm5lci5zdGFydCgnQ2xlYW5pbmcgb3V0cHV0IGRpcmVjdG9yeS4uLicpO1xuICAgIGF3YWl0IHJlbW92ZUZpbGVzKG91dHB1dEZ1bGxQYXRoIHx8ICcnKTtcbiAgICBzcGlubmVyLnN1Y2NlZWQoJ1N1Y2Nlc3NmdWxseSBjbGVhbmVkIG91dHB1dCBkaXJlY3RvcnkhJyk7XG4gIH1cblxuICAvLyBMb2FkIHNlcnZlcmxlc3MgY29uZmlndXJhdGlvblxuICBsZXQgc2VydmVybGVzc0NvbmZpZzogU2VydmVybGVzc0NvbmZpZyA9IHt9O1xuXG4gIHRyeSB7XG4gICAgY29uc3QgY29uZmlnUGF0aCA9IGNvbmZpZyB8fCBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnbGV4LmNvbmZpZy5tanMnKTtcbiAgICBsb2coYExvYWRpbmcgc2VydmVybGVzcyBjb25maWcgZnJvbTogJHtjb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgaWYoZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgICAgY29uc3QgY29uZmlnTW9kdWxlID0gYXdhaXQgaW1wb3J0KGNvbmZpZ1BhdGgpO1xuICAgICAgc2VydmVybGVzc0NvbmZpZyA9IGNvbmZpZ01vZHVsZS5kZWZhdWx0Py5zZXJ2ZXJsZXNzIHx8IGNvbmZpZ01vZHVsZS5zZXJ2ZXJsZXNzIHx8IHt9O1xuICAgICAgbG9nKCdTZXJ2ZXJsZXNzIGNvbmZpZyBsb2FkZWQgc3VjY2Vzc2Z1bGx5JywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBsb2coYExvYWRlZCBmdW5jdGlvbnM6ICR7T2JqZWN0LmtleXMoc2VydmVybGVzc0NvbmZpZy5mdW5jdGlvbnMgfHwge30pLmpvaW4oJywgJyl9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZyhgTm8gc2VydmVybGVzcyBjb25maWcgZm91bmQgYXQgJHtjb25maWdQYXRofSwgdXNpbmcgZGVmYXVsdHNgLCAnd2FybicsIHF1aWV0KTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nKGBFcnJvciBsb2FkaW5nIHNlcnZlcmxlc3MgY29uZmlnOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIC8vIERvbid0IGV4aXQsIGNvbnRpbnVlIHdpdGggZW1wdHkgY29uZmlnXG4gIH1cblxuICAvLyBNZXJnZSBjb25maWcgd2l0aCBjb21tYW5kIGxpbmUgb3B0aW9uc1xuICBjb25zdCBmaW5hbENvbmZpZzogU2VydmVybGVzc0NvbmZpZyA9IHtcbiAgICAuLi5zZXJ2ZXJsZXNzQ29uZmlnLFxuICAgIGN1c3RvbToge1xuICAgICAgJ3NlcnZlcmxlc3Mtb2ZmbGluZSc6IHtcbiAgICAgICAgY29yczogc2VydmVybGVzc0NvbmZpZy5jdXN0b20/Llsnc2VydmVybGVzcy1vZmZsaW5lJ10/LmNvcnMgIT09IGZhbHNlLFxuICAgICAgICBob3N0OiBzZXJ2ZXJsZXNzQ29uZmlnLmN1c3RvbT8uWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXT8uaG9zdCB8fCBob3N0LFxuICAgICAgICBodHRwUG9ydDogc2VydmVybGVzc0NvbmZpZy5jdXN0b20/Llsnc2VydmVybGVzcy1vZmZsaW5lJ10/Lmh0dHBQb3J0IHx8IGh0dHBQb3J0LFxuICAgICAgICBodHRwc1BvcnQ6IHNlcnZlcmxlc3NDb25maWcuY3VzdG9tPy5bJ3NlcnZlcmxlc3Mtb2ZmbGluZSddPy5odHRwc1BvcnQgfHwgaHR0cHNQb3J0LFxuICAgICAgICB3c1BvcnQ6IHNlcnZlcmxlc3NDb25maWcuY3VzdG9tPy5bJ3NlcnZlcmxlc3Mtb2ZmbGluZSddPy53c1BvcnQgfHwgd3NQb3J0XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IG91dHB1dERpciA9IG91dHB1dEZ1bGxQYXRoIHx8ICdsaWInO1xuICBsb2coYFVzaW5nIG91dHB1dCBkaXJlY3Rvcnk6ICR7b3V0cHV0RGlyfWAsICdpbmZvJywgcXVpZXQpO1xuXG4gIHRyeSB7XG4gICAgc3Bpbm5lci5zdGFydCgnU3RhcnRpbmcgc2VydmVybGVzcyBkZXZlbG9wbWVudCBzZXJ2ZXIuLi4nKTtcblxuICAgIGNvbnN0IGh0dHBQb3J0ID0gZmluYWxDb25maWcuY3VzdG9tIVsnc2VydmVybGVzcy1vZmZsaW5lJ10hLmh0dHBQb3J0ITtcbiAgICBjb25zdCB3c1BvcnQgPSBmaW5hbENvbmZpZy5jdXN0b20hWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXSEud3NQb3J0ITtcbiAgICBjb25zdCBob3N0ID0gZmluYWxDb25maWcuY3VzdG9tIVsnc2VydmVybGVzcy1vZmZsaW5lJ10hLmhvc3QhO1xuXG4gICAgbG9nKGBDcmVhdGluZyBIVFRQIHNlcnZlciBvbiAke2hvc3R9OiR7aHR0cFBvcnR9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgbG9nKGBDcmVhdGluZyBXZWJTb2NrZXQgc2VydmVyIG9uIHBvcnQgJHt3c1BvcnR9YCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgICAvLyBDcmVhdGUgRXhwcmVzcyBzZXJ2ZXJcbiAgICBjb25zdCBleHByZXNzQXBwID0gYXdhaXQgY3JlYXRlRXhwcmVzc1NlcnZlcihcbiAgICAgIGZpbmFsQ29uZmlnLFxuICAgICAgb3V0cHV0RGlyLFxuICAgICAgaHR0cFBvcnQsXG4gICAgICBob3N0LFxuICAgICAgcXVpZXQsXG4gICAgICBkZWJ1Z1xuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgV2ViU29ja2V0IHNlcnZlclxuICAgIGNvbnN0IHdzU2VydmVyID0gY3JlYXRlV2ViU29ja2V0U2VydmVyKFxuICAgICAgZmluYWxDb25maWcsXG4gICAgICBvdXRwdXREaXIsXG4gICAgICB3c1BvcnQsXG4gICAgICBxdWlldCxcbiAgICAgIGRlYnVnXG4gICAgKTtcblxuICAgIC8vIEhhbmRsZSBzZXJ2ZXIgZXJyb3JzXG4gICAgd3NTZXJ2ZXIub24oJ2Vycm9yJywgKGVycm9yKSA9PiB7XG4gICAgICBsb2coYFdlYlNvY2tldCBzZXJ2ZXIgZXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICBzcGlubmVyLmZhaWwoJ0ZhaWxlZCB0byBzdGFydCBXZWJTb2NrZXQgc2VydmVyLicpO1xuICAgICAgY2FsbGJhY2soMSk7XG4gICAgICByZXR1cm47XG4gICAgfSk7XG5cbiAgICAvLyBTdGFydCBFeHByZXNzIHNlcnZlclxuICAgIGNvbnN0IHNlcnZlciA9IGV4cHJlc3NBcHAubGlzdGVuKGh0dHBQb3J0LCBob3N0LCAoKSA9PiB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoJ1NlcnZlcmxlc3MgZGV2ZWxvcG1lbnQgc2VydmVyIHN0YXJ0ZWQuJyk7XG5cbiAgICAgIGRpc3BsYXlTZXJ2ZXJTdGF0dXMoXG4gICAgICAgIGh0dHBQb3J0LFxuICAgICAgICBmaW5hbENvbmZpZy5jdXN0b20hWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXSEuaHR0cHNQb3J0ISxcbiAgICAgICAgd3NQb3J0LFxuICAgICAgICBob3N0LFxuICAgICAgICBxdWlldFxuICAgICAgKTtcblxuICAgICAgZmV0Y2hQdWJsaWNJcCh1c2VQdWJsaWNJcCkudGhlbigocHVibGljSXApID0+IHtcbiAgICAgICAgaWYocHVibGljSXApIHtcbiAgICAgICAgICBkaXNwbGF5U2VydmVyU3RhdHVzKFxuICAgICAgICAgICAgaHR0cFBvcnQsXG4gICAgICAgICAgICBmaW5hbENvbmZpZy5jdXN0b20hWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXSEuaHR0cHNQb3J0ISxcbiAgICAgICAgICAgIHdzUG9ydCxcbiAgICAgICAgICAgIGhvc3QsXG4gICAgICAgICAgICBxdWlldCxcbiAgICAgICAgICAgIHB1YmxpY0lwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBIYW5kbGUgRXhwcmVzcyBzZXJ2ZXIgZXJyb3JzXG4gICAgc2VydmVyLm9uKCdlcnJvcicsIChlcnJvcikgPT4ge1xuICAgICAgbG9nKGBFeHByZXNzIHNlcnZlciBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIHNwaW5uZXIuZmFpbCgnRmFpbGVkIHRvIHN0YXJ0IEV4cHJlc3Mgc2VydmVyLicpO1xuICAgICAgY2FsbGJhY2soMSk7XG4gICAgICByZXR1cm47XG4gICAgfSk7XG5cbiAgICAvLyBIYW5kbGUgZ3JhY2VmdWwgc2h1dGRvd25cbiAgICBjb25zdCBzaHV0ZG93biA9ICgpID0+IHtcbiAgICAgIGxvZygnXFxuU2h1dHRpbmcgZG93biBzZXJ2ZXJsZXNzIGRldmVsb3BtZW50IHNlcnZlci4uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgc2VydmVyLmNsb3NlKCk7XG4gICAgICB3c1NlcnZlci5jbG9zZSgpO1xuICAgICAgY2FsbGJhY2soMCk7XG4gICAgfTtcblxuICAgIHByb2Nlc3Mub24oJ1NJR0lOVCcsIHNodXRkb3duKTtcbiAgICBwcm9jZXNzLm9uKCdTSUdURVJNJywgc2h1dGRvd24pO1xuXG4gICAgLy8gS2VlcCB0aGUgcHJvY2VzcyBhbGl2ZVxuICAgIHByb2Nlc3Muc3RkaW4ucmVzdW1lKCk7XG5cbiAgICBsb2coJ1NlcnZlcmxlc3MgZGV2ZWxvcG1lbnQgc2VydmVyIGlzIHJ1bm5pbmcuIFByZXNzIEN0cmwrQyB0byBzdG9wLicsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgLy8gRG9uJ3QgY2FsbCBjYWxsYmFjayBoZXJlLCBsZXQgdGhlIHByb2Nlc3Mgc3RheSBhbGl2ZVxuICAgIHJldHVybiAwO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICBzcGlubmVyLmZhaWwoJ0ZhaWxlZCB0byBzdGFydCBzZXJ2ZXJsZXNzIGRldmVsb3BtZW50IHNlcnZlci4nKTtcbiAgICBjYWxsYmFjaygxKTtcbiAgICByZXR1cm4gMTtcbiAgfVxufTsiXSwKICAibWFwcGluZ3MiOiAiQUFJQSxPQUFPLFdBQVc7QUFDbEIsT0FBTyxXQUFXO0FBQ2xCLE9BQU8sYUFBYTtBQUNwQixTQUFRLGNBQWMsWUFBWSxXQUFXLHFC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V0FBTyxHQUFHLFNBQVMsQ0FBQyxVQUFVO0FBQzVCLFVBQUkseUJBQXlCLE1BQU0sT0FBTyxJQUFJLFNBQVMsS0FBSztBQUM1RCxjQUFRLEtBQUssaUNBQWlDO0FBQzlDLGVBQVMsQ0FBQztBQUNWO0FBQUEsSUFDRixDQUFDO0FBR0QsVUFBTSxXQUFXLE1BQU07QUFDckIsVUFBSSxvREFBb0QsUUFBUSxLQUFLO0FBQ3JFLGFBQU8sTUFBTTtBQUNiLGVBQVMsTUFBTTtBQUNmLGVBQVMsQ0FBQztBQUFBLElBQ1o7QUFFQSxZQUFRLEdBQUcsVUFBVSxRQUFRO0FBQzdCLFlBQVEsR0FBRyxXQUFXLFFBQVE7QUFHOUIsWUFBUSxNQUFNLE9BQU87QUFFckIsUUFBSSxtRUFBbUUsUUFBUSxLQUFLO0FBR3BGLFdBQU87QUFBQSxFQUNULFNBQVMsT0FBTztBQUNkLFFBQUk7QUFBQSxFQUFLLE9BQU8sV0FBVyxNQUFNLE9BQU8sSUFBSSxTQUFTLEtBQUs7QUFDMUQsWUFBUSxLQUFLLGdEQUFnRDtBQUM3RCxhQUFTLENBQUM7QUFDVixXQUFPO0FBQUEsRUFDVDtBQUNGOyIsCiAgIm5hbWVzIjogWyJsb2ciLCAiaHR0cFBvcnQiLCAid3NQb3J0IiwgImhvc3QiXQp9Cg==
|
|
655
|
+
|
|
656
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9zZXJ2ZXJsZXNzL3NlcnZlcmxlc3MudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCBib3hlbiBmcm9tICdib3hlbic7XG5pbXBvcnQgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQge3JlYWRGaWxlU3luYywgZXhpc3RzU3luYywgbWtkaXJTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2hvbWVkaXJ9IGZyb20gJ29zJztcbmltcG9ydCB7cmVzb2x2ZSBhcyBwYXRoUmVzb2x2ZSwgam9pbn0gZnJvbSAncGF0aCc7XG5pbXBvcnQge1dlYlNvY2tldFNlcnZlcn0gZnJvbSAnd3MnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lciwgcmVtb3ZlRmlsZXN9IGZyb20gJy4uLy4uL3V0aWxzL2FwcC5qcyc7XG5pbXBvcnQge2xvZ30gZnJvbSAnLi4vLi4vdXRpbHMvbG9nLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJsZXNzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNsaU5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgZGVidWc/OiBib29sZWFuO1xuICByZWFkb25seSBob3N0Pzogc3RyaW5nO1xuICByZWFkb25seSBodHRwUG9ydD86IG51bWJlcjtcbiAgcmVhZG9ubHkgaHR0cHNQb3J0PzogbnVtYmVyO1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJlbW92ZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHRlc3Q/OiBib29sZWFuO1xuICByZWFkb25seSB1c2VQdWJsaWNJcD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHZhcmlhYmxlcz86IHN0cmluZztcbiAgcmVhZG9ubHkgd3NQb3J0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgdHlwZSBTZXJ2ZXJsZXNzQ2FsbGJhY2sgPSAoc3RhdHVzOiBudW1iZXIpID0+IHZvaWQ7XG5cbmludGVyZmFjZSBQdWJsaWNJcENhY2hlIHtcbiAgaXA6IHN0cmluZztcbiAgdGltZXN0YW1wOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBTZXJ2ZXJsZXNzSGFuZGxlciB7XG4gIHJlYWRvbmx5IGhhbmRsZXI6IHN0cmluZztcbiAgcmVhZG9ubHkgZXZlbnRzPzogQXJyYXk8e1xuICAgIHJlYWRvbmx5IGh0dHA/OiB7XG4gICAgICByZWFkb25seSBjb3JzPzogYm9vbGVhbjtcbiAgICAgIHJlYWRvbmx5IG1ldGhvZD86IHN0cmluZztcbiAgICAgIHJlYWRvbmx5IHBhdGg/OiBzdHJpbmc7XG4gICAgfTtcbiAgICByZWFkb25seSB3ZWJzb2NrZXQ/OiB7XG4gICAgICByZWFkb25seSByb3V0ZT86IHN0cmluZztcbiAgICB9O1xuICB9Pjtcbn1cblxuaW50ZXJmYWNlIFNlcnZlcmxlc3NDb25maWcge1xuICByZWFkb25seSBjdXN0b20/OiB7XG4gICAgcmVhZG9ubHkgJ3NlcnZlcmxlc3Mtb2ZmbGluZSc/OiB7XG4gICAgICByZWFkb25seSBjb3JzPzogYm9vbGVhbjtcbiAgICAgIHJlYWRvbmx5IGhvc3Q/OiBzdHJpbmc7XG4gICAgICByZWFkb25seSBodHRwUG9ydD86IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IGh0dHBzUG9ydD86IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IHdzUG9ydD86IG51bWJlcjtcbiAgICB9O1xuICB9O1xuICByZWFkb25seSBmdW5jdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBTZXJ2ZXJsZXNzSGFuZGxlcj47XG59XG5cbmNvbnN0IGdldENhY2hlRGlyID0gKCk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNhY2hlRGlyID0gam9pbihob21lZGlyKCksICcubGV4LWNhY2hlJyk7XG4gIGlmKCFleGlzdHNTeW5jKGNhY2hlRGlyKSkge1xuICAgIG1rZGlyU3luYyhjYWNoZURpciwge3JlY3Vyc2l2ZTogdHJ1ZX0pO1xuICB9XG4gIHJldHVybiBjYWNoZURpcjtcbn07XG5cbmNvbnN0IGdldENhY2hlUGF0aCA9ICgpOiBzdHJpbmcgPT4gam9pbihnZXRDYWNoZURpcigpLCAncHVibGljLWlwLmpzb24nKTtcblxuY29uc3QgcmVhZFB1YmxpY0lwQ2FjaGUgPSAoKTogUHVibGljSXBDYWNoZSB8IG51bGwgPT4ge1xuICBjb25zdCBjYWNoZVBhdGggPSBnZXRDYWNoZVBhdGgoKTtcbiAgaWYoIWV4aXN0c1N5bmMoY2FjaGVQYXRoKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjYWNoZURhdGEgPSByZWFkRmlsZVN5bmMoY2FjaGVQYXRoLCAndXRmOCcpO1xuICAgIGNvbnN0IGNhY2hlOiBQdWJsaWNJcENhY2hlID0gSlNPTi5wYXJzZShjYWNoZURhdGEpO1xuXG4gICAgLy8gQ2hlY2sgaWYgY2FjaGUgaXMgb2xkZXIgdGhhbiAxIHdlZWtcbiAgICBjb25zdCBvbmVXZWVrTXMgPSA3ICogMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgICBpZihEYXRlLm5vdygpIC0gY2FjaGUudGltZXN0YW1wID4gb25lV2Vla01zKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FjaGU7XG4gIH0gY2F0Y2h7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cbmNvbnN0IHdyaXRlUHVibGljSXBDYWNoZSA9IChpcDogc3RyaW5nKTogdm9pZCA9PiB7XG4gIGNvbnN0IGNhY2hlUGF0aCA9IGdldENhY2hlUGF0aCgpO1xuICBjb25zdCBjYWNoZTogUHVibGljSXBDYWNoZSA9IHtcbiAgICBpcCxcbiAgICB0aW1lc3RhbXA6IERhdGUubm93KClcbiAgfTtcbiAgd3JpdGVGaWxlU3luYyhjYWNoZVBhdGgsIEpTT04uc3RyaW5naWZ5KGNhY2hlLCBudWxsLCAyKSk7XG59O1xuXG5jb25zdCBmZXRjaFB1YmxpY0lwID0gKGZvcmNlUmVmcmVzaDogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+ID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gIGlmKCFmb3JjZVJlZnJlc2gpIHtcbiAgICBjb25zdCBjYWNoZWQgPSByZWFkUHVibGljSXBDYWNoZSgpO1xuICAgIGlmKGNhY2hlZCkge1xuICAgICAgcmVzb2x2ZShjYWNoZWQuaXApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVzZSBmZXRjaCBpbnN0ZWFkIG9mIGh0dHBzXG4gIGZldGNoKCdodHRwczovL2FwaS5pcGlmeS5vcmcnKVxuICAgIC50aGVuKChyZXMpID0+IHJlcy50ZXh0KCkpXG4gICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgIGNvbnN0IGlwID0gZGF0YS50cmltKCk7XG4gICAgICBpZihpcCkge1xuICAgICAgICB3cml0ZVB1YmxpY0lwQ2FjaGUoaXApO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShpcCk7XG4gICAgfSlcbiAgICAuY2F0Y2goKCkgPT4gcmVzb2x2ZSh1bmRlZmluZWQpKTtcbn0pO1xuXG5jb25zdCBkaXNwbGF5U2VydmVyU3RhdHVzID0gKFxuICBodHRwUG9ydDogbnVtYmVyLFxuICBodHRwc1BvcnQ6IG51bWJlcixcbiAgd3NQb3J0OiBudW1iZXIsXG4gIGhvc3Q6IHN0cmluZyxcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIHB1YmxpY0lwPzogc3RyaW5nXG4pID0+IHtcbiAgaWYocXVpZXQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBodHRwVXJsID0gYGh0dHA6Ly8ke2hvc3R9OiR7aHR0cFBvcnR9YDtcbiAgY29uc3QgaHR0cHNVcmwgPSBgaHR0cHM6Ly8ke2hvc3R9OiR7aHR0cHNQb3J0fWA7XG4gIGNvbnN0IHdzVXJsID0gYHdzOi8vJHtob3N0fToke3dzUG9ydH1gO1xuICBjb25zdCB3c3NVcmwgPSBgd3NzOi8vJHtob3N0fToke3dzUG9ydH1gO1xuXG4gIGxldCB1cmxMaW5lcyA9IGAke2NoYWxrLmdyZWVuKCdIVFRQOicpfSAgICAgICR7Y2hhbGsudW5kZXJsaW5lKGh0dHBVcmwpfVxcbmA7XG4gIHVybExpbmVzICs9IGAke2NoYWxrLmdyZWVuKCdIVFRQUzonKX0gICAgICR7Y2hhbGsudW5kZXJsaW5lKGh0dHBzVXJsKX1cXG5gO1xuICB1cmxMaW5lcyArPSBgJHtjaGFsay5ncmVlbignV2ViU29ja2V0OicpfSAke2NoYWxrLnVuZGVybGluZSh3c1VybCl9XFxuYDtcbiAgdXJsTGluZXMgKz0gYCR7Y2hhbGsuZ3JlZW4oJ1dTUzonKX0gICAgICAgJHtjaGFsay51bmRlcmxpbmUod3NzVXJsKX1cXG5gO1xuXG4gIGlmKHB1YmxpY0lwKSB7XG4gICAgdXJsTGluZXMgKz0gYFxcbiR7Y2hhbGsuZ3JlZW4oJ1B1YmxpYzonKX0gICAgJHtjaGFsay51bmRlcmxpbmUoYGh0dHA6Ly8ke3B1YmxpY0lwfToke2h0dHBQb3J0fWApfVxcbmA7XG4gIH1cblxuICBjb25zdCBzdGF0dXNCb3ggPSBib3hlbihcbiAgICBgJHtjaGFsay5jeWFuLmJvbGQoJ/CfmoAgU2VydmVybGVzcyBEZXZlbG9wbWVudCBTZXJ2ZXIgUnVubmluZycpfVxcblxcbiR7dXJsTGluZXN9XFxuYCArXG4gICAgYCR7Y2hhbGsueWVsbG93KCdQcmVzcyBDdHJsK0MgdG8gc3RvcCB0aGUgc2VydmVyJyl9YCxcbiAgICB7XG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICcjMWExYTFhJyxcbiAgICAgIGJvcmRlckNvbG9yOiAnY3lhbicsXG4gICAgICBib3JkZXJTdHlsZTogJ3JvdW5kJyxcbiAgICAgIG1hcmdpbjogMSxcbiAgICAgIHBhZGRpbmc6IDFcbiAgICB9XG4gICk7XG5cbiAgY29uc29sZS5sb2coYFxcbiR7c3RhdHVzQm94fVxcbmApO1xufTtcblxuY29uc3QgbG9hZEhhbmRsZXIgPSBhc3luYyAoaGFuZGxlclBhdGg6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpID0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGhSZXNvbHZlKG91dHB1dERpciwgaGFuZGxlclBhdGgpO1xuICAgIGxvZyhgTG9hZGluZyBoYW5kbGVyIGZyb206ICR7ZnVsbFBhdGh9YCwgJ2luZm8nLCBmYWxzZSk7XG5cbiAgICBpZighZXhpc3RzU3luYyhmdWxsUGF0aCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSGFuZGxlciBmaWxlIG5vdCBmb3VuZDogJHtmdWxsUGF0aH1gKTtcbiAgICB9XG5cbiAgICAvLyBEeW5hbWljIGltcG9ydCBvZiB0aGUgaGFuZGxlciB3aXRoIGJldHRlciBlcnJvciBoYW5kbGluZ1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBoYW5kbGVyTW9kdWxlID0gYXdhaXQgaW1wb3J0KGZ1bGxQYXRoKTtcbiAgICAgIGxvZyhgSGFuZGxlciBtb2R1bGUgbG9hZGVkOiAke09iamVjdC5rZXlzKGhhbmRsZXJNb2R1bGUpfWAsICdpbmZvJywgZmFsc2UpO1xuXG4gICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlck1vZHVsZS5kZWZhdWx0IHx8IGhhbmRsZXJNb2R1bGUuaGFuZGxlciB8fCBoYW5kbGVyTW9kdWxlO1xuICAgICAgbG9nKGBIYW5kbGVyIGZvdW5kOiAke3R5cGVvZiBoYW5kbGVyfWAsICdpbmZvJywgZmFsc2UpO1xuXG4gICAgICByZXR1cm4gaGFuZGxlcjtcbiAgICB9IGNhdGNoKGltcG9ydEVycm9yKSB7XG4gICAgICBsb2coYEltcG9ydCBlcnJvciBmb3IgaGFuZGxlciAke2hhbmRsZXJQYXRofTogJHtpbXBvcnRFcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIGZhbHNlKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfSBjYXRjaChlcnJvcikge1xuICAgIGxvZyhgRXJyb3IgbG9hZGluZyBoYW5kbGVyICR7aGFuZGxlclBhdGh9OiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgZmFsc2UpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG59O1xuXG5jb25zdCBjYXB0dXJlQ29uc29sZUxvZ3MgPSAoaGFuZGxlcjogKGV2ZW50OiBhbnksIGNvbnRleHQ6IGFueSkgPT4gUHJvbWlzZTxhbnk+LCBxdWlldDogYm9vbGVhbikgPT4ge1xuICBpZihxdWlldCkge1xuICAgIHJldHVybiBoYW5kbGVyO1xuICB9XG5cbiAgcmV0dXJuIGFzeW5jIChldmVudDogYW55LCBjb250ZXh0OiBhbnkpID0+IHtcbiAgICAvLyBDYXB0dXJlIGNvbnNvbGUubG9nLCBjb25zb2xlLmVycm9yLCBldGMuXG4gICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlTG9nID0gY29uc29sZS5sb2c7XG4gICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlRXJyb3IgPSBjb25zb2xlLmVycm9yO1xuICAgIGNvbnN0IG9yaWdpbmFsQ29uc29sZVdhcm4gPSBjb25zb2xlLndhcm47XG4gICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlSW5mbyA9IGNvbnNvbGUuaW5mbztcblxuICAgIGNvbnN0IGxvZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgICBjb25zb2xlLmxvZyA9ICguLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgICAgbG9ncy5wdXNoKGBbTE9HXSAke2FyZ3Muam9pbignICcpfWApO1xuICAgICAgb3JpZ2luYWxDb25zb2xlTG9nKC4uLmFyZ3MpO1xuICAgIH07XG5cbiAgICBjb25zb2xlLmVycm9yID0gKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICBsb2dzLnB1c2goYFtFUlJPUl0gJHthcmdzLmpvaW4oJyAnKX1gKTtcbiAgICAgIG9yaWdpbmFsQ29uc29sZUVycm9yKC4uLmFyZ3MpO1xuICAgIH07XG5cbiAgICBjb25zb2xlLndhcm4gPSAoLi4uYXJnczogYW55W10pID0+IHtcbiAgICAgIGxvZ3MucHVzaChgW1dBUk5dICR7YXJncy5qb2luKCcgJyl9YCk7XG4gICAgICBvcmlnaW5hbENvbnNvbGVXYXJuKC4uLmFyZ3MpO1xuICAgIH07XG5cbiAgICBjb25zb2xlLmluZm8gPSAoLi4uYXJnczogYW55W10pID0+IHtcbiAgICAgIGxvZ3MucHVzaChgW0lORk9dICR7YXJncy5qb2luKCcgJyl9YCk7XG4gICAgICBvcmlnaW5hbENvbnNvbGVJbmZvKC4uLmFyZ3MpO1xuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaGFuZGxlcihldmVudCwgY29udGV4dCk7XG5cbiAgICAgIC8vIE91dHB1dCBjYXB0dXJlZCBsb2dzXG4gICAgICBpZihsb2dzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JheSgnLS0tIEhhbmRsZXIgQ29uc29sZSBPdXRwdXQgLS0tJykpO1xuICAgICAgICBsb2dzLmZvckVhY2goKGxvZykgPT4gY29uc29sZS5sb2coY2hhbGsuZ3JheShsb2cpKSk7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyYXkoJy0tLSBFbmQgSGFuZGxlciBDb25zb2xlIE91dHB1dCAtLS0nKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIC8vIFJlc3RvcmUgb3JpZ2luYWwgY29uc29sZSBtZXRob2RzXG4gICAgICBjb25zb2xlLmxvZyA9IG9yaWdpbmFsQ29uc29sZUxvZztcbiAgICAgIGNvbnNvbGUuZXJyb3IgPSBvcmlnaW5hbENvbnNvbGVFcnJvcjtcbiAgICAgIGNvbnNvbGUud2FybiA9IG9yaWdpbmFsQ29uc29sZVdhcm47XG4gICAgICBjb25zb2xlLmluZm8gPSBvcmlnaW5hbENvbnNvbGVJbmZvO1xuICAgIH1cbiAgfTtcbn07XG5cbmNvbnN0IGNyZWF0ZUV4cHJlc3NTZXJ2ZXIgPSBhc3luYyAoXG4gIGNvbmZpZzogU2VydmVybGVzc0NvbmZpZyxcbiAgb3V0cHV0RGlyOiBzdHJpbmcsXG4gIGh0dHBQb3J0OiBudW1iZXIsXG4gIGhvc3Q6IHN0cmluZyxcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuXG4pID0+IHtcbiAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuXG4gIC8vIEVuYWJsZSBDT1JTXG4gIGFwcC51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgJyonKTtcbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1NZXRob2RzJywgJ0dFVCwgUE9TVCwgUFVULCBERUxFVEUsIFBBVENILCBPUFRJT05TJyk7XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycycsICcqJyk7XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctQ3JlZGVudGlhbHMnLCAndHJ1ZScpO1xuXG4gICAgaWYocmVxLm1ldGhvZCA9PT0gJ09QVElPTlMnKSB7XG4gICAgICByZXMuc2VuZFN0YXR1cygyMDApO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0KCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBQYXJzZSBKU09OIGJvZGllc1xuICBhcHAudXNlKGV4cHJlc3MuanNvbigpKTtcblxuICAvLyBMb2FkIEdyYXBoUUwgaGFuZGxlclxuICBjb25zdCBsb2FkR3JhcGhRTFNjaGVtYSA9IGFzeW5jICgpID0+IHtcbiAgICB0cnkge1xuICAgICAgLy8gVHJ5IHRvIGZpbmQgYSBHcmFwaFFMIGhhbmRsZXJcbiAgICAgIGxldCBncmFwaHFsSGFuZGxlciA9IG51bGw7XG5cbiAgICAgIGlmKGNvbmZpZy5mdW5jdGlvbnMpIHtcbiAgICAgICAgZm9yKGNvbnN0IFtmdW5jdGlvbk5hbWUsIGZ1bmN0aW9uQ29uZmlnXSBvZiBPYmplY3QuZW50cmllcyhjb25maWcuZnVuY3Rpb25zKSkge1xuICAgICAgICAgIGlmKGZ1bmN0aW9uQ29uZmlnLmV2ZW50cykge1xuICAgICAgICAgICAgZm9yKGNvbnN0IGV2ZW50IG9mIGZ1bmN0aW9uQ29uZmlnLmV2ZW50cykge1xuICAgICAgICAgICAgICBpZihldmVudC5odHRwICYmIGV2ZW50Lmh0dHAucGF0aCkge1xuICAgICAgICAgICAgICAgIC8vIExvb2sgZm9yIEdyYXBoUUwgZW5kcG9pbnRzXG4gICAgICAgICAgICAgICAgaWYoZXZlbnQuaHR0cC5wYXRoID09PSAnL3B1YmxpYycgfHwgZXZlbnQuaHR0cC5wYXRoID09PSAnL2dyYXBocWwnKSB7XG4gICAgICAgICAgICAgICAgICBncmFwaHFsSGFuZGxlciA9IGF3YWl0IGxvYWRIYW5kbGVyKGZ1bmN0aW9uQ29uZmlnLmhhbmRsZXIsIG91dHB1dERpcik7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoZ3JhcGhxbEhhbmRsZXIpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihncmFwaHFsSGFuZGxlcikge1xuICAgICAgICBsb2coJ0ZvdW5kIEdyYXBoUUwgaGFuZGxlcicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICByZXR1cm4gZ3JhcGhxbEhhbmRsZXI7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICBsb2coYEVycm9yIGxvYWRpbmcgR3JhcGhRTCBoYW5kbGVyOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9O1xuXG4gIC8vIFNldCB1cCBHcmFwaFFMIGhhbmRsZXIgZm9yIEdyYXBoUUwgcmVxdWVzdHNcbiAgdHJ5IHtcbiAgICBjb25zdCBncmFwaHFsSGFuZGxlciA9IGF3YWl0IGxvYWRHcmFwaFFMU2NoZW1hKCk7XG4gICAgaWYoZ3JhcGhxbEhhbmRsZXIpIHtcbiAgICAgIC8vIEZpbmQgdGhlIEdyYXBoUUwgcGF0aCBmcm9tIHRoZSBzZXJ2ZXJsZXNzIGNvbmZpZ1xuICAgICAgbGV0IGdyYXBocWxQYXRoID0gJy9ncmFwaHFsJzsgLy8gZGVmYXVsdCBmYWxsYmFja1xuXG4gICAgICBpZihjb25maWcuZnVuY3Rpb25zKSB7XG4gICAgICAgIGZvcihjb25zdCBbX2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgaWYoZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICBmb3IoY29uc3QgZXZlbnQgb2YgZnVuY3Rpb25Db25maWcuZXZlbnRzKSB7XG4gICAgICAgICAgICAgIGlmKGV2ZW50Py5odHRwPy5wYXRoKSB7XG4gICAgICAgICAgICAgICAgZ3JhcGhxbFBhdGggPSBldmVudC5odHRwLnBhdGg7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoZ3JhcGhxbFBhdGggIT09ICcvZ3JhcGhxbCcpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBTZXQgdXAgR3JhcGhRTCBlbmRwb2ludCB3aXRoIGVuaGFuY2VkIGNvbnNvbGUubG9nIGNhcHR1cmVcbiAgICAgIGFwcC51c2UoZ3JhcGhxbFBhdGgsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgICAgICAvLyBHcmFwaFFMIERlYnVnIExvZ2dpbmdcbiAgICAgICAgaWYoZGVidWcgJiYgcmVxLmJvZHkgJiYgcmVxLmJvZHkucXVlcnkpIHtcbiAgICAgICAgICBsb2coJ/CflI0gR3JhcGhRTCBEZWJ1ZyBNb2RlOiBBbmFseXppbmcgcmVxdWVzdC4uLicsICdpbmZvJywgZmFsc2UpO1xuICAgICAgICAgIGxvZyhg8J+TnSBHcmFwaFFMIFF1ZXJ5OiAke3JlcS5ib2R5LnF1ZXJ5fWAsICdpbmZvJywgZmFsc2UpO1xuICAgICAgICAgIGlmKHJlcS5ib2R5LnZhcmlhYmxlcykge1xuICAgICAgICAgICAgbG9nKGDwn5OKIEdyYXBoUUwgVmFyaWFibGVzOiAke0pTT04uc3RyaW5naWZ5KHJlcS5ib2R5LnZhcmlhYmxlcywgbnVsbCwgMil9YCwgJ2luZm8nLCBmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHJlcS5ib2R5Lm9wZXJhdGlvbk5hbWUpIHtcbiAgICAgICAgICAgIGxvZyhg8J+Pt++4jyAgR3JhcGhRTCBPcGVyYXRpb246ICR7cmVxLmJvZHkub3BlcmF0aW9uTmFtZX1gLCAnaW5mbycsIGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmhhbmNlZCBjb25zb2xlLmxvZyBjYXB0dXJlXG4gICAgICAgIGNvbnN0IG9yaWdpbmFsQ29uc29sZUxvZyA9IGNvbnNvbGUubG9nO1xuICAgICAgICBjb25zdCBsb2dzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGNvbnNvbGUubG9nID0gKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICBjb25zdCBsb2dNZXNzYWdlID0gYXJncy5tYXAoKGFyZykgPT5cbiAgICAgICAgICAgICh0eXBlb2YgYXJnID09PSAnb2JqZWN0JyA/IEpTT04uc3RyaW5naWZ5KGFyZywgbnVsbCwgMikgOiBTdHJpbmcoYXJnKSlcbiAgICAgICAgICApLmpvaW4oJyAnKTtcbiAgICAgICAgICBsb2dzLnB1c2gobG9nTWVzc2FnZSk7XG4gICAgICAgICAgb3JpZ2luYWxDb25zb2xlTG9nKGBbR3JhcGhRTF0gJHtsb2dNZXNzYWdlfWApO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIENyZWF0ZSBjb250ZXh0IGZvciB0aGUgaGFuZGxlclxuICAgICAgICBjb25zdCBjb250ZXh0ID0ge1xuICAgICAgICAgIGF3c1JlcXVlc3RJZDogJ3Rlc3QtcmVxdWVzdC1pZCcsXG4gICAgICAgICAgZnVuY3Rpb25OYW1lOiAnZ3JhcGhxbCcsXG4gICAgICAgICAgZnVuY3Rpb25WZXJzaW9uOiAnJExBVEVTVCcsXG4gICAgICAgICAgZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzOiAoKSA9PiAzMDAwMCxcbiAgICAgICAgICBpbnZva2VkRnVuY3Rpb25Bcm46ICdhcm46YXdzOmxhbWJkYTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmZ1bmN0aW9uOmdyYXBocWwnLFxuICAgICAgICAgIGxvZ0dyb3VwTmFtZTogJy9hd3MvbGFtYmRhL2dyYXBocWwnLFxuICAgICAgICAgIGxvZ1N0cmVhbU5hbWU6ICd0ZXN0LWxvZy1zdHJlYW0nLFxuICAgICAgICAgIHJlcSxcbiAgICAgICAgICByZXNcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBXcmFwIGhhbmRsZXIgd2l0aCBjb25zb2xlIGxvZyBjYXB0dXJlXG4gICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gY2FwdHVyZUNvbnNvbGVMb2dzKGdyYXBocWxIYW5kbGVyLCBxdWlldCk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBDYWxsIHRoZSBoYW5kbGVyIHdpdGggR3JhcGhRTCBwYXJhbWV0ZXJzXG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JhcHBlZEhhbmRsZXIoe1xuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxLmJvZHkpLFxuICAgICAgICAgICAgaGVhZGVyczogcmVxLmhlYWRlcnMsXG4gICAgICAgICAgICBodHRwTWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBwYXRoOiBncmFwaHFsUGF0aCxcbiAgICAgICAgICAgIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyczoge31cbiAgICAgICAgICB9LCBjb250ZXh0KTtcblxuICAgICAgICAgIC8vIFJlc3RvcmUgY29uc29sZS5sb2dcbiAgICAgICAgICBjb25zb2xlLmxvZyA9IG9yaWdpbmFsQ29uc29sZUxvZztcblxuICAgICAgICAgIC8vIEhhbmRsZSB0aGUgcmVzdWx0XG4gICAgICAgICAgaWYocmVzdWx0ICYmIHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnICYmIHJlc3VsdC5zdGF0dXNDb2RlKSB7XG4gICAgICAgICAgICByZXMuc3RhdHVzKHJlc3VsdC5zdGF0dXNDb2RlKTtcbiAgICAgICAgICAgIGlmKHJlc3VsdC5oZWFkZXJzKSB7XG4gICAgICAgICAgICAgIE9iamVjdC5lbnRyaWVzKHJlc3VsdC5oZWFkZXJzKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICAgICAgICByZXMuc2V0SGVhZGVyKGtleSwgU3RyaW5nKHZhbHVlKSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzLnNlbmQocmVzdWx0LmJvZHkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXMuanNvbihyZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgIC8vIFJlc3RvcmUgY29uc29sZS5sb2dcbiAgICAgICAgICBjb25zb2xlLmxvZyA9IG9yaWdpbmFsQ29uc29sZUxvZztcbiAgICAgICAgICBsb2coYEdyYXBoUUwgaGFuZGxlciBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIGZhbHNlKTtcbiAgICAgICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7ZXJyb3I6IGVycm9yLm1lc3NhZ2V9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGxvZyhgR3JhcGhRTCBlbmRwb2ludCBhdmFpbGFibGUgYXQgaHR0cDovLyR7aG9zdH06JHtodHRwUG9ydH0ke2dyYXBocWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgIH1cbiAgfSBjYXRjaChlcnJvcikge1xuICAgIGxvZyhgRXJyb3Igc2V0dGluZyB1cCBHcmFwaFFMOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICB9XG5cbiAgLy8gRmFsbGJhY2sgZm9yIG5vbi1HcmFwaFFMIHJvdXRlcyAtIGhhbmRsZSBhbGwgcmVtYWluaW5nIHJvdXRlc1xuICBhcHAudXNlKCcvJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IHJlcS51cmwgfHwgJy8nO1xuICAgICAgY29uc3QgbWV0aG9kID0gcmVxLm1ldGhvZCB8fCAnR0VUJztcbiAgICAgIGNvbnN0IHBhdGhuYW1lID0gcmVxLnBhdGggfHwgdXJsLnNwbGl0KCc/JylbMF07IC8vIEV4dHJhY3QgcGF0aG5hbWUgd2l0aG91dCBxdWVyeSBzdHJpbmdcblxuICAgICAgbG9nKGAke21ldGhvZH0gJHt1cmx9IChwYXRobmFtZTogJHtwYXRobmFtZX0pYCwgJ2luZm8nLCBmYWxzZSk7XG5cbiAgICAgIC8vIEZpbmQgbWF0Y2hpbmcgZnVuY3Rpb25cbiAgICAgIGxldCBtYXRjaGVkRnVuY3Rpb24gPSBudWxsO1xuXG4gICAgICBpZihjb25maWcuZnVuY3Rpb25zKSB7XG4gICAgICAgIGZvcihjb25zdCBbZnVuY3Rpb25OYW1lLCBmdW5jdGlvbkNvbmZpZ10gb2YgT2JqZWN0LmVudHJpZXMoY29uZmlnLmZ1bmN0aW9ucykpIHtcbiAgICAgICAgICBpZihmdW5jdGlvbkNvbmZpZy5ldmVudHMpIHtcbiAgICAgICAgICAgIGZvcihjb25zdCBldmVudCBvZiBmdW5jdGlvbkNvbmZpZy5ldmVudHMpIHtcbiAgICAgICAgICAgICAgaWYoZXZlbnQuaHR0cCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50UGF0aCA9IGV2ZW50Lmh0dHAucGF0aCB8fCAnLyc7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRNZXRob2QgPSBldmVudC5odHRwLm1ldGhvZCB8fCAnR0VUJztcblxuICAgICAgICAgICAgICAgIC8vIEltcHJvdmVkIHBhdGggbWF0Y2hpbmcgLSBjb21wYXJlIHBhdGhuYW1lIHdpdGhvdXQgcXVlcnkgc3RyaW5nXG4gICAgICAgICAgICAgICAgaWYoZXZlbnRQYXRoICYmIGV2ZW50UGF0aCA9PT0gcGF0aG5hbWUgJiYgZXZlbnRNZXRob2QgPT09IG1ldGhvZCkge1xuICAgICAgICAgICAgICAgICAgbWF0Y2hlZEZ1bmN0aW9uID0gZnVuY3Rpb25OYW1lO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKG1hdGNoZWRGdW5jdGlvbikge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmKG1hdGNoZWRGdW5jdGlvbiAmJiBjb25maWcuZnVuY3Rpb25zW21hdGNoZWRGdW5jdGlvbl0pIHtcbiAgICAgICAgLy8gUmVzb2x2ZSBoYW5kbGVyIHBhdGggcmVsYXRpdmUgdG8gb3V0cHV0IGRpcmVjdG9yeVxuICAgICAgICBjb25zdCBoYW5kbGVyUGF0aCA9IGNvbmZpZy5mdW5jdGlvbnNbbWF0Y2hlZEZ1bmN0aW9uXS5oYW5kbGVyO1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gYXdhaXQgbG9hZEhhbmRsZXIoaGFuZGxlclBhdGgsIG91dHB1dERpcik7XG5cbiAgICAgICAgaWYoaGFuZGxlcikge1xuICAgICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gY2FwdHVyZUNvbnNvbGVMb2dzKGhhbmRsZXIsIHF1aWV0KTtcblxuICAgICAgICAgIGNvbnN0IGV2ZW50ID0ge1xuICAgICAgICAgICAgYm9keTogcmVxLmJvZHksXG4gICAgICAgICAgICBoZWFkZXJzOiByZXEuaGVhZGVycyxcbiAgICAgICAgICAgIGh0dHBNZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgIHBhdGg6IHVybCxcbiAgICAgICAgICAgIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyczogcmVxLnF1ZXJ5XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgICBhd3NSZXF1ZXN0SWQ6ICd0ZXN0LXJlcXVlc3QtaWQnLFxuICAgICAgICAgICAgZnVuY3Rpb25OYW1lOiBtYXRjaGVkRnVuY3Rpb24sXG4gICAgICAgICAgICBmdW5jdGlvblZlcnNpb246ICckTEFURVNUJyxcbiAgICAgICAgICAgIGdldFJlbWFpbmluZ1RpbWVJbk1pbGxpczogKCkgPT4gMzAwMDAsXG4gICAgICAgICAgICBpbnZva2VkRnVuY3Rpb25Bcm46IGBhcm46YXdzOmxhbWJkYTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmZ1bmN0aW9uOiR7bWF0Y2hlZEZ1bmN0aW9ufWAsXG4gICAgICAgICAgICBsb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgbG9nU3RyZWFtTmFtZTogJ3Rlc3QtbG9nLXN0cmVhbScsXG4gICAgICAgICAgICBtZW1vcnlMaW1pdEluTUI6ICcxMjgnXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cmFwcGVkSGFuZGxlcihldmVudCwgY29udGV4dCk7XG5cbiAgICAgICAgICAgIGlmKHJlc3VsdCAmJiB0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0JyAmJiByZXN1bHQuc3RhdHVzQ29kZSkge1xuICAgICAgICAgICAgICByZXMuc3RhdHVzKHJlc3VsdC5zdGF0dXNDb2RlKTtcbiAgICAgICAgICAgICAgaWYocmVzdWx0LmhlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyhyZXN1bHQuaGVhZGVycykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgICAgICAgICByZXMuc2V0SGVhZGVyKGtleSwgU3RyaW5nKHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzLnNlbmQocmVzdWx0LmJvZHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmVzLmpzb24ocmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgICAgICBsb2coYEhhbmRsZXIgZXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBmYWxzZSk7XG4gICAgICAgICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7ZXJyb3I6IGVycm9yLm1lc3NhZ2V9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oe2Vycm9yOiAnSGFuZGxlciBub3QgZm91bmQnfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtlcnJvcjogJ0Z1bmN0aW9uIG5vdCBmb3VuZCd9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICBsb2coYFJvdXRlIGhhbmRsaW5nIGVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgZmFsc2UpO1xuICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oe2Vycm9yOiBlcnJvci5tZXNzYWdlfSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gYXBwO1xufTtcblxuY29uc3QgY3JlYXRlV2ViU29ja2V0U2VydmVyID0gKFxuICBjb25maWc6IFNlcnZlcmxlc3NDb25maWcsXG4gIG91dHB1dERpcjogc3RyaW5nLFxuICB3c1BvcnQ6IG51bWJlcixcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuXG4pID0+IHtcbiAgY29uc3Qgd3NzID0gbmV3IFdlYlNvY2tldFNlcnZlcih7cG9ydDogd3NQb3J0fSk7XG5cbiAgd3NzLm9uKCdjb25uZWN0aW9uJywgYXN5bmMgKHdzLCByZXEpID0+IHtcbiAgICBsb2coYFdlYlNvY2tldCBjb25uZWN0aW9uIGVzdGFibGlzaGVkOiAke3JlcS51cmx9YCwgJ2luZm8nLCBmYWxzZSk7XG5cbiAgICB3cy5vbignbWVzc2FnZScsIGFzeW5jIChtZXNzYWdlKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZShtZXNzYWdlLnRvU3RyaW5nKCkpO1xuXG4gICAgICAgIC8vIEZpbmQgbWF0Y2hpbmcgV2ViU29ja2V0IGZ1bmN0aW9uXG4gICAgICAgIGxldCBtYXRjaGVkRnVuY3Rpb24gPSBudWxsO1xuXG4gICAgICAgIGlmKGNvbmZpZy5mdW5jdGlvbnMpIHtcbiAgICAgICAgICBmb3IoY29uc3QgW2Z1bmN0aW9uTmFtZSwgZnVuY3Rpb25Db25maWddIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZy5mdW5jdGlvbnMpKSB7XG4gICAgICAgICAgICBpZihmdW5jdGlvbkNvbmZpZy5ldmVudHMpIHtcbiAgICAgICAgICAgICAgZm9yKGNvbnN0IGV2ZW50IG9mIGZ1bmN0aW9uQ29uZmlnLmV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmKGV2ZW50LndlYnNvY2tldCkge1xuICAgICAgICAgICAgICAgICAgY29uc3Qgcm91dGUgPSBldmVudC53ZWJzb2NrZXQucm91dGUgfHwgJyRjb25uZWN0JztcbiAgICAgICAgICAgICAgICAgIGlmKHJvdXRlID09PSAnJGRlZmF1bHQnIHx8IHJvdXRlID09PSBkYXRhLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGVkRnVuY3Rpb24gPSBmdW5jdGlvbk5hbWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYobWF0Y2hlZEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG1hdGNoZWRGdW5jdGlvbiAmJiBjb25maWcuZnVuY3Rpb25zW21hdGNoZWRGdW5jdGlvbl0pIHtcbiAgICAgICAgICBjb25zdCBoYW5kbGVyID0gYXdhaXQgbG9hZEhhbmRsZXIoY29uZmlnLmZ1bmN0aW9uc1ttYXRjaGVkRnVuY3Rpb25dLmhhbmRsZXIsIG91dHB1dERpcik7XG5cbiAgICAgICAgICBpZihoYW5kbGVyKSB7XG4gICAgICAgICAgICAvLyBXcmFwIGhhbmRsZXIgd2l0aCBjb25zb2xlIGxvZyBjYXB0dXJlXG4gICAgICAgICAgICBjb25zdCB3cmFwcGVkSGFuZGxlciA9IGNhcHR1cmVDb25zb2xlTG9ncyhoYW5kbGVyLCBxdWlldCk7XG4gICAgICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgICAgYm9keTogZGF0YS5ib2R5IHx8IG51bGwsXG4gICAgICAgICAgICAgIHJlcXVlc3RDb250ZXh0OiB7XG4gICAgICAgICAgICAgICAgYXBpR2F0ZXdheToge1xuICAgICAgICAgICAgICAgICAgZW5kcG9pbnQ6IGB3czovL2xvY2FsaG9zdDoke3dzUG9ydH1gXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWQ6ICd0ZXN0LWNvbm5lY3Rpb24taWQnLFxuICAgICAgICAgICAgICAgIHJvdXRlS2V5OiBkYXRhLmFjdGlvbiB8fCAnJGRlZmF1bHQnXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgICAgIGF3c1JlcXVlc3RJZDogJ3Rlc3QtcmVxdWVzdC1pZCcsXG4gICAgICAgICAgICAgIGZ1bmN0aW9uTmFtZTogbWF0Y2hlZEZ1bmN0aW9uLFxuICAgICAgICAgICAgICBmdW5jdGlvblZlcnNpb246ICckTEFURVNUJyxcbiAgICAgICAgICAgICAgZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzOiAoKSA9PiAzMDAwMCxcbiAgICAgICAgICAgICAgaW52b2tlZEZ1bmN0aW9uQXJuOiBgYXJuOmF3czpsYW1iZGE6dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpmdW5jdGlvbjoke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgICBsb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke21hdGNoZWRGdW5jdGlvbn1gLFxuICAgICAgICAgICAgICBsb2dTdHJlYW1OYW1lOiAndGVzdC1sb2ctc3RyZWFtJyxcbiAgICAgICAgICAgICAgbWVtb3J5TGltaXRJbk1COiAnMTI4J1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JhcHBlZEhhbmRsZXIoZXZlbnQsIGNvbnRleHQpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgTGFtYmRhIHJlc3BvbnNlIGZvcm1hdCBmb3IgV2ViU29ja2V0XG4gICAgICAgICAgICBpZihyZXN1bHQgJiYgdHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0LnN0YXR1c0NvZGUpIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIExhbWJkYSByZXNwb25zZSBvYmplY3QsIGV4dHJhY3QgdGhlIGJvZHlcbiAgICAgICAgICAgICAgY29uc3QgYm9keSA9IHJlc3VsdC5ib2R5IHx8ICcnO1xuICAgICAgICAgICAgICB3cy5zZW5kKGJvZHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIGRpcmVjdCByZXNwb25zZSwgc3RyaW5naWZ5IGl0XG4gICAgICAgICAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoe2Vycm9yOiAnSGFuZGxlciBub3QgZm91bmQnfSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KHtlcnJvcjogJ1dlYlNvY2tldCBmdW5jdGlvbiBub3QgZm91bmQnfSkpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIGxvZyhgV2ViU29ja2V0IGVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgZmFsc2UpO1xuICAgICAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KHtlcnJvcjogZXJyb3IubWVzc2FnZX0pKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHdzLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgIGxvZygnV2ViU29ja2V0IGNvbm5lY3Rpb24gY2xvc2VkJywgJ2luZm8nLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIHJldHVybiB3c3M7XG59O1xuXG5jb25zdCBsb2FkRW52RmlsZSA9IChlbnZQYXRoOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0+IHtcbiAgY29uc3QgZW52VmFyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIGlmKCFleGlzdHNTeW5jKGVudlBhdGgpKSB7XG4gICAgcmV0dXJuIGVudlZhcnM7XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IGVudkNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZW52UGF0aCwgJ3V0ZjgnKTtcbiAgICBjb25zdCBsaW5lcyA9IGVudkNvbnRlbnQuc3BsaXQoJ1xcbicpO1xuXG4gICAgZm9yKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XG5cbiAgICAgIC8vIFNraXAgZW1wdHkgbGluZXMgYW5kIGNvbW1lbnRzXG4gICAgICBpZighdHJpbW1lZExpbmUgfHwgdHJpbW1lZExpbmUuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBQYXJzZSBLRVk9dmFsdWUgZm9ybWF0XG4gICAgICBjb25zdCBlcXVhbEluZGV4ID0gdHJpbW1lZExpbmUuaW5kZXhPZignPScpO1xuICAgICAgaWYoZXF1YWxJbmRleCA+IDApIHtcbiAgICAgICAgY29uc3Qga2V5ID0gdHJpbW1lZExpbmUuc3Vic3RyaW5nKDAsIGVxdWFsSW5kZXgpLnRyaW0oKTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0cmltbWVkTGluZS5zdWJzdHJpbmcoZXF1YWxJbmRleCArIDEpLnRyaW0oKTtcblxuICAgICAgICAvLyBSZW1vdmUgcXVvdGVzIGlmIHByZXNlbnRcbiAgICAgICAgY29uc3QgY2xlYW5WYWx1ZSA9IHZhbHVlLnJlcGxhY2UoL15bXCInXXxbXCInXSQvZywgJycpO1xuXG4gICAgICAgIGlmKGtleSkge1xuICAgICAgICAgIGVudlZhcnNba2V5XSA9IGNsZWFuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYFdhcm5pbmc6IENvdWxkIG5vdCBsb2FkIC5lbnYgZmlsZSBhdCAke2VudlBhdGh9OiAke2Vycm9yLm1lc3NhZ2V9YCwgJ3dhcm4nLCBmYWxzZSk7XG4gIH1cblxuICByZXR1cm4gZW52VmFycztcbn07XG5cbmV4cG9ydCBjb25zdCBzZXJ2ZXJsZXNzID0gYXN5bmMgKFxuICBjbWQ6IFNlcnZlcmxlc3NPcHRpb25zLFxuICBjYWxsYmFjazogU2VydmVybGVzc0NhbGxiYWNrID0gKCkgPT4gKHt9KVxuKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcbiAgY29uc3Qge1xuICAgIGNsaU5hbWUgPSAnTGV4JyxcbiAgICBjb25maWcsXG4gICAgZGVidWcgPSBmYWxzZSxcbiAgICBob3N0ID0gJ2xvY2FsaG9zdCcsXG4gICAgaHR0cFBvcnQgPSAzMDAwLFxuICAgIGh0dHBzUG9ydCA9IDMwMDEsXG4gICAgcXVpZXQgPSBmYWxzZSxcbiAgICByZW1vdmUgPSBmYWxzZSxcbiAgICB0ZXN0ID0gZmFsc2UsXG4gICAgdXNlUHVibGljSXAsXG4gICAgdmFyaWFibGVzLFxuICAgIHdzUG9ydCA9IDMwMDJcbiAgfSA9IGNtZDtcblxuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgbG9nKGAke2NsaU5hbWV9IHN0YXJ0aW5nIHNlcnZlcmxlc3MgZGV2ZWxvcG1lbnQgc2VydmVyLi4uYCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgYXdhaXQgTGV4Q29uZmlnLnBhcnNlQ29uZmlnKGNtZCk7XG5cbiAgY29uc3Qge291dHB1dEZ1bGxQYXRofSA9IExleENvbmZpZy5jb25maWc7XG5cbiAgLy8gTG9hZCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgZnJvbSAuZW52IGZpbGVzXG4gIGNvbnN0IGVudlBhdGhzID0gW1xuICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICcuZW52JyksXG4gICAgcGF0aFJlc29sdmUocHJvY2Vzcy5jd2QoKSwgJy5lbnYubG9jYWwnKSxcbiAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLmVudi5kZXZlbG9wbWVudCcpXG4gIF07XG5cbiAgbGV0IGVudlZhcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICAvLyBMb2FkIGZyb20gLmVudiBmaWxlcyBpbiBvcmRlciAobGF0ZXIgZmlsZXMgb3ZlcnJpZGUgZWFybGllciBvbmVzKVxuICBmb3IoY29uc3QgZW52UGF0aCBvZiBlbnZQYXRocykge1xuICAgIGNvbnN0IGZpbGVFbnZWYXJzID0gbG9hZEVudkZpbGUoZW52UGF0aCk7XG4gICAgaWYoT2JqZWN0LmtleXMoZmlsZUVudlZhcnMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGxvZyhgTG9hZGVkIGVudmlyb25tZW50IHZhcmlhYmxlcyBmcm9tOiAke2VudlBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgfVxuICAgIGVudlZhcnMgPSB7Li4uZW52VmFycywgLi4uZmlsZUVudlZhcnN9O1xuICB9XG5cbiAgLy8gU3RhcnQgd2l0aCBkZWZhdWx0IE5PREVfRU5WIGFuZCBsb2FkZWQgLmVudiB2YXJpYWJsZXNcbiAgbGV0IHZhcmlhYmxlc09iajogb2JqZWN0ID0ge05PREVfRU5WOiAnZGV2ZWxvcG1lbnQnLCAuLi5lbnZWYXJzfTtcblxuICAvLyBPdmVycmlkZSB3aXRoIGNvbW1hbmQgbGluZSB2YXJpYWJsZXMgaWYgcHJvdmlkZWRcbiAgaWYodmFyaWFibGVzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsaVZhcnMgPSBKU09OLnBhcnNlKHZhcmlhYmxlcyk7XG4gICAgICB2YXJpYWJsZXNPYmogPSB7Li4udmFyaWFibGVzT2JqLCAuLi5jbGlWYXJzfTtcbiAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgb3B0aW9uIGlzIG5vdCBhIHZhbGlkIEpTT04gb2JqZWN0LmAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIGNhbGxiYWNrKDEpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9XG5cbiAgcHJvY2Vzcy5lbnYgPSB7Li4ucHJvY2Vzcy5lbnYsIC4uLnZhcmlhYmxlc09ian07XG5cbiAgLy8gSWYgaW4gdGVzdCBtb2RlLCBleGl0IGVhcmx5IGFmdGVyIGxvYWRpbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gIGlmKHRlc3QpIHtcbiAgICBsb2coJ1Rlc3QgbW9kZTogRW52aXJvbm1lbnQgdmFyaWFibGVzIGxvYWRlZCwgZXhpdGluZycsICdpbmZvJywgcXVpZXQpO1xuICAgIGNhbGxiYWNrKDApO1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgaWYocmVtb3ZlKSB7XG4gICAgc3Bpbm5lci5zdGFydCgnQ2xlYW5pbmcgb3V0cHV0IGRpcmVjdG9yeS4uLicpO1xuICAgIGF3YWl0IHJlbW92ZUZpbGVzKG91dHB1dEZ1bGxQYXRoIHx8ICcnKTtcbiAgICBzcGlubmVyLnN1Y2NlZWQoJ1N1Y2Nlc3NmdWxseSBjbGVhbmVkIG91dHB1dCBkaXJlY3RvcnkhJyk7XG4gIH1cblxuICAvLyBMb2FkIHNlcnZlcmxlc3MgY29uZmlndXJhdGlvblxuICBsZXQgc2VydmVybGVzc0NvbmZpZzogU2VydmVybGVzc0NvbmZpZyA9IHt9O1xuXG4gIHRyeSB7XG4gICAgY29uc3QgY29uZmlnUGF0aCA9IGNvbmZpZyB8fCBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnbGV4LmNvbmZpZy5tanMnKTtcbiAgICBsb2coYExvYWRpbmcgc2VydmVybGVzcyBjb25maWcgZnJvbTogJHtjb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgaWYoZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgICAgY29uc3QgY29uZmlnTW9kdWxlID0gYXdhaXQgaW1wb3J0KGNvbmZpZ1BhdGgpO1xuICAgICAgc2VydmVybGVzc0NvbmZpZyA9IGNvbmZpZ01vZHVsZS5kZWZhdWx0Py5zZXJ2ZXJsZXNzIHx8IGNvbmZpZ01vZHVsZS5zZXJ2ZXJsZXNzIHx8IHt9O1xuICAgICAgbG9nKCdTZXJ2ZXJsZXNzIGNvbmZpZyBsb2FkZWQgc3VjY2Vzc2Z1bGx5JywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBsb2coYExvYWRlZCBmdW5jdGlvbnM6ICR7T2JqZWN0LmtleXMoc2VydmVybGVzc0NvbmZpZy5mdW5jdGlvbnMgfHwge30pLmpvaW4oJywgJyl9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZyhgTm8gc2VydmVybGVzcyBjb25maWcgZm91bmQgYXQgJHtjb25maWdQYXRofSwgdXNpbmcgZGVmYXVsdHNgLCAnd2FybicsIHF1aWV0KTtcbiAgICB9XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYEVycm9yIGxvYWRpbmcgc2VydmVybGVzcyBjb25maWc6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgLy8gRG9uJ3QgZXhpdCwgY29udGludWUgd2l0aCBlbXB0eSBjb25maWdcbiAgfVxuXG4gIC8vIE1lcmdlIGNvbmZpZyB3aXRoIGNvbW1hbmQgbGluZSBvcHRpb25zXG4gIGNvbnN0IGZpbmFsQ29uZmlnOiBTZXJ2ZXJsZXNzQ29uZmlnID0ge1xuICAgIC4uLnNlcnZlcmxlc3NDb25maWcsXG4gICAgY3VzdG9tOiB7XG4gICAgICAnc2VydmVybGVzcy1vZmZsaW5lJzoge1xuICAgICAgICBjb3JzOiBzZXJ2ZXJsZXNzQ29uZmlnLmN1c3RvbT8uWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXT8uY29ycyAhPT0gZmFsc2UsXG4gICAgICAgIGhvc3Q6IHNlcnZlcmxlc3NDb25maWcuY3VzdG9tPy5bJ3NlcnZlcmxlc3Mtb2ZmbGluZSddPy5ob3N0IHx8IGhvc3QsXG4gICAgICAgIGh0dHBQb3J0OiBzZXJ2ZXJsZXNzQ29uZmlnLmN1c3RvbT8uWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXT8uaHR0cFBvcnQgfHwgaHR0cFBvcnQsXG4gICAgICAgIGh0dHBzUG9ydDogc2VydmVybGVzc0NvbmZpZy5jdXN0b20/Llsnc2VydmVybGVzcy1vZmZsaW5lJ10/Lmh0dHBzUG9ydCB8fCBodHRwc1BvcnQsXG4gICAgICAgIHdzUG9ydDogc2VydmVybGVzc0NvbmZpZy5jdXN0b20/Llsnc2VydmVybGVzcy1vZmZsaW5lJ10/LndzUG9ydCB8fCB3c1BvcnRcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb3V0cHV0RGlyID0gb3V0cHV0RnVsbFBhdGggfHwgJ2xpYic7XG4gIGxvZyhgVXNpbmcgb3V0cHV0IGRpcmVjdG9yeTogJHtvdXRwdXREaXJ9YCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgdHJ5IHtcbiAgICBzcGlubmVyLnN0YXJ0KCdTdGFydGluZyBzZXJ2ZXJsZXNzIGRldmVsb3BtZW50IHNlcnZlci4uLicpO1xuXG4gICAgY29uc3QgaHR0cFBvcnQgPSBmaW5hbENvbmZpZy5jdXN0b20hWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXSEuaHR0cFBvcnQhO1xuICAgIGNvbnN0IHdzUG9ydCA9IGZpbmFsQ29uZmlnLmN1c3RvbSFbJ3NlcnZlcmxlc3Mtb2ZmbGluZSddIS53c1BvcnQhO1xuICAgIGNvbnN0IGhvc3QgPSBmaW5hbENvbmZpZy5jdXN0b20hWydzZXJ2ZXJsZXNzLW9mZmxpbmUnXSEuaG9zdCE7XG5cbiAgICBsb2coYENyZWF0aW5nIEhUVFAgc2VydmVyIG9uICR7aG9zdH06JHtodHRwUG9ydH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICBsb2coYENyZWF0aW5nIFdlYlNvY2tldCBzZXJ2ZXIgb24gcG9ydCAke3dzUG9ydH1gLCAnaW5mbycsIHF1aWV0KTtcblxuICAgIC8vIENyZWF0ZSBFeHByZXNzIHNlcnZlclxuICAgIGNvbnN0IGV4cHJlc3NBcHAgPSBhd2FpdCBjcmVhdGVFeHByZXNzU2VydmVyKFxuICAgICAgZmluYWxDb25maWcsXG4gICAgICBvdXRwdXREaXIsXG4gICAgICBodHRwUG9ydCxcbiAgICAgIGhvc3QsXG4gICAgICBxdWlldCxcbiAgICAgIGRlYnVnXG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBXZWJTb2NrZXQgc2VydmVyXG4gICAgY29uc3Qgd3NTZXJ2ZXIgPSBjcmVhdGVXZWJTb2NrZXRTZXJ2ZXIoXG4gICAgICBmaW5hbENvbmZpZyxcbiAgICAgIG91dHB1dERpcixcbiAgICAgIHdzUG9ydCxcbiAgICAgIHF1aWV0LFxuICAgICAgZGVidWdcbiAgICApO1xuXG4gICAgLy8gSGFuZGxlIHNlcnZlciBlcnJvcnNcbiAgICB3c1NlcnZlci5vbignZXJyb3InLCAoZXJyb3IpID0+IHtcbiAgICAgIGxvZyhgV2ViU29ja2V0IHNlcnZlciBlcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIHNwaW5uZXIuZmFpbCgnRmFpbGVkIHRvIHN0YXJ0IFdlYlNvY2tldCBzZXJ2ZXIuJyk7XG4gICAgICBjYWxsYmFjaygxKTtcbiAgICAgIHJldHVybjtcbiAgICB9KTtcblxuICAgIC8vIFN0YXJ0IEV4cHJlc3Mgc2VydmVyXG4gICAgY29uc3Qgc2VydmVyID0gZXhwcmVzc0FwcC5saXN0ZW4oaHR0cFBvcnQsIGhvc3QsICgpID0+IHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnU2VydmVybGVzcyBkZXZlbG9wbWVudCBzZXJ2ZXIgc3RhcnRlZC4nKTtcblxuICAgICAgZGlzcGxheVNlcnZlclN0YXR1cyhcbiAgICAgICAgaHR0cFBvcnQsXG4gICAgICAgIGZpbmFsQ29uZmlnLmN1c3RvbSFbJ3NlcnZlcmxlc3Mtb2ZmbGluZSddIS5odHRwc1BvcnQhLFxuICAgICAgICB3c1BvcnQsXG4gICAgICAgIGhvc3QsXG4gICAgICAgIHF1aWV0XG4gICAgICApO1xuXG4gICAgICBmZXRjaFB1YmxpY0lwKHVzZVB1YmxpY0lwKS50aGVuKChwdWJsaWNJcCkgPT4ge1xuICAgICAgICBpZihwdWJsaWNJcCkge1xuICAgICAgICAgIGRpc3BsYXlTZXJ2ZXJTdGF0dXMoXG4gICAgICAgICAgICBodHRwUG9ydCxcbiAgICAgICAgICAgIGZpbmFsQ29uZmlnLmN1c3RvbSFbJ3NlcnZlcmxlc3Mtb2ZmbGluZSddIS5odHRwc1BvcnQhLFxuICAgICAgICAgICAgd3NQb3J0LFxuICAgICAgICAgICAgaG9zdCxcbiAgICAgICAgICAgIHF1aWV0LFxuICAgICAgICAgICAgcHVibGljSXBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIEhhbmRsZSBFeHByZXNzIHNlcnZlciBlcnJvcnNcbiAgICBzZXJ2ZXIub24oJ2Vycm9yJywgKGVycm9yKSA9PiB7XG4gICAgICBsb2coYEV4cHJlc3Mgc2VydmVyIGVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gc3RhcnQgRXhwcmVzcyBzZXJ2ZXIuJyk7XG4gICAgICBjYWxsYmFjaygxKTtcbiAgICAgIHJldHVybjtcbiAgICB9KTtcblxuICAgIC8vIEhhbmRsZSBncmFjZWZ1bCBzaHV0ZG93blxuICAgIGNvbnN0IHNodXRkb3duID0gKCkgPT4ge1xuICAgICAgbG9nKCdcXG5TaHV0dGluZyBkb3duIHNlcnZlcmxlc3MgZGV2ZWxvcG1lbnQgc2VydmVyLi4uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgIHdzU2VydmVyLmNsb3NlKCk7XG4gICAgICBjYWxsYmFjaygwKTtcbiAgICB9O1xuXG4gICAgcHJvY2Vzcy5vbignU0lHSU5UJywgc2h1dGRvd24pO1xuICAgIHByb2Nlc3Mub24oJ1NJR1RFUk0nLCBzaHV0ZG93bik7XG5cbiAgICAvLyBLZWVwIHRoZSBwcm9jZXNzIGFsaXZlXG4gICAgcHJvY2Vzcy5zdGRpbi5yZXN1bWUoKTtcblxuICAgIGxvZygnU2VydmVybGVzcyBkZXZlbG9wbWVudCBzZXJ2ZXIgaXMgcnVubmluZy4gUHJlc3MgQ3RybCtDIHRvIHN0b3AuJywgJ2luZm8nLCBxdWlldCk7XG5cbiAgICAvLyBEb24ndCBjYWxsIGNhbGxiYWNrIGhlcmUsIGxldCB0aGUgcHJvY2VzcyBzdGF5IGFsaXZlXG4gICAgcmV0dXJuIDA7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gc3RhcnQgc2VydmVybGVzcyBkZXZlbG9wbWVudCBzZXJ2ZXIuJyk7XG4gICAgY2FsbGJhY2soMSk7XG4gICAgcmV0dXJuIDE7XG4gIH1cbn07Il0sIm5hbWVzIjpbImJveGVuIiwiY2hhbGsiLCJleHByZXNzIiwicmVhZEZpbGVTeW5jIiwiZXhpc3RzU3luYyIsIm1rZGlyU3luYyIsIndyaXRlRmlsZVN5bmMiLCJob21lZGlyIiwicmVzb2x2ZSIsInBhdGhSZXNvbHZlIiwiam9pbiIsIldlYlNvY2tldFNlcnZlciIsIkxleENvbmZpZyIsImNyZWF0ZVNwaW5uZXIiLCJyZW1vdmVGaWxlcyIsImxvZyIsImdldENhY2hlRGlyIiwiY2FjaGVEaXIiLCJyZWN1cnNpdmUiLCJnZXRDYWNoZVBhdGgiLCJyZWFkUHVibGljSXBDYWNoZSIsImNhY2hlUGF0aCIsImNhY2hlRGF0YSIsImNhY2hlIiwiSlNPTiIsInBhcnNlIiwib25lV2Vla01zIiwiRGF0ZSIsIm5vdyIsInRpbWVzdGFtcCIsIndyaXRlUHVibGljSXBDYWNoZSIsImlwIiwic3RyaW5naWZ5IiwiZmV0Y2hQdWJsaWNJcCIsImZvcmNlUmVmcmVzaCIsIlByb21pc2UiLCJjYWNoZWQiLCJmZXRjaCIsInRoZW4iLCJyZXMiLCJ0ZXh0IiwiZGF0YSIsInRyaW0iLCJjYXRjaCIsInVuZGVmaW5lZCIsImRpc3BsYXlTZXJ2ZXJTdGF0dXMiLCJodHRwUG9ydCIsImh0dHBzUG9ydCIsIndzUG9ydCIsImhvc3QiLCJxdWlldCIsInB1YmxpY0lwIiwiaHR0cFVybCIsImh0dHBzVXJsIiwid3NVcmwiLCJ3c3NVcmwiLCJ1cmxMaW5lcyIsImdyZWVuIiwidW5kZXJsaW5lIiwic3RhdHVzQm94IiwiY3lhbiIsImJvbGQiLCJ5ZWxsb3ciLCJiYWNrZ3JvdW5kQ29sb3IiLCJib3JkZXJDb2xvciIsImJvcmRlclN0eWxlIiwibWFyZ2luIiwicGFkZGluZyIsImNvbnNvbGUiLCJsb2FkSGFuZGxlciIsImhhbmRsZXJQYXRoIiwib3V0cHV0RGlyIiwiZnVsbFBhdGgiLCJFcnJvciIsImhhbmRsZXJNb2R1bGUiLCJPYmplY3QiLCJrZXlzIiwiaGFuZGxlciIsImRlZmF1bHQiLCJpbXBvcnRFcnJvciIsIm1lc3NhZ2UiLCJlcnJvciIsImNhcHR1cmVDb25zb2xlTG9ncyIsImV2ZW50IiwiY29udGV4dCIsIm9yaWdpbmFsQ29uc29sZUxvZyIsIm9yaWdpbmFsQ29uc29sZUVycm9yIiwib3JpZ2luYWxDb25zb2xlV2FybiIsIndhcm4iLCJvcmlnaW5hbENvbnNvbGVJbmZvIiwiaW5mbyIsImxvZ3MiLCJhcmdzIiwicHVzaCIsInJlc3VsdCIsImxlbmd0aCIsImdyYXkiLCJmb3JFYWNoIiwiY3JlYXRlRXhwcmVzc1NlcnZlciIsImNvbmZpZyIsImRlYnVnIiwiYXBwIiwidXNlIiwicmVxIiwibmV4dCIsImhlYWRlciIsIm1ldGhvZCIsInNlbmRTdGF0dXMiLCJqc29uIiwibG9hZEdyYXBoUUxTY2hlbWEiLCJncmFwaHFsSGFuZGxlciIsImZ1bmN0aW9ucyIsImZ1bmN0aW9uTmFtZSIsImZ1bmN0aW9uQ29uZmlnIiwiZW50cmllcyIsImV2ZW50cyIsImh0dHAiLCJwYXRoIiwiZ3JhcGhxbFBhdGgiLCJfZnVuY3Rpb25OYW1lIiwiYm9keSIsInF1ZXJ5IiwidmFyaWFibGVzIiwib3BlcmF0aW9uTmFtZSIsImxvZ01lc3NhZ2UiLCJtYXAiLCJhcmciLCJTdHJpbmciLCJhd3NSZXF1ZXN0SWQiLCJmdW5jdGlvblZlcnNpb24iLCJnZXRSZW1haW5pbmdUaW1lSW5NaWxsaXMiLCJpbnZva2VkRnVuY3Rpb25Bcm4iLCJsb2dHcm91cE5hbWUiLCJsb2dTdHJlYW1OYW1lIiwid3JhcHBlZEhhbmRsZXIiLCJoZWFkZXJzIiwiaHR0cE1ldGhvZCIsInF1ZXJ5U3RyaW5nUGFyYW1ldGVycyIsInN0YXR1c0NvZGUiLCJzdGF0dXMiLCJrZXkiLCJ2YWx1ZSIsInNldEhlYWRlciIsInNlbmQiLCJ1cmwiLCJwYXRobmFtZSIsInNwbGl0IiwibWF0Y2hlZEZ1bmN0aW9uIiwiZXZlbnRQYXRoIiwiZXZlbnRNZXRob2QiLCJtZW1vcnlMaW1pdEluTUIiLCJjcmVhdGVXZWJTb2NrZXRTZXJ2ZXIiLCJ3c3MiLCJwb3J0Iiwib24iLCJ3cyIsInRvU3RyaW5nIiwid2Vic29ja2V0Iiwicm91dGUiLCJhY3Rpb24iLCJyZXF1ZXN0Q29udGV4dCIsImFwaUdhdGV3YXkiLCJlbmRwb2ludCIsImNvbm5lY3Rpb25JZCIsInJvdXRlS2V5IiwibG9hZEVudkZpbGUiLCJlbnZQYXRoIiwiZW52VmFycyIsImVudkNvbnRlbnQiLCJsaW5lcyIsImxpbmUiLCJ0cmltbWVkTGluZSIsInN0YXJ0c1dpdGgiLCJlcXVhbEluZGV4IiwiaW5kZXhPZiIsInN1YnN0cmluZyIsImNsZWFuVmFsdWUiLCJyZXBsYWNlIiwic2VydmVybGVzcyIsImNtZCIsImNhbGxiYWNrIiwiY2xpTmFtZSIsInJlbW92ZSIsInRlc3QiLCJ1c2VQdWJsaWNJcCIsInNwaW5uZXIiLCJwYXJzZUNvbmZpZyIsIm91dHB1dEZ1bGxQYXRoIiwiZW52UGF0aHMiLCJwcm9jZXNzIiwiY3dkIiwiZmlsZUVudlZhcnMiLCJ2YXJpYWJsZXNPYmoiLCJOT0RFX0VOViIsImNsaVZhcnMiLCJfZXJyb3IiLCJlbnYiLCJzdGFydCIsInN1Y2NlZWQiLCJzZXJ2ZXJsZXNzQ29uZmlnIiwiY29uZmlnUGF0aCIsImNvbmZpZ01vZHVsZSIsImZpbmFsQ29uZmlnIiwiY3VzdG9tIiwiY29ycyIsImV4cHJlc3NBcHAiLCJ3c1NlcnZlciIsImZhaWwiLCJzZXJ2ZXIiLCJsaXN0ZW4iLCJzaHV0ZG93biIsImNsb3NlIiwic3RkaW4iLCJyZXN1bWUiXSwibWFwcGluZ3MiOiJBQUFBOzs7Q0FHQyxHQUNELE9BQU9BLFdBQVcsUUFBUTtBQUMxQixPQUFPQyxXQUFXLFFBQVE7QUFDMUIsT0FBT0MsYUFBYSxVQUFVO0FBQzlCLFNBQVFDLFlBQVksRUFBRUMsVUFBVSxFQUFFQyxTQUFTLEVBQUVDLGFBQWEsUUFBTyxLQUFLO0FBQ3RFLFNBQVFDLE9BQU8sUUFBTyxLQUFLO0FBQzNCLFNBQVFDLFdBQVdDLFdBQVcsRUFBRUMsSUFBSSxRQUFPLE9BQU87QUFDbEQsU0FBUUMsZUFBZSxRQUFPLEtBQUs7QUFFbkMsU0FBUUMsU0FBUyxRQUFPLHFCQUFxQjtBQUM3QyxTQUFRQyxhQUFhLEVBQUVDLFdBQVcsUUFBTyxxQkFBcUI7QUFDOUQsU0FBUUMsR0FBRyxRQUFPLHFCQUFxQjtBQW1EdkMsTUFBTUMsY0FBYztJQUNsQixNQUFNQyxXQUFXUCxLQUFLSCxXQUFXO0lBQ2pDLElBQUcsQ0FBQ0gsV0FBV2EsV0FBVztRQUN4QlosVUFB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
|