@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/bin/lwp.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Local CLI (lwp) - Command-line interface for Local
5
+ *
6
+ * This is the entry point for the lwp command.
7
+ * It loads the compiled TypeScript from lib/index.js
8
+ */
9
+
10
+ require('../lib/index.js');
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Bootstrap System
3
+ *
4
+ * Connects the CLI to Local's GraphQL server:
5
+ * - Detects Local installation
6
+ * - Installs and activates addon if needed
7
+ * - Starts Local if needed
8
+ * - Waits for GraphQL server to be ready
9
+ * - Reads connection info
10
+ */
11
+ import { getLocalPaths, LocalPaths } from './paths';
12
+ export interface ConnectionInfo {
13
+ url: string;
14
+ subscriptionUrl: string;
15
+ port: number;
16
+ authToken: string;
17
+ }
18
+ export interface BootstrapResult {
19
+ success: boolean;
20
+ connectionInfo?: ConnectionInfo;
21
+ error?: string;
22
+ actions: string[];
23
+ }
24
+ /**
25
+ * Check if Local is installed
26
+ */
27
+ export declare function isLocalInstalled(): boolean;
28
+ /**
29
+ * Check if Local is currently running
30
+ */
31
+ export declare function isLocalRunning(): Promise<boolean>;
32
+ /**
33
+ * Start Local application
34
+ */
35
+ export declare function startLocal(): Promise<void>;
36
+ /**
37
+ * Stop Local application
38
+ */
39
+ export declare function stopLocal(): Promise<void>;
40
+ /**
41
+ * Restart Local application
42
+ */
43
+ export declare function restartLocal(): Promise<void>;
44
+ /**
45
+ * Get the addon installation path
46
+ */
47
+ export declare function getAddonPath(): string;
48
+ /**
49
+ * Check if the addon is installed in Local's addons directory
50
+ */
51
+ export declare function isAddonInstalled(): boolean;
52
+ /**
53
+ * Check if the addon is activated in enabled-addons.json
54
+ */
55
+ export declare function isAddonActivated(): boolean;
56
+ /**
57
+ * Activate the addon by modifying enabled-addons.json
58
+ * Returns true if restart is needed (addon was just activated)
59
+ */
60
+ export declare function activateAddon(): boolean;
61
+ /**
62
+ * Install the addon from bundled package or create dev symlink
63
+ */
64
+ export declare function installAddon(options?: {
65
+ onStatus?: (status: string) => void;
66
+ }): Promise<{
67
+ success: boolean;
68
+ error?: string;
69
+ needsRestart: boolean;
70
+ }>;
71
+ /**
72
+ * Ensure addon is installed and activated
73
+ */
74
+ export declare function ensureAddon(options?: {
75
+ onStatus?: (status: string) => void;
76
+ }): Promise<{
77
+ success: boolean;
78
+ error?: string;
79
+ needsRestart: boolean;
80
+ }>;
81
+ /**
82
+ * Read GraphQL connection info from graphql-connection-info.json
83
+ */
84
+ export declare function readConnectionInfo(): ConnectionInfo | null;
85
+ /**
86
+ * Wait for GraphQL server to be ready
87
+ */
88
+ export declare function waitForGraphQL(timeoutMs?: number, pollIntervalMs?: number): Promise<boolean>;
89
+ /**
90
+ * Main bootstrap function
91
+ * Ensures addon is installed, Local is running, and GraphQL is accessible
92
+ */
93
+ export declare function bootstrap(options?: {
94
+ verbose?: boolean;
95
+ skipAddonInstall?: boolean;
96
+ onStatus?: (status: string) => void;
97
+ }): Promise<BootstrapResult>;
98
+ export { getLocalPaths, LocalPaths };
@@ -0,0 +1,493 @@
1
+ "use strict";
2
+ /**
3
+ * Bootstrap System
4
+ *
5
+ * Connects the CLI to Local's GraphQL server:
6
+ * - Detects Local installation
7
+ * - Installs and activates addon if needed
8
+ * - Starts Local if needed
9
+ * - Waits for GraphQL server to be ready
10
+ * - Reads connection info
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.getLocalPaths = void 0;
47
+ exports.isLocalInstalled = isLocalInstalled;
48
+ exports.isLocalRunning = isLocalRunning;
49
+ exports.startLocal = startLocal;
50
+ exports.stopLocal = stopLocal;
51
+ exports.restartLocal = restartLocal;
52
+ exports.getAddonPath = getAddonPath;
53
+ exports.isAddonInstalled = isAddonInstalled;
54
+ exports.isAddonActivated = isAddonActivated;
55
+ exports.activateAddon = activateAddon;
56
+ exports.installAddon = installAddon;
57
+ exports.ensureAddon = ensureAddon;
58
+ exports.readConnectionInfo = readConnectionInfo;
59
+ exports.waitForGraphQL = waitForGraphQL;
60
+ exports.bootstrap = bootstrap;
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const child_process_1 = require("child_process");
64
+ const util_1 = require("util");
65
+ const paths_1 = require("./paths");
66
+ Object.defineProperty(exports, "getLocalPaths", { enumerable: true, get: function () { return paths_1.getLocalPaths; } });
67
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
68
+ /**
69
+ * Check if Local is installed
70
+ */
71
+ function isLocalInstalled() {
72
+ const paths = (0, paths_1.getLocalPaths)();
73
+ try {
74
+ if (process.platform === 'darwin') {
75
+ return fs.existsSync(paths.appExecutable);
76
+ }
77
+ else if (process.platform === 'win32') {
78
+ return fs.existsSync(paths.appExecutable);
79
+ }
80
+ else {
81
+ // Linux - check if 'local' is in PATH or at expected location
82
+ try {
83
+ (0, child_process_1.execSync)('which local', { stdio: 'ignore' });
84
+ return true;
85
+ }
86
+ catch {
87
+ return fs.existsSync(paths.appExecutable);
88
+ }
89
+ }
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ /**
96
+ * Check if Local is currently running
97
+ */
98
+ async function isLocalRunning() {
99
+ try {
100
+ if (process.platform === 'darwin') {
101
+ // Use pgrep with -f to match any process containing "Local"
102
+ // Also check if GraphQL connection info exists and is recent
103
+ const { stdout } = await execAsync(`pgrep -f "Local.app"`);
104
+ return stdout.trim().length > 0;
105
+ }
106
+ else if (process.platform === 'win32') {
107
+ const { stdout } = await execAsync(`tasklist /FI "IMAGENAME eq Local.exe"`);
108
+ return stdout.includes('Local.exe');
109
+ }
110
+ else {
111
+ const { stdout } = await execAsync(`pgrep -f "local"`);
112
+ return stdout.trim().length > 0;
113
+ }
114
+ }
115
+ catch {
116
+ // pgrep returns non-zero if no processes found
117
+ // Check if connection info exists as a fallback
118
+ const connectionInfo = readConnectionInfo();
119
+ return connectionInfo !== null;
120
+ }
121
+ }
122
+ /**
123
+ * Start Local application
124
+ */
125
+ async function startLocal() {
126
+ const paths = (0, paths_1.getLocalPaths)();
127
+ try {
128
+ if (process.platform === 'darwin') {
129
+ // Just activate Local - don't try to hide it (requires accessibility permissions)
130
+ await execAsync(`open -a "Local"`);
131
+ }
132
+ else if (process.platform === 'win32') {
133
+ // /MIN = start minimized
134
+ await execAsync(`start /MIN "" "${paths.appExecutable}"`);
135
+ }
136
+ else {
137
+ await execAsync(`${paths.appExecutable} &`);
138
+ }
139
+ }
140
+ catch {
141
+ // Ignore errors - Local might already be running
142
+ }
143
+ }
144
+ /**
145
+ * Stop Local application
146
+ */
147
+ async function stopLocal() {
148
+ try {
149
+ if (process.platform === 'darwin') {
150
+ await execAsync(`osascript -e 'quit app "Local"'`);
151
+ }
152
+ else if (process.platform === 'win32') {
153
+ await execAsync(`taskkill /IM Local.exe /F`);
154
+ }
155
+ else {
156
+ await execAsync(`pkill -f local`);
157
+ }
158
+ }
159
+ catch {
160
+ // Ignore errors - Local might not be running
161
+ }
162
+ }
163
+ /**
164
+ * Restart Local application
165
+ */
166
+ async function restartLocal() {
167
+ await stopLocal();
168
+ // Wait a bit for the process to fully stop
169
+ await delay(2000);
170
+ await startLocal();
171
+ }
172
+ // ===========================================
173
+ // Addon Management
174
+ // ===========================================
175
+ /**
176
+ * Addon directory name in Local's addons folder
177
+ * Local uses @scope-name format (replaces / with -)
178
+ */
179
+ const ADDON_DIR_NAME = '@local-labs-local-addon-cli';
180
+ /**
181
+ * Addon key in enabled-addons.json (package name)
182
+ */
183
+ const ADDON_ENABLED_KEY = '@local-labs-jpollock/local-addon-cli';
184
+ /**
185
+ * Get the addon installation path
186
+ */
187
+ function getAddonPath() {
188
+ const paths = (0, paths_1.getLocalPaths)();
189
+ return path.join(paths.addonsDir, ADDON_DIR_NAME);
190
+ }
191
+ /**
192
+ * Check if the addon is installed in Local's addons directory
193
+ */
194
+ function isAddonInstalled() {
195
+ const addonPath = getAddonPath();
196
+ // Check for directory or symlink
197
+ try {
198
+ const stat = fs.lstatSync(addonPath);
199
+ return stat.isDirectory() || stat.isSymbolicLink();
200
+ }
201
+ catch {
202
+ return false;
203
+ }
204
+ }
205
+ /**
206
+ * Check if the addon is activated in enabled-addons.json
207
+ */
208
+ function isAddonActivated() {
209
+ const paths = (0, paths_1.getLocalPaths)();
210
+ try {
211
+ if (!fs.existsSync(paths.enabledAddonsFile)) {
212
+ return false;
213
+ }
214
+ const content = fs.readFileSync(paths.enabledAddonsFile, 'utf-8');
215
+ const enabledAddons = JSON.parse(content);
216
+ return enabledAddons[ADDON_ENABLED_KEY] === true;
217
+ }
218
+ catch {
219
+ return false;
220
+ }
221
+ }
222
+ /**
223
+ * Activate the addon by modifying enabled-addons.json
224
+ * Returns true if restart is needed (addon was just activated)
225
+ */
226
+ function activateAddon() {
227
+ const paths = (0, paths_1.getLocalPaths)();
228
+ try {
229
+ let enabledAddons = {};
230
+ if (fs.existsSync(paths.enabledAddonsFile)) {
231
+ const content = fs.readFileSync(paths.enabledAddonsFile, 'utf-8');
232
+ enabledAddons = JSON.parse(content);
233
+ }
234
+ // Check if already activated
235
+ if (enabledAddons[ADDON_ENABLED_KEY] === true) {
236
+ return false; // Already active, no restart needed
237
+ }
238
+ // Activate the addon
239
+ enabledAddons[ADDON_ENABLED_KEY] = true;
240
+ fs.writeFileSync(paths.enabledAddonsFile, JSON.stringify(enabledAddons, null, 2));
241
+ return true; // Restart needed
242
+ }
243
+ catch {
244
+ return false;
245
+ }
246
+ }
247
+ /**
248
+ * Copy a directory recursively
249
+ */
250
+ function copyDirSync(src, dest) {
251
+ fs.mkdirSync(dest, { recursive: true });
252
+ const entries = fs.readdirSync(src, { withFileTypes: true });
253
+ for (const entry of entries) {
254
+ const srcPath = path.join(src, entry.name);
255
+ const destPath = path.join(dest, entry.name);
256
+ if (entry.isDirectory()) {
257
+ copyDirSync(srcPath, destPath);
258
+ }
259
+ else {
260
+ fs.copyFileSync(srcPath, destPath);
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Find the bundled addon path (included in npm package)
266
+ * Located at addon-dist/ relative to the CLI package root
267
+ */
268
+ function findBundledAddonPath() {
269
+ // From lib/bootstrap/ -> addon-dist/
270
+ const bundledPath = path.resolve(__dirname, '..', '..', 'addon-dist');
271
+ if (fs.existsSync(path.join(bundledPath, 'package.json'))) {
272
+ return bundledPath;
273
+ }
274
+ return null;
275
+ }
276
+ /**
277
+ * Find the local development addon path (for dev mode)
278
+ * Looks for the addon relative to the CLI package in monorepo
279
+ */
280
+ function findDevAddonPath() {
281
+ // Check if we're in the monorepo structure
282
+ // Works from both lib/bootstrap (compiled) and src/bootstrap (ts-node)
283
+ const cliDir = __dirname;
284
+ const addonPath = path.resolve(cliDir, '..', '..', '..', 'addon');
285
+ if (fs.existsSync(path.join(addonPath, 'package.json'))) {
286
+ return addonPath;
287
+ }
288
+ return null;
289
+ }
290
+ /**
291
+ * Install the addon from bundled package or create dev symlink
292
+ */
293
+ async function installAddon(options = {}) {
294
+ const log = options.onStatus || (() => { });
295
+ const paths = (0, paths_1.getLocalPaths)();
296
+ const addonPath = getAddonPath();
297
+ try {
298
+ // Ensure addons directory exists
299
+ if (!fs.existsSync(paths.addonsDir)) {
300
+ fs.mkdirSync(paths.addonsDir, { recursive: true });
301
+ }
302
+ // Try bundled addon first (production - included in npm package)
303
+ const bundledAddonPath = findBundledAddonPath();
304
+ if (bundledAddonPath) {
305
+ log('Installing bundled addon...');
306
+ // Copy bundled addon to Local's addons directory
307
+ copyDirSync(bundledAddonPath, addonPath);
308
+ log('Addon installed successfully.');
309
+ }
310
+ else {
311
+ // Try development mode - create symlink to local addon in monorepo
312
+ const devAddonPath = findDevAddonPath();
313
+ if (devAddonPath) {
314
+ log('Using development addon (symlink)...');
315
+ fs.symlinkSync(devAddonPath, addonPath);
316
+ log(`Created symlink: ${addonPath} -> ${devAddonPath}`);
317
+ }
318
+ else {
319
+ throw new Error('Addon not found. Please reinstall the CLI package: npm install -g @local-labs/local-cli');
320
+ }
321
+ }
322
+ // Activate the addon
323
+ const needsRestart = activateAddon();
324
+ return { success: true, needsRestart };
325
+ }
326
+ catch (error) {
327
+ return {
328
+ success: false,
329
+ error: error.message || 'Failed to install addon',
330
+ needsRestart: false,
331
+ };
332
+ }
333
+ }
334
+ /**
335
+ * Ensure addon is installed and activated
336
+ */
337
+ async function ensureAddon(options = {}) {
338
+ const log = options.onStatus || (() => { });
339
+ // Check if addon is installed
340
+ if (!isAddonInstalled()) {
341
+ log('Addon not installed. Installing...');
342
+ const result = await installAddon(options);
343
+ if (!result.success) {
344
+ return result;
345
+ }
346
+ return { success: true, needsRestart: true };
347
+ }
348
+ // Check if addon is activated
349
+ if (!isAddonActivated()) {
350
+ log('Activating addon...');
351
+ const needsRestart = activateAddon();
352
+ return { success: true, needsRestart };
353
+ }
354
+ return { success: true, needsRestart: false };
355
+ }
356
+ // ===========================================
357
+ // Connection Info
358
+ // ===========================================
359
+ /**
360
+ * Read GraphQL connection info from graphql-connection-info.json
361
+ */
362
+ function readConnectionInfo() {
363
+ const paths = (0, paths_1.getLocalPaths)();
364
+ try {
365
+ if (!fs.existsSync(paths.graphqlConnectionInfoFile)) {
366
+ return null;
367
+ }
368
+ const content = fs.readFileSync(paths.graphqlConnectionInfoFile, 'utf-8');
369
+ const info = JSON.parse(content);
370
+ return {
371
+ url: info.url || `http://127.0.0.1:${info.port}/graphql`,
372
+ subscriptionUrl: info.subscriptionUrl || `ws://127.0.0.1:${info.port}/graphql`,
373
+ port: info.port,
374
+ authToken: info.authToken || '',
375
+ };
376
+ }
377
+ catch {
378
+ return null;
379
+ }
380
+ }
381
+ /**
382
+ * Wait for GraphQL server to be ready
383
+ */
384
+ async function waitForGraphQL(timeoutMs = 30000, pollIntervalMs = 500) {
385
+ const start = Date.now();
386
+ while (Date.now() - start < timeoutMs) {
387
+ const connectionInfo = readConnectionInfo();
388
+ if (connectionInfo) {
389
+ try {
390
+ // Use AbortController for per-request timeout (2 seconds)
391
+ const controller = new AbortController();
392
+ const requestTimeout = setTimeout(() => controller.abort(), 2000);
393
+ const response = await fetch(connectionInfo.url, {
394
+ method: 'POST',
395
+ headers: {
396
+ 'Content-Type': 'application/json',
397
+ Authorization: `Bearer ${connectionInfo.authToken}`,
398
+ },
399
+ body: JSON.stringify({ query: '{ __typename }' }),
400
+ signal: controller.signal,
401
+ });
402
+ clearTimeout(requestTimeout);
403
+ if (response.ok) {
404
+ return true;
405
+ }
406
+ }
407
+ catch {
408
+ // Server not ready yet - connection refused, timeout, etc.
409
+ }
410
+ }
411
+ await delay(pollIntervalMs);
412
+ }
413
+ return false;
414
+ }
415
+ /**
416
+ * Delay helper
417
+ */
418
+ function delay(ms) {
419
+ return new Promise((resolve) => setTimeout(resolve, ms));
420
+ }
421
+ /**
422
+ * Main bootstrap function
423
+ * Ensures addon is installed, Local is running, and GraphQL is accessible
424
+ */
425
+ async function bootstrap(options = {}) {
426
+ const actions = [];
427
+ const log = (msg) => {
428
+ actions.push(msg);
429
+ if (options.verbose) {
430
+ console.log(msg);
431
+ }
432
+ if (options.onStatus) {
433
+ options.onStatus(msg);
434
+ }
435
+ };
436
+ // Check if Local is installed
437
+ if (!isLocalInstalled()) {
438
+ return {
439
+ success: false,
440
+ error: 'Local is not installed. Download from https://localwp.com',
441
+ actions,
442
+ };
443
+ }
444
+ // Ensure addon is installed and activated (unless skipped)
445
+ let needsRestart = false;
446
+ if (!options.skipAddonInstall) {
447
+ const addonResult = await ensureAddon({ onStatus: log });
448
+ if (!addonResult.success) {
449
+ return {
450
+ success: false,
451
+ error: addonResult.error || 'Failed to install addon',
452
+ actions,
453
+ };
454
+ }
455
+ needsRestart = addonResult.needsRestart;
456
+ }
457
+ // Check if Local is running
458
+ const running = await isLocalRunning();
459
+ if (needsRestart && running) {
460
+ log('Restarting Local to activate addon...');
461
+ await restartLocal();
462
+ }
463
+ else if (!running) {
464
+ log('Starting Local...');
465
+ await startLocal();
466
+ }
467
+ // Wait for GraphQL server
468
+ log('Waiting for GraphQL...');
469
+ const ready = await waitForGraphQL();
470
+ if (!ready) {
471
+ return {
472
+ success: false,
473
+ error: 'Timed out waiting for Local. Is Local running?',
474
+ actions,
475
+ };
476
+ }
477
+ log('GraphQL server ready.');
478
+ // Read connection info
479
+ const connectionInfo = readConnectionInfo();
480
+ if (!connectionInfo) {
481
+ return {
482
+ success: false,
483
+ error: 'Could not read GraphQL connection info.',
484
+ actions,
485
+ };
486
+ }
487
+ return {
488
+ success: true,
489
+ connectionInfo,
490
+ actions,
491
+ };
492
+ }
493
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYm9vdHN0cmFwL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7O0dBU0c7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJCSCw0Q0FvQkM7QUFLRCx3Q0FvQkM7QUFLRCxnQ0FnQkM7QUFLRCw4QkFZQztBQUtELG9DQUtDO0FBb0JELG9DQUdDO0FBS0QsNENBVUM7QUFLRCw0Q0FlQztBQU1ELHNDQXdCQztBQXlERCxvQ0FrREM7QUFLRCxrQ0F1QkM7QUFTRCxnREFvQkM7QUFLRCx3Q0F1Q0M7QUFhRCw4QkFnRkM7QUEzZkQsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUM3QixpREFBK0M7QUFDL0MsK0JBQWlDO0FBQ2pDLG1DQUFvRDtBQXlmM0MsOEZBemZBLHFCQUFhLE9BeWZBO0FBdmZ0QixNQUFNLFNBQVMsR0FBRyxJQUFBLGdCQUFTLEVBQUMsb0JBQUksQ0FBQyxDQUFDO0FBZ0JsQzs7R0FFRztBQUNILFNBQWdCLGdCQUFnQjtJQUM5QixNQUFNLEtBQUssR0FBRyxJQUFBLHFCQUFhLEdBQUUsQ0FBQztJQUU5QixJQUFJLENBQUM7UUFDSCxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDbEMsT0FBTyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUM1QyxDQUFDO2FBQU0sSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ3hDLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDNUMsQ0FBQzthQUFNLENBQUM7WUFDTiw4REFBOEQ7WUFDOUQsSUFBSSxDQUFDO2dCQUNILElBQUEsd0JBQVEsRUFBQyxhQUFhLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFD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LFlBQVksR0FBRyxXQUFXLENBQUMsWUFBWSxDQUFDO0lBQzFDLENBQUM7SUFFRCw0QkFBNEI7SUFDNUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLEVBQUUsQ0FBQztJQUV2QyxJQUFJLFlBQVksSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM1QixHQUFHLENBQUMsdUNBQXVDLENBQUMsQ0FBQztRQUM3QyxNQUFNLFlBQVksRUFBRSxDQUFDO0lBQ3ZCLENBQUM7U0FBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDekIsTUFBTSxVQUFVLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0lBQzlCLE1BQU0sS0FBSyxHQUFHLE1BQU0sY0FBYyxFQUFFLENBQUM7SUFFckMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1gsT0FBTztZQUNMLE9BQU8sRUFBRSxLQUFLO1lBQ2QsS0FBSyxFQUFFLGdEQUFnRDtZQUN2RCxPQUFPO1NBQ1IsQ0FBQztJQUNKLENBQUM7SUFFRCxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztJQUU3Qix1QkFBdUI7SUFDdkIsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLEVBQUUsQ0FBQztJQUU1QyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDcEIsT0FBTztZQUNMLE9BQU8sRUFBRSxLQUFLO1lBQ2QsS0FBSyxFQUFFLHlDQUF5QztZQUNoRCxPQUFPO1NBQ1IsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ0wsT0FBTyxFQUFFLElBQUk7UUFDYixjQUFjO1FBQ2QsT0FBTztLQUNSLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCb290c3RyYXAgU3lzdGVtXG4gKlxuICogQ29ubmVjdHMgdGhlIENMSSB0byBMb2NhbCdzIEdyYXBoUUwgc2VydmVyOlxuICogLSBEZXRlY3RzIExvY2FsIGluc3RhbGxhdGlvblxuICogLSBJbnN0YWxscyBhbmQgYWN0aXZhdGVzIGFkZG9uIGlmIG5lZWRlZFxuICogLSBTdGFydHMgTG9jYWwgaWYgbmVlZGVkXG4gKiAtIFdhaXRzIGZvciBHcmFwaFFMIHNlcnZlciB0byBiZSByZWFkeVxuICogLSBSZWFkcyBjb25uZWN0aW9uIGluZm9cbiAqL1xuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZXhlYywgZXhlY1N5bmMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IHByb21pc2lmeSB9IGZyb20gJ3V0aWwnO1xuaW1wb3J0IHsgZ2V0TG9jYWxQYXRocywgTG9jYWxQYXRocyB9IGZyb20gJy4vcGF0aHMnO1xuXG5jb25zdCBleGVjQXN5bmMgPSBwcm9taXNpZnkoZXhlYyk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdGlvbkluZm8ge1xuICB1cmw6IHN0cmluZztcbiAgc3Vic2NyaXB0aW9uVXJsOiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbiAgYXV0aFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQm9vdHN0cmFwUmVzdWx0IHtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgY29ubmVjdGlvbkluZm8/OiBDb25uZWN0aW9uSW5mbztcbiAgZXJyb3I/OiBzdHJpbmc7XG4gIGFjdGlvbnM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIExvY2FsIGlzIGluc3RhbGxlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNMb2NhbEluc3RhbGxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgcGF0aHMgPSBnZXRMb2NhbFBhdGhzKCk7XG5cbiAgdHJ5IHtcbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcbiAgICAgIHJldHVybiBmcy5leGlzdHNTeW5jKHBhdGhzLmFwcEV4ZWN1dGFibGUpO1xuICAgIH0gZWxzZSBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgICAgcmV0dXJuIGZzLmV4aXN0c1N5bmMocGF0aHMuYXBwRXhlY3V0YWJsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIExpbnV4IC0gY2hlY2sgaWYgJ2xvY2FsJyBpcyBpbiBQQVRIIG9yIGF0IGV4cGVjdGVkIGxvY2F0aW9uXG4gICAgICB0cnkge1xuICAgICAgICBleGVjU3luYygnd2hpY2ggbG9jYWwnLCB7IHN0ZGlvOiAnaWdub3JlJyB9KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZzLmV4aXN0c1N5bmMocGF0aHMuYXBwRXhlY3V0YWJsZSk7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBDaGVjayBpZiBMb2NhbCBpcyBjdXJyZW50bHkgcnVubmluZ1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaXNMb2NhbFJ1bm5pbmcoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdkYXJ3aW4nKSB7XG4gICAgICAvLyBVc2UgcGdyZXAgd2l0aCAtZiB0byBtYXRjaCBhbnkgcHJvY2VzcyBjb250YWluaW5nIFwiTG9jYWxcIlxuICAgICAgLy8gQWxzbyBjaGVjayBpZiBHcmFwaFFMIGNvbm5lY3Rpb24gaW5mbyBleGlzdHMgYW5kIGlzIHJlY2VudFxuICAgICAgY29uc3QgeyBzdGRvdXQgfSA9IGF3YWl0IGV4ZWNBc3luYyhgcGdyZXAgLWYgXCJMb2NhbC5hcHBcImApO1xuICAgICAgcmV0dXJuIHN0ZG91dC50cmltKCkubGVuZ3RoID4gMDtcbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpIHtcbiAgICAgIGNvbnN0IHsgc3Rkb3V0IH0gPSBhd2FpdCBleGVjQXN5bmMoYHRhc2tsaXN0IC9GSSBcIklNQUdFTkFNRSBlcSBMb2NhbC5leGVcImApO1xuICAgICAgcmV0dXJuIHN0ZG91dC5pbmNsdWRlcygnTG9jYWwuZXhlJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHsgc3Rkb3V0IH0gPSBhd2FpdCBleGVjQXN5bmMoYHBncmVwIC1mIFwibG9jYWxcImApO1xuICAgICAgcmV0dXJuIHN0ZG91dC50cmltKCkubGVuZ3RoID4gMDtcbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIHBncmVwIHJldHVybnMgbm9uLXplcm8gaWYgbm8gcHJvY2Vzc2VzIGZvdW5kXG4gICAgLy8gQ2hlY2sgaWYgY29ubmVjdGlvbiBpbmZvIGV4aXN0cyBhcyBhIGZhbGxiYWNrXG4gICAgY29uc3QgY29ubmVjdGlvbkluZm8gPSByZWFkQ29ubmVjdGlvbkluZm8oKTtcbiAgICByZXR1cm4gY29ubmVjdGlvbkluZm8gIT09IG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBTdGFydCBMb2NhbCBhcHBsaWNhdGlvblxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRMb2NhbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcGF0aHMgPSBnZXRMb2NhbFBhdGhzKCk7XG5cbiAgdHJ5IHtcbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcbiAgICAgIC8vIEp1c3QgYWN0aXZhdGUgTG9jYWwgLSBkb24ndCB0cnkgdG8gaGlkZSBpdCAocmVxdWlyZXMgYWNjZXNzaWJpbGl0eSBwZXJtaXNzaW9ucylcbiAgICAgIGF3YWl0IGV4ZWNBc3luYyhgb3BlbiAtYSBcIkxvY2FsXCJgKTtcbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpIHtcbiAgICAgIC8vIC9NSU4gPSBzdGFydCBtaW5pbWl6ZWRcbiAgICAgIGF3YWl0IGV4ZWNBc3luYyhgc3RhcnQgL01JTiBcIlwiIFwiJHtwYXRocy5hcHBFeGVjdXRhYmxlfVwiYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IGV4ZWNBc3luYyhgJHtwYXRocy5hcHBFeGVjdXRhYmxlfSAmYCk7XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBJZ25vcmUgZXJyb3JzIC0gTG9jYWwgbWlnaHQgYWxyZWFkeSBiZSBydW5uaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBTdG9wIExvY2FsIGFwcGxpY2F0aW9uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdG9wTG9jYWwoKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdkYXJ3aW4nKSB7XG4gICAgICBhd2FpdCBleGVjQXN5bmMoYG9zYXNjcmlwdCAtZSAncXVpdCBhcHAgXCJMb2NhbFwiJ2ApO1xuICAgIH0gZWxzZSBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgICAgYXdhaXQgZXhlY0FzeW5jKGB0YXNra2lsbCAvSU0gTG9jYWwuZXhlIC9GYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IGV4ZWNBc3luYyhgcGtpbGwgLWYgbG9jYWxgKTtcbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIElnbm9yZSBlcnJvcnMgLSBMb2NhbCBtaWdodCBub3QgYmUgcnVubmluZ1xuICB9XG59XG5cbi8qKlxuICogUmVzdGFydCBMb2NhbCBhcHBsaWNhdGlvblxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdGFydExvY2FsKCk6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBzdG9wTG9jYWwoKTtcbiAgLy8gV2FpdCBhIGJpdCBmb3IgdGhlIHByb2Nlc3MgdG8gZnVsbHkgc3RvcFxuICBhd2FpdCBkZWxheSgyMDAwKTtcbiAgYXdhaXQgc3RhcnRMb2NhbCgpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBBZGRvbiBNYW5hZ2VtZW50XG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQWRkb24gZGlyZWN0b3J5IG5hbWUgaW4gTG9jYWwncyBhZGRvbnMgZm9sZGVyXG4gKiBMb2NhbCB1c2VzIEBzY29wZS1uYW1lIGZvcm1hdCAocmVwbGFjZXMgLyB3aXRoIC0pXG4gKi9cbmNvbnN0IEFERE9OX0RJUl9OQU1FID0gJ0Bsb2NhbC1sYWJzLWxvY2FsLWFkZG9uLWNsaSc7XG5cbi8qKlxuICogQWRkb24ga2V5IGluIGVuYWJsZWQtYWRkb25zLmpzb24gKHBhY2thZ2UgbmFtZSlcbiAqL1xuY29uc3QgQURET05fRU5BQkxFRF9LRVkgPSAnQGxvY2FsLWxhYnMtanBvbGxvY2svbG9jYWwtYWRkb24tY2xpJztcblxuLyoqXG4gKiBHZXQgdGhlIGFkZG9uIGluc3RhbGxhdGlvbiBwYXRoXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRvblBhdGgoKTogc3RyaW5nIHtcbiAgY29uc3QgcGF0aHMgPSBnZXRMb2NhbFBhdGhzKCk7XG4gIHJldHVybiBwYXRoLmpvaW4ocGF0aHMuYWRkb25zRGlyLCBBRERPTl9ESVJfTkFNRSk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGFkZG9uIGlzIGluc3RhbGxlZCBpbiBMb2NhbCdzIGFkZG9ucyBkaXJlY3RvcnlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQWRkb25JbnN0YWxsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IGFkZG9uUGF0aCA9IGdldEFkZG9uUGF0aCgpO1xuXG4gIC8vIENoZWNrIGZvciBkaXJlY3Rvcnkgb3Igc3ltbGlua1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXQgPSBmcy5sc3RhdFN5bmMoYWRkb25QYXRoKTtcbiAgICByZXR1cm4gc3RhdC5pc0RpcmVjdG9yeSgpIHx8IHN0YXQuaXNTeW1ib2xpY0xpbmsoKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGFkZG9uIGlzIGFjdGl2YXRlZCBpbiBlbmFibGVkLWFkZG9ucy5qc29uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0FkZG9uQWN0aXZhdGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCBwYXRocyA9IGdldExvY2FsUGF0aHMoKTtcblxuICB0cnkge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhwYXRocy5lbmFibGVkQWRkb25zRmlsZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKHBhdGhzLmVuYWJsZWRBZGRvbnNGaWxlLCAndXRmLTgnKTtcbiAgICBjb25zdCBlbmFibGVkQWRkb25zOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9IEpTT04ucGFyc2UoY29udGVudCk7XG5cbiAgICByZXR1cm4gZW5hYmxlZEFkZG9uc1tBRERPTl9FTkFCTEVEX0tFWV0gPT09IHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIEFjdGl2YXRlIHRoZSBhZGRvbiBieSBtb2RpZnlpbmcgZW5hYmxlZC1hZGRvbnMuanNvblxuICogUmV0dXJucyB0cnVlIGlmIHJlc3RhcnQgaXMgbmVlZGVkIChhZGRvbiB3YXMganVzdCBhY3RpdmF0ZWQpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhY3RpdmF0ZUFkZG9uKCk6IGJvb2xlYW4ge1xuICBjb25zdCBwYXRocyA9IGdldExvY2FsUGF0aHMoKTtcblxuICB0cnkge1xuICAgIGxldCBlbmFibGVkQWRkb25zOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9IHt9O1xuXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMocGF0aHMuZW5hYmxlZEFkZG9uc0ZpbGUpKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKHBhdGhzLmVuYWJsZWRBZGRvbnNGaWxlLCAndXRmLTgnKTtcbiAgICAgIGVuYWJsZWRBZGRvbnMgPSBKU09OLnBhcnNlKGNvbnRlbnQpO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGFscmVhZHkgYWN0aXZhdGVkXG4gICAgaWYgKGVuYWJsZWRBZGRvbnNbQURET05fRU5BQkxFRF9LRVldID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7IC8vIEFscmVhZHkgYWN0aXZlLCBubyByZXN0YXJ0IG5lZWRlZFxuICAgIH1cblxuICAgIC8vIEFjdGl2YXRlIHRoZSBhZGRvblxuICAgIGVuYWJsZWRBZGRvbnNbQURET05fRU5BQkxFRF9LRVldID0gdHJ1ZTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGhzLmVuYWJsZWRBZGRvbnNGaWxlLCBKU09OLnN0cmluZ2lmeShlbmFibGVkQWRkb25zLCBudWxsLCAyKSk7XG5cbiAgICByZXR1cm4gdHJ1ZTsgLy8gUmVzdGFydCBuZWVkZWRcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogQ29weSBhIGRpcmVjdG9yeSByZWN1cnNpdmVseVxuICovXG5mdW5jdGlvbiBjb3B5RGlyU3luYyhzcmM6IHN0cmluZywgZGVzdDogc3RyaW5nKTogdm9pZCB7XG4gIGZzLm1rZGlyU3luYyhkZXN0LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoc3JjLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3Qgc3JjUGF0aCA9IHBhdGguam9pbihzcmMsIGVudHJ5Lm5hbWUpO1xuICAgIGNvbnN0IGRlc3RQYXRoID0gcGF0aC5qb2luKGRlc3QsIGVudHJ5Lm5hbWUpO1xuXG4gICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGNvcHlEaXJTeW5jKHNyY1BhdGgsIGRlc3RQYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZnMuY29weUZpbGVTeW5jKHNyY1BhdGgsIGRlc3RQYXRoKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBGaW5kIHRoZSBidW5kbGVkIGFkZG9uIHBhdGggKGluY2x1ZGVkIGluIG5wbSBwYWNrYWdlKVxuICogTG9jYXRlZCBhdCBhZGRvbi1kaXN0LyByZWxhdGl2ZSB0byB0aGUgQ0xJIHBhY2thZ2Ugcm9vdFxuICovXG5mdW5jdGlvbiBmaW5kQnVuZGxlZEFkZG9uUGF0aCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgLy8gRnJvbSBsaWIvYm9vdHN0cmFwLyAtPiBhZGRvbi1kaXN0L1xuICBjb25zdCBidW5kbGVkUGF0aCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLicsICcuLicsICdhZGRvbi1kaXN0Jyk7XG5cbiAgaWYgKGZzLmV4aXN0c1N5bmMocGF0aC5qb2luKGJ1bmRsZWRQYXRoLCAncGFja2FnZS5qc29uJykpKSB7XG4gICAgcmV0dXJuIGJ1bmRsZWRQYXRoO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogRmluZCB0aGUgbG9jYWwgZGV2ZWxvcG1lbnQgYWRkb24gcGF0aCAoZm9yIGRldiBtb2RlKVxuICogTG9va3MgZm9yIHRoZSBhZGRvbiByZWxhdGl2ZSB0byB0aGUgQ0xJIHBhY2thZ2UgaW4gbW9ub3JlcG9cbiAqL1xuZnVuY3Rpb24gZmluZERldkFkZG9uUGF0aCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgLy8gQ2hlY2sgaWYgd2UncmUgaW4gdGhlIG1vbm9yZXBvIHN0cnVjdHVyZVxuICAvLyBXb3JrcyBmcm9tIGJvdGggbGliL2Jvb3RzdHJhcCAoY29tcGlsZWQpIGFuZCBzcmMvYm9vdHN0cmFwICh0cy1ub2RlKVxuICBjb25zdCBjbGlEaXIgPSBfX2Rpcm5hbWU7XG4gIGNvbnN0IGFkZG9uUGF0aCA9IHBhdGgucmVzb2x2ZShjbGlEaXIsICcuLicsICcuLicsICcuLicsICdhZGRvbicpO1xuXG4gIGlmIChmcy5leGlzdHNTeW5jKHBhdGguam9pbihhZGRvblBhdGgsICdwYWNrYWdlLmpzb24nKSkpIHtcbiAgICByZXR1cm4gYWRkb25QYXRoO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogSW5zdGFsbCB0aGUgYWRkb24gZnJvbSBidW5kbGVkIHBhY2thZ2Ugb3IgY3JlYXRlIGRldiBzeW1saW5rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsQWRkb24ob3B0aW9uczoge1xuICBvblN0YXR1cz86IChzdGF0dXM6IHN0cmluZykgPT4gdm9pZDtcbn0gPSB7fSk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcj86IHN0cmluZzsgbmVlZHNSZXN0YXJ0OiBib29sZWFuIH0+IHtcbiAgY29uc3QgbG9nID0gb3B0aW9ucy5vblN0YXR1cyB8fCAoKCkgPT4ge30pO1xuICBjb25zdCBwYXRocyA9IGdldExvY2FsUGF0aHMoKTtcbiAgY29uc3QgYWRkb25QYXRoID0gZ2V0QWRkb25QYXRoKCk7XG5cbiAgdHJ5IHtcbiAgICAvLyBFbnN1cmUgYWRkb25zIGRpcmVjdG9yeSBleGlzdHNcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMocGF0aHMuYWRkb25zRGlyKSkge1xuICAgICAgZnMubWtkaXJTeW5jKHBhdGhzLmFkZG9uc0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuXG4gICAgLy8gVHJ5IGJ1bmRsZWQgYWRkb24gZmlyc3QgKHByb2R1Y3Rpb24gLSBpbmNsdWRlZCBpbiBucG0gcGFja2FnZSlcbiAgICBjb25zdCBidW5kbGVkQWRkb25QYXRoID0gZmluZEJ1bmRsZWRBZGRvblBhdGgoKTtcblxuICAgIGlmIChidW5kbGVkQWRkb25QYXRoKSB7XG4gICAgICBsb2coJ0luc3RhbGxpbmcgYnVuZGxlZCBhZGRvbi4uLicpO1xuXG4gICAgICAvLyBDb3B5IGJ1bmRsZWQgYWRkb24gdG8gTG9jYWwncyBhZGRvbnMgZGlyZWN0b3J5XG4gICAgICBjb3B5RGlyU3luYyhidW5kbGVkQWRkb25QYXRoLCBhZGRvblBhdGgpO1xuXG4gICAgICBsb2coJ0FkZG9uIGluc3RhbGxlZCBzdWNjZXNzZnVsbHkuJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFRyeSBkZXZlbG9wbWVudCBtb2RlIC0gY3JlYXRlIHN5bWxpbmsgdG8gbG9jYWwgYWRkb24gaW4gbW9ub3JlcG9cbiAgICAgIGNvbnN0IGRldkFkZG9uUGF0aCA9IGZpbmREZXZBZGRvblBhdGgoKTtcblxuICAgICAgaWYgKGRldkFkZG9uUGF0aCkge1xuICAgICAgICBsb2coJ1VzaW5nIGRldmVsb3BtZW50IGFkZG9uIChzeW1saW5rKS4uLicpO1xuXG4gICAgICAgIGZzLnN5bWxpbmtTeW5jKGRldkFkZG9uUGF0aCwgYWRkb25QYXRoKTtcbiAgICAgICAgbG9nKGBDcmVhdGVkIHN5bWxpbms6ICR7YWRkb25QYXRofSAtPiAke2RldkFkZG9uUGF0aH1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnQWRkb24gbm90IGZvdW5kLiBQbGVhc2UgcmVpbnN0YWxsIHRoZSBDTEkgcGFja2FnZTogbnBtIGluc3RhbGwgLWcgQGxvY2FsLWxhYnMvbG9jYWwtY2xpJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFjdGl2YXRlIHRoZSBhZGRvblxuICAgIGNvbnN0IG5lZWRzUmVzdGFydCA9IGFjdGl2YXRlQWRkb24oKTtcblxuICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIG5lZWRzUmVzdGFydCB9O1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfHwgJ0ZhaWxlZCB0byBpbnN0YWxsIGFkZG9uJyxcbiAgICAgIG5lZWRzUmVzdGFydDogZmFsc2UsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIEVuc3VyZSBhZGRvbiBpcyBpbnN0YWxsZWQgYW5kIGFjdGl2YXRlZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5zdXJlQWRkb24ob3B0aW9uczoge1xuICBvblN0YXR1cz86IChzdGF0dXM6IHN0cmluZykgPT4gdm9pZDtcbn0gPSB7fSk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcj86IHN0cmluZzsgbmVlZHNSZXN0YXJ0OiBib29sZWFuIH0+IHtcbiAgY29uc3QgbG9nID0gb3B0aW9ucy5vblN0YXR1cyB8fCAoKCkgPT4ge30pO1xuXG4gIC8vIENoZWNrIGlmIGFkZG9uIGlzIGluc3RhbGxlZFxuICBpZiAoIWlzQWRkb25JbnN0YWxsZWQoKSkge1xuICAgIGxvZygnQWRkb24gbm90IGluc3RhbGxlZC4gSW5zdGFsbGluZy4uLicpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGluc3RhbGxBZGRvbihvcHRpb25zKTtcbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBuZWVkc1Jlc3RhcnQ6IHRydWUgfTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGFkZG9uIGlzIGFjdGl2YXRlZFxuICBpZiAoIWlzQWRkb25BY3RpdmF0ZWQoKSkge1xuICAgIGxvZygnQWN0aXZhdGluZyBhZGRvbi4uLicpO1xuICAgIGNvbnN0IG5lZWRzUmVzdGFydCA9IGFjdGl2YXRlQWRkb24oKTtcbiAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBuZWVkc1Jlc3RhcnQgfTtcbiAgfVxuXG4gIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIG5lZWRzUmVzdGFydDogZmFsc2UgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ29ubmVjdGlvbiBJbmZvXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogUmVhZCBHcmFwaFFMIGNvbm5lY3Rpb24gaW5mbyBmcm9tIGdyYXBocWwtY29ubmVjdGlvbi1pbmZvLmpzb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRDb25uZWN0aW9uSW5mbygpOiBDb25uZWN0aW9uSW5mbyB8IG51bGwge1xuICBjb25zdCBwYXRocyA9IGdldExvY2FsUGF0aHMoKTtcblxuICB0cnkge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhwYXRocy5ncmFwaHFsQ29ubmVjdGlvbkluZm9GaWxlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhwYXRocy5ncmFwaHFsQ29ubmVjdGlvbkluZm9GaWxlLCAndXRmLTgnKTtcbiAgICBjb25zdCBpbmZvID0gSlNPTi5wYXJzZShjb250ZW50KTtcblxuICAgIHJldHVybiB7XG4gICAgICB1cmw6IGluZm8udXJsIHx8IGBodHRwOi8vMTI3LjAuMC4xOiR7aW5mby5wb3J0fS9ncmFwaHFsYCxcbiAgICAgIHN1YnNjcmlwdGlvblVybDogaW5mby5zdWJzY3JpcHRpb25VcmwgfHwgYHdzOi8vMTI3LjAuMC4xOiR7aW5mby5wb3J0fS9ncmFwaHFsYCxcbiAgICAgIHBvcnQ6IGluZm8ucG9ydCxcbiAgICAgIGF1dGhUb2tlbjogaW5mby5hdXRoVG9rZW4gfHwgJycsXG4gICAgfTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBXYWl0IGZvciBHcmFwaFFMIHNlcnZlciB0byBiZSByZWFkeVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2FpdEZvckdyYXBoUUwoXG4gIHRpbWVvdXRNczogbnVtYmVyID0gMzAwMDAsXG4gIHBvbGxJbnRlcnZhbE1zOiBudW1iZXIgPSA1MDBcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG5cbiAgd2hpbGUgKERhdGUubm93KCkgLSBzdGFydCA8IHRpbWVvdXRNcykge1xuICAgIGNvbnN0IGNvbm5lY3Rpb25JbmZvID0gcmVhZENvbm5lY3Rpb25JbmZvKCk7XG5cbiAgICBpZiAoY29ubmVjdGlvbkluZm8pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFVzZSBBYm9ydENvbnRyb2xsZXIgZm9yIHBlci1yZXF1ZXN0IHRpbWVvdXQgKDIgc2Vjb25kcylcbiAgICAgICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgMjAwMCk7XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChjb25uZWN0aW9uSW5mby51cmwsIHtcbiAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2Nvbm5lY3Rpb25JbmZvLmF1dGhUb2tlbn1gLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBxdWVyeTogJ3sgX190eXBlbmFtZSB9JyB9KSxcbiAgICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICB9KTtcblxuICAgICAgICBjbGVhclRpbWVvdXQocmVxdWVzdFRpbWVvdXQpO1xuXG4gICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gU2VydmVyIG5vdCByZWFkeSB5ZXQgLSBjb25uZWN0aW9uIHJlZnVzZWQsIHRpbWVvdXQsIGV0Yy5cbiAgICAgIH1cbiAgICB9XG5cbiAgICBhd2FpdCBkZWxheShwb2xsSW50ZXJ2YWxNcyk7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogRGVsYXkgaGVscGVyXG4gKi9cbmZ1bmN0aW9uIGRlbGF5KG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbi8qKlxuICogTWFpbiBib290c3RyYXAgZnVuY3Rpb25cbiAqIEVuc3VyZXMgYWRkb24gaXMgaW5zdGFsbGVkLCBMb2NhbCBpcyBydW5uaW5nLCBhbmQgR3JhcGhRTCBpcyBhY2Nlc3NpYmxlXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBib290c3RyYXAob3B0aW9uczoge1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbiAgc2tpcEFkZG9uSW5zdGFsbD86IGJvb2xlYW47XG4gIG9uU3RhdHVzPzogKHN0YXR1czogc3RyaW5nKSA9PiB2b2lkO1xufSA9IHt9KTogUHJvbWlzZTxCb290c3RyYXBSZXN1bHQ+IHtcbiAgY29uc3QgYWN0aW9uczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgbG9nID0gKG1zZzogc3RyaW5nKSA9PiB7XG4gICAgYWN0aW9ucy5wdXNoKG1zZyk7XG4gICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgY29uc29sZS5sb2cobXNnKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMub25TdGF0dXMpIHtcbiAgICAgIG9wdGlvbnMub25TdGF0dXMobXNnKTtcbiAgICB9XG4gIH07XG5cbiAgLy8gQ2hlY2sgaWYgTG9jYWwgaXMgaW5zdGFsbGVkXG4gIGlmICghaXNMb2NhbEluc3RhbGxlZCgpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXJyb3I6ICdMb2NhbCBpcyBub3QgaW5zdGFsbGVkLiBEb3dubG9hZCBmcm9tIGh0dHBzOi8vbG9jYWx3cC5jb20nLFxuICAgICAgYWN0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgLy8gRW5zdXJlIGFkZG9uIGlzIGluc3RhbGxlZCBhbmQgYWN0aXZhdGVkICh1bmxlc3Mgc2tpcHBlZClcbiAgbGV0IG5lZWRzUmVzdGFydCA9IGZhbHNlO1xuICBpZiAoIW9wdGlvbnMuc2tpcEFkZG9uSW5zdGFsbCkge1xuICAgIGNvbnN0IGFkZG9uUmVzdWx0ID0gYXdhaXQgZW5zdXJlQWRkb24oeyBvblN0YXR1czogbG9nIH0pO1xuICAgIGlmICghYWRkb25SZXN1bHQuc3VjY2Vzcykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIGVycm9yOiBhZGRvblJlc3VsdC5lcnJvciB8fCAnRmFpbGVkIHRvIGluc3RhbGwgYWRkb24nLFxuICAgICAgICBhY3Rpb25zLFxuICAgICAgfTtcbiAgICB9XG4gICAgbmVlZHNSZXN0YXJ0ID0gYWRkb25SZXN1bHQubmVlZHNSZXN0YXJ0O1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgTG9jYWwgaXMgcnVubmluZ1xuICBjb25zdCBydW5uaW5nID0gYXdhaXQgaXNMb2NhbFJ1bm5pbmcoKTtcblxuICBpZiAobmVlZHNSZXN0YXJ0ICYmIHJ1bm5pbmcpIHtcbiAgICBsb2coJ1Jlc3RhcnRpbmcgTG9jYWwgdG8gYWN0aXZhdGUgYWRkb24uLi4nKTtcbiAgICBhd2FpdCByZXN0YXJ0TG9jYWwoKTtcbiAgfSBlbHNlIGlmICghcnVubmluZykge1xuICAgIGxvZygnU3RhcnRpbmcgTG9jYWwuLi4nKTtcbiAgICBhd2FpdCBzdGFydExvY2FsKCk7XG4gIH1cblxuICAvLyBXYWl0IGZvciBHcmFwaFFMIHNlcnZlclxuICBsb2coJ1dhaXRpbmcgZm9yIEdyYXBoUUwuLi4nKTtcbiAgY29uc3QgcmVhZHkgPSBhd2FpdCB3YWl0Rm9yR3JhcGhRTCgpO1xuXG4gIGlmICghcmVhZHkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBlcnJvcjogJ1RpbWVkIG91dCB3YWl0aW5nIGZvciBMb2NhbC4gSXMgTG9jYWwgcnVubmluZz8nLFxuICAgICAgYWN0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgbG9nKCdHcmFwaFFMIHNlcnZlciByZWFkeS4nKTtcblxuICAvLyBSZWFkIGNvbm5lY3Rpb24gaW5mb1xuICBjb25zdCBjb25uZWN0aW9uSW5mbyA9IHJlYWRDb25uZWN0aW9uSW5mbygpO1xuXG4gIGlmICghY29ubmVjdGlvbkluZm8pIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBlcnJvcjogJ0NvdWxkIG5vdCByZWFkIEdyYXBoUUwgY29ubmVjdGlvbiBpbmZvLicsXG4gICAgICBhY3Rpb25zLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgY29ubmVjdGlvbkluZm8sXG4gICAgYWN0aW9ucyxcbiAgfTtcbn1cblxuZXhwb3J0IHsgZ2V0TG9jYWxQYXRocywgTG9jYWxQYXRocyB9O1xuIl19