@local-labs-jpollock/local-cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/addon-dist/bin/mcp-stdio.js +2808 -0
  2. package/addon-dist/lib/common/constants.d.ts +22 -0
  3. package/addon-dist/lib/common/constants.js +26 -0
  4. package/addon-dist/lib/common/theme.d.ts +68 -0
  5. package/addon-dist/lib/common/theme.js +126 -0
  6. package/addon-dist/lib/common/types.d.ts +298 -0
  7. package/addon-dist/lib/common/types.js +6 -0
  8. package/addon-dist/lib/main/config/ConnectionInfo.d.ts +25 -0
  9. package/addon-dist/lib/main/config/ConnectionInfo.js +82 -0
  10. package/addon-dist/lib/main/index.d.ts +12 -0
  11. package/addon-dist/lib/main/index.js +3322 -0
  12. package/addon-dist/lib/main/mcp/McpAuth.d.ts +37 -0
  13. package/addon-dist/lib/main/mcp/McpAuth.js +87 -0
  14. package/addon-dist/lib/main/mcp/McpServer.d.ts +67 -0
  15. package/addon-dist/lib/main/mcp/McpServer.js +343 -0
  16. package/addon-dist/lib/main/mcp/tools/changePhpVersion.d.ts +7 -0
  17. package/addon-dist/lib/main/mcp/tools/changePhpVersion.js +81 -0
  18. package/addon-dist/lib/main/mcp/tools/cloneSite.d.ts +7 -0
  19. package/addon-dist/lib/main/mcp/tools/cloneSite.js +66 -0
  20. package/addon-dist/lib/main/mcp/tools/createSite.d.ts +7 -0
  21. package/addon-dist/lib/main/mcp/tools/createSite.js +137 -0
  22. package/addon-dist/lib/main/mcp/tools/deleteSite.d.ts +7 -0
  23. package/addon-dist/lib/main/mcp/tools/deleteSite.js +72 -0
  24. package/addon-dist/lib/main/mcp/tools/exportDatabase.d.ts +7 -0
  25. package/addon-dist/lib/main/mcp/tools/exportDatabase.js +72 -0
  26. package/addon-dist/lib/main/mcp/tools/exportSite.d.ts +7 -0
  27. package/addon-dist/lib/main/mcp/tools/exportSite.js +103 -0
  28. package/addon-dist/lib/main/mcp/tools/getLocalInfo.d.ts +7 -0
  29. package/addon-dist/lib/main/mcp/tools/getLocalInfo.js +72 -0
  30. package/addon-dist/lib/main/mcp/tools/getSite.d.ts +7 -0
  31. package/addon-dist/lib/main/mcp/tools/getSite.js +68 -0
  32. package/addon-dist/lib/main/mcp/tools/getSiteLogs.d.ts +7 -0
  33. package/addon-dist/lib/main/mcp/tools/getSiteLogs.js +149 -0
  34. package/addon-dist/lib/main/mcp/tools/helpers.d.ts +59 -0
  35. package/addon-dist/lib/main/mcp/tools/helpers.js +179 -0
  36. package/addon-dist/lib/main/mcp/tools/importDatabase.d.ts +7 -0
  37. package/addon-dist/lib/main/mcp/tools/importDatabase.js +109 -0
  38. package/addon-dist/lib/main/mcp/tools/importSite.d.ts +7 -0
  39. package/addon-dist/lib/main/mcp/tools/importSite.js +149 -0
  40. package/addon-dist/lib/main/mcp/tools/index.d.ts +26 -0
  41. package/addon-dist/lib/main/mcp/tools/index.js +117 -0
  42. package/addon-dist/lib/main/mcp/tools/listBlueprints.d.ts +7 -0
  43. package/addon-dist/lib/main/mcp/tools/listBlueprints.js +54 -0
  44. package/addon-dist/lib/main/mcp/tools/listServices.d.ts +7 -0
  45. package/addon-dist/lib/main/mcp/tools/listServices.js +112 -0
  46. package/addon-dist/lib/main/mcp/tools/listSites.d.ts +7 -0
  47. package/addon-dist/lib/main/mcp/tools/listSites.js +62 -0
  48. package/addon-dist/lib/main/mcp/tools/openAdminer.d.ts +7 -0
  49. package/addon-dist/lib/main/mcp/tools/openAdminer.js +59 -0
  50. package/addon-dist/lib/main/mcp/tools/openSite.d.ts +7 -0
  51. package/addon-dist/lib/main/mcp/tools/openSite.js +62 -0
  52. package/addon-dist/lib/main/mcp/tools/renameSite.d.ts +7 -0
  53. package/addon-dist/lib/main/mcp/tools/renameSite.js +70 -0
  54. package/addon-dist/lib/main/mcp/tools/restartSite.d.ts +7 -0
  55. package/addon-dist/lib/main/mcp/tools/restartSite.js +56 -0
  56. package/addon-dist/lib/main/mcp/tools/saveBlueprint.d.ts +7 -0
  57. package/addon-dist/lib/main/mcp/tools/saveBlueprint.js +89 -0
  58. package/addon-dist/lib/main/mcp/tools/startSite.d.ts +7 -0
  59. package/addon-dist/lib/main/mcp/tools/startSite.js +54 -0
  60. package/addon-dist/lib/main/mcp/tools/stopSite.d.ts +7 -0
  61. package/addon-dist/lib/main/mcp/tools/stopSite.js +54 -0
  62. package/addon-dist/lib/main/mcp/tools/toggleXdebug.d.ts +7 -0
  63. package/addon-dist/lib/main/mcp/tools/toggleXdebug.js +69 -0
  64. package/addon-dist/lib/main/mcp/tools/trustSsl.d.ts +7 -0
  65. package/addon-dist/lib/main/mcp/tools/trustSsl.js +59 -0
  66. package/addon-dist/lib/main/mcp/tools/wpCli.d.ts +7 -0
  67. package/addon-dist/lib/main/mcp/tools/wpCli.js +110 -0
  68. package/addon-dist/lib/main.d.ts +1 -0
  69. package/addon-dist/lib/main.js +10 -0
  70. package/addon-dist/lib/renderer/index.d.ts +7 -0
  71. package/addon-dist/lib/renderer/index.js +479 -0
  72. package/addon-dist/package.json +73 -0
  73. package/bin/lwp.js +10 -0
  74. package/lib/bootstrap/index.d.ts +98 -0
  75. package/lib/bootstrap/index.js +493 -0
  76. package/lib/bootstrap/paths.d.ts +28 -0
  77. package/lib/bootstrap/paths.js +96 -0
  78. package/lib/client/GraphQLClient.d.ts +38 -0
  79. package/lib/client/GraphQLClient.js +71 -0
  80. package/lib/client/index.d.ts +4 -0
  81. package/lib/client/index.js +10 -0
  82. package/lib/formatters/index.d.ts +75 -0
  83. package/lib/formatters/index.js +139 -0
  84. package/lib/index.d.ts +8 -0
  85. package/lib/index.js +1173 -0
  86. package/package.json +72 -0
package/lib/index.js ADDED
@@ -0,0 +1,1173 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Local CLI (lwp)
5
+ *
6
+ * Command-line interface for managing Local WordPress sites.
7
+ * Connects directly to Local's GraphQL server.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const commander_1 = require("commander");
14
+ const ora_1 = __importDefault(require("ora"));
15
+ const bootstrap_1 = require("./bootstrap");
16
+ const client_1 = require("./client");
17
+ const formatters_1 = require("./formatters");
18
+ const program = new commander_1.Command();
19
+ // Store client globally after bootstrap
20
+ let client = null;
21
+ /**
22
+ * Ensure we're connected to Local's GraphQL server
23
+ */
24
+ async function ensureConnected(options) {
25
+ if (client) {
26
+ return client;
27
+ }
28
+ const spinner = options.quiet ? null : (0, ora_1.default)('Connecting to Local...').start();
29
+ try {
30
+ const result = await (0, bootstrap_1.bootstrap)({
31
+ verbose: false,
32
+ onStatus: (status) => {
33
+ if (spinner)
34
+ spinner.text = status;
35
+ },
36
+ });
37
+ if (!result.success || !result.connectionInfo) {
38
+ spinner?.fail('Failed to connect');
39
+ console.error((0, formatters_1.formatError)(result.error || 'Unknown error'));
40
+ process.exit(1);
41
+ }
42
+ spinner?.succeed('Connected to Local');
43
+ client = new client_1.GraphQLClient(result.connectionInfo);
44
+ return client;
45
+ }
46
+ catch (error) {
47
+ spinner?.fail('Failed to connect');
48
+ console.error((0, formatters_1.formatError)(error.message));
49
+ process.exit(1);
50
+ }
51
+ }
52
+ /**
53
+ * Helper to run site-specific commands with common boilerplate
54
+ *
55
+ * Handles: connection, spinner, site lookup, error formatting
56
+ */
57
+ async function runSiteCommand(siteName, config, execute) {
58
+ const globalOpts = program.opts();
59
+ const spinner = globalOpts.quiet ? null : (0, ora_1.default)(`${config.action} "${siteName}"...`).start();
60
+ try {
61
+ const gql = await ensureConnected(globalOpts);
62
+ const siteId = await findSiteId(gql, siteName);
63
+ const result = await execute(gql, siteId);
64
+ const message = config.successMessage
65
+ ? config.successMessage(result)
66
+ : `${config.action} "${siteName}" completed`;
67
+ spinner?.succeed(message);
68
+ }
69
+ catch (error) {
70
+ spinner?.fail(`Failed to ${config.action.toLowerCase()} "${siteName}"`);
71
+ console.error((0, formatters_1.formatError)(error.message));
72
+ process.exit(1);
73
+ }
74
+ }
75
+ program
76
+ .name('lwp')
77
+ .description('Command-line interface for Local WordPress development')
78
+ .version('0.1.0');
79
+ // Global options
80
+ program
81
+ .option('--json', 'Output results as JSON')
82
+ .option('--quiet', 'Minimal output (IDs/names only)')
83
+ .option('--no-color', 'Disable colored output');
84
+ // ===========================================
85
+ // Sites Commands
86
+ // ===========================================
87
+ const sites = program.command('sites').description('Manage WordPress sites');
88
+ sites
89
+ .command('list')
90
+ .description('List all WordPress sites')
91
+ .option('--status <status>', 'Filter by status (running|stopped|all)', 'all')
92
+ .action(async (cmdOptions) => {
93
+ const globalOpts = program.opts();
94
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
95
+ try {
96
+ const gql = await ensureConnected(globalOpts);
97
+ const data = await gql.query(`
98
+ query {
99
+ sites {
100
+ id
101
+ name
102
+ domain
103
+ status
104
+ path
105
+ }
106
+ }
107
+ `);
108
+ let sitesToShow = data.sites.map((s) => ({
109
+ id: s.id,
110
+ name: s.name,
111
+ domain: s.domain,
112
+ status: s.status.toLowerCase(),
113
+ path: s.path,
114
+ }));
115
+ // Filter by status if specified
116
+ if (cmdOptions.status !== 'all') {
117
+ sitesToShow = sitesToShow.filter((s) => s.status === cmdOptions.status);
118
+ }
119
+ console.log((0, formatters_1.formatSiteList)(sitesToShow, format, { noColor: globalOpts.noColor }));
120
+ }
121
+ catch (error) {
122
+ console.error((0, formatters_1.formatError)(error.message));
123
+ process.exit(1);
124
+ }
125
+ });
126
+ sites
127
+ .command('get <site>')
128
+ .description('Get detailed info about a site')
129
+ .action(async (site) => {
130
+ const globalOpts = program.opts();
131
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
132
+ try {
133
+ const gql = await ensureConnected(globalOpts);
134
+ // First find the site by name or ID
135
+ const sitesData = await gql.query(`
136
+ query { sites { id name } }
137
+ `);
138
+ const foundSite = sitesData.sites.find((s) => s.id === site || s.name.toLowerCase().includes(site.toLowerCase()));
139
+ if (!foundSite) {
140
+ console.error((0, formatters_1.formatError)(`Site not found: "${site}"`));
141
+ process.exit(1);
142
+ }
143
+ const data = await gql.query(`
144
+ query($id: ID!) {
145
+ site(id: $id) {
146
+ id
147
+ name
148
+ domain
149
+ status
150
+ path
151
+ url
152
+ host
153
+ httpPort
154
+ xdebugEnabled
155
+ services {
156
+ name
157
+ version
158
+ role
159
+ }
160
+ hostConnections {
161
+ hostId
162
+ remoteSiteId
163
+ }
164
+ }
165
+ }
166
+ `, { id: foundSite.id });
167
+ console.log((0, formatters_1.formatSiteDetail)(data.site, format, { noColor: globalOpts.noColor }));
168
+ }
169
+ catch (error) {
170
+ console.error((0, formatters_1.formatError)(error.message));
171
+ process.exit(1);
172
+ }
173
+ });
174
+ sites
175
+ .command('start <site>')
176
+ .description('Start a site')
177
+ .action(async (site) => {
178
+ await runSiteCommand(site, { action: 'Starting', successMessage: () => `Started "${site}"` }, async (gql, siteId) => {
179
+ return gql.mutate(`mutation($id: ID!) { startSite(id: $id) { id status } }`, { id: siteId });
180
+ });
181
+ });
182
+ sites
183
+ .command('stop <site>')
184
+ .description('Stop a site')
185
+ .action(async (site) => {
186
+ await runSiteCommand(site, { action: 'Stopping', successMessage: () => `Stopped "${site}"` }, async (gql, siteId) => {
187
+ return gql.mutate(`mutation($id: ID!) { stopSite(id: $id) { id status } }`, { id: siteId });
188
+ });
189
+ });
190
+ sites
191
+ .command('restart <site>')
192
+ .description('Restart a site')
193
+ .action(async (site) => {
194
+ await runSiteCommand(site, { action: 'Restarting', successMessage: () => `Restarted "${site}"` }, async (gql, siteId) => {
195
+ return gql.mutate(`mutation($id: ID!) { restartSite(id: $id) { id status } }`, { id: siteId });
196
+ });
197
+ });
198
+ sites
199
+ .command('open <site>')
200
+ .description('Open site in browser')
201
+ .option('--admin', 'Open WP Admin instead of frontend')
202
+ .action(async (site, cmdOptions) => {
203
+ await runSiteCommand(site, { action: 'Opening', successMessage: () => `Opened "${site}"` }, async (gql, siteId) => {
204
+ return gql.mutate(`
205
+ mutation($input: OpenSiteInput!) {
206
+ openSite(input: $input) { success error }
207
+ }
208
+ `, { input: { siteId, openAdmin: cmdOptions.admin || false } });
209
+ });
210
+ });
211
+ sites
212
+ .command('create <name>')
213
+ .description('Create a new WordPress site')
214
+ .option('--php <version>', 'PHP version (e.g., 8.2.10)')
215
+ .option('--web <server>', 'Web server (nginx|apache)')
216
+ .option('--db <database>', 'Database (mysql|mariadb)')
217
+ .option('--blueprint <name>', 'Use a blueprint')
218
+ .option('--wp-user <username>', 'WordPress admin username', 'admin')
219
+ .option('--wp-email <email>', 'WordPress admin email')
220
+ .action(async (name, cmdOptions) => {
221
+ const globalOpts = program.opts();
222
+ const spinner = globalOpts.quiet ? null : (0, ora_1.default)(`Creating "${name}"...`).start();
223
+ try {
224
+ const gql = await ensureConnected(globalOpts);
225
+ const input = { name };
226
+ if (cmdOptions.php)
227
+ input.phpVersion = cmdOptions.php;
228
+ if (cmdOptions.web)
229
+ input.webServer = cmdOptions.web;
230
+ if (cmdOptions.db)
231
+ input.database = cmdOptions.db;
232
+ if (cmdOptions.blueprint)
233
+ input.blueprint = cmdOptions.blueprint;
234
+ if (cmdOptions.wpUser)
235
+ input.wpAdminUsername = cmdOptions.wpUser;
236
+ if (cmdOptions.wpEmail)
237
+ input.wpAdminEmail = cmdOptions.wpEmail;
238
+ const data = await gql.mutate(`
239
+ mutation($input: CreateSiteInput!) {
240
+ createSite(input: $input) { success siteId siteName error }
241
+ }
242
+ `, { input });
243
+ if (!data.createSite.success) {
244
+ spinner?.fail('Create failed');
245
+ console.error((0, formatters_1.formatError)(data.createSite.error || 'Failed to create site'));
246
+ process.exit(1);
247
+ }
248
+ spinner?.succeed(`Created "${data.createSite.siteName}" (${data.createSite.siteId})`);
249
+ }
250
+ catch (error) {
251
+ spinner?.fail('Create failed');
252
+ console.error((0, formatters_1.formatError)(error.message));
253
+ process.exit(1);
254
+ }
255
+ });
256
+ sites
257
+ .command('delete <site>')
258
+ .description('Delete a site')
259
+ .option('-y, --yes', 'Skip confirmation')
260
+ .option('--keep-files', 'Keep site files (only remove from Local)')
261
+ .action(async (site, cmdOptions) => {
262
+ await runSiteCommand(site, { action: 'Deleting', successMessage: () => `Deleted "${site}"` }, async (gql, siteId) => {
263
+ const data = await gql.mutate(`
264
+ mutation($input: DeleteSiteInput!) {
265
+ deleteSite(input: $input) { success error }
266
+ }
267
+ `, { input: { id: siteId, trashFiles: !cmdOptions.keepFiles } });
268
+ if (!data.deleteSite.success) {
269
+ throw new Error(data.deleteSite.error || 'Failed to delete site');
270
+ }
271
+ return data;
272
+ });
273
+ });
274
+ sites
275
+ .command('clone <site> <newName>')
276
+ .description('Clone a site')
277
+ .action(async (site, newName) => {
278
+ await runSiteCommand(site, { action: `Cloning`, successMessage: (data) => `Cloned to "${data.cloneSite.newSiteName}" (${data.cloneSite.newSiteId})` }, async (gql, siteId) => {
279
+ const data = await gql.mutate(`
280
+ mutation($input: CloneSiteInput!) {
281
+ cloneSite(input: $input) { success newSiteId newSiteName error }
282
+ }
283
+ `, { input: { siteId, newName } });
284
+ if (!data.cloneSite.success) {
285
+ throw new Error(data.cloneSite.error || 'Failed to clone site');
286
+ }
287
+ return data;
288
+ });
289
+ });
290
+ sites
291
+ .command('export <site>')
292
+ .description('Export site to zip file')
293
+ .option('-o, --output <path>', 'Output file path')
294
+ .action(async (site, cmdOptions) => {
295
+ await runSiteCommand(site, { action: 'Exporting', successMessage: (data) => `Exported to ${data.exportSite.outputPath}` }, async (gql, siteId) => {
296
+ const data = await gql.mutate(`
297
+ mutation($input: ExportSiteInput!) {
298
+ exportSite(input: $input) { success outputPath error }
299
+ }
300
+ `, { input: { siteId, outputPath: cmdOptions.output } });
301
+ if (!data.exportSite.success) {
302
+ throw new Error(data.exportSite.error || 'Failed to export site');
303
+ }
304
+ return data;
305
+ });
306
+ });
307
+ sites
308
+ .command('import <zipFile>')
309
+ .description('Import site from zip file')
310
+ .option('-n, --name <name>', 'Site name (defaults to zip filename)')
311
+ .action(async (zipFile, cmdOptions) => {
312
+ const globalOpts = program.opts();
313
+ const spinner = globalOpts.quiet ? null : (0, ora_1.default)(`Importing site...`).start();
314
+ try {
315
+ const gql = await ensureConnected(globalOpts);
316
+ const data = await gql.mutate(`
317
+ mutation($input: ImportSiteInput!) {
318
+ importSite(input: $input) { success siteId siteName error }
319
+ }
320
+ `, { input: { zipPath: zipFile, siteName: cmdOptions.name } });
321
+ if (!data.importSite.success) {
322
+ spinner?.fail('Import failed');
323
+ console.error((0, formatters_1.formatError)(data.importSite.error || 'Failed to import site'));
324
+ process.exit(1);
325
+ }
326
+ spinner?.succeed(`Imported "${data.importSite.siteName}" (${data.importSite.siteId})`);
327
+ }
328
+ catch (error) {
329
+ spinner?.fail('Import failed');
330
+ console.error((0, formatters_1.formatError)(error.message));
331
+ process.exit(1);
332
+ }
333
+ });
334
+ sites
335
+ .command('rename <site> <newName>')
336
+ .description('Rename a site')
337
+ .action(async (site, newName) => {
338
+ await runSiteCommand(site, { action: 'Renaming', successMessage: () => `Renamed to "${newName}"` }, async (gql, siteId) => {
339
+ const data = await gql.mutate(`
340
+ mutation($input: McpRenameSiteInput!) {
341
+ mcpRenameSite(input: $input) { success error }
342
+ }
343
+ `, { input: { siteId, newName } });
344
+ if (!data.mcpRenameSite.success) {
345
+ throw new Error(data.mcpRenameSite.error || 'Failed to rename site');
346
+ }
347
+ return data;
348
+ });
349
+ });
350
+ sites
351
+ .command('ssl <site>')
352
+ .description('Trust SSL certificate for a site')
353
+ .action(async (site) => {
354
+ await runSiteCommand(site, { action: 'Trusting SSL for', successMessage: () => `SSL certificate trusted for "${site}"` }, async (gql, siteId) => {
355
+ const data = await gql.mutate(`
356
+ mutation($input: TrustSslInput!) {
357
+ trustSsl(input: $input) { success error }
358
+ }
359
+ `, { input: { siteId } });
360
+ if (!data.trustSsl.success) {
361
+ throw new Error(data.trustSsl.error || 'Failed to trust SSL');
362
+ }
363
+ return data;
364
+ });
365
+ });
366
+ sites
367
+ .command('php <site> <version>')
368
+ .description('Change PHP version for a site')
369
+ .action(async (site, version) => {
370
+ await runSiteCommand(site, { action: `Changing PHP to ${version} for`, successMessage: () => `PHP version changed to ${version}` }, async (gql, siteId) => {
371
+ const data = await gql.mutate(`
372
+ mutation($input: ChangePhpVersionInput!) {
373
+ changePhpVersion(input: $input) { success error }
374
+ }
375
+ `, { input: { siteId, phpVersion: version } });
376
+ if (!data.changePhpVersion.success) {
377
+ throw new Error(data.changePhpVersion.error || 'Failed to change PHP version');
378
+ }
379
+ return data;
380
+ });
381
+ });
382
+ sites
383
+ .command('xdebug <site>')
384
+ .description('Toggle Xdebug for a site')
385
+ .option('--on', 'Enable Xdebug')
386
+ .option('--off', 'Disable Xdebug')
387
+ .action(async (site, cmdOptions) => {
388
+ const enabled = cmdOptions.on ? true : cmdOptions.off ? false : undefined;
389
+ const action = enabled === undefined ? 'Toggling' : enabled ? 'Enabling' : 'Disabling';
390
+ await runSiteCommand(site, { action: `${action} Xdebug for`, successMessage: (data) => `Xdebug ${data.toggleXdebug.enabled ? 'enabled' : 'disabled'}` }, async (gql, siteId) => {
391
+ // If no flag specified, get current state and toggle
392
+ let targetEnabled = enabled;
393
+ if (targetEnabled === undefined) {
394
+ const siteData = await gql.query(`
395
+ query($id: ID!) { site(id: $id) { xdebugEnabled } }
396
+ `, { id: siteId });
397
+ targetEnabled = !siteData.site.xdebugEnabled;
398
+ }
399
+ const data = await gql.mutate(`
400
+ mutation($input: ToggleXdebugInput!) {
401
+ toggleXdebug(input: $input) { success enabled error }
402
+ }
403
+ `, { input: { siteId, enabled: targetEnabled } });
404
+ if (!data.toggleXdebug.success) {
405
+ throw new Error(data.toggleXdebug.error || 'Failed to toggle Xdebug');
406
+ }
407
+ return data;
408
+ });
409
+ });
410
+ sites
411
+ .command('logs <site>')
412
+ .description('Get site logs')
413
+ .option('-t, --type <type>', 'Log type (php|nginx|mysql)', 'php')
414
+ .option('-n, --lines <n>', 'Number of lines', '50')
415
+ .action(async (site, cmdOptions) => {
416
+ const globalOpts = program.opts();
417
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
418
+ try {
419
+ const gql = await ensureConnected(globalOpts);
420
+ const siteId = await findSiteId(gql, site);
421
+ const data = await gql.mutate(`
422
+ mutation($input: GetSiteLogsInput!) {
423
+ getSiteLogs(input: $input) { success logs error }
424
+ }
425
+ `, { input: { siteId, logType: cmdOptions.type, lines: parseInt(cmdOptions.lines, 10) } });
426
+ if (!data.getSiteLogs.success) {
427
+ console.error((0, formatters_1.formatError)(data.getSiteLogs.error || 'Failed to get logs'));
428
+ process.exit(1);
429
+ }
430
+ if (format === 'json') {
431
+ console.log(JSON.stringify(data.getSiteLogs.logs, null, 2));
432
+ }
433
+ else if (data.getSiteLogs.logs.length === 0) {
434
+ console.log('No logs found.');
435
+ }
436
+ else {
437
+ data.getSiteLogs.logs.forEach((line) => console.log(line));
438
+ }
439
+ }
440
+ catch (error) {
441
+ console.error((0, formatters_1.formatError)(error.message));
442
+ process.exit(1);
443
+ }
444
+ });
445
+ // ===========================================
446
+ // WP-CLI Command
447
+ // ===========================================
448
+ program
449
+ .command('wp <site> [args...]')
450
+ .description('Run WP-CLI commands against a site')
451
+ .action(async (site, args) => {
452
+ const globalOpts = program.opts();
453
+ try {
454
+ const gql = await ensureConnected(globalOpts);
455
+ const siteId = await findSiteId(gql, site);
456
+ const data = await gql.mutate(`
457
+ mutation($input: WpCliInput!) {
458
+ wpCli(input: $input) { success output error }
459
+ }
460
+ `, { input: { siteId, args } });
461
+ if (!data.wpCli.success) {
462
+ console.error((0, formatters_1.formatError)(data.wpCli.error || 'WP-CLI command failed'));
463
+ process.exit(1);
464
+ }
465
+ console.log(data.wpCli.output);
466
+ }
467
+ catch (error) {
468
+ console.error((0, formatters_1.formatError)(error.message));
469
+ process.exit(1);
470
+ }
471
+ });
472
+ // ===========================================
473
+ // Info Command
474
+ // ===========================================
475
+ program
476
+ .command('info')
477
+ .description('Show Local application info')
478
+ .action(async () => {
479
+ const globalOpts = program.opts();
480
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
481
+ try {
482
+ const gql = await ensureConnected(globalOpts);
483
+ // Get sites count and basic info
484
+ const data = await gql.query(`
485
+ query { sites { id status } }
486
+ `);
487
+ const running = data.sites.filter((s) => s.status.toLowerCase() === 'running').length;
488
+ const stopped = data.sites.filter((s) => s.status.toLowerCase() !== 'running').length;
489
+ const info = {
490
+ totalSites: data.sites.length,
491
+ runningSites: running,
492
+ stoppedSites: stopped,
493
+ graphqlEndpoint: client?.['url'] || 'connected',
494
+ };
495
+ console.log((0, formatters_1.formatSiteDetail)(info, format, { noColor: globalOpts.noColor }));
496
+ }
497
+ catch (error) {
498
+ console.error((0, formatters_1.formatError)(error.message));
499
+ process.exit(1);
500
+ }
501
+ });
502
+ // ===========================================
503
+ // Services Command
504
+ // ===========================================
505
+ program
506
+ .command('services')
507
+ .description('List available service versions')
508
+ .action(async () => {
509
+ const globalOpts = program.opts();
510
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
511
+ try {
512
+ const gql = await ensureConnected(globalOpts);
513
+ const data = await gql.query(`
514
+ query {
515
+ listServices {
516
+ success
517
+ services { role name version }
518
+ error
519
+ }
520
+ }
521
+ `);
522
+ if (!data.listServices.success) {
523
+ console.error((0, formatters_1.formatError)(data.listServices.error || 'Failed to list services'));
524
+ process.exit(1);
525
+ }
526
+ if (format === 'json') {
527
+ console.log(JSON.stringify(data.listServices.services, null, 2));
528
+ }
529
+ else {
530
+ const grouped = {};
531
+ for (const svc of data.listServices.services) {
532
+ if (!grouped[svc.role])
533
+ grouped[svc.role] = [];
534
+ grouped[svc.role].push(`${svc.version} (${svc.name})`);
535
+ }
536
+ for (const [role, versions] of Object.entries(grouped)) {
537
+ console.log(`\n${role.charAt(0).toUpperCase() + role.slice(1)} Versions:`);
538
+ versions.forEach((v) => console.log(` - ${v}`));
539
+ }
540
+ }
541
+ }
542
+ catch (error) {
543
+ console.error((0, formatters_1.formatError)(error.message));
544
+ process.exit(1);
545
+ }
546
+ });
547
+ // ===========================================
548
+ // Blueprints Command
549
+ // ===========================================
550
+ const blueprints = program.command('blueprints').description('Manage blueprints');
551
+ blueprints
552
+ .command('list')
553
+ .description('List available blueprints')
554
+ .action(async () => {
555
+ const globalOpts = program.opts();
556
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
557
+ try {
558
+ const gql = await ensureConnected(globalOpts);
559
+ const data = await gql.query(`
560
+ query {
561
+ blueprints {
562
+ success
563
+ blueprints { name }
564
+ error
565
+ }
566
+ }
567
+ `);
568
+ if (!data.blueprints.success) {
569
+ console.error((0, formatters_1.formatError)(data.blueprints.error || 'Failed to list blueprints'));
570
+ process.exit(1);
571
+ }
572
+ if (format === 'json') {
573
+ console.log(JSON.stringify(data.blueprints.blueprints, null, 2));
574
+ }
575
+ else if (data.blueprints.blueprints.length === 0) {
576
+ console.log('No blueprints found.');
577
+ }
578
+ else {
579
+ console.log('Blueprints:');
580
+ data.blueprints.blueprints.forEach((b) => console.log(` - ${b.name}`));
581
+ }
582
+ }
583
+ catch (error) {
584
+ console.error((0, formatters_1.formatError)(error.message));
585
+ process.exit(1);
586
+ }
587
+ });
588
+ blueprints
589
+ .command('save <site> <name>')
590
+ .description('Save a site as a blueprint')
591
+ .action(async (site, name) => {
592
+ await runSiteCommand(site, { action: 'Saving blueprint from', successMessage: () => `Saved blueprint "${name}"` }, async (gql, siteId) => {
593
+ const data = await gql.mutate(`
594
+ mutation($input: SaveBlueprintInput!) {
595
+ saveBlueprint(input: $input) { success error }
596
+ }
597
+ `, { input: { siteId, name } });
598
+ if (!data.saveBlueprint.success) {
599
+ throw new Error(data.saveBlueprint.error || 'Failed to save blueprint');
600
+ }
601
+ return data;
602
+ });
603
+ });
604
+ // ===========================================
605
+ // Database Commands
606
+ // ===========================================
607
+ const db = program.command('db').description('Database operations');
608
+ db
609
+ .command('export <site>')
610
+ .description('Export database to SQL file')
611
+ .option('-o, --output <path>', 'Output file path')
612
+ .action(async (site, cmdOptions) => {
613
+ await runSiteCommand(site, { action: 'Exporting database for', successMessage: (data) => `Exported to ${data.exportDatabase.outputPath}` }, async (gql, siteId) => {
614
+ const data = await gql.mutate(`
615
+ mutation($input: ExportDatabaseInput!) {
616
+ exportDatabase(input: $input) { success outputPath error }
617
+ }
618
+ `, { input: { siteId, outputPath: cmdOptions.output } });
619
+ if (!data.exportDatabase.success) {
620
+ throw new Error(data.exportDatabase.error || 'Failed to export database');
621
+ }
622
+ return data;
623
+ });
624
+ });
625
+ db
626
+ .command('import <site> <sqlFile>')
627
+ .description('Import SQL file into database')
628
+ .action(async (site, sqlFile) => {
629
+ await runSiteCommand(site, { action: 'Importing database for', successMessage: () => 'Database imported successfully' }, async (gql, siteId) => {
630
+ const data = await gql.mutate(`
631
+ mutation($input: ImportDatabaseInput!) {
632
+ importDatabase(input: $input) { success error }
633
+ }
634
+ `, { input: { siteId, sqlPath: sqlFile } });
635
+ if (!data.importDatabase.success) {
636
+ throw new Error(data.importDatabase.error || 'Failed to import database');
637
+ }
638
+ return data;
639
+ });
640
+ });
641
+ db
642
+ .command('adminer <site>')
643
+ .description('Open Adminer database UI')
644
+ .action(async (site) => {
645
+ await runSiteCommand(site, { action: 'Opening Adminer for', successMessage: () => 'Opened Adminer' }, async (gql, siteId) => {
646
+ return gql.mutate(`
647
+ mutation($input: OpenAdminerInput!) {
648
+ openAdminer(input: $input) { success error }
649
+ }
650
+ `, { input: { siteId } });
651
+ });
652
+ });
653
+ // ===========================================
654
+ // Backups Commands
655
+ // ===========================================
656
+ const backups = program.command('backups').description('Cloud backup operations');
657
+ backups
658
+ .command('status')
659
+ .description('Check backup service availability')
660
+ .action(async () => {
661
+ const globalOpts = program.opts();
662
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
663
+ try {
664
+ const gql = await ensureConnected(globalOpts);
665
+ const data = await gql.query(`
666
+ query {
667
+ backupStatus {
668
+ available
669
+ featureEnabled
670
+ dropbox { authenticated accountId email }
671
+ googleDrive { authenticated accountId email }
672
+ }
673
+ }
674
+ `);
675
+ if (format === 'json') {
676
+ console.log(JSON.stringify(data.backupStatus, null, 2));
677
+ }
678
+ else {
679
+ const status = data.backupStatus;
680
+ console.log(`\nBackup Status:`);
681
+ console.log(` Available: ${status.available ? 'Yes' : 'No'}`);
682
+ console.log(` Feature Enabled: ${status.featureEnabled ? 'Yes' : 'No'}`);
683
+ if (status.dropbox) {
684
+ console.log(`\n Dropbox: ${status.dropbox.authenticated ? `Connected (${status.dropbox.email})` : 'Not connected'}`);
685
+ }
686
+ if (status.googleDrive) {
687
+ console.log(` Google Drive: ${status.googleDrive.authenticated ? `Connected (${status.googleDrive.email})` : 'Not connected'}`);
688
+ }
689
+ }
690
+ }
691
+ catch (error) {
692
+ console.error((0, formatters_1.formatError)(error.message));
693
+ process.exit(1);
694
+ }
695
+ });
696
+ backups
697
+ .command('list <site>')
698
+ .description('List backups for a site')
699
+ .option('-p, --provider <provider>', 'Backup provider (dropbox|googleDrive)', 'dropbox')
700
+ .action(async (site, cmdOptions) => {
701
+ const globalOpts = program.opts();
702
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
703
+ try {
704
+ const gql = await ensureConnected(globalOpts);
705
+ const siteId = await findSiteId(gql, site);
706
+ const data = await gql.query(`
707
+ query($siteId: ID!, $provider: String!) {
708
+ listBackups(siteId: $siteId, provider: $provider) {
709
+ success
710
+ backups { snapshotId timestamp note }
711
+ error
712
+ }
713
+ }
714
+ `, { siteId, provider: cmdOptions.provider });
715
+ if (!data.listBackups.success) {
716
+ console.error((0, formatters_1.formatError)(data.listBackups.error || 'Failed to list backups'));
717
+ process.exit(1);
718
+ }
719
+ if (format === 'json') {
720
+ console.log(JSON.stringify(data.listBackups.backups, null, 2));
721
+ }
722
+ else if (data.listBackups.backups.length === 0) {
723
+ console.log('No backups found.');
724
+ }
725
+ else {
726
+ console.log(`\nBackups (${cmdOptions.provider}):`);
727
+ for (const backup of data.listBackups.backups) {
728
+ const date = new Date(backup.timestamp).toLocaleString();
729
+ console.log(` ${backup.snapshotId} - ${date}${backup.note ? ` - ${backup.note}` : ''}`);
730
+ }
731
+ }
732
+ }
733
+ catch (error) {
734
+ console.error((0, formatters_1.formatError)(error.message));
735
+ process.exit(1);
736
+ }
737
+ });
738
+ backups
739
+ .command('create <site>')
740
+ .description('Create a backup')
741
+ .option('-p, --provider <provider>', 'Backup provider (dropbox|googleDrive)', 'dropbox')
742
+ .option('-n, --note <note>', 'Backup note')
743
+ .action(async (site, cmdOptions) => {
744
+ await runSiteCommand(site, { action: 'Creating backup for', successMessage: (data) => `Backup created: ${data.createBackup.snapshotId}` }, async (gql, siteId) => {
745
+ const data = await gql.mutate(`
746
+ mutation($siteId: ID!, $provider: String!, $note: String) {
747
+ createBackup(siteId: $siteId, provider: $provider, note: $note) {
748
+ success snapshotId error
749
+ }
750
+ }
751
+ `, { siteId, provider: cmdOptions.provider, note: cmdOptions.note });
752
+ if (!data.createBackup.success) {
753
+ throw new Error(data.createBackup.error || 'Failed to create backup');
754
+ }
755
+ return data;
756
+ });
757
+ });
758
+ backups
759
+ .command('restore <site> <snapshotId>')
760
+ .description('Restore from backup')
761
+ .option('-p, --provider <provider>', 'Backup provider (dropbox|googleDrive)', 'dropbox')
762
+ .option('-y, --yes', 'Skip confirmation')
763
+ .action(async (site, snapshotId, cmdOptions) => {
764
+ await runSiteCommand(site, { action: 'Restoring backup for', successMessage: (data) => data.restoreBackup.message || 'Backup restored successfully' }, async (gql, siteId) => {
765
+ const data = await gql.mutate(`
766
+ mutation($siteId: ID!, $provider: String!, $snapshotId: String!, $confirm: Boolean) {
767
+ restoreBackup(siteId: $siteId, provider: $provider, snapshotId: $snapshotId, confirm: $confirm) {
768
+ success message error
769
+ }
770
+ }
771
+ `, { siteId, provider: cmdOptions.provider, snapshotId, confirm: cmdOptions.yes || false });
772
+ if (!data.restoreBackup.success) {
773
+ throw new Error(data.restoreBackup.error || 'Failed to restore backup');
774
+ }
775
+ return data;
776
+ });
777
+ });
778
+ backups
779
+ .command('delete <site> <snapshotId>')
780
+ .description('Delete a backup')
781
+ .option('-p, --provider <provider>', 'Backup provider (dropbox|googleDrive)', 'dropbox')
782
+ .option('-y, --yes', 'Skip confirmation')
783
+ .action(async (site, snapshotId, cmdOptions) => {
784
+ await runSiteCommand(site, { action: 'Deleting backup for', successMessage: () => 'Backup deleted' }, async (gql, siteId) => {
785
+ const data = await gql.mutate(`
786
+ mutation($siteId: ID!, $provider: String!, $snapshotId: String!, $confirm: Boolean) {
787
+ deleteBackup(siteId: $siteId, provider: $provider, snapshotId: $snapshotId, confirm: $confirm) {
788
+ success error
789
+ }
790
+ }
791
+ `, { siteId, provider: cmdOptions.provider, snapshotId, confirm: cmdOptions.yes || false });
792
+ if (!data.deleteBackup.success) {
793
+ throw new Error(data.deleteBackup.error || 'Failed to delete backup');
794
+ }
795
+ return data;
796
+ });
797
+ });
798
+ // ===========================================
799
+ // WP Engine Commands
800
+ // ===========================================
801
+ const wpe = program.command('wpe').description('WP Engine sync operations');
802
+ wpe
803
+ .command('status')
804
+ .description('Check WP Engine authentication status')
805
+ .action(async () => {
806
+ const globalOpts = program.opts();
807
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
808
+ try {
809
+ const gql = await ensureConnected(globalOpts);
810
+ const data = await gql.query(`
811
+ query {
812
+ wpeStatus {
813
+ authenticated
814
+ email
815
+ accountId
816
+ accountName
817
+ }
818
+ }
819
+ `);
820
+ if (format === 'json') {
821
+ console.log(JSON.stringify(data.wpeStatus, null, 2));
822
+ }
823
+ else {
824
+ const status = data.wpeStatus;
825
+ if (status.authenticated) {
826
+ console.log(`\nWP Engine: Connected`);
827
+ console.log(` Email: ${status.email}`);
828
+ console.log(` Account: ${status.accountName} (${status.accountId})`);
829
+ }
830
+ else {
831
+ console.log(`\nWP Engine: Not connected`);
832
+ console.log(` Run 'lwp wpe login' to authenticate`);
833
+ }
834
+ }
835
+ }
836
+ catch (error) {
837
+ console.error((0, formatters_1.formatError)(error.message));
838
+ process.exit(1);
839
+ }
840
+ });
841
+ wpe
842
+ .command('login')
843
+ .description('Authenticate with WP Engine')
844
+ .action(async () => {
845
+ const globalOpts = program.opts();
846
+ const spinner = globalOpts.quiet ? null : (0, ora_1.default)(`Opening WP Engine login...`).start();
847
+ try {
848
+ const gql = await ensureConnected(globalOpts);
849
+ const data = await gql.mutate(`
850
+ mutation {
851
+ wpeAuthenticate { success email message error }
852
+ }
853
+ `);
854
+ if (!data.wpeAuthenticate.success) {
855
+ spinner?.fail('Authentication failed');
856
+ console.error((0, formatters_1.formatError)(data.wpeAuthenticate.error || 'Failed to authenticate'));
857
+ process.exit(1);
858
+ }
859
+ spinner?.succeed(`Authenticated as ${data.wpeAuthenticate.email}`);
860
+ }
861
+ catch (error) {
862
+ spinner?.fail('Authentication failed');
863
+ console.error((0, formatters_1.formatError)(error.message));
864
+ process.exit(1);
865
+ }
866
+ });
867
+ wpe
868
+ .command('logout')
869
+ .description('Logout from WP Engine')
870
+ .action(async () => {
871
+ const globalOpts = program.opts();
872
+ const spinner = globalOpts.quiet ? null : (0, ora_1.default)(`Logging out...`).start();
873
+ try {
874
+ const gql = await ensureConnected(globalOpts);
875
+ const data = await gql.mutate(`
876
+ mutation {
877
+ wpeLogout { success error }
878
+ }
879
+ `);
880
+ if (!data.wpeLogout.success) {
881
+ spinner?.fail('Logout failed');
882
+ console.error((0, formatters_1.formatError)(data.wpeLogout.error || 'Failed to logout'));
883
+ process.exit(1);
884
+ }
885
+ spinner?.succeed('Logged out from WP Engine');
886
+ }
887
+ catch (error) {
888
+ spinner?.fail('Logout failed');
889
+ console.error((0, formatters_1.formatError)(error.message));
890
+ process.exit(1);
891
+ }
892
+ });
893
+ wpe
894
+ .command('sites')
895
+ .description('List WP Engine sites')
896
+ .action(async () => {
897
+ const globalOpts = program.opts();
898
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
899
+ try {
900
+ const gql = await ensureConnected(globalOpts);
901
+ const data = await gql.query(`
902
+ query {
903
+ listWpeSites {
904
+ success
905
+ sites { id name environment primaryDomain }
906
+ error
907
+ }
908
+ }
909
+ `);
910
+ if (!data.listWpeSites.success) {
911
+ console.error((0, formatters_1.formatError)(data.listWpeSites.error || 'Failed to list sites'));
912
+ process.exit(1);
913
+ }
914
+ if (format === 'json') {
915
+ console.log(JSON.stringify(data.listWpeSites.sites, null, 2));
916
+ }
917
+ else if (data.listWpeSites.sites.length === 0) {
918
+ console.log('No WP Engine sites found.');
919
+ }
920
+ else {
921
+ console.log('\nWP Engine Sites:');
922
+ for (const site of data.listWpeSites.sites) {
923
+ console.log(` ${site.name} (${site.environment}) - ${site.primaryDomain}`);
924
+ }
925
+ }
926
+ }
927
+ catch (error) {
928
+ console.error((0, formatters_1.formatError)(error.message));
929
+ process.exit(1);
930
+ }
931
+ });
932
+ wpe
933
+ .command('link <site>')
934
+ .description('Show WP Engine connection for a local site')
935
+ .action(async (site) => {
936
+ const globalOpts = program.opts();
937
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
938
+ try {
939
+ const gql = await ensureConnected(globalOpts);
940
+ const siteId = await findSiteId(gql, site);
941
+ const data = await gql.query(`
942
+ query($siteId: ID!) {
943
+ getWpeLink(siteId: $siteId) {
944
+ linked
945
+ siteName
946
+ connections { remoteInstallId installName environment primaryDomain }
947
+ }
948
+ }
949
+ `, { siteId });
950
+ if (format === 'json') {
951
+ console.log(JSON.stringify(data.getWpeLink, null, 2));
952
+ }
953
+ else {
954
+ const link = data.getWpeLink;
955
+ if (!link.linked || link.connections.length === 0) {
956
+ console.log(`\n"${link.siteName}" is not linked to WP Engine`);
957
+ }
958
+ else {
959
+ console.log(`\n"${link.siteName}" WP Engine Connections:`);
960
+ for (const conn of link.connections) {
961
+ console.log(` ${conn.installName} (${conn.environment}) - ${conn.primaryDomain}`);
962
+ console.log(` ID: ${conn.remoteInstallId}`);
963
+ }
964
+ }
965
+ }
966
+ }
967
+ catch (error) {
968
+ console.error((0, formatters_1.formatError)(error.message));
969
+ process.exit(1);
970
+ }
971
+ });
972
+ wpe
973
+ .command('push <site>')
974
+ .description('Push local site to WP Engine')
975
+ .option('-r, --remote <installId>', 'Remote install ID')
976
+ .option('--sql', 'Include database')
977
+ .option('-y, --yes', 'Skip confirmation')
978
+ .action(async (site, cmdOptions) => {
979
+ await runSiteCommand(site, { action: 'Pushing to WP Engine', successMessage: (data) => data.pushToWpe.message || 'Pushed to WP Engine' }, async (gql, siteId) => {
980
+ // Get remote install ID if not provided
981
+ let remoteInstallId = cmdOptions.remote;
982
+ if (!remoteInstallId) {
983
+ const linkData = await gql.query(`
984
+ query($siteId: ID!) {
985
+ getWpeLink(siteId: $siteId) {
986
+ connections { remoteInstallId }
987
+ }
988
+ }
989
+ `, { siteId });
990
+ if (linkData.getWpeLink.connections.length === 0) {
991
+ throw new Error('Site is not linked to WP Engine. Use --remote to specify install ID.');
992
+ }
993
+ remoteInstallId = linkData.getWpeLink.connections[0].remoteInstallId;
994
+ }
995
+ const data = await gql.mutate(`
996
+ mutation($localSiteId: ID!, $remoteInstallId: ID!, $includeSql: Boolean, $confirm: Boolean) {
997
+ pushToWpe(localSiteId: $localSiteId, remoteInstallId: $remoteInstallId, includeSql: $includeSql, confirm: $confirm) {
998
+ success message error
999
+ }
1000
+ }
1001
+ `, { localSiteId: siteId, remoteInstallId, includeSql: cmdOptions.sql || false, confirm: cmdOptions.yes || false });
1002
+ if (!data.pushToWpe.success) {
1003
+ throw new Error(data.pushToWpe.error || 'Failed to push to WP Engine');
1004
+ }
1005
+ return data;
1006
+ });
1007
+ });
1008
+ wpe
1009
+ .command('pull <site>')
1010
+ .description('Pull from WP Engine to local site')
1011
+ .option('-r, --remote <installId>', 'Remote install ID')
1012
+ .option('--sql', 'Include database')
1013
+ .action(async (site, cmdOptions) => {
1014
+ await runSiteCommand(site, { action: 'Pulling from WP Engine for', successMessage: (data) => data.pullFromWpe.message || 'Pulled from WP Engine' }, async (gql, siteId) => {
1015
+ // Get remote install ID if not provided
1016
+ let remoteInstallId = cmdOptions.remote;
1017
+ if (!remoteInstallId) {
1018
+ const linkData = await gql.query(`
1019
+ query($siteId: ID!) {
1020
+ getWpeLink(siteId: $siteId) {
1021
+ connections { remoteInstallId }
1022
+ }
1023
+ }
1024
+ `, { siteId });
1025
+ if (linkData.getWpeLink.connections.length === 0) {
1026
+ throw new Error('Site is not linked to WP Engine. Use --remote to specify install ID.');
1027
+ }
1028
+ remoteInstallId = linkData.getWpeLink.connections[0].remoteInstallId;
1029
+ }
1030
+ const data = await gql.mutate(`
1031
+ mutation($localSiteId: ID!, $remoteInstallId: ID!, $includeSql: Boolean) {
1032
+ pullFromWpe(localSiteId: $localSiteId, remoteInstallId: $remoteInstallId, includeSql: $includeSql) {
1033
+ success message error
1034
+ }
1035
+ }
1036
+ `, { localSiteId: siteId, remoteInstallId, includeSql: cmdOptions.sql || false });
1037
+ if (!data.pullFromWpe.success) {
1038
+ throw new Error(data.pullFromWpe.error || 'Failed to pull from WP Engine');
1039
+ }
1040
+ return data;
1041
+ });
1042
+ });
1043
+ wpe
1044
+ .command('history <site>')
1045
+ .description('Show sync history for a site')
1046
+ .option('-l, --limit <n>', 'Number of events to show', '10')
1047
+ .action(async (site, cmdOptions) => {
1048
+ const globalOpts = program.opts();
1049
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
1050
+ try {
1051
+ const gql = await ensureConnected(globalOpts);
1052
+ const siteId = await findSiteId(gql, site);
1053
+ const data = await gql.query(`
1054
+ query($siteId: ID!, $limit: Int) {
1055
+ getSyncHistory(siteId: $siteId, limit: $limit) {
1056
+ success
1057
+ events { remoteInstallName timestamp direction status }
1058
+ error
1059
+ }
1060
+ }
1061
+ `, { siteId, limit: parseInt(cmdOptions.limit, 10) });
1062
+ if (!data.getSyncHistory.success) {
1063
+ console.error((0, formatters_1.formatError)(data.getSyncHistory.error || 'Failed to get sync history'));
1064
+ process.exit(1);
1065
+ }
1066
+ if (format === 'json') {
1067
+ console.log(JSON.stringify(data.getSyncHistory.events, null, 2));
1068
+ }
1069
+ else if (data.getSyncHistory.events.length === 0) {
1070
+ console.log('No sync history found.');
1071
+ }
1072
+ else {
1073
+ console.log('\nSync History:');
1074
+ for (const event of data.getSyncHistory.events) {
1075
+ const date = new Date(event.timestamp).toLocaleString();
1076
+ const arrow = event.direction === 'push' ? '→' : '←';
1077
+ console.log(` ${date} ${arrow} ${event.remoteInstallName} (${event.status})`);
1078
+ }
1079
+ }
1080
+ }
1081
+ catch (error) {
1082
+ console.error((0, formatters_1.formatError)(error.message));
1083
+ process.exit(1);
1084
+ }
1085
+ });
1086
+ wpe
1087
+ .command('diff <site>')
1088
+ .description('Show file changes between local and WP Engine')
1089
+ .option('-d, --direction <dir>', 'Direction (push|pull)', 'push')
1090
+ .action(async (site, cmdOptions) => {
1091
+ const globalOpts = program.opts();
1092
+ const format = (0, formatters_1.getOutputFormat)(globalOpts);
1093
+ try {
1094
+ const gql = await ensureConnected(globalOpts);
1095
+ const siteId = await findSiteId(gql, site);
1096
+ const data = await gql.query(`
1097
+ query($siteId: ID!, $direction: String) {
1098
+ getSiteChanges(siteId: $siteId, direction: $direction) {
1099
+ success
1100
+ added { path }
1101
+ modified { path }
1102
+ deleted { path }
1103
+ totalChanges
1104
+ error
1105
+ }
1106
+ }
1107
+ `, { siteId, direction: cmdOptions.direction });
1108
+ if (!data.getSiteChanges.success) {
1109
+ console.error((0, formatters_1.formatError)(data.getSiteChanges.error || 'Failed to get changes'));
1110
+ process.exit(1);
1111
+ }
1112
+ if (format === 'json') {
1113
+ console.log(JSON.stringify(data.getSiteChanges, null, 2));
1114
+ }
1115
+ else {
1116
+ const changes = data.getSiteChanges;
1117
+ console.log(`\nChanges to ${cmdOptions.direction} (${changes.totalChanges} total):`);
1118
+ if (changes.added.length > 0) {
1119
+ console.log('\n Added:');
1120
+ changes.added.forEach((f) => console.log(` + ${f.path}`));
1121
+ }
1122
+ if (changes.modified.length > 0) {
1123
+ console.log('\n Modified:');
1124
+ changes.modified.forEach((f) => console.log(` ~ ${f.path}`));
1125
+ }
1126
+ if (changes.deleted.length > 0) {
1127
+ console.log('\n Deleted:');
1128
+ changes.deleted.forEach((f) => console.log(` - ${f.path}`));
1129
+ }
1130
+ if (changes.totalChanges === 0) {
1131
+ console.log(' No changes detected.');
1132
+ }
1133
+ }
1134
+ }
1135
+ catch (error) {
1136
+ console.error((0, formatters_1.formatError)(error.message));
1137
+ process.exit(1);
1138
+ }
1139
+ });
1140
+ // ===========================================
1141
+ // Helper Functions
1142
+ // ===========================================
1143
+ /**
1144
+ * Find site ID by name or ID
1145
+ *
1146
+ * Optimization: First tries direct ID lookup (O(1)) before falling back to
1147
+ * fetching all sites for name matching (O(n)). This significantly improves
1148
+ * performance when users specify site IDs directly.
1149
+ */
1150
+ async function findSiteId(gql, siteQuery) {
1151
+ // Try direct ID lookup first - much faster for exact ID matches
1152
+ try {
1153
+ const directLookup = await gql.query(`query GetSiteById($id: ID!) { site(id: $id) { id } }`, { id: siteQuery });
1154
+ if (directLookup.site) {
1155
+ return directLookup.site.id;
1156
+ }
1157
+ }
1158
+ catch {
1159
+ // ID lookup failed, fall through to name search
1160
+ }
1161
+ // Fall back to fetching all sites for name matching
1162
+ const data = await gql.query(`
1163
+ query { sites { id name } }
1164
+ `);
1165
+ const site = data.sites.find((s) => s.name.toLowerCase().includes(siteQuery.toLowerCase()));
1166
+ if (!site) {
1167
+ throw new Error(`Site not found: "${siteQuery}"`);
1168
+ }
1169
+ return site.id;
1170
+ }
1171
+ // Parse and execute
1172
+ program.parse();
1173
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQTs7Ozs7R0FLRzs7Ozs7QUFFSCx5Q0FBb0M7QUFDcEMsOENBQXNCO0FBQ3RCLDJDQUF3RDtBQUN4RCxxQ0FBeUM7QUFDekMsNkNBUXNCO0FBRXRCLE1BQU0sT0FBTyxHQUFHLElBQUksbUJBQU8sRUFBRSxDQUFDO0FBRTlCLHdDQUF3QztBQUN4QyxJQUFJLE1BQU0sR0FBeUIsSUFBSSxDQUFDO0FBRXhDOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGVBQWUsQ0FBQyxPQUF5QjtJQUN0RCxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ1gsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBQSxhQUFHLEVBQUMsd0JBQXdCLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUU3RSxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEscUJBQVMsRUFBQztZQUM3QixPQUFPLEVBQUUsS0FBSztZQUNkLFFBQVEsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUNuQixJQUFJLE9BQU87b0JBQUUsT0FBTyxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7WUFDckMsQ0FBQztTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzlDLE9BQU8sRUFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNuQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUEsd0JBQVcsRUFBQyxNQUFNLENBQUMsS0FBSyxJQUFJLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFD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SSxLQUFLLENBQUMsb0JBQW9CLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUNqQixDQUFDO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcblxuLyoqXG4gKiBMb2NhbCBDTEkgKGx3cClcbiAqXG4gKiBDb21tYW5kLWxpbmUgaW50ZXJmYWNlIGZvciBtYW5hZ2luZyBMb2NhbCBXb3JkUHJlc3Mgc2l0ZXMuXG4gKiBDb25uZWN0cyBkaXJlY3RseSB0byBMb2NhbCdzIEdyYXBoUUwgc2VydmVyLlxuICovXG5cbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IG9yYSBmcm9tICdvcmEnO1xuaW1wb3J0IHsgYm9vdHN0cmFwLCBDb25uZWN0aW9uSW5mbyB9IGZyb20gJy4vYm9vdHN0cmFwJztcbmltcG9ydCB7IEdyYXBoUUxDbGllbnQgfSBmcm9tICcuL2NsaWVudCc7XG5pbXBvcnQge1xuICBmb3JtYXRTaXRlTGlzdCxcbiAgZm9ybWF0U2l0ZURldGFpbCxcbiAgZm9ybWF0U3VjY2VzcyxcbiAgZm9ybWF0RXJyb3IsXG4gIGdldE91dHB1dEZvcm1hdCxcbiAgRm9ybWF0dGVyT3B0aW9ucyxcbiAgU2l0ZUluZm8sXG59IGZyb20gJy4vZm9ybWF0dGVycyc7XG5cbmNvbnN0IHByb2dyYW0gPSBuZXcgQ29tbWFuZCgpO1xuXG4vLyBTdG9yZSBjbGllbnQgZ2xvYmFsbHkgYWZ0ZXIgYm9vdHN0cmFwXG5sZXQgY2xpZW50OiBHcmFwaFFMQ2xpZW50IHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICogRW5zdXJlIHdlJ3JlIGNvbm5lY3RlZCB0byBMb2NhbCdzIEdyYXBoUUwgc2VydmVyXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVuc3VyZUNvbm5lY3RlZChvcHRpb25zOiBGb3JtYXR0ZXJPcHRpb25zKTogUHJvbWlzZTxHcmFwaFFMQ2xpZW50PiB7XG4gIGlmIChjbGllbnQpIHtcbiAgICByZXR1cm4gY2xpZW50O1xuICB9XG5cbiAgY29uc3Qgc3Bpbm5lciA9IG9wdGlvbnMucXVpZXQgPyBudWxsIDogb3JhKCdDb25uZWN0aW5nIHRvIExvY2FsLi4uJykuc3RhcnQoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJvb3RzdHJhcCh7XG4gICAgICB2ZXJib3NlOiBmYWxzZSxcbiAgICAgIG9uU3RhdHVzOiAoc3RhdHVzKSA9PiB7XG4gICAgICAgIGlmIChzcGlubmVyKSBzcGlubmVyLnRleHQgPSBzdGF0dXM7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcyB8fCAhcmVzdWx0LmNvbm5lY3Rpb25JbmZvKSB7XG4gICAgICBzcGlubmVyPy5mYWlsKCdGYWlsZWQgdG8gY29ubmVjdCcpO1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihyZXN1bHQuZXJyb3IgfHwgJ1Vua25vd24gZXJyb3InKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuXG4gICAgc3Bpbm5lcj8uc3VjY2VlZCgnQ29ubmVjdGVkIHRvIExvY2FsJyk7XG4gICAgY2xpZW50ID0gbmV3IEdyYXBoUUxDbGllbnQocmVzdWx0LmNvbm5lY3Rpb25JbmZvKTtcbiAgICByZXR1cm4gY2xpZW50O1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgc3Bpbm5lcj8uZmFpbCgnRmFpbGVkIHRvIGNvbm5lY3QnKTtcbiAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGVycm9yLm1lc3NhZ2UpKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cblxuLyoqXG4gKiBIZWxwZXIgdG8gcnVuIHNpdGUtc3BlY2lmaWMgY29tbWFuZHMgd2l0aCBjb21tb24gYm9pbGVycGxhdGVcbiAqXG4gKiBIYW5kbGVzOiBjb25uZWN0aW9uLCBzcGlubmVyLCBzaXRlIGxvb2t1cCwgZXJyb3IgZm9ybWF0dGluZ1xuICovXG5hc3luYyBmdW5jdGlvbiBydW5TaXRlQ29tbWFuZDxUPihcbiAgc2l0ZU5hbWU6IHN0cmluZyxcbiAgY29uZmlnOiB7XG4gICAgYWN0aW9uOiBzdHJpbmc7XG4gICAgc3VjY2Vzc01lc3NhZ2U/OiAocmVzdWx0OiBUKSA9PiBzdHJpbmc7XG4gIH0sXG4gIGV4ZWN1dGU6IChncWw6IEdyYXBoUUxDbGllbnQsIHNpdGVJZDogc3RyaW5nKSA9PiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gIGNvbnN0IHNwaW5uZXIgPSBnbG9iYWxPcHRzLnF1aWV0ID8gbnVsbCA6IG9yYShgJHtjb25maWcuYWN0aW9ufSBcIiR7c2l0ZU5hbWV9XCIuLi5gKS5zdGFydCgpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuICAgIGNvbnN0IHNpdGVJZCA9IGF3YWl0IGZpbmRTaXRlSWQoZ3FsLCBzaXRlTmFtZSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY3V0ZShncWwsIHNpdGVJZCk7XG5cbiAgICBjb25zdCBtZXNzYWdlID0gY29uZmlnLnN1Y2Nlc3NNZXNzYWdlXG4gICAgICA/IGNvbmZpZy5zdWNjZXNzTWVzc2FnZShyZXN1bHQpXG4gICAgICA6IGAke2NvbmZpZy5hY3Rpb259IFwiJHtzaXRlTmFtZX1cIiBjb21wbGV0ZWRgO1xuICAgIHNwaW5uZXI/LnN1Y2NlZWQobWVzc2FnZSk7XG4gIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICBzcGlubmVyPy5mYWlsKGBGYWlsZWQgdG8gJHtjb25maWcuYWN0aW9uLnRvTG93ZXJDYXNlKCl9IFwiJHtzaXRlTmFtZX1cImApO1xuICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxufVxuXG5wcm9ncmFtXG4gIC5uYW1lKCdsd3AnKVxuICAuZGVzY3JpcHRpb24oJ0NvbW1hbmQtbGluZSBpbnRlcmZhY2UgZm9yIExvY2FsIFdvcmRQcmVzcyBkZXZlbG9wbWVudCcpXG4gIC52ZXJzaW9uKCcwLjEuMCcpO1xuXG4vLyBHbG9iYWwgb3B0aW9uc1xucHJvZ3JhbVxuICAub3B0aW9uKCctLWpzb24nLCAnT3V0cHV0IHJlc3VsdHMgYXMgSlNPTicpXG4gIC5vcHRpb24oJy0tcXVpZXQnLCAnTWluaW1hbCBvdXRwdXQgKElEcy9uYW1lcyBvbmx5KScpXG4gIC5vcHRpb24oJy0tbm8tY29sb3InLCAnRGlzYWJsZSBjb2xvcmVkIG91dHB1dCcpO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTaXRlcyBDb21tYW5kc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5jb25zdCBzaXRlcyA9IHByb2dyYW0uY29tbWFuZCgnc2l0ZXMnKS5kZXNjcmlwdGlvbignTWFuYWdlIFdvcmRQcmVzcyBzaXRlcycpO1xuXG5zaXRlc1xuICAuY29tbWFuZCgnbGlzdCcpXG4gIC5kZXNjcmlwdGlvbignTGlzdCBhbGwgV29yZFByZXNzIHNpdGVzJylcbiAgLm9wdGlvbignLS1zdGF0dXMgPHN0YXR1cz4nLCAnRmlsdGVyIGJ5IHN0YXR1cyAocnVubmluZ3xzdG9wcGVkfGFsbCknLCAnYWxsJylcbiAgLmFjdGlvbihhc3luYyAoY21kT3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLnF1ZXJ5PHsgc2l0ZXM6IEFycmF5PHsgaWQ6IHN0cmluZzsgbmFtZTogc3RyaW5nOyBkb21haW46IHN0cmluZzsgc3RhdHVzOiBzdHJpbmc7IHBhdGg6IHN0cmluZyB9PiB9PihgXG4gICAgICAgIHF1ZXJ5IHtcbiAgICAgICAgICBzaXRlcyB7XG4gICAgICAgICAgICBpZFxuICAgICAgICAgICAgbmFtZVxuICAgICAgICAgICAgZG9tYWluXG4gICAgICAgICAgICBzdGF0dXNcbiAgICAgICAgICAgIHBhdGhcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGApO1xuXG4gICAgICBsZXQgc2l0ZXNUb1Nob3cgPSBkYXRhLnNpdGVzLm1hcCgocykgPT4gKHtcbiAgICAgICAgaWQ6IHMuaWQsXG4gICAgICAgIG5hbWU6IHMubmFtZSxcbiAgICAgICAgZG9tYWluOiBzLmRvbWFpbixcbiAgICAgICAgc3RhdHVzOiBzLnN0YXR1cy50b0xvd2VyQ2FzZSgpLFxuICAgICAgICBwYXRoOiBzLnBhdGgsXG4gICAgICB9KSk7XG5cbiAgICAgIC8vIEZpbHRlciBieSBzdGF0dXMgaWYgc3BlY2lmaWVkXG4gICAgICBpZiAoY21kT3B0aW9ucy5zdGF0dXMgIT09ICdhbGwnKSB7XG4gICAgICAgIHNpdGVzVG9TaG93ID0gc2l0ZXNUb1Nob3cuZmlsdGVyKChzKSA9PiBzLnN0YXR1cyA9PT0gY21kT3B0aW9ucy5zdGF0dXMpO1xuICAgICAgfVxuXG4gICAgICBjb25zb2xlLmxvZyhmb3JtYXRTaXRlTGlzdChzaXRlc1RvU2hvdywgZm9ybWF0LCB7IG5vQ29sb3I6IGdsb2JhbE9wdHMubm9Db2xvciB9KSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ2dldCA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ0dldCBkZXRhaWxlZCBpbmZvIGFib3V0IGEgc2l0ZScpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUpID0+IHtcbiAgICBjb25zdCBnbG9iYWxPcHRzID0gcHJvZ3JhbS5vcHRzKCkgYXMgRm9ybWF0dGVyT3B0aW9ucztcbiAgICBjb25zdCBmb3JtYXQgPSBnZXRPdXRwdXRGb3JtYXQoZ2xvYmFsT3B0cyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICAvLyBGaXJzdCBmaW5kIHRoZSBzaXRlIGJ5IG5hbWUgb3IgSURcbiAgICAgIGNvbnN0IHNpdGVzRGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IHNpdGVzOiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9PiB9PihgXG4gICAgICAgIHF1ZXJ5IHsgc2l0ZXMgeyBpZCBuYW1lIH0gfVxuICAgICAgYCk7XG5cbiAgICAgIGNvbnN0IGZvdW5kU2l0ZSA9IHNpdGVzRGF0YS5zaXRlcy5maW5kKFxuICAgICAgICAocykgPT4gcy5pZCA9PT0gc2l0ZSB8fCBzLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhzaXRlLnRvTG93ZXJDYXNlKCkpXG4gICAgICApO1xuXG4gICAgICBpZiAoIWZvdW5kU2l0ZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGBTaXRlIG5vdCBmb3VuZDogXCIke3NpdGV9XCJgKSk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IHNpdGU6IGFueSB9PihgXG4gICAgICAgIHF1ZXJ5KCRpZDogSUQhKSB7XG4gICAgICAgICAgc2l0ZShpZDogJGlkKSB7XG4gICAgICAgICAgICBpZFxuICAgICAgICAgICAgbmFtZVxuICAgICAgICAgICAgZG9tYWluXG4gICAgICAgICAgICBzdGF0dXNcbiAgICAgICAgICAgIHBhdGhcbiAgICAgICAgICAgIHVybFxuICAgICAgICAgICAgaG9zdFxuICAgICAgICAgICAgaHR0cFBvcnRcbiAgICAgICAgICAgIHhkZWJ1Z0VuYWJsZWRcbiAgICAgICAgICAgIHNlcnZpY2VzIHtcbiAgICAgICAgICAgICAgbmFtZVxuICAgICAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICAgICAgIHJvbGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhvc3RDb25uZWN0aW9ucyB7XG4gICAgICAgICAgICAgIGhvc3RJZFxuICAgICAgICAgICAgICByZW1vdGVTaXRlSWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaWQ6IGZvdW5kU2l0ZS5pZCB9KTtcblxuICAgICAgY29uc29sZS5sb2coZm9ybWF0U2l0ZURldGFpbChkYXRhLnNpdGUsIGZvcm1hdCwgeyBub0NvbG9yOiBnbG9iYWxPcHRzLm5vQ29sb3IgfSkpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbnNpdGVzXG4gIC5jb21tYW5kKCdzdGFydCA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1N0YXJ0IGEgc2l0ZScpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUpID0+IHtcbiAgICBhd2FpdCBydW5TaXRlQ29tbWFuZChzaXRlLCB7IGFjdGlvbjogJ1N0YXJ0aW5nJywgc3VjY2Vzc01lc3NhZ2U6ICgpID0+IGBTdGFydGVkIFwiJHtzaXRlfVwiYCB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIHJldHVybiBncWwubXV0YXRlKGBtdXRhdGlvbigkaWQ6IElEISkgeyBzdGFydFNpdGUoaWQ6ICRpZCkgeyBpZCBzdGF0dXMgfSB9YCwgeyBpZDogc2l0ZUlkIH0pO1xuICAgIH0pO1xuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ3N0b3AgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdTdG9wIGEgc2l0ZScpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUpID0+IHtcbiAgICBhd2FpdCBydW5TaXRlQ29tbWFuZChzaXRlLCB7IGFjdGlvbjogJ1N0b3BwaW5nJywgc3VjY2Vzc01lc3NhZ2U6ICgpID0+IGBTdG9wcGVkIFwiJHtzaXRlfVwiYCB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIHJldHVybiBncWwubXV0YXRlKGBtdXRhdGlvbigkaWQ6IElEISkgeyBzdG9wU2l0ZShpZDogJGlkKSB7IGlkIHN0YXR1cyB9IH1gLCB7IGlkOiBzaXRlSWQgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG5zaXRlc1xuICAuY29tbWFuZCgncmVzdGFydCA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1Jlc3RhcnQgYSBzaXRlJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSkgPT4ge1xuICAgIGF3YWl0IHJ1blNpdGVDb21tYW5kKHNpdGUsIHsgYWN0aW9uOiAnUmVzdGFydGluZycsIHN1Y2Nlc3NNZXNzYWdlOiAoKSA9PiBgUmVzdGFydGVkIFwiJHtzaXRlfVwiYCB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIHJldHVybiBncWwubXV0YXRlKGBtdXRhdGlvbigkaWQ6IElEISkgeyByZXN0YXJ0U2l0ZShpZDogJGlkKSB7IGlkIHN0YXR1cyB9IH1gLCB7IGlkOiBzaXRlSWQgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG5zaXRlc1xuICAuY29tbWFuZCgnb3BlbiA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ09wZW4gc2l0ZSBpbiBicm93c2VyJylcbiAgLm9wdGlvbignLS1hZG1pbicsICdPcGVuIFdQIEFkbWluIGluc3RlYWQgb2YgZnJvbnRlbmQnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdPcGVuaW5nJywgc3VjY2Vzc01lc3NhZ2U6ICgpID0+IGBPcGVuZWQgXCIke3NpdGV9XCJgIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgcmV0dXJuIGdxbC5tdXRhdGUoYFxuICAgICAgICBtdXRhdGlvbigkaW5wdXQ6IE9wZW5TaXRlSW5wdXQhKSB7XG4gICAgICAgICAgb3BlblNpdGUoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dDogeyBzaXRlSWQsIG9wZW5BZG1pbjogY21kT3B0aW9ucy5hZG1pbiB8fCBmYWxzZSB9IH0pO1xuICAgIH0pO1xuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ2NyZWF0ZSA8bmFtZT4nKVxuICAuZGVzY3JpcHRpb24oJ0NyZWF0ZSBhIG5ldyBXb3JkUHJlc3Mgc2l0ZScpXG4gIC5vcHRpb24oJy0tcGhwIDx2ZXJzaW9uPicsICdQSFAgdmVyc2lvbiAoZS5nLiwgOC4yLjEwKScpXG4gIC5vcHRpb24oJy0td2ViIDxzZXJ2ZXI+JywgJ1dlYiBzZXJ2ZXIgKG5naW54fGFwYWNoZSknKVxuICAub3B0aW9uKCctLWRiIDxkYXRhYmFzZT4nLCAnRGF0YWJhc2UgKG15c3FsfG1hcmlhZGIpJylcbiAgLm9wdGlvbignLS1ibHVlcHJpbnQgPG5hbWU+JywgJ1VzZSBhIGJsdWVwcmludCcpXG4gIC5vcHRpb24oJy0td3AtdXNlciA8dXNlcm5hbWU+JywgJ1dvcmRQcmVzcyBhZG1pbiB1c2VybmFtZScsICdhZG1pbicpXG4gIC5vcHRpb24oJy0td3AtZW1haWwgPGVtYWlsPicsICdXb3JkUHJlc3MgYWRtaW4gZW1haWwnKVxuICAuYWN0aW9uKGFzeW5jIChuYW1lLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gICAgY29uc3Qgc3Bpbm5lciA9IGdsb2JhbE9wdHMucXVpZXQgPyBudWxsIDogb3JhKGBDcmVhdGluZyBcIiR7bmFtZX1cIi4uLmApLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBpbnB1dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7IG5hbWUgfTtcbiAgICAgIGlmIChjbWRPcHRpb25zLnBocCkgaW5wdXQucGhwVmVyc2lvbiA9IGNtZE9wdGlvbnMucGhwO1xuICAgICAgaWYgKGNtZE9wdGlvbnMud2ViKSBpbnB1dC53ZWJTZXJ2ZXIgPSBjbWRPcHRpb25zLndlYjtcbiAgICAgIGlmIChjbWRPcHRpb25zLmRiKSBpbnB1dC5kYXRhYmFzZSA9IGNtZE9wdGlvbnMuZGI7XG4gICAgICBpZiAoY21kT3B0aW9ucy5ibHVlcHJpbnQpIGlucHV0LmJsdWVwcmludCA9IGNtZE9wdGlvbnMuYmx1ZXByaW50O1xuICAgICAgaWYgKGNtZE9wdGlvbnMud3BVc2VyKSBpbnB1dC53cEFkbWluVXNlcm5hbWUgPSBjbWRPcHRpb25zLndwVXNlcjtcbiAgICAgIGlmIChjbWRPcHRpb25zLndwRW1haWwpIGlucHV0LndwQWRtaW5FbWFpbCA9IGNtZE9wdGlvbnMud3BFbWFpbDtcblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBjcmVhdGVTaXRlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IHNpdGVJZDogc3RyaW5nOyBzaXRlTmFtZTogc3RyaW5nOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBDcmVhdGVTaXRlSW5wdXQhKSB7XG4gICAgICAgICAgY3JlYXRlU2l0ZShpbnB1dDogJGlucHV0KSB7IHN1Y2Nlc3Mgc2l0ZUlkIHNpdGVOYW1lIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dCB9KTtcblxuICAgICAgaWYgKCFkYXRhLmNyZWF0ZVNpdGUuc3VjY2Vzcykge1xuICAgICAgICBzcGlubmVyPy5mYWlsKCdDcmVhdGUgZmFpbGVkJyk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZGF0YS5jcmVhdGVTaXRlLmVycm9yIHx8ICdGYWlsZWQgdG8gY3JlYXRlIHNpdGUnKSk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cblxuICAgICAgc3Bpbm5lcj8uc3VjY2VlZChgQ3JlYXRlZCBcIiR7ZGF0YS5jcmVhdGVTaXRlLnNpdGVOYW1lfVwiICgke2RhdGEuY3JlYXRlU2l0ZS5zaXRlSWR9KWApO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIHNwaW5uZXI/LmZhaWwoJ0NyZWF0ZSBmYWlsZWQnKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbnNpdGVzXG4gIC5jb21tYW5kKCdkZWxldGUgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdEZWxldGUgYSBzaXRlJylcbiAgLm9wdGlvbignLXksIC0teWVzJywgJ1NraXAgY29uZmlybWF0aW9uJylcbiAgLm9wdGlvbignLS1rZWVwLWZpbGVzJywgJ0tlZXAgc2l0ZSBmaWxlcyAob25seSByZW1vdmUgZnJvbSBMb2NhbCknKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdEZWxldGluZycsIHN1Y2Nlc3NNZXNzYWdlOiAoKSA9PiBgRGVsZXRlZCBcIiR7c2l0ZX1cImAgfSwgYXN5bmMgKGdxbCwgc2l0ZUlkKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IGRlbGV0ZVNpdGU6IHsgc3VjY2VzczogYm9vbGVhbjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIG11dGF0aW9uKCRpbnB1dDogRGVsZXRlU2l0ZUlucHV0ISkge1xuICAgICAgICAgIGRlbGV0ZVNpdGUoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dDogeyBpZDogc2l0ZUlkLCB0cmFzaEZpbGVzOiAhY21kT3B0aW9ucy5rZWVwRmlsZXMgfSB9KTtcbiAgICAgIGlmICghZGF0YS5kZWxldGVTaXRlLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuZGVsZXRlU2l0ZS5lcnJvciB8fCAnRmFpbGVkIHRvIGRlbGV0ZSBzaXRlJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbnNpdGVzXG4gIC5jb21tYW5kKCdjbG9uZSA8c2l0ZT4gPG5ld05hbWU+JylcbiAgLmRlc2NyaXB0aW9uKCdDbG9uZSBhIHNpdGUnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBuZXdOYW1lKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246IGBDbG9uaW5nYCwgc3VjY2Vzc01lc3NhZ2U6IChkYXRhOiB7IGNsb25lU2l0ZTogeyBuZXdTaXRlTmFtZTogc3RyaW5nOyBuZXdTaXRlSWQ6IHN0cmluZyB9IH0pID0+IGBDbG9uZWQgdG8gXCIke2RhdGEuY2xvbmVTaXRlLm5ld1NpdGVOYW1lfVwiICgke2RhdGEuY2xvbmVTaXRlLm5ld1NpdGVJZH0pYCB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwubXV0YXRlPHsgY2xvbmVTaXRlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IG5ld1NpdGVJZDogc3RyaW5nOyBuZXdTaXRlTmFtZTogc3RyaW5nOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBDbG9uZVNpdGVJbnB1dCEpIHtcbiAgICAgICAgICBjbG9uZVNpdGUoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIG5ld1NpdGVJZCBuZXdTaXRlTmFtZSBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkLCBuZXdOYW1lIH0gfSk7XG4gICAgICBpZiAoIWRhdGEuY2xvbmVTaXRlLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuY2xvbmVTaXRlLmVycm9yIHx8ICdGYWlsZWQgdG8gY2xvbmUgc2l0ZScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSk7XG4gIH0pO1xuXG5zaXRlc1xuICAuY29tbWFuZCgnZXhwb3J0IDxzaXRlPicpXG4gIC5kZXNjcmlwdGlvbignRXhwb3J0IHNpdGUgdG8gemlwIGZpbGUnKVxuICAub3B0aW9uKCctbywgLS1vdXRwdXQgPHBhdGg+JywgJ091dHB1dCBmaWxlIHBhdGgnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdFeHBvcnRpbmcnLCBzdWNjZXNzTWVzc2FnZTogKGRhdGE6IHsgZXhwb3J0U2l0ZTogeyBvdXRwdXRQYXRoOiBzdHJpbmcgfSB9KSA9PiBgRXhwb3J0ZWQgdG8gJHtkYXRhLmV4cG9ydFNpdGUub3V0cHV0UGF0aH1gIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBleHBvcnRTaXRlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IG91dHB1dFBhdGg6IHN0cmluZzsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIG11dGF0aW9uKCRpbnB1dDogRXhwb3J0U2l0ZUlucHV0ISkge1xuICAgICAgICAgIGV4cG9ydFNpdGUoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIG91dHB1dFBhdGggZXJyb3IgfVxuICAgICAgICB9XG4gICAgICBgLCB7IGlucHV0OiB7IHNpdGVJZCwgb3V0cHV0UGF0aDogY21kT3B0aW9ucy5vdXRwdXQgfSB9KTtcbiAgICAgIGlmICghZGF0YS5leHBvcnRTaXRlLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuZXhwb3J0U2l0ZS5lcnJvciB8fCAnRmFpbGVkIHRvIGV4cG9ydCBzaXRlJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbnNpdGVzXG4gIC5jb21tYW5kKCdpbXBvcnQgPHppcEZpbGU+JylcbiAgLmRlc2NyaXB0aW9uKCdJbXBvcnQgc2l0ZSBmcm9tIHppcCBmaWxlJylcbiAgLm9wdGlvbignLW4sIC0tbmFtZSA8bmFtZT4nLCAnU2l0ZSBuYW1lIChkZWZhdWx0cyB0byB6aXAgZmlsZW5hbWUpJylcbiAgLmFjdGlvbihhc3luYyAoemlwRmlsZSwgY21kT3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IHNwaW5uZXIgPSBnbG9iYWxPcHRzLnF1aWV0ID8gbnVsbCA6IG9yYShgSW1wb3J0aW5nIHNpdGUuLi5gKS5zdGFydCgpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGdxbCA9IGF3YWl0IGVuc3VyZUNvbm5lY3RlZChnbG9iYWxPcHRzKTtcblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBpbXBvcnRTaXRlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IHNpdGVJZDogc3RyaW5nOyBzaXRlTmFtZTogc3RyaW5nOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBJbXBvcnRTaXRlSW5wdXQhKSB7XG4gICAgICAgICAgaW1wb3J0U2l0ZShpbnB1dDogJGlucHV0KSB7IHN1Y2Nlc3Mgc2l0ZUlkIHNpdGVOYW1lIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dDogeyB6aXBQYXRoOiB6aXBGaWxlLCBzaXRlTmFtZTogY21kT3B0aW9ucy5uYW1lIH0gfSk7XG5cbiAgICAgIGlmICghZGF0YS5pbXBvcnRTaXRlLnN1Y2Nlc3MpIHtcbiAgICAgICAgc3Bpbm5lcj8uZmFpbCgnSW1wb3J0IGZhaWxlZCcpO1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEuaW1wb3J0U2l0ZS5lcnJvciB8fCAnRmFpbGVkIHRvIGltcG9ydCBzaXRlJykpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG5cbiAgICAgIHNwaW5uZXI/LnN1Y2NlZWQoYEltcG9ydGVkIFwiJHtkYXRhLmltcG9ydFNpdGUuc2l0ZU5hbWV9XCIgKCR7ZGF0YS5pbXBvcnRTaXRlLnNpdGVJZH0pYCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgc3Bpbm5lcj8uZmFpbCgnSW1wb3J0IGZhaWxlZCcpO1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ3JlbmFtZSA8c2l0ZT4gPG5ld05hbWU+JylcbiAgLmRlc2NyaXB0aW9uKCdSZW5hbWUgYSBzaXRlJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgbmV3TmFtZSkgPT4ge1xuICAgIGF3YWl0IHJ1blNpdGVDb21tYW5kKHNpdGUsIHsgYWN0aW9uOiAnUmVuYW1pbmcnLCBzdWNjZXNzTWVzc2FnZTogKCkgPT4gYFJlbmFtZWQgdG8gXCIke25ld05hbWV9XCJgIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBtY3BSZW5hbWVTaXRlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkaW5wdXQ6IE1jcFJlbmFtZVNpdGVJbnB1dCEpIHtcbiAgICAgICAgICBtY3BSZW5hbWVTaXRlKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkLCBuZXdOYW1lIH0gfSk7XG4gICAgICBpZiAoIWRhdGEubWNwUmVuYW1lU2l0ZS5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLm1jcFJlbmFtZVNpdGUuZXJyb3IgfHwgJ0ZhaWxlZCB0byByZW5hbWUgc2l0ZScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSk7XG4gIH0pO1xuXG5zaXRlc1xuICAuY29tbWFuZCgnc3NsIDxzaXRlPicpXG4gIC5kZXNjcmlwdGlvbignVHJ1c3QgU1NMIGNlcnRpZmljYXRlIGZvciBhIHNpdGUnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdUcnVzdGluZyBTU0wgZm9yJywgc3VjY2Vzc01lc3NhZ2U6ICgpID0+IGBTU0wgY2VydGlmaWNhdGUgdHJ1c3RlZCBmb3IgXCIke3NpdGV9XCJgIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyB0cnVzdFNzbDogeyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBUcnVzdFNzbElucHV0ISkge1xuICAgICAgICAgIHRydXN0U3NsKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkIH0gfSk7XG4gICAgICBpZiAoIWRhdGEudHJ1c3RTc2wuc3VjY2Vzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZGF0YS50cnVzdFNzbC5lcnJvciB8fCAnRmFpbGVkIHRvIHRydXN0IFNTTCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSk7XG4gIH0pO1xuXG5zaXRlc1xuICAuY29tbWFuZCgncGhwIDxzaXRlPiA8dmVyc2lvbj4nKVxuICAuZGVzY3JpcHRpb24oJ0NoYW5nZSBQSFAgdmVyc2lvbiBmb3IgYSBzaXRlJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgdmVyc2lvbikgPT4ge1xuICAgIGF3YWl0IHJ1blNpdGVDb21tYW5kKHNpdGUsIHsgYWN0aW9uOiBgQ2hhbmdpbmcgUEhQIHRvICR7dmVyc2lvbn0gZm9yYCwgc3VjY2Vzc01lc3NhZ2U6ICgpID0+IGBQSFAgdmVyc2lvbiBjaGFuZ2VkIHRvICR7dmVyc2lvbn1gIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBjaGFuZ2VQaHBWZXJzaW9uOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkaW5wdXQ6IENoYW5nZVBocFZlcnNpb25JbnB1dCEpIHtcbiAgICAgICAgICBjaGFuZ2VQaHBWZXJzaW9uKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkLCBwaHBWZXJzaW9uOiB2ZXJzaW9uIH0gfSk7XG4gICAgICBpZiAoIWRhdGEuY2hhbmdlUGhwVmVyc2lvbi5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLmNoYW5nZVBocFZlcnNpb24uZXJyb3IgfHwgJ0ZhaWxlZCB0byBjaGFuZ2UgUEhQIHZlcnNpb24nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0pO1xuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ3hkZWJ1ZyA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1RvZ2dsZSBYZGVidWcgZm9yIGEgc2l0ZScpXG4gIC5vcHRpb24oJy0tb24nLCAnRW5hYmxlIFhkZWJ1ZycpXG4gIC5vcHRpb24oJy0tb2ZmJywgJ0Rpc2FibGUgWGRlYnVnJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgY21kT3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IGVuYWJsZWQgPSBjbWRPcHRpb25zLm9uID8gdHJ1ZSA6IGNtZE9wdGlvbnMub2ZmID8gZmFsc2UgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWN0aW9uID0gZW5hYmxlZCA9PT0gdW5kZWZpbmVkID8gJ1RvZ2dsaW5nJyA6IGVuYWJsZWQgPyAnRW5hYmxpbmcnIDogJ0Rpc2FibGluZyc7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246IGAke2FjdGlvbn0gWGRlYnVnIGZvcmAsIHN1Y2Nlc3NNZXNzYWdlOiAoZGF0YTogeyB0b2dnbGVYZGVidWc6IHsgZW5hYmxlZDogYm9vbGVhbiB9IH0pID0+IGBYZGVidWcgJHtkYXRhLnRvZ2dsZVhkZWJ1Zy5lbmFibGVkID8gJ2VuYWJsZWQnIDogJ2Rpc2FibGVkJ31gIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgLy8gSWYgbm8gZmxhZyBzcGVjaWZpZWQsIGdldCBjdXJyZW50IHN0YXRlIGFuZCB0b2dnbGVcbiAgICAgIGxldCB0YXJnZXRFbmFibGVkID0gZW5hYmxlZDtcbiAgICAgIGlmICh0YXJnZXRFbmFibGVkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3Qgc2l0ZURhdGEgPSBhd2FpdCBncWwucXVlcnk8eyBzaXRlOiB7IHhkZWJ1Z0VuYWJsZWQ6IGJvb2xlYW4gfSB9PihgXG4gICAgICAgICAgcXVlcnkoJGlkOiBJRCEpIHsgc2l0ZShpZDogJGlkKSB7IHhkZWJ1Z0VuYWJsZWQgfSB9XG4gICAgICAgIGAsIHsgaWQ6IHNpdGVJZCB9KTtcbiAgICAgICAgdGFyZ2V0RW5hYmxlZCA9ICFzaXRlRGF0YS5zaXRlLnhkZWJ1Z0VuYWJsZWQ7XG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IHRvZ2dsZVhkZWJ1ZzogeyBzdWNjZXNzOiBib29sZWFuOyBlbmFibGVkOiBib29sZWFuOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBUb2dnbGVYZGVidWdJbnB1dCEpIHtcbiAgICAgICAgICB0b2dnbGVYZGVidWcoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIGVuYWJsZWQgZXJyb3IgfVxuICAgICAgICB9XG4gICAgICBgLCB7IGlucHV0OiB7IHNpdGVJZCwgZW5hYmxlZDogdGFyZ2V0RW5hYmxlZCB9IH0pO1xuICAgICAgaWYgKCFkYXRhLnRvZ2dsZVhkZWJ1Zy5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLnRvZ2dsZVhkZWJ1Zy5lcnJvciB8fCAnRmFpbGVkIHRvIHRvZ2dsZSBYZGVidWcnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0pO1xuICB9KTtcblxuc2l0ZXNcbiAgLmNvbW1hbmQoJ2xvZ3MgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdHZXQgc2l0ZSBsb2dzJylcbiAgLm9wdGlvbignLXQsIC0tdHlwZSA8dHlwZT4nLCAnTG9nIHR5cGUgKHBocHxuZ2lueHxteXNxbCknLCAncGhwJylcbiAgLm9wdGlvbignLW4sIC0tbGluZXMgPG4+JywgJ051bWJlciBvZiBsaW5lcycsICc1MCcpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUsIGNtZE9wdGlvbnMpID0+IHtcbiAgICBjb25zdCBnbG9iYWxPcHRzID0gcHJvZ3JhbS5vcHRzKCkgYXMgRm9ybWF0dGVyT3B0aW9ucztcbiAgICBjb25zdCBmb3JtYXQgPSBnZXRPdXRwdXRGb3JtYXQoZ2xvYmFsT3B0cyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuICAgICAgY29uc3Qgc2l0ZUlkID0gYXdhaXQgZmluZFNpdGVJZChncWwsIHNpdGUpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IGdldFNpdGVMb2dzOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IGxvZ3M6IHN0cmluZ1tdOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBHZXRTaXRlTG9nc0lucHV0ISkge1xuICAgICAgICAgIGdldFNpdGVMb2dzKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBsb2dzIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dDogeyBzaXRlSWQsIGxvZ1R5cGU6IGNtZE9wdGlvbnMudHlwZSwgbGluZXM6IHBhcnNlSW50KGNtZE9wdGlvbnMubGluZXMsIDEwKSB9IH0pO1xuXG4gICAgICBpZiAoIWRhdGEuZ2V0U2l0ZUxvZ3Muc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEuZ2V0U2l0ZUxvZ3MuZXJyb3IgfHwgJ0ZhaWxlZCB0byBnZXQgbG9ncycpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5nZXRTaXRlTG9ncy5sb2dzLCBudWxsLCAyKSk7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEuZ2V0U2l0ZUxvZ3MubG9ncy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coJ05vIGxvZ3MgZm91bmQuJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkYXRhLmdldFNpdGVMb2dzLmxvZ3MuZm9yRWFjaCgobGluZSkgPT4gY29uc29sZS5sb2cobGluZSkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFdQLUNMSSBDb21tYW5kXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbnByb2dyYW1cbiAgLmNvbW1hbmQoJ3dwIDxzaXRlPiBbYXJncy4uLl0nKVxuICAuZGVzY3JpcHRpb24oJ1J1biBXUC1DTEkgY29tbWFuZHMgYWdhaW5zdCBhIHNpdGUnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBhcmdzKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuICAgICAgY29uc3Qgc2l0ZUlkID0gYXdhaXQgZmluZFNpdGVJZChncWwsIHNpdGUpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IHdwQ2xpOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IG91dHB1dDogc3RyaW5nOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBXcENsaUlucHV0ISkge1xuICAgICAgICAgIHdwQ2xpKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBvdXRwdXQgZXJyb3IgfVxuICAgICAgICB9XG4gICAgICBgLCB7IGlucHV0OiB7IHNpdGVJZCwgYXJncyB9IH0pO1xuXG4gICAgICBpZiAoIWRhdGEud3BDbGkuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEud3BDbGkuZXJyb3IgfHwgJ1dQLUNMSSBjb21tYW5kIGZhaWxlZCcpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBjb25zb2xlLmxvZyhkYXRhLndwQ2xpLm91dHB1dCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSW5mbyBDb21tYW5kXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbnByb2dyYW1cbiAgLmNvbW1hbmQoJ2luZm8nKVxuICAuZGVzY3JpcHRpb24oJ1Nob3cgTG9jYWwgYXBwbGljYXRpb24gaW5mbycpXG4gIC5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG5cbiAgICAgIC8vIEdldCBzaXRlcyBjb3VudCBhbmQgYmFzaWMgaW5mb1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IHNpdGVzOiBBcnJheTx7IGlkOiBzdHJpbmc7IHN0YXR1czogc3RyaW5nIH0+IH0+KGBcbiAgICAgICAgcXVlcnkgeyBzaXRlcyB7IGlkIHN0YXR1cyB9IH1cbiAgICAgIGApO1xuXG4gICAgICBjb25zdCBydW5uaW5nID0gZGF0YS5zaXRlcy5maWx0ZXIoKHMpID0+IHMuc3RhdHVzLnRvTG93ZXJDYXNlKCkgPT09ICdydW5uaW5nJykubGVuZ3RoO1xuICAgICAgY29uc3Qgc3RvcHBlZCA9IGRhdGEuc2l0ZXMuZmlsdGVyKChzKSA9PiBzLnN0YXR1cy50b0xvd2VyQ2FzZSgpICE9PSAncnVubmluZycpLmxlbmd0aDtcblxuICAgICAgY29uc3QgaW5mbyA9IHtcbiAgICAgICAgdG90YWxTaXRlczogZGF0YS5zaXRlcy5sZW5ndGgsXG4gICAgICAgIHJ1bm5pbmdTaXRlczogcnVubmluZyxcbiAgICAgICAgc3RvcHBlZFNpdGVzOiBzdG9wcGVkLFxuICAgICAgICBncmFwaHFsRW5kcG9pbnQ6IGNsaWVudD8uWyd1cmwnXSB8fCAnY29ubmVjdGVkJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnNvbGUubG9nKGZvcm1hdFNpdGVEZXRhaWwoaW5mbywgZm9ybWF0LCB7IG5vQ29sb3I6IGdsb2JhbE9wdHMubm9Db2xvciB9KSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gU2VydmljZXMgQ29tbWFuZFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5wcm9ncmFtXG4gIC5jb21tYW5kKCdzZXJ2aWNlcycpXG4gIC5kZXNjcmlwdGlvbignTGlzdCBhdmFpbGFibGUgc2VydmljZSB2ZXJzaW9ucycpXG4gIC5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwucXVlcnk8eyBsaXN0U2VydmljZXM6IHsgc3VjY2VzczogYm9vbGVhbjsgc2VydmljZXM6IEFycmF5PHsgcm9sZTogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHZlcnNpb246IHN0cmluZyB9PjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIHF1ZXJ5IHtcbiAgICAgICAgICBsaXN0U2VydmljZXMge1xuICAgICAgICAgICAgc3VjY2Vzc1xuICAgICAgICAgICAgc2VydmljZXMgeyByb2xlIG5hbWUgdmVyc2lvbiB9XG4gICAgICAgICAgICBlcnJvclxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgYCk7XG5cbiAgICAgIGlmICghZGF0YS5saXN0U2VydmljZXMuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEubGlzdFNlcnZpY2VzLmVycm9yIHx8ICdGYWlsZWQgdG8gbGlzdCBzZXJ2aWNlcycpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5saXN0U2VydmljZXMuc2VydmljZXMsIG51bGwsIDIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGdyb3VwZWQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IHN2YyBvZiBkYXRhLmxpc3RTZXJ2aWNlcy5zZXJ2aWNlcykge1xuICAgICAgICAgIGlmICghZ3JvdXBlZFtzdmMucm9sZV0pIGdyb3VwZWRbc3ZjLnJvbGVdID0gW107XG4gICAgICAgICAgZ3JvdXBlZFtzdmMucm9sZV0ucHVzaChgJHtzdmMudmVyc2lvbn0gKCR7c3ZjLm5hbWV9KWApO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBbcm9sZSwgdmVyc2lvbnNdIG9mIE9iamVjdC5lbnRyaWVzKGdyb3VwZWQpKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYFxcbiR7cm9sZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHJvbGUuc2xpY2UoMSl9IFZlcnNpb25zOmApO1xuICAgICAgICAgIHZlcnNpb25zLmZvckVhY2goKHYpID0+IGNvbnNvbGUubG9nKGAgIC0gJHt2fWApKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEJsdWVwcmludHMgQ29tbWFuZFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5jb25zdCBibHVlcHJpbnRzID0gcHJvZ3JhbS5jb21tYW5kKCdibHVlcHJpbnRzJykuZGVzY3JpcHRpb24oJ01hbmFnZSBibHVlcHJpbnRzJyk7XG5cbmJsdWVwcmludHNcbiAgLmNvbW1hbmQoJ2xpc3QnKVxuICAuZGVzY3JpcHRpb24oJ0xpc3QgYXZhaWxhYmxlIGJsdWVwcmludHMnKVxuICAuYWN0aW9uKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBnbG9iYWxPcHRzID0gcHJvZ3JhbS5vcHRzKCkgYXMgRm9ybWF0dGVyT3B0aW9ucztcbiAgICBjb25zdCBmb3JtYXQgPSBnZXRPdXRwdXRGb3JtYXQoZ2xvYmFsT3B0cyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLnF1ZXJ5PHsgYmx1ZXByaW50czogeyBzdWNjZXNzOiBib29sZWFuOyBibHVlcHJpbnRzOiBBcnJheTx7IG5hbWU6IHN0cmluZyB9PjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIHF1ZXJ5IHtcbiAgICAgICAgICBibHVlcHJpbnRzIHtcbiAgICAgICAgICAgIHN1Y2Nlc3NcbiAgICAgICAgICAgIGJsdWVwcmludHMgeyBuYW1lIH1cbiAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgKTtcblxuICAgICAgaWYgKCFkYXRhLmJsdWVwcmludHMuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEuYmx1ZXByaW50cy5lcnJvciB8fCAnRmFpbGVkIHRvIGxpc3QgYmx1ZXByaW50cycpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5ibHVlcHJpbnRzLmJsdWVwcmludHMsIG51bGwsIDIpKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5ibHVlcHJpbnRzLmJsdWVwcmludHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdObyBibHVlcHJpbnRzIGZvdW5kLicpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coJ0JsdWVwcmludHM6Jyk7XG4gICAgICAgIGRhdGEuYmx1ZXByaW50cy5ibHVlcHJpbnRzLmZvckVhY2goKGIpID0+IGNvbnNvbGUubG9nKGAgIC0gJHtiLm5hbWV9YCkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbmJsdWVwcmludHNcbiAgLmNvbW1hbmQoJ3NhdmUgPHNpdGU+IDxuYW1lPicpXG4gIC5kZXNjcmlwdGlvbignU2F2ZSBhIHNpdGUgYXMgYSBibHVlcHJpbnQnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBuYW1lKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdTYXZpbmcgYmx1ZXByaW50IGZyb20nLCBzdWNjZXNzTWVzc2FnZTogKCkgPT4gYFNhdmVkIGJsdWVwcmludCBcIiR7bmFtZX1cImAgfSwgYXN5bmMgKGdxbCwgc2l0ZUlkKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IHNhdmVCbHVlcHJpbnQ6IHsgc3VjY2VzczogYm9vbGVhbjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIG11dGF0aW9uKCRpbnB1dDogU2F2ZUJsdWVwcmludElucHV0ISkge1xuICAgICAgICAgIHNhdmVCbHVlcHJpbnQoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBpbnB1dDogeyBzaXRlSWQsIG5hbWUgfSB9KTtcbiAgICAgIGlmICghZGF0YS5zYXZlQmx1ZXByaW50LnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuc2F2ZUJsdWVwcmludC5lcnJvciB8fCAnRmFpbGVkIHRvIHNhdmUgYmx1ZXByaW50Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERhdGFiYXNlIENvbW1hbmRzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmNvbnN0IGRiID0gcHJvZ3JhbS5jb21tYW5kKCdkYicpLmRlc2NyaXB0aW9uKCdEYXRhYmFzZSBvcGVyYXRpb25zJyk7XG5cbmRiXG4gIC5jb21tYW5kKCdleHBvcnQgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdFeHBvcnQgZGF0YWJhc2UgdG8gU1FMIGZpbGUnKVxuICAub3B0aW9uKCctbywgLS1vdXRwdXQgPHBhdGg+JywgJ091dHB1dCBmaWxlIHBhdGgnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdFeHBvcnRpbmcgZGF0YWJhc2UgZm9yJywgc3VjY2Vzc01lc3NhZ2U6IChkYXRhOiB7IGV4cG9ydERhdGFiYXNlOiB7IG91dHB1dFBhdGg6IHN0cmluZyB9IH0pID0+IGBFeHBvcnRlZCB0byAke2RhdGEuZXhwb3J0RGF0YWJhc2Uub3V0cHV0UGF0aH1gIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBleHBvcnREYXRhYmFzZTogeyBzdWNjZXNzOiBib29sZWFuOyBvdXRwdXRQYXRoOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkaW5wdXQ6IEV4cG9ydERhdGFiYXNlSW5wdXQhKSB7XG4gICAgICAgICAgZXhwb3J0RGF0YWJhc2UoaW5wdXQ6ICRpbnB1dCkgeyBzdWNjZXNzIG91dHB1dFBhdGggZXJyb3IgfVxuICAgICAgICB9XG4gICAgICBgLCB7IGlucHV0OiB7IHNpdGVJZCwgb3V0cHV0UGF0aDogY21kT3B0aW9ucy5vdXRwdXQgfSB9KTtcbiAgICAgIGlmICghZGF0YS5leHBvcnREYXRhYmFzZS5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLmV4cG9ydERhdGFiYXNlLmVycm9yIHx8ICdGYWlsZWQgdG8gZXhwb3J0IGRhdGFiYXNlJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbmRiXG4gIC5jb21tYW5kKCdpbXBvcnQgPHNpdGU+IDxzcWxGaWxlPicpXG4gIC5kZXNjcmlwdGlvbignSW1wb3J0IFNRTCBmaWxlIGludG8gZGF0YWJhc2UnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBzcWxGaWxlKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdJbXBvcnRpbmcgZGF0YWJhc2UgZm9yJywgc3VjY2Vzc01lc3NhZ2U6ICgpID0+ICdEYXRhYmFzZSBpbXBvcnRlZCBzdWNjZXNzZnVsbHknIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBpbXBvcnREYXRhYmFzZTogeyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBJbXBvcnREYXRhYmFzZUlucHV0ISkge1xuICAgICAgICAgIGltcG9ydERhdGFiYXNlKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkLCBzcWxQYXRoOiBzcWxGaWxlIH0gfSk7XG4gICAgICBpZiAoIWRhdGEuaW1wb3J0RGF0YWJhc2Uuc3VjY2Vzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZGF0YS5pbXBvcnREYXRhYmFzZS5lcnJvciB8fCAnRmFpbGVkIHRvIGltcG9ydCBkYXRhYmFzZScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSk7XG4gIH0pO1xuXG5kYlxuICAuY29tbWFuZCgnYWRtaW5lciA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ09wZW4gQWRtaW5lciBkYXRhYmFzZSBVSScpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUpID0+IHtcbiAgICBhd2FpdCBydW5TaXRlQ29tbWFuZChzaXRlLCB7IGFjdGlvbjogJ09wZW5pbmcgQWRtaW5lciBmb3InLCBzdWNjZXNzTWVzc2FnZTogKCkgPT4gJ09wZW5lZCBBZG1pbmVyJyB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIHJldHVybiBncWwubXV0YXRlKGBcbiAgICAgICAgbXV0YXRpb24oJGlucHV0OiBPcGVuQWRtaW5lcklucHV0ISkge1xuICAgICAgICAgIG9wZW5BZG1pbmVyKGlucHV0OiAkaW5wdXQpIHsgc3VjY2VzcyBlcnJvciB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgaW5wdXQ6IHsgc2l0ZUlkIH0gfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBCYWNrdXBzIENvbW1hbmRzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmNvbnN0IGJhY2t1cHMgPSBwcm9ncmFtLmNvbW1hbmQoJ2JhY2t1cHMnKS5kZXNjcmlwdGlvbignQ2xvdWQgYmFja3VwIG9wZXJhdGlvbnMnKTtcblxuYmFja3Vwc1xuICAuY29tbWFuZCgnc3RhdHVzJylcbiAgLmRlc2NyaXB0aW9uKCdDaGVjayBiYWNrdXAgc2VydmljZSBhdmFpbGFiaWxpdHknKVxuICAuYWN0aW9uKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBnbG9iYWxPcHRzID0gcHJvZ3JhbS5vcHRzKCkgYXMgRm9ybWF0dGVyT3B0aW9ucztcbiAgICBjb25zdCBmb3JtYXQgPSBnZXRPdXRwdXRGb3JtYXQoZ2xvYmFsT3B0cyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLnF1ZXJ5PHsgYmFja3VwU3RhdHVzOiB7IGF2YWlsYWJsZTogYm9vbGVhbjsgZmVhdHVyZUVuYWJsZWQ6IGJvb2xlYW47IGRyb3Bib3g6IGFueTsgZ29vZ2xlRHJpdmU6IGFueSB9IH0+KGBcbiAgICAgICAgcXVlcnkge1xuICAgICAgICAgIGJhY2t1cFN0YXR1cyB7XG4gICAgICAgICAgICBhdmFpbGFibGVcbiAgICAgICAgICAgIGZlYXR1cmVFbmFibGVkXG4gICAgICAgICAgICBkcm9wYm94IHsgYXV0aGVudGljYXRlZCBhY2NvdW50SWQgZW1haWwgfVxuICAgICAgICAgICAgZ29vZ2xlRHJpdmUgeyBhdXRoZW50aWNhdGVkIGFjY291bnRJZCBlbWFpbCB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgKTtcblxuICAgICAgaWYgKGZvcm1hdCA9PT0gJ2pzb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGRhdGEuYmFja3VwU3RhdHVzLCBudWxsLCAyKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBkYXRhLmJhY2t1cFN0YXR1cztcbiAgICAgICAgY29uc29sZS5sb2coYFxcbkJhY2t1cCBTdGF0dXM6YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGAgIEF2YWlsYWJsZTogJHtzdGF0dXMuYXZhaWxhYmxlID8gJ1llcycgOiAnTm8nfWApO1xuICAgICAgICBjb25zb2xlLmxvZyhgICBGZWF0dXJlIEVuYWJsZWQ6ICR7c3RhdHVzLmZlYXR1cmVFbmFibGVkID8gJ1llcycgOiAnTm8nfWApO1xuICAgICAgICBpZiAoc3RhdHVzLmRyb3Bib3gpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgXFxuICBEcm9wYm94OiAke3N0YXR1cy5kcm9wYm94LmF1dGhlbnRpY2F0ZWQgPyBgQ29ubmVjdGVkICgke3N0YXR1cy5kcm9wYm94LmVtYWlsfSlgIDogJ05vdCBjb25uZWN0ZWQnfWApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0dXMuZ29vZ2xlRHJpdmUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICBHb29nbGUgRHJpdmU6ICR7c3RhdHVzLmdvb2dsZURyaXZlLmF1dGhlbnRpY2F0ZWQgPyBgQ29ubmVjdGVkICgke3N0YXR1cy5nb29nbGVEcml2ZS5lbWFpbH0pYCA6ICdOb3QgY29ubmVjdGVkJ31gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbmJhY2t1cHNcbiAgLmNvbW1hbmQoJ2xpc3QgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdMaXN0IGJhY2t1cHMgZm9yIGEgc2l0ZScpXG4gIC5vcHRpb24oJy1wLCAtLXByb3ZpZGVyIDxwcm92aWRlcj4nLCAnQmFja3VwIHByb3ZpZGVyIChkcm9wYm94fGdvb2dsZURyaXZlKScsICdkcm9wYm94JylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgY21kT3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG4gICAgICBjb25zdCBzaXRlSWQgPSBhd2FpdCBmaW5kU2l0ZUlkKGdxbCwgc2l0ZSk7XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwucXVlcnk8eyBsaXN0QmFja3VwczogeyBzdWNjZXNzOiBib29sZWFuOyBiYWNrdXBzOiBBcnJheTx7IHNuYXBzaG90SWQ6IHN0cmluZzsgdGltZXN0YW1wOiBzdHJpbmc7IG5vdGU6IHN0cmluZyB9PjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIHF1ZXJ5KCRzaXRlSWQ6IElEISwgJHByb3ZpZGVyOiBTdHJpbmchKSB7XG4gICAgICAgICAgbGlzdEJhY2t1cHMoc2l0ZUlkOiAkc2l0ZUlkLCBwcm92aWRlcjogJHByb3ZpZGVyKSB7XG4gICAgICAgICAgICBzdWNjZXNzXG4gICAgICAgICAgICBiYWNrdXBzIHsgc25hcHNob3RJZCB0aW1lc3RhbXAgbm90ZSB9XG4gICAgICAgICAgICBlcnJvclxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBzaXRlSWQsIHByb3ZpZGVyOiBjbWRPcHRpb25zLnByb3ZpZGVyIH0pO1xuXG4gICAgICBpZiAoIWRhdGEubGlzdEJhY2t1cHMuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEubGlzdEJhY2t1cHMuZXJyb3IgfHwgJ0ZhaWxlZCB0byBsaXN0IGJhY2t1cHMnKSk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGZvcm1hdCA9PT0gJ2pzb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGRhdGEubGlzdEJhY2t1cHMuYmFja3VwcywgbnVsbCwgMikpO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLmxpc3RCYWNrdXBzLmJhY2t1cHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdObyBiYWNrdXBzIGZvdW5kLicpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYFxcbkJhY2t1cHMgKCR7Y21kT3B0aW9ucy5wcm92aWRlcn0pOmApO1xuICAgICAgICBmb3IgKGNvbnN0IGJhY2t1cCBvZiBkYXRhLmxpc3RCYWNrdXBzLmJhY2t1cHMpIHtcbiAgICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoYmFja3VwLnRpbWVzdGFtcCkudG9Mb2NhbGVTdHJpbmcoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICAke2JhY2t1cC5zbmFwc2hvdElkfSAtICR7ZGF0ZX0ke2JhY2t1cC5ub3RlID8gYCAtICR7YmFja3VwLm5vdGV9YCA6ICcnfWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxuYmFja3Vwc1xuICAuY29tbWFuZCgnY3JlYXRlIDxzaXRlPicpXG4gIC5kZXNjcmlwdGlvbignQ3JlYXRlIGEgYmFja3VwJylcbiAgLm9wdGlvbignLXAsIC0tcHJvdmlkZXIgPHByb3ZpZGVyPicsICdCYWNrdXAgcHJvdmlkZXIgKGRyb3Bib3h8Z29vZ2xlRHJpdmUpJywgJ2Ryb3Bib3gnKVxuICAub3B0aW9uKCctbiwgLS1ub3RlIDxub3RlPicsICdCYWNrdXAgbm90ZScpXG4gIC5hY3Rpb24oYXN5bmMgKHNpdGUsIGNtZE9wdGlvbnMpID0+IHtcbiAgICBhd2FpdCBydW5TaXRlQ29tbWFuZChzaXRlLCB7IGFjdGlvbjogJ0NyZWF0aW5nIGJhY2t1cCBmb3InLCBzdWNjZXNzTWVzc2FnZTogKGRhdGE6IHsgY3JlYXRlQmFja3VwOiB7IHNuYXBzaG90SWQ6IHN0cmluZyB9IH0pID0+IGBCYWNrdXAgY3JlYXRlZDogJHtkYXRhLmNyZWF0ZUJhY2t1cC5zbmFwc2hvdElkfWAgfSwgYXN5bmMgKGdxbCwgc2l0ZUlkKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IGNyZWF0ZUJhY2t1cDogeyBzdWNjZXNzOiBib29sZWFuOyBzbmFwc2hvdElkOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkc2l0ZUlkOiBJRCEsICRwcm92aWRlcjogU3RyaW5nISwgJG5vdGU6IFN0cmluZykge1xuICAgICAgICAgIGNyZWF0ZUJhY2t1cChzaXRlSWQ6ICRzaXRlSWQsIHByb3ZpZGVyOiAkcHJvdmlkZXIsIG5vdGU6ICRub3RlKSB7XG4gICAgICAgICAgICBzdWNjZXNzIHNuYXBzaG90SWQgZXJyb3JcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgc2l0ZUlkLCBwcm92aWRlcjogY21kT3B0aW9ucy5wcm92aWRlciwgbm90ZTogY21kT3B0aW9ucy5ub3RlIH0pO1xuICAgICAgaWYgKCFkYXRhLmNyZWF0ZUJhY2t1cC5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLmNyZWF0ZUJhY2t1cC5lcnJvciB8fCAnRmFpbGVkIHRvIGNyZWF0ZSBiYWNrdXAnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0pO1xuICB9KTtcblxuYmFja3Vwc1xuICAuY29tbWFuZCgncmVzdG9yZSA8c2l0ZT4gPHNuYXBzaG90SWQ+JylcbiAgLmRlc2NyaXB0aW9uKCdSZXN0b3JlIGZyb20gYmFja3VwJylcbiAgLm9wdGlvbignLXAsIC0tcHJvdmlkZXIgPHByb3ZpZGVyPicsICdCYWNrdXAgcHJvdmlkZXIgKGRyb3Bib3h8Z29vZ2xlRHJpdmUpJywgJ2Ryb3Bib3gnKVxuICAub3B0aW9uKCcteSwgLS15ZXMnLCAnU2tpcCBjb25maXJtYXRpb24nKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBzbmFwc2hvdElkLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdSZXN0b3JpbmcgYmFja3VwIGZvcicsIHN1Y2Nlc3NNZXNzYWdlOiAoZGF0YTogeyByZXN0b3JlQmFja3VwOiB7IG1lc3NhZ2U6IHN0cmluZyB9IH0pID0+IGRhdGEucmVzdG9yZUJhY2t1cC5tZXNzYWdlIHx8ICdCYWNrdXAgcmVzdG9yZWQgc3VjY2Vzc2Z1bGx5JyB9LCBhc3luYyAoZ3FsLCBzaXRlSWQpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwubXV0YXRlPHsgcmVzdG9yZUJhY2t1cDogeyBzdWNjZXNzOiBib29sZWFuOyBtZXNzYWdlOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkc2l0ZUlkOiBJRCEsICRwcm92aWRlcjogU3RyaW5nISwgJHNuYXBzaG90SWQ6IFN0cmluZyEsICRjb25maXJtOiBCb29sZWFuKSB7XG4gICAgICAgICAgcmVzdG9yZUJhY2t1cChzaXRlSWQ6ICRzaXRlSWQsIHByb3ZpZGVyOiAkcHJvdmlkZXIsIHNuYXBzaG90SWQ6ICRzbmFwc2hvdElkLCBjb25maXJtOiAkY29uZmlybSkge1xuICAgICAgICAgICAgc3VjY2VzcyBtZXNzYWdlIGVycm9yXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgLCB7IHNpdGVJZCwgcHJvdmlkZXI6IGNtZE9wdGlvbnMucHJvdmlkZXIsIHNuYXBzaG90SWQsIGNvbmZpcm06IGNtZE9wdGlvbnMueWVzIHx8IGZhbHNlIH0pO1xuICAgICAgaWYgKCFkYXRhLnJlc3RvcmVCYWNrdXAuc3VjY2Vzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZGF0YS5yZXN0b3JlQmFja3VwLmVycm9yIHx8ICdGYWlsZWQgdG8gcmVzdG9yZSBiYWNrdXAnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0pO1xuICB9KTtcblxuYmFja3Vwc1xuICAuY29tbWFuZCgnZGVsZXRlIDxzaXRlPiA8c25hcHNob3RJZD4nKVxuICAuZGVzY3JpcHRpb24oJ0RlbGV0ZSBhIGJhY2t1cCcpXG4gIC5vcHRpb24oJy1wLCAtLXByb3ZpZGVyIDxwcm92aWRlcj4nLCAnQmFja3VwIHByb3ZpZGVyIChkcm9wYm94fGdvb2dsZURyaXZlKScsICdkcm9wYm94JylcbiAgLm9wdGlvbignLXksIC0teWVzJywgJ1NraXAgY29uZmlybWF0aW9uJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgc25hcHNob3RJZCwgY21kT3B0aW9ucykgPT4ge1xuICAgIGF3YWl0IHJ1blNpdGVDb21tYW5kKHNpdGUsIHsgYWN0aW9uOiAnRGVsZXRpbmcgYmFja3VwIGZvcicsIHN1Y2Nlc3NNZXNzYWdlOiAoKSA9PiAnQmFja3VwIGRlbGV0ZWQnIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBkZWxldGVCYWNrdXA6IHsgc3VjY2VzczogYm9vbGVhbjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIG11dGF0aW9uKCRzaXRlSWQ6IElEISwgJHByb3ZpZGVyOiBTdHJpbmchLCAkc25hcHNob3RJZDogU3RyaW5nISwgJGNvbmZpcm06IEJvb2xlYW4pIHtcbiAgICAgICAgICBkZWxldGVCYWNrdXAoc2l0ZUlkOiAkc2l0ZUlkLCBwcm92aWRlcjogJHByb3ZpZGVyLCBzbmFwc2hvdElkOiAkc25hcHNob3RJZCwgY29uZmlybTogJGNvbmZpcm0pIHtcbiAgICAgICAgICAgIHN1Y2Nlc3MgZXJyb3JcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgc2l0ZUlkLCBwcm92aWRlcjogY21kT3B0aW9ucy5wcm92aWRlciwgc25hcHNob3RJZCwgY29uZmlybTogY21kT3B0aW9ucy55ZXMgfHwgZmFsc2UgfSk7XG4gICAgICBpZiAoIWRhdGEuZGVsZXRlQmFja3VwLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuZGVsZXRlQmFja3VwLmVycm9yIHx8ICdGYWlsZWQgdG8gZGVsZXRlIGJhY2t1cCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSk7XG4gIH0pO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBXUCBFbmdpbmUgQ29tbWFuZHNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuY29uc3Qgd3BlID0gcHJvZ3JhbS5jb21tYW5kKCd3cGUnKS5kZXNjcmlwdGlvbignV1AgRW5naW5lIHN5bmMgb3BlcmF0aW9ucycpO1xuXG53cGVcbiAgLmNvbW1hbmQoJ3N0YXR1cycpXG4gIC5kZXNjcmlwdGlvbignQ2hlY2sgV1AgRW5naW5lIGF1dGhlbnRpY2F0aW9uIHN0YXR1cycpXG4gIC5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwucXVlcnk8eyB3cGVTdGF0dXM6IHsgYXV0aGVudGljYXRlZDogYm9vbGVhbjsgZW1haWw6IHN0cmluZzsgYWNjb3VudElkOiBzdHJpbmc7IGFjY291bnROYW1lOiBzdHJpbmcgfSB9PihgXG4gICAgICAgIHF1ZXJ5IHtcbiAgICAgICAgICB3cGVTdGF0dXMge1xuICAgICAgICAgICAgYXV0aGVudGljYXRlZFxuICAgICAgICAgICAgZW1haWxcbiAgICAgICAgICAgIGFjY291bnRJZFxuICAgICAgICAgICAgYWNjb3VudE5hbWVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGApO1xuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS53cGVTdGF0dXMsIG51bGwsIDIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHN0YXR1cyA9IGRhdGEud3BlU3RhdHVzO1xuICAgICAgICBpZiAoc3RhdHVzLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgXFxuV1AgRW5naW5lOiBDb25uZWN0ZWRgKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICBFbWFpbDogJHtzdGF0dXMuZW1haWx9YCk7XG4gICAgICAgICAgY29uc29sZS5sb2coYCAgQWNjb3VudDogJHtzdGF0dXMuYWNjb3VudE5hbWV9ICgke3N0YXR1cy5hY2NvdW50SWR9KWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBcXG5XUCBFbmdpbmU6IE5vdCBjb25uZWN0ZWRgKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICBSdW4gJ2x3cCB3cGUgbG9naW4nIHRvIGF1dGhlbnRpY2F0ZWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxud3BlXG4gIC5jb21tYW5kKCdsb2dpbicpXG4gIC5kZXNjcmlwdGlvbignQXV0aGVudGljYXRlIHdpdGggV1AgRW5naW5lJylcbiAgLmFjdGlvbihhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gICAgY29uc3Qgc3Bpbm5lciA9IGdsb2JhbE9wdHMucXVpZXQgPyBudWxsIDogb3JhKGBPcGVuaW5nIFdQIEVuZ2luZSBsb2dpbi4uLmApLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IHdwZUF1dGhlbnRpY2F0ZTogeyBzdWNjZXNzOiBib29sZWFuOyBlbWFpbDogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbiB7XG4gICAgICAgICAgd3BlQXV0aGVudGljYXRlIHsgc3VjY2VzcyBlbWFpbCBtZXNzYWdlIGVycm9yIH1cbiAgICAgICAgfVxuICAgICAgYCk7XG5cbiAgICAgIGlmICghZGF0YS53cGVBdXRoZW50aWNhdGUuc3VjY2Vzcykge1xuICAgICAgICBzcGlubmVyPy5mYWlsKCdBdXRoZW50aWNhdGlvbiBmYWlsZWQnKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihkYXRhLndwZUF1dGhlbnRpY2F0ZS5lcnJvciB8fCAnRmFpbGVkIHRvIGF1dGhlbnRpY2F0ZScpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBzcGlubmVyPy5zdWNjZWVkKGBBdXRoZW50aWNhdGVkIGFzICR7ZGF0YS53cGVBdXRoZW50aWNhdGUuZW1haWx9YCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgc3Bpbm5lcj8uZmFpbCgnQXV0aGVudGljYXRpb24gZmFpbGVkJyk7XG4gICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGVycm9yLm1lc3NhZ2UpKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH0pO1xuXG53cGVcbiAgLmNvbW1hbmQoJ2xvZ291dCcpXG4gIC5kZXNjcmlwdGlvbignTG9nb3V0IGZyb20gV1AgRW5naW5lJylcbiAgLmFjdGlvbihhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gICAgY29uc3Qgc3Bpbm5lciA9IGdsb2JhbE9wdHMucXVpZXQgPyBudWxsIDogb3JhKGBMb2dnaW5nIG91dC4uLmApLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLm11dGF0ZTx7IHdwZUxvZ291dDogeyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgbXV0YXRpb24ge1xuICAgICAgICAgIHdwZUxvZ291dCB7IHN1Y2Nlc3MgZXJyb3IgfVxuICAgICAgICB9XG4gICAgICBgKTtcblxuICAgICAgaWYgKCFkYXRhLndwZUxvZ291dC5zdWNjZXNzKSB7XG4gICAgICAgIHNwaW5uZXI/LmZhaWwoJ0xvZ291dCBmYWlsZWQnKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihkYXRhLndwZUxvZ291dC5lcnJvciB8fCAnRmFpbGVkIHRvIGxvZ291dCcpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBzcGlubmVyPy5zdWNjZWVkKCdMb2dnZWQgb3V0IGZyb20gV1AgRW5naW5lJyk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgc3Bpbm5lcj8uZmFpbCgnTG9nb3V0IGZhaWxlZCcpO1xuICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihlcnJvci5tZXNzYWdlKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9KTtcblxud3BlXG4gIC5jb21tYW5kKCdzaXRlcycpXG4gIC5kZXNjcmlwdGlvbignTGlzdCBXUCBFbmdpbmUgc2l0ZXMnKVxuICAuYWN0aW9uKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBnbG9iYWxPcHRzID0gcHJvZ3JhbS5vcHRzKCkgYXMgRm9ybWF0dGVyT3B0aW9ucztcbiAgICBjb25zdCBmb3JtYXQgPSBnZXRPdXRwdXRGb3JtYXQoZ2xvYmFsT3B0cyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZ3FsID0gYXdhaXQgZW5zdXJlQ29ubmVjdGVkKGdsb2JhbE9wdHMpO1xuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLnF1ZXJ5PHsgbGlzdFdwZVNpdGVzOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IHNpdGVzOiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgZW52aXJvbm1lbnQ6IHN0cmluZzsgcHJpbWFyeURvbWFpbjogc3RyaW5nIH0+OyBlcnJvcjogc3RyaW5nIHwgbnVsbCB9IH0+KGBcbiAgICAgICAgcXVlcnkge1xuICAgICAgICAgIGxpc3RXcGVTaXRlcyB7XG4gICAgICAgICAgICBzdWNjZXNzXG4gICAgICAgICAgICBzaXRlcyB7IGlkIG5hbWUgZW52aXJvbm1lbnQgcHJpbWFyeURvbWFpbiB9XG4gICAgICAgICAgICBlcnJvclxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgYCk7XG5cbiAgICAgIGlmICghZGF0YS5saXN0V3BlU2l0ZXMuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEubGlzdFdwZVNpdGVzLmVycm9yIHx8ICdGYWlsZWQgdG8gbGlzdCBzaXRlcycpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5saXN0V3BlU2l0ZXMuc2l0ZXMsIG51bGwsIDIpKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5saXN0V3BlU2l0ZXMuc2l0ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdObyBXUCBFbmdpbmUgc2l0ZXMgZm91bmQuJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZygnXFxuV1AgRW5naW5lIFNpdGVzOicpO1xuICAgICAgICBmb3IgKGNvbnN0IHNpdGUgb2YgZGF0YS5saXN0V3BlU2l0ZXMuc2l0ZXMpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICAke3NpdGUubmFtZX0gKCR7c2l0ZS5lbnZpcm9ubWVudH0pIC0gJHtzaXRlLnByaW1hcnlEb21haW59YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGVycm9yLm1lc3NhZ2UpKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH0pO1xuXG53cGVcbiAgLmNvbW1hbmQoJ2xpbmsgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdTaG93IFdQIEVuZ2luZSBjb25uZWN0aW9uIGZvciBhIGxvY2FsIHNpdGUnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gICAgY29uc3QgZm9ybWF0ID0gZ2V0T3V0cHV0Rm9ybWF0KGdsb2JhbE9wdHMpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGdxbCA9IGF3YWl0IGVuc3VyZUNvbm5lY3RlZChnbG9iYWxPcHRzKTtcbiAgICAgIGNvbnN0IHNpdGVJZCA9IGF3YWl0IGZpbmRTaXRlSWQoZ3FsLCBzaXRlKTtcblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IGdldFdwZUxpbms6IHsgbGlua2VkOiBib29sZWFuOyBzaXRlTmFtZTogc3RyaW5nOyBjb25uZWN0aW9uczogQXJyYXk8eyByZW1vdGVJbnN0YWxsSWQ6IHN0cmluZzsgaW5zdGFsbE5hbWU6IHN0cmluZzsgZW52aXJvbm1lbnQ6IHN0cmluZzsgcHJpbWFyeURvbWFpbjogc3RyaW5nIH0+IH0gfT4oYFxuICAgICAgICBxdWVyeSgkc2l0ZUlkOiBJRCEpIHtcbiAgICAgICAgICBnZXRXcGVMaW5rKHNpdGVJZDogJHNpdGVJZCkge1xuICAgICAgICAgICAgbGlua2VkXG4gICAgICAgICAgICBzaXRlTmFtZVxuICAgICAgICAgICAgY29ubmVjdGlvbnMgeyByZW1vdGVJbnN0YWxsSWQgaW5zdGFsbE5hbWUgZW52aXJvbm1lbnQgcHJpbWFyeURvbWFpbiB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgLCB7IHNpdGVJZCB9KTtcblxuICAgICAgaWYgKGZvcm1hdCA9PT0gJ2pzb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGRhdGEuZ2V0V3BlTGluaywgbnVsbCwgMikpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbGluayA9IGRhdGEuZ2V0V3BlTGluaztcbiAgICAgICAgaWYgKCFsaW5rLmxpbmtlZCB8fCBsaW5rLmNvbm5lY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBcXG5cIiR7bGluay5zaXRlTmFtZX1cIiBpcyBub3QgbGlua2VkIHRvIFdQIEVuZ2luZWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBcXG5cIiR7bGluay5zaXRlTmFtZX1cIiBXUCBFbmdpbmUgQ29ubmVjdGlvbnM6YCk7XG4gICAgICAgICAgZm9yIChjb25zdCBjb25uIG9mIGxpbmsuY29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAgICR7Y29ubi5pbnN0YWxsTmFtZX0gKCR7Y29ubi5lbnZpcm9ubWVudH0pIC0gJHtjb25uLnByaW1hcnlEb21haW59YCk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICAgIElEOiAke2Nvbm4ucmVtb3RlSW5zdGFsbElkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbndwZVxuICAuY29tbWFuZCgncHVzaCA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1B1c2ggbG9jYWwgc2l0ZSB0byBXUCBFbmdpbmUnKVxuICAub3B0aW9uKCctciwgLS1yZW1vdGUgPGluc3RhbGxJZD4nLCAnUmVtb3RlIGluc3RhbGwgSUQnKVxuICAub3B0aW9uKCctLXNxbCcsICdJbmNsdWRlIGRhdGFiYXNlJylcbiAgLm9wdGlvbignLXksIC0teWVzJywgJ1NraXAgY29uZmlybWF0aW9uJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgY21kT3B0aW9ucykgPT4ge1xuICAgIGF3YWl0IHJ1blNpdGVDb21tYW5kKHNpdGUsIHsgYWN0aW9uOiAnUHVzaGluZyB0byBXUCBFbmdpbmUnLCBzdWNjZXNzTWVzc2FnZTogKGRhdGE6IHsgcHVzaFRvV3BlOiB7IG1lc3NhZ2U6IHN0cmluZyB9IH0pID0+IGRhdGEucHVzaFRvV3BlLm1lc3NhZ2UgfHwgJ1B1c2hlZCB0byBXUCBFbmdpbmUnIH0sIGFzeW5jIChncWwsIHNpdGVJZCkgPT4ge1xuICAgICAgLy8gR2V0IHJlbW90ZSBpbnN0YWxsIElEIGlmIG5vdCBwcm92aWRlZFxuICAgICAgbGV0IHJlbW90ZUluc3RhbGxJZCA9IGNtZE9wdGlvbnMucmVtb3RlO1xuICAgICAgaWYgKCFyZW1vdGVJbnN0YWxsSWQpIHtcbiAgICAgICAgY29uc3QgbGlua0RhdGEgPSBhd2FpdCBncWwucXVlcnk8eyBnZXRXcGVMaW5rOiB7IGNvbm5lY3Rpb25zOiBBcnJheTx7IHJlbW90ZUluc3RhbGxJZDogc3RyaW5nIH0+IH0gfT4oYFxuICAgICAgICAgIHF1ZXJ5KCRzaXRlSWQ6IElEISkge1xuICAgICAgICAgICAgZ2V0V3BlTGluayhzaXRlSWQ6ICRzaXRlSWQpIHtcbiAgICAgICAgICAgICAgY29ubmVjdGlvbnMgeyByZW1vdGVJbnN0YWxsSWQgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgYCwgeyBzaXRlSWQgfSk7XG4gICAgICAgIGlmIChsaW5rRGF0YS5nZXRXcGVMaW5rLmNvbm5lY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU2l0ZSBpcyBub3QgbGlua2VkIHRvIFdQIEVuZ2luZS4gVXNlIC0tcmVtb3RlIHRvIHNwZWNpZnkgaW5zdGFsbCBJRC4nKTtcbiAgICAgICAgfVxuICAgICAgICByZW1vdGVJbnN0YWxsSWQgPSBsaW5rRGF0YS5nZXRXcGVMaW5rLmNvbm5lY3Rpb25zWzBdLnJlbW90ZUluc3RhbGxJZDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwubXV0YXRlPHsgcHVzaFRvV3BlOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IG1lc3NhZ2U6IHN0cmluZzsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIG11dGF0aW9uKCRsb2NhbFNpdGVJZDogSUQhLCAkcmVtb3RlSW5zdGFsbElkOiBJRCEsICRpbmNsdWRlU3FsOiBCb29sZWFuLCAkY29uZmlybTogQm9vbGVhbikge1xuICAgICAgICAgIHB1c2hUb1dwZShsb2NhbFNpdGVJZDogJGxvY2FsU2l0ZUlkLCByZW1vdGVJbnN0YWxsSWQ6ICRyZW1vdGVJbnN0YWxsSWQsIGluY2x1ZGVTcWw6ICRpbmNsdWRlU3FsLCBjb25maXJtOiAkY29uZmlybSkge1xuICAgICAgICAgICAgc3VjY2VzcyBtZXNzYWdlIGVycm9yXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgLCB7IGxvY2FsU2l0ZUlkOiBzaXRlSWQsIHJlbW90ZUluc3RhbGxJZCwgaW5jbHVkZVNxbDogY21kT3B0aW9ucy5zcWwgfHwgZmFsc2UsIGNvbmZpcm06IGNtZE9wdGlvbnMueWVzIHx8IGZhbHNlIH0pO1xuICAgICAgaWYgKCFkYXRhLnB1c2hUb1dwZS5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLnB1c2hUb1dwZS5lcnJvciB8fCAnRmFpbGVkIHRvIHB1c2ggdG8gV1AgRW5naW5lJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbndwZVxuICAuY29tbWFuZCgncHVsbCA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1B1bGwgZnJvbSBXUCBFbmdpbmUgdG8gbG9jYWwgc2l0ZScpXG4gIC5vcHRpb24oJy1yLCAtLXJlbW90ZSA8aW5zdGFsbElkPicsICdSZW1vdGUgaW5zdGFsbCBJRCcpXG4gIC5vcHRpb24oJy0tc3FsJywgJ0luY2x1ZGUgZGF0YWJhc2UnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgYXdhaXQgcnVuU2l0ZUNvbW1hbmQoc2l0ZSwgeyBhY3Rpb246ICdQdWxsaW5nIGZyb20gV1AgRW5naW5lIGZvcicsIHN1Y2Nlc3NNZXNzYWdlOiAoZGF0YTogeyBwdWxsRnJvbVdwZTogeyBtZXNzYWdlOiBzdHJpbmcgfSB9KSA9PiBkYXRhLnB1bGxGcm9tV3BlLm1lc3NhZ2UgfHwgJ1B1bGxlZCBmcm9tIFdQIEVuZ2luZScgfSwgYXN5bmMgKGdxbCwgc2l0ZUlkKSA9PiB7XG4gICAgICAvLyBHZXQgcmVtb3RlIGluc3RhbGwgSUQgaWYgbm90IHByb3ZpZGVkXG4gICAgICBsZXQgcmVtb3RlSW5zdGFsbElkID0gY21kT3B0aW9ucy5yZW1vdGU7XG4gICAgICBpZiAoIXJlbW90ZUluc3RhbGxJZCkge1xuICAgICAgICBjb25zdCBsaW5rRGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IGdldFdwZUxpbms6IHsgY29ubmVjdGlvbnM6IEFycmF5PHsgcmVtb3RlSW5zdGFsbElkOiBzdHJpbmcgfT4gfSB9PihgXG4gICAgICAgICAgcXVlcnkoJHNpdGVJZDogSUQhKSB7XG4gICAgICAgICAgICBnZXRXcGVMaW5rKHNpdGVJZDogJHNpdGVJZCkge1xuICAgICAgICAgICAgICBjb25uZWN0aW9ucyB7IHJlbW90ZUluc3RhbGxJZCB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICBgLCB7IHNpdGVJZCB9KTtcbiAgICAgICAgaWYgKGxpbmtEYXRhLmdldFdwZUxpbmsuY29ubmVjdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaXRlIGlzIG5vdCBsaW5rZWQgdG8gV1AgRW5naW5lLiBVc2UgLS1yZW1vdGUgdG8gc3BlY2lmeSBpbnN0YWxsIElELicpO1xuICAgICAgICB9XG4gICAgICAgIHJlbW90ZUluc3RhbGxJZCA9IGxpbmtEYXRhLmdldFdwZUxpbmsuY29ubmVjdGlvbnNbMF0ucmVtb3RlSW5zdGFsbElkO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5tdXRhdGU8eyBwdWxsRnJvbVdwZTogeyBzdWNjZXNzOiBib29sZWFuOyBtZXNzYWdlOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBtdXRhdGlvbigkbG9jYWxTaXRlSWQ6IElEISwgJHJlbW90ZUluc3RhbGxJZDogSUQhLCAkaW5jbHVkZVNxbDogQm9vbGVhbikge1xuICAgICAgICAgIHB1bGxGcm9tV3BlKGxvY2FsU2l0ZUlkOiAkbG9jYWxTaXRlSWQsIHJlbW90ZUluc3RhbGxJZDogJHJlbW90ZUluc3RhbGxJZCwgaW5jbHVkZVNxbDogJGluY2x1ZGVTcWwpIHtcbiAgICAgICAgICAgIHN1Y2Nlc3MgbWVzc2FnZSBlcnJvclxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgYCwgeyBsb2NhbFNpdGVJZDogc2l0ZUlkLCByZW1vdGVJbnN0YWxsSWQsIGluY2x1ZGVTcWw6IGNtZE9wdGlvbnMuc3FsIHx8IGZhbHNlIH0pO1xuICAgICAgaWYgKCFkYXRhLnB1bGxGcm9tV3BlLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEucHVsbEZyb21XcGUuZXJyb3IgfHwgJ0ZhaWxlZCB0byBwdWxsIGZyb20gV1AgRW5naW5lJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9KTtcbiAgfSk7XG5cbndwZVxuICAuY29tbWFuZCgnaGlzdG9yeSA8c2l0ZT4nKVxuICAuZGVzY3JpcHRpb24oJ1Nob3cgc3luYyBoaXN0b3J5IGZvciBhIHNpdGUnKVxuICAub3B0aW9uKCctbCwgLS1saW1pdCA8bj4nLCAnTnVtYmVyIG9mIGV2ZW50cyB0byBzaG93JywgJzEwJylcbiAgLmFjdGlvbihhc3luYyAoc2l0ZSwgY21kT3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IGdsb2JhbE9wdHMgPSBwcm9ncmFtLm9wdHMoKSBhcyBGb3JtYXR0ZXJPcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdCA9IGdldE91dHB1dEZvcm1hdChnbG9iYWxPcHRzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBncWwgPSBhd2FpdCBlbnN1cmVDb25uZWN0ZWQoZ2xvYmFsT3B0cyk7XG4gICAgICBjb25zdCBzaXRlSWQgPSBhd2FpdCBmaW5kU2l0ZUlkKGdxbCwgc2l0ZSk7XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBncWwucXVlcnk8eyBnZXRTeW5jSGlzdG9yeTogeyBzdWNjZXNzOiBib29sZWFuOyBldmVudHM6IEFycmF5PHsgcmVtb3RlSW5zdGFsbE5hbWU6IHN0cmluZzsgdGltZXN0YW1wOiBzdHJpbmc7IGRpcmVjdGlvbjogc3RyaW5nOyBzdGF0dXM6IHN0cmluZyB9PjsgZXJyb3I6IHN0cmluZyB8IG51bGwgfSB9PihgXG4gICAgICAgIHF1ZXJ5KCRzaXRlSWQ6IElEISwgJGxpbWl0OiBJbnQpIHtcbiAgICAgICAgICBnZXRTeW5jSGlzdG9yeShzaXRlSWQ6ICRzaXRlSWQsIGxpbWl0OiAkbGltaXQpIHtcbiAgICAgICAgICAgIHN1Y2Nlc3NcbiAgICAgICAgICAgIGV2ZW50cyB7IHJlbW90ZUluc3RhbGxOYW1lIHRpbWVzdGFtcCBkaXJlY3Rpb24gc3RhdHVzIH1cbiAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgLCB7IHNpdGVJZCwgbGltaXQ6IHBhcnNlSW50KGNtZE9wdGlvbnMubGltaXQsIDEwKSB9KTtcblxuICAgICAgaWYgKCFkYXRhLmdldFN5bmNIaXN0b3J5LnN1Y2Nlc3MpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihmb3JtYXRFcnJvcihkYXRhLmdldFN5bmNIaXN0b3J5LmVycm9yIHx8ICdGYWlsZWQgdG8gZ2V0IHN5bmMgaGlzdG9yeScpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5nZXRTeW5jSGlzdG9yeS5ldmVudHMsIG51bGwsIDIpKTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5nZXRTeW5jSGlzdG9yeS5ldmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdObyBzeW5jIGhpc3RvcnkgZm91bmQuJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZygnXFxuU3luYyBIaXN0b3J5OicpO1xuICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGRhdGEuZ2V0U3luY0hpc3RvcnkuZXZlbnRzKSB7XG4gICAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKGV2ZW50LnRpbWVzdGFtcCkudG9Mb2NhbGVTdHJpbmcoKTtcbiAgICAgICAgICBjb25zdCBhcnJvdyA9IGV2ZW50LmRpcmVjdGlvbiA9PT0gJ3B1c2gnID8gJ+KGkicgOiAn4oaQJztcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICAke2RhdGV9ICR7YXJyb3d9ICR7ZXZlbnQucmVtb3RlSW5zdGFsbE5hbWV9ICgke2V2ZW50LnN0YXR1c30pYCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGVycm9yLm1lc3NhZ2UpKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH0pO1xuXG53cGVcbiAgLmNvbW1hbmQoJ2RpZmYgPHNpdGU+JylcbiAgLmRlc2NyaXB0aW9uKCdTaG93IGZpbGUgY2hhbmdlcyBiZXR3ZWVuIGxvY2FsIGFuZCBXUCBFbmdpbmUnKVxuICAub3B0aW9uKCctZCwgLS1kaXJlY3Rpb24gPGRpcj4nLCAnRGlyZWN0aW9uIChwdXNofHB1bGwpJywgJ3B1c2gnKVxuICAuYWN0aW9uKGFzeW5jIChzaXRlLCBjbWRPcHRpb25zKSA9PiB7XG4gICAgY29uc3QgZ2xvYmFsT3B0cyA9IHByb2dyYW0ub3B0cygpIGFzIEZvcm1hdHRlck9wdGlvbnM7XG4gICAgY29uc3QgZm9ybWF0ID0gZ2V0T3V0cHV0Rm9ybWF0KGdsb2JhbE9wdHMpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGdxbCA9IGF3YWl0IGVuc3VyZUNvbm5lY3RlZChnbG9iYWxPcHRzKTtcbiAgICAgIGNvbnN0IHNpdGVJZCA9IGF3YWl0IGZpbmRTaXRlSWQoZ3FsLCBzaXRlKTtcblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGdxbC5xdWVyeTx7IGdldFNpdGVDaGFuZ2VzOiB7IHN1Y2Nlc3M6IGJvb2xlYW47IGFkZGVkOiBBcnJheTx7IHBhdGg6IHN0cmluZyB9PjsgbW9kaWZpZWQ6IEFycmF5PHsgcGF0aDogc3RyaW5nIH0+OyBkZWxldGVkOiBBcnJheTx7IHBhdGg6IHN0cmluZyB9PjsgdG90YWxDaGFuZ2VzOiBudW1iZXI7IGVycm9yOiBzdHJpbmcgfCBudWxsIH0gfT4oYFxuICAgICAgICBxdWVyeSgkc2l0ZUlkOiBJRCEsICRkaXJlY3Rpb246IFN0cmluZykge1xuICAgICAgICAgIGdldFNpdGVDaGFuZ2VzKHNpdGVJZDogJHNpdGVJZCwgZGlyZWN0aW9uOiAkZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBzdWNjZXNzXG4gICAgICAgICAgICBhZGRlZCB7IHBhdGggfVxuICAgICAgICAgICAgbW9kaWZpZWQgeyBwYXRoIH1cbiAgICAgICAgICAgIGRlbGV0ZWQgeyBwYXRoIH1cbiAgICAgICAgICAgIHRvdGFsQ2hhbmdlc1xuICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGAsIHsgc2l0ZUlkLCBkaXJlY3Rpb246IGNtZE9wdGlvbnMuZGlyZWN0aW9uIH0pO1xuXG4gICAgICBpZiAoIWRhdGEuZ2V0U2l0ZUNoYW5nZXMuc3VjY2Vzcykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9yKGRhdGEuZ2V0U2l0ZUNoYW5nZXMuZXJyb3IgfHwgJ0ZhaWxlZCB0byBnZXQgY2hhbmdlcycpKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSAnanNvbicpIHtcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YS5nZXRTaXRlQ2hhbmdlcywgbnVsbCwgMikpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgY2hhbmdlcyA9IGRhdGEuZ2V0U2l0ZUNoYW5nZXM7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXG5DaGFuZ2VzIHRvICR7Y21kT3B0aW9ucy5kaXJlY3Rpb259ICgke2NoYW5nZXMudG90YWxDaGFuZ2VzfSB0b3RhbCk6YCk7XG5cbiAgICAgICAgaWYgKGNoYW5nZXMuYWRkZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdcXG4gIEFkZGVkOicpO1xuICAgICAgICAgIGNoYW5nZXMuYWRkZWQuZm9yRWFjaCgoZikgPT4gY29uc29sZS5sb2coYCAgICArICR7Zi5wYXRofWApKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlcy5tb2RpZmllZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ1xcbiAgTW9kaWZpZWQ6Jyk7XG4gICAgICAgICAgY2hhbmdlcy5tb2RpZmllZC5mb3JFYWNoKChmKSA9PiBjb25zb2xlLmxvZyhgICAgIH4gJHtmLnBhdGh9YCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzLmRlbGV0ZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdcXG4gIERlbGV0ZWQ6Jyk7XG4gICAgICAgICAgY2hhbmdlcy5kZWxldGVkLmZvckVhY2goKGYpID0+IGNvbnNvbGUubG9nKGAgICAgLSAke2YucGF0aH1gKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXMudG90YWxDaGFuZ2VzID09PSAwKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJyAgTm8gY2hhbmdlcyBkZXRlY3RlZC4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0RXJyb3IoZXJyb3IubWVzc2FnZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhlbHBlciBGdW5jdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBGaW5kIHNpdGUgSUQgYnkgbmFtZSBvciBJRFxuICpcbiAqIE9wdGltaXphdGlvbjogRmlyc3QgdHJpZXMgZGlyZWN0IElEIGxvb2t1cCAoTygxKSkgYmVmb3JlIGZhbGxpbmcgYmFjayB0b1xuICogZmV0Y2hpbmcgYWxsIHNpdGVzIGZvciBuYW1lIG1hdGNoaW5nIChPKG4pKS4gVGhpcyBzaWduaWZpY2FudGx5IGltcHJvdmVzXG4gKiBwZXJmb3JtYW5jZSB3aGVuIHVzZXJzIHNwZWNpZnkgc2l0ZSBJRHMgZGlyZWN0bHkuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZpbmRTaXRlSWQoZ3FsOiBHcmFwaFFMQ2xpZW50LCBzaXRlUXVlcnk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIC8vIFRyeSBkaXJlY3QgSUQgbG9va3VwIGZpcnN0IC0gbXVjaCBmYXN0ZXIgZm9yIGV4YWN0IElEIG1hdGNoZXNcbiAgdHJ5IHtcbiAgICBjb25zdCBkaXJlY3RMb29rdXAgPSBhd2FpdCBncWwucXVlcnk8eyBzaXRlOiB7IGlkOiBzdHJpbmcgfSB8IG51bGwgfT4oXG4gICAgICBgcXVlcnkgR2V0U2l0ZUJ5SWQoJGlkOiBJRCEpIHsgc2l0ZShpZDogJGlkKSB7IGlkIH0gfWAsXG4gICAgICB7IGlkOiBzaXRlUXVlcnkgfVxuICAgICk7XG5cbiAgICBpZiAoZGlyZWN0TG9va3VwLnNpdGUpIHtcbiAgICAgIHJldHVybiBkaXJlY3RMb29rdXAuc2l0ZS5pZDtcbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIElEIGxvb2t1cCBmYWlsZWQsIGZhbGwgdGhyb3VnaCB0byBuYW1lIHNlYXJjaFxuICB9XG5cbiAgLy8gRmFsbCBiYWNrIHRvIGZldGNoaW5nIGFsbCBzaXRlcyBmb3IgbmFtZSBtYXRjaGluZ1xuICBjb25zdCBkYXRhID0gYXdhaXQgZ3FsLnF1ZXJ5PHsgc2l0ZXM6IEFycmF5PHsgaWQ6IHN0cmluZzsgbmFtZTogc3RyaW5nIH0+IH0+KGBcbiAgICBxdWVyeSB7IHNpdGVzIHsgaWQgbmFtZSB9IH1cbiAgYCk7XG5cbiAgY29uc3Qgc2l0ZSA9IGRhdGEuc2l0ZXMuZmluZChcbiAgICAocykgPT4gcy5uYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2l0ZVF1ZXJ5LnRvTG93ZXJDYXNlKCkpXG4gICk7XG5cbiAgaWYgKCFzaXRlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTaXRlIG5vdCBmb3VuZDogXCIke3NpdGVRdWVyeX1cImApO1xuICB9XG5cbiAgcmV0dXJuIHNpdGUuaWQ7XG59XG5cbi8vIFBhcnNlIGFuZCBleGVjdXRlXG5wcm9ncmFtLnBhcnNlKCk7XG4iXX0=