@quantiya/codevibe-claude-plugin 1.0.8 → 1.0.10

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.
@@ -41,11 +41,13 @@ var __importStar = (this && this.__importStar) || (function () {
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
42
  exports.authService = exports.AuthService = void 0;
43
43
  const crypto = __importStar(require("crypto"));
44
+ const fs = __importStar(require("fs"));
44
45
  const http = __importStar(require("http"));
45
46
  const child_process_1 = require("child_process");
46
47
  const config_1 = require("../config");
47
48
  const keychain_1 = require("../keychain");
48
49
  const logger_1 = require("../logger");
50
+ const fetch_helpers_1 = require("./fetch-helpers");
49
51
  const CALLBACK_PORT = 8080;
50
52
  const CALLBACK_PATH = '/callback';
51
53
  const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
@@ -61,10 +63,154 @@ class AuthService {
61
63
  return AuthService.instance;
62
64
  }
63
65
  /**
64
- * Open URL in default browser
66
+ * Open URL in the user's default browser. Cross-platform: macOS, Linux,
67
+ * WSL, Windows. Always prints the URL to stdout first as a fallback —
68
+ * if no browser-opening command is available, the user can copy-paste.
69
+ *
70
+ * On WSL, prefers opening the Windows host browser via WSL interop
71
+ * (wslview → cmd.exe → powershell.exe) before falling back to xdg-open.
65
72
  */
66
73
  openBrowser(url) {
67
- (0, child_process_1.spawn)('open', [url], { detached: true, stdio: 'ignore' }).unref();
74
+ // Always print the URL first so users can copy-paste if automatic
75
+ // browser-opening fails (especially important on headless WSL setups).
76
+ console.log('');
77
+ console.log('Opening your browser for sign-in...');
78
+ console.log('If your browser does not open automatically, visit this URL manually:');
79
+ console.log(` ${url}`);
80
+ console.log('');
81
+ const attempts = this.getBrowserCommands();
82
+ this.tryBrowserCommand(attempts, url, 0);
83
+ }
84
+ /**
85
+ * Returns the list of browser-opening commands to try in order, based on
86
+ * the current platform. On WSL, returns WSL interop commands first so the
87
+ * Windows browser opens (which is what users actually want on WSL).
88
+ */
89
+ getBrowserCommands() {
90
+ const platform = process.platform;
91
+ if (platform === 'darwin') {
92
+ return [{ cmd: 'open', fixedArgs: [] }];
93
+ }
94
+ if (platform === 'win32') {
95
+ // cmd's start needs an empty title as the first arg so that URLs
96
+ // containing special characters aren't misinterpreted as the title.
97
+ return [{ cmd: 'cmd', fixedArgs: ['/c', 'start', ''] }];
98
+ }
99
+ // Linux or WSL
100
+ const attempts = [];
101
+ if (this.isRunningInWSL()) {
102
+ // Prefer opening the Windows host browser via WSL interop.
103
+ attempts.push({ cmd: 'wslview', fixedArgs: [] });
104
+ attempts.push({ cmd: 'cmd.exe', fixedArgs: ['/c', 'start', ''] });
105
+ attempts.push({
106
+ cmd: 'powershell.exe',
107
+ fixedArgs: ['-NoProfile', '-Command', 'Start-Process'],
108
+ });
109
+ }
110
+ // Fall back to generic Linux openers
111
+ attempts.push({ cmd: 'xdg-open', fixedArgs: [] });
112
+ return attempts;
113
+ }
114
+ /**
115
+ * Detect whether we're running inside WSL (1 or 2). Returns false on
116
+ * any non-Linux platform or if /proc/sys/kernel/osrelease is not readable.
117
+ */
118
+ isRunningInWSL() {
119
+ if (process.platform !== 'linux')
120
+ return false;
121
+ try {
122
+ const osRelease = fs.readFileSync('/proc/sys/kernel/osrelease', 'utf8');
123
+ return /microsoft|wsl/i.test(osRelease);
124
+ }
125
+ catch {
126
+ return false;
127
+ }
128
+ }
129
+ /**
130
+ * Try each browser-opening command in order. Advances to the next fallback on:
131
+ * - Spawn failure (ENOENT / the command not being installed)
132
+ * - Synchronous throw from spawn()
133
+ * - Runtime failure where the command spawns but exits with a non-zero
134
+ * code (e.g. wslview when WSL interop is disabled, xdg-open when no
135
+ * default browser is registered, cmd.exe failing to launch start)
136
+ * - Process terminated by signal
137
+ *
138
+ * Stays on the current command when:
139
+ * - Process exits with code 0 (success)
140
+ * - Process is still running after 3 seconds (assumed success — opener
141
+ * is doing real work like launching a slow app, not hung)
142
+ *
143
+ * If all attempts exhaust, logs at debug level — the user still has the
144
+ * sign-in URL printed to stdout as a copy-paste fallback.
145
+ */
146
+ tryBrowserCommand(attempts, url, index) {
147
+ if (index >= attempts.length) {
148
+ logger_1.logger.debug('[AuthService] No browser-opening command succeeded. ' +
149
+ 'User must open the sign-in URL manually (printed to stdout above).');
150
+ return;
151
+ }
152
+ const attempt = attempts[index];
153
+ const args = [...attempt.fixedArgs, url];
154
+ let settled = false;
155
+ // Helper to advance exactly once — guards against both 'error' and 'exit'
156
+ // events firing for the same child, or the timeout racing with an event.
157
+ const advance = (reason) => {
158
+ if (settled)
159
+ return;
160
+ settled = true;
161
+ logger_1.logger.debug(`[AuthService] Browser command '${attempt.cmd}' ${reason}; trying next fallback`);
162
+ this.tryBrowserCommand(attempts, url, index + 1);
163
+ };
164
+ // Helper to mark this attempt as successful so no future event handlers
165
+ // fire tryBrowserCommand on the next index.
166
+ const stopTrying = (reason) => {
167
+ if (settled)
168
+ return;
169
+ settled = true;
170
+ logger_1.logger.debug(`[AuthService] Browser command '${attempt.cmd}' ${reason}`);
171
+ };
172
+ let child;
173
+ try {
174
+ child = (0, child_process_1.spawn)(attempt.cmd, args, {
175
+ detached: true,
176
+ stdio: 'ignore',
177
+ });
178
+ }
179
+ catch (err) {
180
+ advance(`threw synchronously: ${err?.message || err}`);
181
+ return;
182
+ }
183
+ // Fires when the OS cannot spawn the process at all (most commonly ENOENT
184
+ // for "command not found"). The process never actually ran.
185
+ child.on('error', (err) => {
186
+ advance(`failed to spawn: ${err?.message || err}`);
187
+ });
188
+ // Fires after the spawned process exits. code === 0 is success (opener
189
+ // delegated cleanly and returned). Non-zero code or a signal means the
190
+ // opener failed at runtime — we fall through to the next fallback.
191
+ child.on('exit', (code, signal) => {
192
+ if (code === 0) {
193
+ stopTrying('exited successfully');
194
+ }
195
+ else if (signal) {
196
+ advance(`terminated by signal ${signal}`);
197
+ }
198
+ else {
199
+ advance(`exited with code ${code}`);
200
+ }
201
+ });
202
+ // If the opener is still running after 3 seconds, it is almost certainly
203
+ // doing real work (launching a slow browser, waiting for Windows interop)
204
+ // rather than hung. Stop trying more fallbacks so we don't spawn multiple
205
+ // browsers. The child keeps running independently because detached:true.
206
+ const timer = setTimeout(() => {
207
+ stopTrying('still running after 3s, assuming success');
208
+ }, 3000);
209
+ // Don't let the timer itself keep the Node event loop alive.
210
+ timer.unref();
211
+ // Detach the child from the parent's event loop so Node doesn't block
212
+ // on its exit. Exit handler still fires if/when the child actually exits.
213
+ child.unref();
68
214
  }
69
215
  /**
70
216
  * Generate state for CSRF protection
@@ -98,11 +244,11 @@ class AuthService {
98
244
  code: code,
99
245
  redirect_uri: REDIRECT_URI,
100
246
  });
101
- const response = await fetch(tokenUrl, {
247
+ const response = await (0, fetch_helpers_1.fetchWithDiagnostics)(tokenUrl, {
102
248
  method: 'POST',
103
249
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
104
250
  body: params.toString(),
105
- });
251
+ }, 'Token exchange');
106
252
  if (!response.ok) {
107
253
  const errorText = await response.text();
108
254
  throw new Error(`Token exchange failed: ${response.status} ${errorText}`);
@@ -135,11 +281,11 @@ class AuthService {
135
281
  client_id: config.aws.cognitoClientId,
136
282
  refresh_token: refreshToken,
137
283
  });
138
- const response = await fetch(tokenUrl, {
284
+ const response = await (0, fetch_helpers_1.fetchWithDiagnostics)(tokenUrl, {
139
285
  method: 'POST',
140
286
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
141
287
  body: params.toString(),
142
- });
288
+ }, 'Token refresh');
143
289
  if (!response.ok) {
144
290
  throw new Error(`Token refresh failed: ${response.status}`);
145
291
  }
@@ -209,14 +355,22 @@ class AuthService {
209
355
  }, 500);
210
356
  }
211
357
  catch (err) {
358
+ // HTML-escape the error message so newlines and special chars
359
+ // render safely. Multi-line diagnostic messages (from
360
+ // fetchWithDiagnostics) need <pre> to preserve formatting.
361
+ const safeMessage = String(err?.message || err)
362
+ .replace(/&/g, '&amp;')
363
+ .replace(/</g, '&lt;')
364
+ .replace(/>/g, '&gt;');
212
365
  res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
213
366
  res.end(`
214
367
  <!DOCTYPE html>
215
368
  <html>
216
369
  <head><title>Error</title></head>
217
- <body style="font-family: system-ui; max-width: 600px; margin: 50px auto; text-align: center;">
218
- <h1 style="color: #ef4444;">&#10007; Authentication Failed</h1>
219
- <p>${err.message}</p>
370
+ <body style="font-family: system-ui; max-width: 720px; margin: 50px auto; padding: 0 16px;">
371
+ <h1 style="color: #ef4444; text-align: center;">&#10007; Authentication Failed</h1>
372
+ <pre style="background: #f4f4f5; padding: 16px; border-radius: 8px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 1.5;">${safeMessage}</pre>
373
+ <p style="text-align: center; color: #71717a; margin-top: 24px;">You can close this window and try again in your terminal.</p>
220
374
  </body>
221
375
  </html>
222
376
  `);
@@ -307,4 +461,4 @@ class AuthService {
307
461
  }
308
462
  exports.AuthService = AuthService;
309
463
  exports.authService = AuthService.getInstance();
310
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F1dGgvYXV0aC1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxFQUFFO0FBQ0Ysa0JBQWtCO0FBQ2xCLGdCQUFnQjtBQUNoQixFQUFFO0FBQ0YsK0JBQStCO0FBQy9CLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVGLCtDQUFpQztBQUNqQywyQ0FBNkI7QUFDN0IsaURBQXNDO0FBQ3RDLHNDQUFzRDtBQUN0RCwwQ0FBOEM7QUFDOUMsc0NBQW1DO0FBR25DLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQztBQUMzQixNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUM7QUFDbEMsTUFBTSxZQUFZLEdBQUcsb0JBQW9CLGFBQWEsR0FBRyxhQUFhLEVBQUUsQ0FBQztBQUV6RTs7R0FFRztBQUNILE1BQWEsV0FBVztJQUd0QixnQkFBdUIsQ0FBQztJQUV4QixNQUFNLENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDO0lBQzlCLENBQUM7SUFFRDs7T0FFRztJQUNLLFdBQVcsQ0FBQyxHQUFXO1FBQzdCLElBQUEscUJBQUssRUFBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDcEUsQ0FBQztJQUVEOztPQUVHO0lBQ0ssYUFBYTtRQUNuQixPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFRDs7T0FF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LEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDcEMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztZQUNoQixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsU0FBUztRQUNiLE1BQU0sTUFBTSxHQUFHLE1BQU0sMEJBQWUsQ0FBQyxTQUFTLENBQUMsSUFBQSx1QkFBYyxHQUFFLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ2xDLENBQUM7UUFFRCxPQUFPO1lBQ0wsYUFBYSxFQUFFLENBQUMsMEJBQWUsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDO1lBQ3RELE1BQU07U0FDUCxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBeFRELGtDQXdUQztBQUVZLFFBQUEsV0FBVyxHQUFHLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vXG4vLyBhdXRoLXNlcnZpY2UudHNcbi8vIENvZGVWaWJlIENvcmVcbi8vXG4vLyBPQXV0aCBhdXRoZW50aWNhdGlvbiBzZXJ2aWNlXG4vL1xuXG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCAqIGFzIGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgeyBzcGF3biB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgZ2V0Q29uZmlnLCBnZXRFbnZpcm9ubWVudCB9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgeyBrZXljaGFpbk1hbmFnZXIgfSBmcm9tICcuLi9rZXljaGFpbic7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IHsgVG9rZW5EYXRhIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5jb25zdCBDQUxMQkFDS19QT1JUID0gODA4MDtcbmNvbnN0IENBTExCQUNLX1BBVEggPSAnL2NhbGxiYWNrJztcbmNvbnN0IFJFRElSRUNUX1VSSSA9IGBodHRwOi8vbG9jYWxob3N0OiR7Q0FMTEJBQ0tfUE9SVH0ke0NBTExCQUNLX1BBVEh9YDtcblxuLyoqXG4gKiBBdXRoZW50aWNhdGlvbiBzZXJ2aWNlIGZvciBPQXV0aCBmbG93c1xuICovXG5leHBvcnQgY2xhc3MgQXV0aFNlcnZpY2Uge1xuICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogQXV0aFNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgc3RhdGljIGdldEluc3RhbmNlKCk6IEF1dGhTZXJ2aWNlIHtcbiAgICBpZiAoIUF1dGhTZXJ2aWNlLmluc3RhbmNlKSB7XG4gICAgICBBdXRoU2VydmljZS5pbnN0YW5jZSA9IG5ldyBBdXRoU2VydmljZSgpO1xuICAgIH1cbiAgICByZXR1cm4gQXV0aFNlcnZpY2UuaW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogT3BlbiBVUkwgaW4gZGVmYXVsdCBicm93c2VyXG4gICAqL1xuICBwcml2YXRlIG9wZW5Ccm93c2VyKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgc3Bhd24oJ29wZW4nLCBbdXJsXSwgeyBkZXRhY2hlZDogdHJ1ZSwgc3RkaW86ICdpZ25vcmUnIH0pLnVucmVmKCk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgc3RhdGUgZm9yIENTUkYgcHJvdGVjdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVN0YXRlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNyeXB0by5yYW5kb21CeXRlcygzMikudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGF1dGhvcml6YXRpb24gVVJMXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkQXV0aFVybChzdGF0ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGNsaWVudF9pZDogY29uZmlnLmF3cy5jb2duaXRvQ2xpZW50SWQsXG4gICAgICByZXNwb25zZV90eXBlOiAnY29kZScsXG4gICAgICBzY29wZTogJ2VtYWlsIG9wZW5pZCBwcm9maWxlJyxcbiAgICAgIHJlZGlyZWN0X3VyaTogUkVESVJFQ1RfVVJJLFxuICAgICAgc3RhdGU6IHN0YXRlLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGBodHRwczovLyR7Y29uZmlnLmF3cy5jb2duaXRvRG9tYWlufS9vYXV0aDIvYXV0aG9yaXplPyR7cGFyYW1zLnRvU3RyaW5nKCl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGNoYW5nZSBhdXRob3JpemF0aW9uIGNvZGUgZm9yIHRva2Vuc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGNoYW5nZUNvZGVGb3JUb2tlbnMoY29kZTogc3RyaW5nKTogUHJvbWlzZTx7XG4gICAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgICBpZFRva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gICAgZXhwaXJlc0luOiBudW1iZXI7XG4gIH0+IHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCB0b2tlblVybCA9IGBodHRwczovLyR7Y29uZmlnLmF3cy5jb2duaXRvRG9tYWlufS9vYXV0aDIvdG9rZW5gO1xuXG4gICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XG4gICAgICBncmFudF90eXBlOiAnYXV0aG9yaXphdGlvbl9jb2RlJyxcbiAgICAgIGNsaWVudF9pZDogY29uZmlnLmF3cy5jb2duaXRvQ2xpZW50SWQsXG4gICAgICBjb2RlOiBjb2RlLFxuICAgICAgcmVkaXJlY3RfdXJpOiBSRURJUkVDVF9VUkksXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRva2VuVXJsLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnIH0sXG4gICAgICBib2R5OiBwYXJhbXMudG9TdHJpbmcoKSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IGVycm9yVGV4dCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gZXhjaGFuZ2UgZmFpbGVkOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtlcnJvclRleHR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyB7XG4gICAgICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgICAgIGlkX3Rva2VuOiBzdHJpbmc7XG4gICAgICByZWZyZXNoX3Rva2VuOiBzdHJpbmc7XG4gICAgICBleHBpcmVzX2luOiBudW1iZXI7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICBpZFRva2VuOiBkYXRhLmlkX3Rva2VuLFxuICAgICAgcmVmcmVzaFRva2VuOiBkYXRhLnJlZnJlc2hfdG9rZW4sXG4gICAgICBleHBpcmVzSW46IGRhdGEuZXhwaXJlc19pbixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERlY29kZSBKV1QgcGF5bG9hZFxuICAgKi9cbiAgcHJpdmF0ZSBkZWNvZGVKd3QodG9rZW46IHN0cmluZyk6IGFueSB7XG4gICAgY29uc3QgcGFydHMgPSB0b2tlbi5zcGxpdCgnLicpO1xuICAgIGlmIChwYXJ0cy5sZW5ndGggIT09IDMpIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBKV1QnKTtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShCdWZmZXIuZnJvbShwYXJ0c1sxXSwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCd1dGYtOCcpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWZyZXNoIHRva2Vuc1xuICAgKi9cbiAgYXN5bmMgcmVmcmVzaFRva2VucyhyZWZyZXNoVG9rZW46IHN0cmluZyk6IFByb21pc2U8e1xuICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gICAgaWRUb2tlbjogc3RyaW5nO1xuICAgIGV4cGlyZXNJbjogbnVtYmVyO1xuICB9PiB7XG4gICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gICAgY29uc3QgdG9rZW5VcmwgPSBgaHR0cHM6Ly8ke2NvbmZpZy5hd3MuY29nbml0b0RvbWFpbn0vb2F1dGgyL3Rva2VuYDtcblxuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgZ3JhbnRfdHlwZTogJ3JlZnJlc2hfdG9rZW4nLFxuICAgICAgY2xpZW50X2lkOiBjb25maWcuYXdzLmNvZ25pdG9DbGllbnRJZCxcbiAgICAgIHJlZnJlc2hfdG9rZW46IHJlZnJlc2hUb2tlbixcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godG9rZW5VcmwsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgfSxcbiAgICAgIGJvZHk6IHBhcmFtcy50b1N0cmluZygpLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUb2tlbiByZWZyZXNoIGZhaWxlZDogJHtyZXNwb25zZS5zdGF0dXN9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyB7XG4gICAgICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgICAgIGlkX3Rva2VuOiBzdHJpbmc7XG4gICAgICBleHBpcmVzX2luOiBudW1iZXI7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICBpZFRva2VuOiBkYXRhLmlkX3Rva2VuLFxuICAgICAgZXhwaXJlc0luOiBkYXRhLmV4cGlyZXNfaW4sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dpbiB2aWEgT0F1dGggYnJvd3NlciBmbG93XG4gICAqL1xuICBhc3luYyBsb2dpbigpOiBQcm9taXNlPFRva2VuRGF0YSB8IG51bGw+IHtcbiAgICAvLyBDaGVjayBpZiBhbHJlYWR5IGxvZ2dlZCBpblxuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLmdldFRva2VucyhnZXRFbnZpcm9ubWVudCgpKTtcbiAgICBpZiAoZXhpc3RpbmcgJiYgIWtleWNoYWluTWFuYWdlci5pc1Rva2VuRXhwaXJlZChleGlzdGluZykpIHtcbiAgICAgIHJldHVybiBleGlzdGluZztcbiAgICB9XG5cbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2VuZXJhdGVTdGF0ZSgpO1xuICAgIGNvbnN0IGF1dGhVcmwgPSB0aGlzLmJ1aWxkQXV0aFVybChzdGF0ZSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgICAgIGlmICghcmVxLnVybD8uc3RhcnRzV2l0aChDQUxMQkFDS19QQVRIKSkge1xuICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICByZXMuZW5kKCdOb3QgZm91bmQnKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybCwgYGh0dHA6Ly9sb2NhbGhvc3Q6JHtDQUxMQkFDS19QT1JUfWApO1xuICAgICAgICAgIGNvbnN0IGNvZGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnY29kZScpO1xuICAgICAgICAgIGNvbnN0IHJldHVybmVkU3RhdGUgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc3RhdGUnKTtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdlcnJvcicpO1xuXG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE9BdXRoIGVycm9yOiAke2Vycm9yfWApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChyZXR1cm5lZFN0YXRlICE9PSBzdGF0ZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTdGF0ZSBtaXNtYXRjaCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghY29kZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhdXRob3JpemF0aW9uIGNvZGUnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCB0aGlzLmV4Y2hhbmdlQ29kZUZvclRva2Vucyhjb2RlKTtcbiAgICAgICAgICBjb25zdCBpZFBheWxvYWQgPSB0aGlzLmRlY29kZUp3dCh0b2tlbnMuaWRUb2tlbik7XG5cbiAgICAgICAgICBjb25zdCB0b2tlbkRhdGE6IFRva2VuRGF0YSA9IHtcbiAgICAgICAgICAgIGFjY2Vzc1Rva2VuOiB0b2tlbnMuYWNjZXNzVG9rZW4sXG4gICAgICAgICAgICBpZFRva2VuOiB0b2tlbnMuaWRUb2tlbixcbiAgICAgICAgICAgIHJlZnJlc2hUb2tlbjogdG9rZW5zLnJlZnJlc2hUb2tlbixcbiAgICAgICAgICAgIGV4cGlyZXNBdDogRGF0ZS5ub3coKSArICh0b2tlbnMuZXhwaXJlc0luICogMTAwMCksXG4gICAgICAgICAgICB1c2VySWQ6IGlkUGF5bG9hZC5zdWIsXG4gICAgICAgICAgICBlbWFpbDogaWRQYXlsb2FkLmVtYWlsIHx8ICd1bmtub3duJyxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLnNldFRva2Vucyh0b2tlbkRhdGEsIGdldEVudmlyb25tZW50KCkpO1xuXG4gICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDAsIHsgJ0NvbnRlbnQtVHlwZSc6ICd0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgnIH0pO1xuICAgICAgICAgIHJlcy5lbmQoYFxuICAgICAgICAgICAgPCFET0NUWVBFIGh0bWw+XG4gICAgICAgICAgICA8aHRtbD5cbiAgICAgICAgICAgIDxoZWFkPjx0aXRsZT5TdWNjZXNzPC90aXRsZT48L2hlYWQ+XG4gICAgICAgICAgICA8Ym9keSBzdHlsZT1cImZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7IG1heC13aWR0aDogNjAwcHg7IG1hcmdpbjogNTBweCBhdXRvOyB0ZXh0LWFsaWduOiBjZW50ZXI7XCI+XG4gICAgICAgICAgICAgIDxoMSBzdHlsZT1cImNvbG9yOiAjMjJjNTVlO1wiPiYjMTAwMDM7IEF1dGhlbnRpY2F0aW9uIFN1Y2Nlc3NmdWw8L2gxPlxuICAgICAgICAgICAgICA8cD5Zb3UgY2FuIGNsb3NlIHRoaXMgd2luZG93LjwvcD5cbiAgICAgICAgICAgIDwvYm9keT5cbiAgICAgICAgICAgIDwvaHRtbD5cbiAgICAgICAgICBgKTtcblxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgc2VydmVyLmNsb3NlKCgpID0+IHJlc29sdmUodG9rZW5EYXRhKSk7XG4gICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICByZXMud3JpdGVIZWFkKDQwMCwgeyAnQ29udGVudC1UeXBlJzogJ3RleHQvaHRtbDsgY2hhcnNldD11dGYtOCcgfSk7XG4gICAgICAgICAgcmVzLmVuZChgXG4gICAgICAgICAgICA8IURPQ1RZUEUgaHRtbD5cbiAgICAgICAgICAgIDxodG1sPlxuICAgICAgICAgICAgPGhlYWQ+PHRpdGxlPkVycm9yPC90aXRsZT48L2hlYWQ+XG4gICAgICAgICAgICA8Ym9keSBzdHlsZT1cImZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7IG1heC13aWR0aDogNjAwcHg7IG1hcmdpbjogNTBweCBhdXRvOyB0ZXh0LWFsaWduOiBjZW50ZXI7XCI+XG4gICAgICAgICAgICAgIDxoMSBzdHlsZT1cImNvbG9yOiAjZWY0NDQ0O1wiPiYjMTAwMDc7IEF1dGhlbnRpY2F0aW9uIEZhaWxlZDwvaDE+XG4gICAgICAgICAgICAgIDxwPiR7ZXJyLm1lc3NhZ2V9PC9wPlxuICAgICAgICAgICAgPC9ib2R5PlxuICAgICAgICAgICAgPC9odG1sPlxuICAgICAgICAgIGApO1xuXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKCkgPT4gcmVqZWN0KGVycikpO1xuICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIub24oJ2Vycm9yJywgKGVycjogYW55KSA9PiB7XG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gJ0VBRERSSU5VU0UnKSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgUG9ydCAke0NBTExCQUNLX1BPUlR9IGlzIGluIHVzZWApKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5saXN0ZW4oQ0FMTEJBQ0tfUE9SVCwgJ2xvY2FsaG9zdCcsICgpID0+IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1tBdXRoU2VydmljZV0gQ2FsbGJhY2sgc2VydmVyIHN0YXJ0ZWQnKTtcbiAgICAgICAgdGhpcy5vcGVuQnJvd3NlcihhdXRoVXJsKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBUaW1lb3V0XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgc2VydmVyLmNsb3NlKCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0xvZ2luIHRpbWVvdXQnKSkpO1xuICAgICAgfSwgMiAqIDYwICogMTAwMCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9nb3V0XG4gICAqL1xuICBhc3luYyBsb2dvdXQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gICAgY29uc3QgZGVsZXRlZCA9IGF3YWl0IGtleWNoYWluTWFuYWdlci5kZWxldGVUb2tlbnMoZ2V0RW52aXJvbm1lbnQoKSk7XG5cbiAgICBpZiAoZGVsZXRlZCkge1xuICAgICAgLy8gU3RhcnQgdGVtcG9yYXJ5IHNlcnZlciB0byBoYW5kbGUgc2lnbm91dCBjYWxsYmFja1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKChyZXEsIHJlcykgPT4ge1xuICAgICAgICAgIGlmIChyZXEudXJsPy5zdGFydHNXaXRoKCcvc2lnbm91dCcpKSB7XG4gICAgICAgICAgICByZXMud3JpdGVIZWFkKDIwMCwgeyAnQ29udGVudC1UeXBlJzogJ3RleHQvaHRtbDsgY2hhcnNldD11dGYtOCcgfSk7XG4gICAgICAgICAgICByZXMuZW5kKGBcbiAgICAgICAgICAgICAgPCFET0NUWVBFIGh0bWw+XG4gICAgICAgICAgICAgIDxodG1sPlxuICAgICAgICAgICAgICA8aGVhZD48dGl0bGU+U2lnbmVkIE91dDwvdGl0bGU+PC9oZWFkPlxuICAgICAgICAgICAgICA8Ym9keSBzdHlsZT1cImZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7IG1heC13aWR0aDogNjAwcHg7IG1hcmdpbjogNTBweCBhdXRvOyB0ZXh0LWFsaWduOiBjZW50ZXI7XCI+XG4gICAgICAgICAgICAgICAgPGgxIHN0eWxlPVwiY29sb3I6ICMyMmM1NWU7XCI+JiMxMDAwMzsgU2lnbmVkIE91dDwvaDE+XG4gICAgICAgICAgICAgICAgPHA+WW91IGNhbiBjbG9zZSB0aGlzIHdpbmRvdy48L3A+XG4gICAgICAgICAgICAgIDwvYm9keT5cbiAgICAgICAgICAgICAgPC9odG1sPlxuICAgICAgICAgICAgYCk7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKCkgPT4gcmVzb2x2ZSh0cnVlKSk7XG4gICAgICAgICAgICB9LCA1MDApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXMud3JpdGVIZWFkKDQwNCk7XG4gICAgICAgICAgICByZXMuZW5kKCdOb3QgZm91bmQnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNlcnZlci5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZSh0cnVlKTsgLy8gU3RpbGwgcmV0dXJuIHRydWUgc2luY2UgdG9rZW5zIHdlcmUgZGVsZXRlZFxuICAgICAgICB9KTtcblxuICAgICAgICBzZXJ2ZXIubGlzdGVuKENBTExCQUNLX1BPUlQsICdsb2NhbGhvc3QnLCAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgbG9nb3V0VXJsID0gYGh0dHBzOi8vJHtjb25maWcuYXdzLmNvZ25pdG9Eb21haW59L2xvZ291dD9gICtcbiAgICAgICAgICAgIGBjbGllbnRfaWQ9JHtjb25maWcuYXdzLmNvZ25pdG9DbGllbnRJZH0mYCArXG4gICAgICAgICAgICBgbG9nb3V0X3VyaT0ke2VuY29kZVVSSUNvbXBvbmVudChSRURJUkVDVF9VUkkucmVwbGFjZSgnL2NhbGxiYWNrJywgJy9zaWdub3V0JykpfWA7XG5cbiAgICAgICAgICB0aGlzLm9wZW5Ccm93c2VyKGxvZ291dFVybCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRpbWVvdXQgYWZ0ZXIgMzAgc2Vjb25kc1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKCkgPT4gcmVzb2x2ZSh0cnVlKSk7XG4gICAgICAgIH0sIDMwICogMTAwMCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVsZXRlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBhdXRoIHN0YXR1c1xuICAgKi9cbiAgYXN5bmMgZ2V0U3RhdHVzKCk6IFByb21pc2U8eyBhdXRoZW50aWNhdGVkOiBib29sZWFuOyB0b2tlbnM/OiBUb2tlbkRhdGEgfT4ge1xuICAgIGNvbnN0IHRva2VucyA9IGF3YWl0IGtleWNoYWluTWFuYWdlci5nZXRUb2tlbnMoZ2V0RW52aXJvbm1lbnQoKSk7XG4gICAgaWYgKCF0b2tlbnMpIHtcbiAgICAgIHJldHVybiB7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGF1dGhlbnRpY2F0ZWQ6ICFrZXljaGFpbk1hbmFnZXIuaXNUb2tlbkV4cGlyZWQodG9rZW5zKSxcbiAgICAgIHRva2VucyxcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBhdXRoU2VydmljZSA9IEF1dGhTZXJ2aWNlLmdldEluc3RhbmNlKCk7XG4iXX0=
464
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F1dGgvYXV0aC1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxFQUFFO0FBQ0Ysa0JBQWtCO0FBQ2xCLGdCQUFnQjtBQUNoQixFQUFFO0FBQ0YsK0JBQStCO0FBQy9CLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVGLCtDQUFpQztBQUNqQyx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLGlEQUFzQztBQUN0QyxzQ0FBc0Q7QUFDdEQsMENBQThDO0FBQzlDLHNDQUFtQztBQUVuQyxtREFBdUQ7QUFFdkQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDO0FBQzNCLE1BQU0sYUFBYSxHQUFHLFdBQVcsQ0FBQztBQUNsQyxNQUFNLFlBQVksR0FBRyxvQkFBb0IsYUFBYSxHQUFHLGFBQWEsRUFBRSxDQUFDO0FBRXpFOztHQUVHO0FBQ0gsTUFBYSxXQUFXO0lBR3RCLGdCQUF1QixDQUFDO0lBRXhCLE1BQU0sQ0FBQyxXQUFXO1FBQ2hCLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDMUIsV0FBVyxDQUFDLFFBQVEsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO1FBQzNDLENBQUM7UUFDRCxPQUFPLFdBQVcsQ0FBQyxRQUFRLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxXQUFXLENBQUMsR0FBVztRQUM3QixrRUFBa0U7UUFDbEUsdUVBQXVFO1FBQ3ZFLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsdUVBQXVFLENBQUMsQ0FBQztRQUNyRixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN4QixPQUFP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Q0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNwQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ2hCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxTQUFTO1FBQ2IsTUFBTSxNQUFNLEdBQUcsTUFBTSwwQkFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFBLHVCQUFjLEdBQUUsQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU8sRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDbEMsQ0FBQztRQUVELE9BQU87WUFDTCxhQUFhLEVBQUUsQ0FBQywwQkFBZSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7WUFDdEQsTUFBTTtTQUNQLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUE1ZUQsa0NBNGVDO0FBRVksUUFBQSxXQUFXLEdBQUcsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy9cbi8vIGF1dGgtc2VydmljZS50c1xuLy8gQ29kZVZpYmUgQ29yZVxuLy9cbi8vIE9BdXRoIGF1dGhlbnRpY2F0aW9uIHNlcnZpY2Vcbi8vXG5cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgaHR0cCBmcm9tICdodHRwJztcbmltcG9ydCB7IHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyBnZXRDb25maWcsIGdldEVudmlyb25tZW50IH0gZnJvbSAnLi4vY29uZmlnJztcbmltcG9ydCB7IGtleWNoYWluTWFuYWdlciB9IGZyb20gJy4uL2tleWNoYWluJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgeyBUb2tlbkRhdGEgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBmZXRjaFdpdGhEaWFnbm9zdGljcyB9IGZyb20gJy4vZmV0Y2gtaGVscGVycyc7XG5cbmNvbnN0IENBTExCQUNLX1BPUlQgPSA4MDgwO1xuY29uc3QgQ0FMTEJBQ0tfUEFUSCA9ICcvY2FsbGJhY2snO1xuY29uc3QgUkVESVJFQ1RfVVJJID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtDQUxMQkFDS19QT1JUfSR7Q0FMTEJBQ0tfUEFUSH1gO1xuXG4vKipcbiAqIEF1dGhlbnRpY2F0aW9uIHNlcnZpY2UgZm9yIE9BdXRoIGZsb3dzXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoU2VydmljZSB7XG4gIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBBdXRoU2VydmljZTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogQXV0aFNlcnZpY2Uge1xuICAgIGlmICghQXV0aFNlcnZpY2UuaW5zdGFuY2UpIHtcbiAgICAgIEF1dGhTZXJ2aWNlLmluc3RhbmNlID0gbmV3IEF1dGhTZXJ2aWNlKCk7XG4gICAgfVxuICAgIHJldHVybiBBdXRoU2VydmljZS5pbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIFVSTCBpbiB0aGUgdXNlcidzIGRlZmF1bHQgYnJvd3Nlci4gQ3Jvc3MtcGxhdGZvcm06IG1hY09TLCBMaW51eCxcbiAgICogV1NMLCBXaW5kb3dzLiBBbHdheXMgcHJpbnRzIHRoZSBVUkwgdG8gc3Rkb3V0IGZpcnN0IGFzIGEgZmFsbGJhY2sg4oCUXG4gICAqIGlmIG5vIGJyb3dzZXItb3BlbmluZyBjb21tYW5kIGlzIGF2YWlsYWJsZSwgdGhlIHVzZXIgY2FuIGNvcHktcGFzdGUuXG4gICAqXG4gICAqIE9uIFdTTCwgcHJlZmVycyBvcGVuaW5nIHRoZSBXaW5kb3dzIGhvc3QgYnJvd3NlciB2aWEgV1NMIGludGVyb3BcbiAgICogKHdzbHZpZXcg4oaSIGNtZC5leGUg4oaSIHBvd2Vyc2hlbGwuZXhlKSBiZWZvcmUgZmFsbGluZyBiYWNrIHRvIHhkZy1vcGVuLlxuICAgKi9cbiAgcHJpdmF0ZSBvcGVuQnJvd3Nlcih1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIC8vIEFsd2F5cyBwcmludCB0aGUgVVJMIGZpcnN0IHNvIHVzZXJzIGNhbiBjb3B5LXBhc3RlIGlmIGF1dG9tYXRpY1xuICAgIC8vIGJyb3dzZXItb3BlbmluZyBmYWlscyAoZXNwZWNpYWxseSBpbXBvcnRhbnQgb24gaGVhZGxlc3MgV1NMIHNldHVwcykuXG4gICAgY29uc29sZS5sb2coJycpO1xuICAgIGNvbnNvbGUubG9nKCdPcGVuaW5nIHlvdXIgYnJvd3NlciBmb3Igc2lnbi1pbi4uLicpO1xuICAgIGNvbnNvbGUubG9nKCdJZiB5b3VyIGJyb3dzZXIgZG9lcyBub3Qgb3BlbiBhdXRvbWF0aWNhbGx5LCB2aXNpdCB0aGlzIFVSTCBtYW51YWxseTonKTtcbiAgICBjb25zb2xlLmxvZyhgICAke3VybH1gKTtcbiAgICBjb25zb2xlLmxvZygnJyk7XG5cbiAgICBjb25zdCBhdHRlbXB0cyA9IHRoaXMuZ2V0QnJvd3NlckNvbW1hbmRzKCk7XG4gICAgdGhpcy50cnlCcm93c2VyQ29tbWFuZChhdHRlbXB0cywgdXJsLCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsaXN0IG9mIGJyb3dzZXItb3BlbmluZyBjb21tYW5kcyB0byB0cnkgaW4gb3JkZXIsIGJhc2VkIG9uXG4gICAqIHRoZSBjdXJyZW50IHBsYXRmb3JtLiBPbiBXU0wsIHJldHVybnMgV1NMIGludGVyb3AgY29tbWFuZHMgZmlyc3Qgc28gdGhlXG4gICAqIFdpbmRvd3MgYnJvd3NlciBvcGVucyAod2hpY2ggaXMgd2hhdCB1c2VycyBhY3R1YWxseSB3YW50IG9uIFdTTCkuXG4gICAqL1xuICBwcml2YXRlIGdldEJyb3dzZXJDb21tYW5kcygpOiBBcnJheTx7IGNtZDogc3RyaW5nOyBmaXhlZEFyZ3M6IHN0cmluZ1tdIH0+IHtcbiAgICBjb25zdCBwbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0gPT09ICdkYXJ3aW4nKSB7XG4gICAgICByZXR1cm4gW3sgY21kOiAnb3BlbicsIGZpeGVkQXJnczogW10gfV07XG4gICAgfVxuXG4gICAgaWYgKHBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgICAvLyBjbWQncyBzdGFydCBuZWVkcyBhbiBlbXB0eSB0aXRsZSBhcyB0aGUgZmlyc3QgYXJnIHNvIHRoYXQgVVJMc1xuICAgICAgLy8gY29udGFpbmluZyBzcGVjaWFsIGNoYXJhY3RlcnMgYXJlbid0IG1pc2ludGVycHJldGVkIGFzIHRoZSB0aXRsZS5cbiAgICAgIHJldHVybiBbeyBjbWQ6ICdjbWQnLCBmaXhlZEFyZ3M6IFsnL2MnLCAnc3RhcnQnLCAnJ10gfV07XG4gICAgfVxuXG4gICAgLy8gTGludXggb3IgV1NMXG4gICAgY29uc3QgYXR0ZW1wdHM6IEFycmF5PHsgY21kOiBzdHJpbmc7IGZpeGVkQXJnczogc3RyaW5nW10gfT4gPSBbXTtcblxuICAgIGlmICh0aGlzLmlzUnVubmluZ0luV1NMKCkpIHtcbiAgICAgIC8vIFByZWZlciBvcGVuaW5nIHRoZSBXaW5kb3dzIGhvc3QgYnJvd3NlciB2aWEgV1NMIGludGVyb3AuXG4gICAgICBhdHRlbXB0cy5wdXNoKHsgY21kOiAnd3NsdmlldycsIGZpeGVkQXJnczogW10gfSk7XG4gICAgICBhdHRlbXB0cy5wdXNoKHsgY21kOiAnY21kLmV4ZScsIGZpeGVkQXJnczogWycvYycsICdzdGFydCcsICcnXSB9KTtcbiAgICAgIGF0dGVtcHRzLnB1c2goe1xuICAgICAgICBjbWQ6ICdwb3dlcnNoZWxsLmV4ZScsXG4gICAgICAgIGZpeGVkQXJnczogWyctTm9Qcm9maWxlJywgJy1Db21tYW5kJywgJ1N0YXJ0LVByb2Nlc3MnXSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEZhbGwgYmFjayB0byBnZW5lcmljIExpbnV4IG9wZW5lcnNcbiAgICBhdHRlbXB0cy5wdXNoKHsgY21kOiAneGRnLW9wZW4nLCBmaXhlZEFyZ3M6IFtdIH0pO1xuXG4gICAgcmV0dXJuIGF0dGVtcHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVjdCB3aGV0aGVyIHdlJ3JlIHJ1bm5pbmcgaW5zaWRlIFdTTCAoMSBvciAyKS4gUmV0dXJucyBmYWxzZSBvblxuICAgKiBhbnkgbm9uLUxpbnV4IHBsYXRmb3JtIG9yIGlmIC9wcm9jL3N5cy9rZXJuZWwvb3NyZWxlYXNlIGlzIG5vdCByZWFkYWJsZS5cbiAgICovXG4gIHByaXZhdGUgaXNSdW5uaW5nSW5XU0woKTogYm9vbGVhbiB7XG4gICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gIT09ICdsaW51eCcpIHJldHVybiBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3NSZWxlYXNlID0gZnMucmVhZEZpbGVTeW5jKCcvcHJvYy9zeXMva2VybmVsL29zcmVsZWFzZScsICd1dGY4Jyk7XG4gICAgICByZXR1cm4gL21pY3Jvc29mdHx3c2wvaS50ZXN0KG9zUmVsZWFzZSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyeSBlYWNoIGJyb3dzZXItb3BlbmluZyBjb21tYW5kIGluIG9yZGVyLiBBZHZhbmNlcyB0byB0aGUgbmV4dCBmYWxsYmFjayBvbjpcbiAgICogICAtIFNwYXduIGZhaWx1cmUgKEVOT0VOVCAvIHRoZSBjb21tYW5kIG5vdCBiZWluZyBpbnN0YWxsZWQpXG4gICAqICAgLSBTeW5jaHJvbm91cyB0aHJvdyBmcm9tIHNwYXduKClcbiAgICogICAtIFJ1bnRpbWUgZmFpbHVyZSB3aGVyZSB0aGUgY29tbWFuZCBzcGF3bnMgYnV0IGV4aXRzIHdpdGggYSBub24temVyb1xuICAgKiAgICAgY29kZSAoZS5nLiB3c2x2aWV3IHdoZW4gV1NMIGludGVyb3AgaXMgZGlzYWJsZWQsIHhkZy1vcGVuIHdoZW4gbm9cbiAgICogICAgIGRlZmF1bHQgYnJvd3NlciBpcyByZWdpc3RlcmVkLCBjbWQuZXhlIGZhaWxpbmcgdG8gbGF1bmNoIHN0YXJ0KVxuICAgKiAgIC0gUHJvY2VzcyB0ZXJtaW5hdGVkIGJ5IHNpZ25hbFxuICAgKlxuICAgKiBTdGF5cyBvbiB0aGUgY3VycmVudCBjb21tYW5kIHdoZW46XG4gICAqICAgLSBQcm9jZXNzIGV4aXRzIHdpdGggY29kZSAwIChzdWNjZXNzKVxuICAgKiAgIC0gUHJvY2VzcyBpcyBzdGlsbCBydW5uaW5nIGFmdGVyIDMgc2Vjb25kcyAoYXNzdW1lZCBzdWNjZXNzIOKAlCBvcGVuZXJcbiAgICogICAgIGlzIGRvaW5nIHJlYWwgd29yayBsaWtlIGxhdW5jaGluZyBhIHNsb3cgYXBwLCBub3QgaHVuZylcbiAgICpcbiAgICogSWYgYWxsIGF0dGVtcHRzIGV4aGF1c3QsIGxvZ3MgYXQgZGVidWcgbGV2ZWwg4oCUIHRoZSB1c2VyIHN0aWxsIGhhcyB0aGVcbiAgICogc2lnbi1pbiBVUkwgcHJpbnRlZCB0byBzdGRvdXQgYXMgYSBjb3B5LXBhc3RlIGZhbGxiYWNrLlxuICAgKi9cbiAgcHJpdmF0ZSB0cnlCcm93c2VyQ29tbWFuZChcbiAgICBhdHRlbXB0czogQXJyYXk8eyBjbWQ6IHN0cmluZzsgZml4ZWRBcmdzOiBzdHJpbmdbXSB9PixcbiAgICB1cmw6IHN0cmluZyxcbiAgICBpbmRleDogbnVtYmVyXG4gICk6IHZvaWQge1xuICAgIGlmIChpbmRleCA+PSBhdHRlbXB0cy5sZW5ndGgpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgJ1tBdXRoU2VydmljZV0gTm8gYnJvd3Nlci1vcGVuaW5nIGNvbW1hbmQgc3VjY2VlZGVkLiAnICtcbiAgICAgICAgICAnVXNlciBtdXN0IG9wZW4gdGhlIHNpZ24taW4gVVJMIG1hbnVhbGx5IChwcmludGVkIHRvIHN0ZG91dCBhYm92ZSkuJ1xuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRlbXB0ID0gYXR0ZW1wdHNbaW5kZXhdO1xuICAgIGNvbnN0IGFyZ3MgPSBbLi4uYXR0ZW1wdC5maXhlZEFyZ3MsIHVybF07XG4gICAgbGV0IHNldHRsZWQgPSBmYWxzZTtcblxuICAgIC8vIEhlbHBlciB0byBhZHZhbmNlIGV4YWN0bHkgb25jZSDigJQgZ3VhcmRzIGFnYWluc3QgYm90aCAnZXJyb3InIGFuZCAnZXhpdCdcbiAgICAvLyBldmVudHMgZmlyaW5nIGZvciB0aGUgc2FtZSBjaGlsZCwgb3IgdGhlIHRpbWVvdXQgcmFjaW5nIHdpdGggYW4gZXZlbnQuXG4gICAgY29uc3QgYWR2YW5jZSA9IChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICBgW0F1dGhTZXJ2aWNlXSBCcm93c2VyIGNvbW1hbmQgJyR7YXR0ZW1wdC5jbWR9JyAke3JlYXNvbn07IHRyeWluZyBuZXh0IGZhbGxiYWNrYFxuICAgICAgKTtcbiAgICAgIHRoaXMudHJ5QnJvd3NlckNvbW1hbmQoYXR0ZW1wdHMsIHVybCwgaW5kZXggKyAxKTtcbiAgICB9O1xuXG4gICAgLy8gSGVscGVyIHRvIG1hcmsgdGhpcyBhdHRlbXB0IGFzIHN1Y2Nlc3NmdWwgc28gbm8gZnV0dXJlIGV2ZW50IGhhbmRsZXJzXG4gICAgLy8gZmlyZSB0cnlCcm93c2VyQ29tbWFuZCBvbiB0aGUgbmV4dCBpbmRleC5cbiAgICBjb25zdCBzdG9wVHJ5aW5nID0gKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICBsb2dnZXIuZGVidWcoYFtBdXRoU2VydmljZV0gQnJvd3NlciBjb21tYW5kICcke2F0dGVtcHQuY21kfScgJHtyZWFzb259YCk7XG4gICAgfTtcblxuICAgIGxldCBjaGlsZDtcbiAgICB0cnkge1xuICAgICAgY2hpbGQgPSBzcGF3bihhdHRlbXB0LmNtZCwgYXJncywge1xuICAgICAgICBkZXRhY2hlZDogdHJ1ZSxcbiAgICAgICAgc3RkaW86ICdpZ25vcmUnLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgIGFkdmFuY2UoYHRocmV3IHN5bmNocm9ub3VzbHk6ICR7ZXJyPy5tZXNzYWdlIHx8IGVycn1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGaXJlcyB3aGVuIHRoZSBPUyBjYW5ub3Qgc3Bhd24gdGhlIHByb2Nlc3MgYXQgYWxsIChtb3N0IGNvbW1vbmx5IEVOT0VOVFxuICAgIC8vIGZvciBcImNvbW1hbmQgbm90IGZvdW5kXCIpLiBUaGUgcHJvY2VzcyBuZXZlciBhY3R1YWxseSByYW4uXG4gICAgY2hpbGQub24oJ2Vycm9yJywgKGVycjogYW55KSA9PiB7XG4gICAgICBhZHZhbmNlKGBmYWlsZWQgdG8gc3Bhd246ICR7ZXJyPy5tZXNzYWdlIHx8IGVycn1gKTtcbiAgICB9KTtcblxuICAgIC8vIEZpcmVzIGFmdGVyIHRoZSBzcGF3bmVkIHByb2Nlc3MgZXhpdHMuIGNvZGUgPT09IDAgaXMgc3VjY2VzcyAob3BlbmVyXG4gICAgLy8gZGVsZWdhdGVkIGNsZWFubHkgYW5kIHJldHVybmVkKS4gTm9uLXplcm8gY29kZSBvciBhIHNpZ25hbCBtZWFucyB0aGVcbiAgICAvLyBvcGVuZXIgZmFpbGVkIGF0IHJ1bnRpbWUg4oCUIHdlIGZhbGwgdGhyb3VnaCB0byB0aGUgbmV4dCBmYWxsYmFjay5cbiAgICBjaGlsZC5vbignZXhpdCcsIChjb2RlOiBudW1iZXIgfCBudWxsLCBzaWduYWw6IHN0cmluZyB8IG51bGwpID0+IHtcbiAgICAgIGlmIChjb2RlID09PSAwKSB7XG4gICAgICAgIHN0b3BUcnlpbmcoJ2V4aXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgIH0gZWxzZSBpZiAoc2lnbmFsKSB7XG4gICAgICAgIGFkdmFuY2UoYHRlcm1pbmF0ZWQgYnkgc2lnbmFsICR7c2lnbmFsfWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWR2YW5jZShgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9YCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBJZiB0aGUgb3BlbmVyIGlzIHN0aWxsIHJ1bm5pbmcgYWZ0ZXIgMyBzZWNvbmRzLCBpdCBpcyBhbG1vc3QgY2VydGFpbmx5XG4gICAgLy8gZG9pbmcgcmVhbCB3b3JrIChsYXVuY2hpbmcgYSBzbG93IGJyb3dzZXIsIHdhaXRpbmcgZm9yIFdpbmRvd3MgaW50ZXJvcClcbiAgICAvLyByYXRoZXIgdGhhbiBodW5nLiBTdG9wIHRyeWluZyBtb3JlIGZhbGxiYWNrcyBzbyB3ZSBkb24ndCBzcGF3biBtdWx0aXBsZVxuICAgIC8vIGJyb3dzZXJzLiBUaGUgY2hpbGQga2VlcHMgcnVubmluZyBpbmRlcGVuZGVudGx5IGJlY2F1c2UgZGV0YWNoZWQ6dHJ1ZS5cbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgc3RvcFRyeWluZygnc3RpbGwgcnVubmluZyBhZnRlciAzcywgYXNzdW1pbmcgc3VjY2VzcycpO1xuICAgIH0sIDMwMDApO1xuICAgIC8vIERvbid0IGxldCB0aGUgdGltZXIgaXRzZWxmIGtlZXAgdGhlIE5vZGUgZXZlbnQgbG9vcCBhbGl2ZS5cbiAgICB0aW1lci51bnJlZigpO1xuXG4gICAgLy8gRGV0YWNoIHRoZSBjaGlsZCBmcm9tIHRoZSBwYXJlbnQncyBldmVudCBsb29wIHNvIE5vZGUgZG9lc24ndCBibG9ja1xuICAgIC8vIG9uIGl0cyBleGl0LiBFeGl0IGhhbmRsZXIgc3RpbGwgZmlyZXMgaWYvd2hlbiB0aGUgY2hpbGQgYWN0dWFsbHkgZXhpdHMuXG4gICAgY2hpbGQudW5yZWYoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBzdGF0ZSBmb3IgQ1NSRiBwcm90ZWN0aW9uXG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY3J5cHRvLnJhbmRvbUJ5dGVzKDMyKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYXV0aG9yaXphdGlvbiBVUkxcbiAgICovXG4gIHByaXZhdGUgYnVpbGRBdXRoVXJsKHN0YXRlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbmZpZyA9IGdldENvbmZpZygpO1xuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgY2xpZW50X2lkOiBjb25maWcuYXdzLmNvZ25pdG9DbGllbnRJZCxcbiAgICAgIHJlc3BvbnNlX3R5cGU6ICdjb2RlJyxcbiAgICAgIHNjb3BlOiAnZW1haWwgb3BlbmlkIHByb2ZpbGUnLFxuICAgICAgcmVkaXJlY3RfdXJpOiBSRURJUkVDVF9VUkksXG4gICAgICBzdGF0ZTogc3RhdGUsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gYGh0dHBzOi8vJHtjb25maWcuYXdzLmNvZ25pdG9Eb21haW59L29hdXRoMi9hdXRob3JpemU/JHtwYXJhbXMudG9TdHJpbmcoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4Y2hhbmdlIGF1dGhvcml6YXRpb24gY29kZSBmb3IgdG9rZW5zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGV4Y2hhbmdlQ29kZUZvclRva2Vucyhjb2RlOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICAgIGlkVG9rZW46IHN0cmluZztcbiAgICByZWZyZXNoVG9rZW46IHN0cmluZztcbiAgICBleHBpcmVzSW46IG51bWJlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IGdldENvbmZpZygpO1xuICAgIGNvbnN0IHRva2VuVXJsID0gYGh0dHBzOi8vJHtjb25maWcuYXdzLmNvZ25pdG9Eb21haW59L29hdXRoMi90b2tlbmA7XG5cbiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGdyYW50X3R5cGU6ICdhdXRob3JpemF0aW9uX2NvZGUnLFxuICAgICAgY2xpZW50X2lkOiBjb25maWcuYXdzLmNvZ25pdG9DbGllbnRJZCxcbiAgICAgIGNvZGU6IGNvZGUsXG4gICAgICByZWRpcmVjdF91cmk6IFJFRElSRUNUX1VSSSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hXaXRoRGlhZ25vc3RpY3MoXG4gICAgICB0b2tlblVybCxcbiAgICAgIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnIH0sXG4gICAgICAgIGJvZHk6IHBhcmFtcy50b1N0cmluZygpLFxuICAgICAgfSxcbiAgICAgICdUb2tlbiBleGNoYW5nZSdcbiAgICApO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgY29uc3QgZXJyb3JUZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUb2tlbiBleGNoYW5nZSBmYWlsZWQ6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke2Vycm9yVGV4dH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIHtcbiAgICAgIGFjY2Vzc190b2tlbjogc3RyaW5nO1xuICAgICAgaWRfdG9rZW46IHN0cmluZztcbiAgICAgIHJlZnJlc2hfdG9rZW46IHN0cmluZztcbiAgICAgIGV4cGlyZXNfaW46IG51bWJlcjtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY2Vzc1Rva2VuOiBkYXRhLmFjY2Vzc190b2tlbixcbiAgICAgIGlkVG9rZW46IGRhdGEuaWRfdG9rZW4sXG4gICAgICByZWZyZXNoVG9rZW46IGRhdGEucmVmcmVzaF90b2tlbixcbiAgICAgIGV4cGlyZXNJbjogZGF0YS5leHBpcmVzX2luLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlIEpXVCBwYXlsb2FkXG4gICAqL1xuICBwcml2YXRlIGRlY29kZUp3dCh0b2tlbjogc3RyaW5nKTogYW55IHtcbiAgICBjb25zdCBwYXJ0cyA9IHRva2VuLnNwbGl0KCcuJyk7XG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gMykgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEpXVCcpO1xuICAgIHJldHVybiBKU09OLnBhcnNlKEJ1ZmZlci5mcm9tKHBhcnRzWzFdLCAnYmFzZTY0JykudG9TdHJpbmcoJ3V0Zi04JykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZnJlc2ggdG9rZW5zXG4gICAqL1xuICBhc3luYyByZWZyZXNoVG9rZW5zKHJlZnJlc2hUb2tlbjogc3RyaW5nKTogUHJvbWlzZTx7XG4gICAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgICBpZFRva2VuOiBzdHJpbmc7XG4gICAgZXhwaXJlc0luOiBudW1iZXI7XG4gIH0+IHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCB0b2tlblVybCA9IGBodHRwczovLyR7Y29uZmlnLmF3cy5jb2duaXRvRG9tYWlufS9vYXV0aDIvdG9rZW5gO1xuXG4gICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XG4gICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICBjbGllbnRfaWQ6IGNvbmZpZy5hd3MuY29nbml0b0NsaWVudElkLFxuICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaFdpdGhEaWFnbm9zdGljcyhcbiAgICAgIHRva2VuVXJsLFxuICAgICAge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgfSxcbiAgICAgICAgYm9keTogcGFyYW1zLnRvU3RyaW5nKCksXG4gICAgICB9LFxuICAgICAgJ1Rva2VuIHJlZnJlc2gnXG4gICAgKTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gcmVmcmVzaCBmYWlsZWQ6ICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCkgYXMge1xuICAgICAgYWNjZXNzX3Rva2VuOiBzdHJpbmc7XG4gICAgICBpZF90b2tlbjogc3RyaW5nO1xuICAgICAgZXhwaXJlc19pbjogbnVtYmVyO1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWNjZXNzVG9rZW46IGRhdGEuYWNjZXNzX3Rva2VuLFxuICAgICAgaWRUb2tlbjogZGF0YS5pZF90b2tlbixcbiAgICAgIGV4cGlyZXNJbjogZGF0YS5leHBpcmVzX2luLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogTG9naW4gdmlhIE9BdXRoIGJyb3dzZXIgZmxvd1xuICAgKi9cbiAgYXN5bmMgbG9naW4oKTogUHJvbWlzZTxUb2tlbkRhdGEgfCBudWxsPiB7XG4gICAgLy8gQ2hlY2sgaWYgYWxyZWFkeSBsb2dnZWQgaW5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IGtleWNoYWluTWFuYWdlci5nZXRUb2tlbnMoZ2V0RW52aXJvbm1lbnQoKSk7XG4gICAgaWYgKGV4aXN0aW5nICYmICFrZXljaGFpbk1hbmFnZXIuaXNUb2tlbkV4cGlyZWQoZXhpc3RpbmcpKSB7XG4gICAgICByZXR1cm4gZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLmdlbmVyYXRlU3RhdGUoKTtcbiAgICBjb25zdCBhdXRoVXJsID0gdGhpcy5idWlsZEF1dGhVcmwoc3RhdGUpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgICAgICBpZiAoIXJlcS51cmw/LnN0YXJ0c1dpdGgoQ0FMTEJBQ0tfUEFUSCkpIHtcbiAgICAgICAgICByZXMud3JpdGVIZWFkKDQwNCk7XG4gICAgICAgICAgcmVzLmVuZCgnTm90IGZvdW5kJyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlcS51cmwsIGBodHRwOi8vbG9jYWxob3N0OiR7Q0FMTEJBQ0tfUE9SVH1gKTtcbiAgICAgICAgICBjb25zdCBjb2RlID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ2NvZGUnKTtcbiAgICAgICAgICBjb25zdCByZXR1cm5lZFN0YXRlID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3N0YXRlJyk7XG4gICAgICAgICAgY29uc3QgZXJyb3IgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnZXJyb3InKTtcblxuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBPQXV0aCBlcnJvcjogJHtlcnJvcn1gKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmV0dXJuZWRTdGF0ZSAhPT0gc3RhdGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU3RhdGUgbWlzbWF0Y2gnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWNvZGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYXV0aG9yaXphdGlvbiBjb2RlJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdG9rZW5zID0gYXdhaXQgdGhpcy5leGNoYW5nZUNvZGVGb3JUb2tlbnMoY29kZSk7XG4gICAgICAgICAgY29uc3QgaWRQYXlsb2FkID0gdGhpcy5kZWNvZGVKd3QodG9rZW5zLmlkVG9rZW4pO1xuXG4gICAgICAgICAgY29uc3QgdG9rZW5EYXRhOiBUb2tlbkRhdGEgPSB7XG4gICAgICAgICAgICBhY2Nlc3NUb2tlbjogdG9rZW5zLmFjY2Vzc1Rva2VuLFxuICAgICAgICAgICAgaWRUb2tlbjogdG9rZW5zLmlkVG9rZW4sXG4gICAgICAgICAgICByZWZyZXNoVG9rZW46IHRva2Vucy5yZWZyZXNoVG9rZW4sXG4gICAgICAgICAgICBleHBpcmVzQXQ6IERhdGUubm93KCkgKyAodG9rZW5zLmV4cGlyZXNJbiAqIDEwMDApLFxuICAgICAgICAgICAgdXNlcklkOiBpZFBheWxvYWQuc3ViLFxuICAgICAgICAgICAgZW1haWw6IGlkUGF5bG9hZC5lbWFpbCB8fCAndW5rbm93bicsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGF3YWl0IGtleWNoYWluTWFuYWdlci5zZXRUb2tlbnModG9rZW5EYXRhLCBnZXRFbnZpcm9ubWVudCgpKTtcblxuICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04JyB9KTtcbiAgICAgICAgICByZXMuZW5kKGBcbiAgICAgICAgICAgIDwhRE9DVFlQRSBodG1sPlxuICAgICAgICAgICAgPGh0bWw+XG4gICAgICAgICAgICA8aGVhZD48dGl0bGU+U3VjY2VzczwvdGl0bGU+PC9oZWFkPlxuICAgICAgICAgICAgPGJvZHkgc3R5bGU9XCJmb250LWZhbWlseTogc3lzdGVtLXVpOyBtYXgtd2lkdGg6IDYwMHB4OyBtYXJnaW46IDUwcHggYXV0bzsgdGV4dC1hbGlnbjogY2VudGVyO1wiPlxuICAgICAgICAgICAgICA8aDEgc3R5bGU9XCJjb2xvcjogIzIyYzU1ZTtcIj4mIzEwMDAzOyBBdXRoZW50aWNhdGlvbiBTdWNjZXNzZnVsPC9oMT5cbiAgICAgICAgICAgICAgPHA+WW91IGNhbiBjbG9zZSB0aGlzIHdpbmRvdy48L3A+XG4gICAgICAgICAgICA8L2JvZHk+XG4gICAgICAgICAgICA8L2h0bWw+XG4gICAgICAgICAgYCk7XG5cbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHRva2VuRGF0YSkpO1xuICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgLy8gSFRNTC1lc2NhcGUgdGhlIGVycm9yIG1lc3NhZ2Ugc28gbmV3bGluZXMgYW5kIHNwZWNpYWwgY2hhcnNcbiAgICAgICAgICAvLyByZW5kZXIgc2FmZWx5LiBNdWx0aS1saW5lIGRpYWdub3N0aWMgbWVzc2FnZXMgKGZyb21cbiAgICAgICAgICAvLyBmZXRjaFdpdGhEaWFnbm9zdGljcykgbmVlZCA8cHJlPiB0byBwcmVzZXJ2ZSBmb3JtYXR0aW5nLlxuICAgICAgICAgIGNvbnN0IHNhZmVNZXNzYWdlID0gU3RyaW5nKGVycj8ubWVzc2FnZSB8fCBlcnIpXG4gICAgICAgICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgICAgICAgICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgICAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcblxuICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDAwLCB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04JyB9KTtcbiAgICAgICAgICByZXMuZW5kKGBcbiAgICAgICAgICAgIDwhRE9DVFlQRSBodG1sPlxuICAgICAgICAgICAgPGh0bWw+XG4gICAgICAgICAgICA8aGVhZD48dGl0bGU+RXJyb3I8L3RpdGxlPjwvaGVhZD5cbiAgICAgICAgICAgIDxib2R5IHN0eWxlPVwiZm9udC1mYW1pbHk6IHN5c3RlbS11aTsgbWF4LXdpZHRoOiA3MjBweDsgbWFyZ2luOiA1MHB4IGF1dG87IHBhZGRpbmc6IDAgMTZweDtcIj5cbiAgICAgICAgICAgICAgPGgxIHN0eWxlPVwiY29sb3I6ICNlZjQ0NDQ7IHRleHQtYWxpZ246IGNlbnRlcjtcIj4mIzEwMDA3OyBBdXRoZW50aWNhdGlvbiBGYWlsZWQ8L2gxPlxuICAgICAgICAgICAgICA8cHJlIHN0eWxlPVwiYmFja2dyb3VuZDogI2Y0ZjRmNTsgcGFkZGluZzogMTZweDsgYm9yZGVyLXJhZGl1czogOHB4OyB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7IHdvcmQtd3JhcDogYnJlYWstd29yZDsgZm9udC1zaXplOiAxM3B4OyBsaW5lLWhlaWdodDogMS41O1wiPiR7c2FmZU1lc3NhZ2V9PC9wcmU+XG4gICAgICAgICAgICAgIDxwIHN0eWxlPVwidGV4dC1hbGlnbjogY2VudGVyOyBjb2xvcjogIzcxNzE3YTsgbWFyZ2luLXRvcDogMjRweDtcIj5Zb3UgY2FuIGNsb3NlIHRoaXMgd2luZG93IGFuZCB0cnkgYWdhaW4gaW4geW91ciB0ZXJtaW5hbC48L3A+XG4gICAgICAgICAgICA8L2JvZHk+XG4gICAgICAgICAgICA8L2h0bWw+XG4gICAgICAgICAgYCk7XG5cbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHNlcnZlci5jbG9zZSgoKSA9PiByZWplY3QoZXJyKSk7XG4gICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5vbignZXJyb3InLCAoZXJyOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSAnRUFERFJJTlVTRScpIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBQb3J0ICR7Q0FMTEJBQ0tfUE9SVH0gaXMgaW4gdXNlYCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmxpc3RlbihDQUxMQkFDS19QT1JULCAnbG9jYWxob3N0JywgKCkgPT4ge1xuICAgICAgICBsb2dnZXIuaW5mbygnW0F1dGhTZXJ2aWNlXSBDYWxsYmFjayBzZXJ2ZXIgc3RhcnRlZCcpO1xuICAgICAgICB0aGlzLm9wZW5Ccm93c2VyKGF1dGhVcmwpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFRpbWVvdXRcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoKCkgPT4gcmVqZWN0KG5ldyBFcnJvcignTG9naW4gdGltZW91dCcpKSk7XG4gICAgICB9LCAyICogNjAgKiAxMDAwKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dvdXRcbiAgICovXG4gIGFzeW5jIGxvZ291dCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCBkZWxldGVkID0gYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLmRlbGV0ZVRva2VucyhnZXRFbnZpcm9ubWVudCgpKTtcblxuICAgIGlmIChkZWxldGVkKSB7XG4gICAgICAvLyBTdGFydCB0ZW1wb3Jhcnkgc2VydmVyIHRvIGhhbmRsZSBzaWdub3V0IGNhbGxiYWNrXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoKHJlcSwgcmVzKSA9PiB7XG4gICAgICAgICAgaWYgKHJlcS51cmw/LnN0YXJ0c1dpdGgoJy9zaWdub3V0JykpIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04JyB9KTtcbiAgICAgICAgICAgIHJlcy5lbmQoYFxuICAgICAgICAgICAgICA8IURPQ1RZUEUgaHRtbD5cbiAgICAgICAgICAgICAgPGh0bWw+XG4gICAgICAgICAgICAgIDxoZWFkPjx0aXRsZT5TaWduZWQgT3V0PC90aXRsZT48L2hlYWQ+XG4gICAgICAgICAgICAgIDxib2R5IHN0eWxlPVwiZm9udC1mYW1pbHk6IHN5c3RlbS11aTsgbWF4LXdpZHRoOiA2MDBweDsgbWFyZ2luOiA1MHB4IGF1dG87IHRleHQtYWxpZ246IGNlbnRlcjtcIj5cbiAgICAgICAgICAgICAgICA8aDEgc3R5bGU9XCJjb2xvcjogIzIyYzU1ZTtcIj4mIzEwMDAzOyBTaWduZWQgT3V0PC9oMT5cbiAgICAgICAgICAgICAgICA8cD5Zb3UgY2FuIGNsb3NlIHRoaXMgd2luZG93LjwvcD5cbiAgICAgICAgICAgICAgPC9ib2R5PlxuICAgICAgICAgICAgICA8L2h0bWw+XG4gICAgICAgICAgICBgKTtcblxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHRydWUpKTtcbiAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ05vdCBmb3VuZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2VydmVyLm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgICAgICByZXNvbHZlKHRydWUpOyAvLyBTdGlsbCByZXR1cm4gdHJ1ZSBzaW5jZSB0b2tlbnMgd2VyZSBkZWxldGVkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNlcnZlci5saXN0ZW4oQ0FMTEJBQ0tfUE9SVCwgJ2xvY2FsaG9zdCcsICgpID0+IHtcbiAgICAgICAgICBjb25zdCBsb2dvdXRVcmwgPSBgaHR0cHM6Ly8ke2NvbmZpZy5hd3MuY29nbml0b0RvbWFpbn0vbG9nb3V0P2AgK1xuICAgICAgICAgICAgYGNsaWVudF9pZD0ke2NvbmZpZy5hd3MuY29nbml0b0NsaWVudElkfSZgICtcbiAgICAgICAgICAgIGBsb2dvdXRfdXJpPSR7ZW5jb2RlVVJJQ29tcG9uZW50KFJFRElSRUNUX1VSSS5yZXBsYWNlKCcvY2FsbGJhY2snLCAnL3NpZ25vdXQnKSl9YDtcblxuICAgICAgICAgIHRoaXMub3BlbkJyb3dzZXIobG9nb3V0VXJsKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gVGltZW91dCBhZnRlciAzMCBzZWNvbmRzXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHRydWUpKTtcbiAgICAgICAgfSwgMzAgKiAxMDAwKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBkZWxldGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IGF1dGggc3RhdHVzXG4gICAqL1xuICBhc3luYyBnZXRTdGF0dXMoKTogUHJvbWlzZTx7IGF1dGhlbnRpY2F0ZWQ6IGJvb2xlYW47IHRva2Vucz86IFRva2VuRGF0YSB9PiB7XG4gICAgY29uc3QgdG9rZW5zID0gYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLmdldFRva2VucyhnZXRFbnZpcm9ubWVudCgpKTtcbiAgICBpZiAoIXRva2Vucykge1xuICAgICAgcmV0dXJuIHsgYXV0aGVudGljYXRlZDogZmFsc2UgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYXV0aGVudGljYXRlZDogIWtleWNoYWluTWFuYWdlci5pc1Rva2VuRXhwaXJlZCh0b2tlbnMpLFxuICAgICAgdG9rZW5zLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGF1dGhTZXJ2aWNlID0gQXV0aFNlcnZpY2UuZ2V0SW5zdGFuY2UoKTtcbiJdfQ==
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Wraps fetch() and rewrites "fetch failed" errors to include the underlying
3
+ * cause and a user-actionable diagnostic tip when possible. Non-network errors
4
+ * and HTTP error responses (non-2xx) are not affected — the caller still
5
+ * handles response.ok checks themselves.
6
+ *
7
+ * @param url The URL to fetch
8
+ * @param init Standard fetch init options
9
+ * @param context Optional short label (e.g. "token exchange") for the error message
10
+ */
11
+ export declare function fetchWithDiagnostics(url: string, init?: any, context?: string): Promise<Response>;
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ //
3
+ // fetch-helpers.ts
4
+ // CodeVibe Core
5
+ //
6
+ // Wrapper around Node's built-in fetch() that surfaces the underlying cause
7
+ // of "fetch failed" errors with platform-specific diagnostic tips.
8
+ //
9
+ // Background: Node 18+'s built-in fetch (via undici) throws a generic
10
+ // TypeError with message "fetch failed" for all network-level errors (DNS
11
+ // failures, timeouts, TLS issues, etc.). The real cause is buried in the
12
+ // error's .cause property. This wrapper unpacks that cause and returns a
13
+ // detailed, actionable error message — critical for WSL users where fetch
14
+ // failures are common and usually fixable with known workarounds.
15
+ //
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.fetchWithDiagnostics = fetchWithDiagnostics;
51
+ const dns = __importStar(require("dns"));
52
+ const fs = __importStar(require("fs"));
53
+ // Node 17+ changed the default DNS result order from 'ipv4first' to
54
+ // 'verbatim' (RFC-compliant but problematic for hosts with broken IPv6).
55
+ // On WSL Ubuntu specifically, the kernel often advertises IPv6 addresses
56
+ // via getaddrinfo even though the WSL network namespace has no route to
57
+ // the IPv6 internet — causing every IPv6 connection attempt to fail with
58
+ // EHOSTUNREACH. curl handles this via Happy Eyeballs fallback, but undici
59
+ // (Node's built-in fetch) does not, and throws "fetch failed" without
60
+ // ever trying IPv4.
61
+ //
62
+ // We apply 'ipv4first' ONLY when running inside WSL. On macOS, native
63
+ // Linux, and Windows we leave Node's default ('verbatim') alone — those
64
+ // platforms have healthy dual-stack networking and the current behavior
65
+ // is correct. Narrowly scoping the override to WSL means zero behavioral
66
+ // change for non-WSL users (including IPv6-only networks where ipv4first
67
+ // would add first-connection latency).
68
+ //
69
+ // This runs as a side effect of importing codevibe-core's fetch-helpers,
70
+ // which happens early in every plugin's startup path. Documented here
71
+ // so future maintainers understand why there's a side effect on import.
72
+ if (isRunningInWSL()) {
73
+ try {
74
+ dns.setDefaultResultOrder('ipv4first');
75
+ }
76
+ catch {
77
+ // Older Node versions (< 18.6) don't expose setDefaultResultOrder;
78
+ // skip silently. Users on those versions can still set the
79
+ // NODE_OPTIONS="--dns-result-order=ipv4first" environment variable
80
+ // manually if they hit IPv6 issues.
81
+ }
82
+ }
83
+ /**
84
+ * Detect whether we're running inside WSL (1 or 2). Returns false on any
85
+ * non-Linux platform or if /proc/sys/kernel/osrelease is not readable.
86
+ * Duplicated from auth-service.ts as a module-level helper so it can run
87
+ * at import time, before any class is instantiated.
88
+ */
89
+ function isRunningInWSL() {
90
+ if (process.platform !== 'linux')
91
+ return false;
92
+ try {
93
+ const osRelease = fs.readFileSync('/proc/sys/kernel/osrelease', 'utf8');
94
+ return /microsoft|wsl/i.test(osRelease);
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ /**
101
+ * Wraps fetch() and rewrites "fetch failed" errors to include the underlying
102
+ * cause and a user-actionable diagnostic tip when possible. Non-network errors
103
+ * and HTTP error responses (non-2xx) are not affected — the caller still
104
+ * handles response.ok checks themselves.
105
+ *
106
+ * @param url The URL to fetch
107
+ * @param init Standard fetch init options
108
+ * @param context Optional short label (e.g. "token exchange") for the error message
109
+ */
110
+ async function fetchWithDiagnostics(url, init, context) {
111
+ try {
112
+ return await fetch(url, init);
113
+ }
114
+ catch (err) {
115
+ // Node's undici wraps real errors in err.cause
116
+ const causeCode = err?.cause?.code;
117
+ const causeMessage = err?.cause?.message;
118
+ const causeSummary = causeCode || causeMessage || err?.message || 'unknown';
119
+ const tip = getDiagnosticTip(causeCode);
120
+ const contextLabel = context ? `${context}: ` : '';
121
+ const platformInfo = `Node ${process.version} on ${process.platform}`;
122
+ const detailLines = [
123
+ `${contextLabel}Cannot reach ${url}`,
124
+ ` Underlying error: ${causeSummary}`,
125
+ ];
126
+ if (tip) {
127
+ detailLines.push(` Suggested fix: ${tip}`);
128
+ }
129
+ detailLines.push(` Platform: ${platformInfo}`);
130
+ const detailedError = new Error(detailLines.join('\n'));
131
+ // Preserve the original error as cause so callers can still inspect it
132
+ detailedError.cause = err;
133
+ throw detailedError;
134
+ }
135
+ }
136
+ /**
137
+ * Map common Node network error codes to user-actionable diagnostic hints.
138
+ * Returns null if the code isn't one we recognize.
139
+ */
140
+ function getDiagnosticTip(errorCode) {
141
+ if (!errorCode)
142
+ return null;
143
+ switch (errorCode) {
144
+ case 'ENOTFOUND':
145
+ case 'EAI_AGAIN':
146
+ return 'DNS resolution failed. On WSL Ubuntu, check /etc/resolv.conf, or try running with NODE_OPTIONS="--dns-result-order=ipv4first".';
147
+ case 'ETIMEDOUT':
148
+ case 'ECONNREFUSED':
149
+ case 'ECONNRESET':
150
+ case 'EHOSTUNREACH':
151
+ case 'ENETUNREACH':
152
+ return 'Network unreachable. On WSL Ubuntu, try NODE_OPTIONS="--dns-result-order=ipv4first" (WSL\'s IPv6 is often broken). If behind a corporate proxy, set HTTPS_PROXY.';
153
+ case 'CERT_HAS_EXPIRED':
154
+ case 'CERT_NOT_YET_VALID':
155
+ return 'TLS certificate time error — likely system clock drift. On WSL, run `sudo hwclock -s`, or shut down WSL from PowerShell with `wsl --shutdown` and restart.';
156
+ case 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY':
157
+ case 'SELF_SIGNED_CERT_IN_CHAIN':
158
+ case 'UNABLE_TO_VERIFY_LEAF_SIGNATURE':
159
+ case 'DEPTH_ZERO_SELF_SIGNED_CERT':
160
+ return 'Corporate HTTPS proxy detected — the TLS cert is not trusted by Node. Set NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem, or configure HTTPS_PROXY if a proxy is required.';
161
+ default:
162
+ return null;
163
+ }
164
+ }
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2gtaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hdXRoL2ZldGNoLWhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLEVBQUU7QUFDRixtQkFBbUI7QUFDbkIsZ0JBQWdCO0FBQ2hCLEVBQUU7QUFDRiw0RUFBNEU7QUFDNUUsbUVBQW1FO0FBQ25FLEVBQUU7QUFDRixzRUFBc0U7QUFDdEUsMEVBQTBFO0FBQzFFLHlFQUF5RTtBQUN6RSx5RUFBeUU7QUFDekUsMEVBQTBFO0FBQzFFLGtFQUFrRTtBQUNsRSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZERixvREErQkM7QUExRkQseUNBQTJCO0FBQzNCLHVDQUF5QjtBQUV6QixvRUFBb0U7QUFDcEUseUVBQXlFO0FBQ3pFLHlFQUF5RTtBQUN6RSx3RUFBd0U7QUFDeEUseUVBQXlFO0FBQ3pFLDBFQUEwRTtBQUMxRSxzRUFBc0U7QUFDdEUsb0JBQW9CO0FBQ3BCLEVBQUU7QUFDRixzRUFBc0U7QUFDdEUsd0VBQXdFO0FBQ3hFLHdFQUF3RTtBQUN4RSx5RUFBeUU7QUFDekUseUVBQXlFO0FBQ3pFLHVDQUF1QztBQUN2QyxFQUFFO0FBQ0YseUVBQXlFO0FBQ3pFLHNFQUFzRTtBQUN0RSx3RUFBd0U7QUFDeEUsSUFBSSxjQUFjLEVBQUUsRUFBRSxDQUFDO0lBQ3JCLElBQUksQ0FBQztRQUNILEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsbUVBQW1FO1FBQ25FLDJEQUEyRDtRQUMzRCxtRUFBbUU7UUFDbkUsb0NBQW9DO0lBQ3RDLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGNBQWM7SUFDckIsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMvQyxJQUFJLENBQUM7UUFDSCxNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLDRCQUE0QixFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0ksS0FBSyxVQUFVLG9CQUFvQixDQUN4QyxHQUFXLEVBQ1gsSUFBVSxFQUNWLE9BQWdCO0lBRWhCLElBQUksQ0FBQztRQUNILE9BQU8sTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO1FBQ2xCLCtDQUErQztRQUMvQyxNQUFNLFNBQVMsR0FBdUIsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUM7UUFDdkQsTUFBTSxZQUFZLEdBQXVCLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDO1FBQzdELE1BQU0sWUFBWSxHQUFHLFNBQVMsSUFBSSxZQUFZLElBQUksR0FBRyxFQUFFLE9BQU8sSUFBSSxTQUFTLENBQUM7UUFFNUUsTUFBTSxHQUFHLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDeEMsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDbkQsTUFBTSxZQUFZLEdBQUcsUUFBUSxPQUFPLENBQUMsT0FBTyxPQUFPLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUV0RSxNQUFNLFdBQVcsR0FBYTtZQUM1QixHQUFHLFlBQVksZ0JBQWdCLEdBQUcsRUFBRTtZQUNwQyx1QkFBdUIsWUFBWSxFQUFFO1NBQ3RDLENBQUM7UUFDRixJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ1IsV0FBVyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBQ0QsV0FBVyxDQUFDLElBQUksQ0FBQyxlQUFlLFlBQVksRUFBRSxDQUFDLENBQUM7UUFFaEQsTUFBTSxhQUFhLEdBQUcsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3hELHVFQUF1RTtRQUN0RSxhQUFxQixDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7UUFDbkMsTUFBTSxhQUFhLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLFNBQWtCO0lBQzFDLElBQUksQ0FBQyxTQUFTO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFFNUIsUUFBUSxTQUFTLEVBQUUsQ0FBQztRQUNsQixLQUFLLFdBQVcsQ0FBQztRQUNqQixLQUFLLFdBQVc7WUFDZCxPQUFPLGdJQUFnSSxDQUFDO1FBRTFJLEtBQUssV0FBVyxDQUFDO1FBQ2pCLEtBQUssY0FBYyxDQUFDO1FBQ3BCLEtBQUssWUFBWSxDQUFDO1FBQ2xCLEtBQUssY0FBYyxDQUFDO1FBQ3BCLEtBQUssYUFBYTtZQUNoQixPQUFPLGtLQUFrSyxDQUFDO1FBRTVLLEtBQUssa0JBQWtCLENBQUM7UUFDeEIsS0FBSyxvQkFBb0I7WUFDdkIsT0FBTyw0SkFBNEosQ0FBQztRQUV0SyxLQUFLLG1DQUFtQyxDQUFDO1FBQ3pDLEtBQUssMkJBQTJCLENBQUM7UUFDakMsS0FBSyxpQ0FBaUMsQ0FBQztRQUN2QyxLQUFLLDZCQUE2QjtZQUNoQyxPQUFPLDJLQUEySyxDQUFDO1FBRXJMO1lBQ0UsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuLy8gZmV0Y2gtaGVscGVycy50c1xuLy8gQ29kZVZpYmUgQ29yZVxuLy9cbi8vIFdyYXBwZXIgYXJvdW5kIE5vZGUncyBidWlsdC1pbiBmZXRjaCgpIHRoYXQgc3VyZmFjZXMgdGhlIHVuZGVybHlpbmcgY2F1c2Vcbi8vIG9mIFwiZmV0Y2ggZmFpbGVkXCIgZXJyb3JzIHdpdGggcGxhdGZvcm0tc3BlY2lmaWMgZGlhZ25vc3RpYyB0aXBzLlxuLy9cbi8vIEJhY2tncm91bmQ6IE5vZGUgMTgrJ3MgYnVpbHQtaW4gZmV0Y2ggKHZpYSB1bmRpY2kpIHRocm93cyBhIGdlbmVyaWNcbi8vIFR5cGVFcnJvciB3aXRoIG1lc3NhZ2UgXCJmZXRjaCBmYWlsZWRcIiBmb3IgYWxsIG5ldHdvcmstbGV2ZWwgZXJyb3JzIChETlNcbi8vIGZhaWx1cmVzLCB0aW1lb3V0cywgVExTIGlzc3VlcywgZXRjLikuIFRoZSByZWFsIGNhdXNlIGlzIGJ1cmllZCBpbiB0aGVcbi8vIGVycm9yJ3MgLmNhdXNlIHByb3BlcnR5LiBUaGlzIHdyYXBwZXIgdW5wYWNrcyB0aGF0IGNhdXNlIGFuZCByZXR1cm5zIGFcbi8vIGRldGFpbGVkLCBhY3Rpb25hYmxlIGVycm9yIG1lc3NhZ2Ug4oCUIGNyaXRpY2FsIGZvciBXU0wgdXNlcnMgd2hlcmUgZmV0Y2hcbi8vIGZhaWx1cmVzIGFyZSBjb21tb24gYW5kIHVzdWFsbHkgZml4YWJsZSB3aXRoIGtub3duIHdvcmthcm91bmRzLlxuLy9cblxuaW1wb3J0ICogYXMgZG5zIGZyb20gJ2Rucyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5cbi8vIE5vZGUgMTcrIGNoYW5nZWQgdGhlIGRlZmF1bHQgRE5TIHJlc3VsdCBvcmRlciBmcm9tICdpcHY0Zmlyc3QnIHRvXG4vLyAndmVyYmF0aW0nIChSRkMtY29tcGxpYW50IGJ1dCBwcm9ibGVtYXRpYyBmb3IgaG9zdHMgd2l0aCBicm9rZW4gSVB2NikuXG4vLyBPbiBXU0wgVWJ1bnR1IHNwZWNpZmljYWxseSwgdGhlIGtlcm5lbCBvZnRlbiBhZHZlcnRpc2VzIElQdjYgYWRkcmVzc2VzXG4vLyB2aWEgZ2V0YWRkcmluZm8gZXZlbiB0aG91Z2ggdGhlIFdTTCBuZXR3b3JrIG5hbWVzcGFjZSBoYXMgbm8gcm91dGUgdG9cbi8vIHRoZSBJUHY2IGludGVybmV0IOKAlCBjYXVzaW5nIGV2ZXJ5IElQdjYgY29ubmVjdGlvbiBhdHRlbXB0IHRvIGZhaWwgd2l0aFxuLy8gRUhPU1RVTlJFQUNILiBjdXJsIGhhbmRsZXMgdGhpcyB2aWEgSGFwcHkgRXllYmFsbHMgZmFsbGJhY2ssIGJ1dCB1bmRpY2lcbi8vIChOb2RlJ3MgYnVpbHQtaW4gZmV0Y2gpIGRvZXMgbm90LCBhbmQgdGhyb3dzIFwiZmV0Y2ggZmFpbGVkXCIgd2l0aG91dFxuLy8gZXZlciB0cnlpbmcgSVB2NC5cbi8vXG4vLyBXZSBhcHBseSAnaXB2NGZpcnN0JyBPTkxZIHdoZW4gcnVubmluZyBpbnNpZGUgV1NMLiBPbiBtYWNPUywgbmF0aXZlXG4vLyBMaW51eCwgYW5kIFdpbmRvd3Mgd2UgbGVhdmUgTm9kZSdzIGRlZmF1bHQgKCd2ZXJiYXRpbScpIGFsb25lIOKAlCB0aG9zZVxuLy8gcGxhdGZvcm1zIGhhdmUgaGVhbHRoeSBkdWFsLXN0YWNrIG5ldHdvcmtpbmcgYW5kIHRoZSBjdXJyZW50IGJlaGF2aW9yXG4vLyBpcyBjb3JyZWN0LiBOYXJyb3dseSBzY29waW5nIHRoZSBvdmVycmlkZSB0byBXU0wgbWVhbnMgemVybyBiZWhhdmlvcmFsXG4vLyBjaGFuZ2UgZm9yIG5vbi1XU0wgdXNlcnMgKGluY2x1ZGluZyBJUHY2LW9ubHkgbmV0d29ya3Mgd2hlcmUgaXB2NGZpcnN0XG4vLyB3b3VsZCBhZGQgZmlyc3QtY29ubmVjdGlvbiBsYXRlbmN5KS5cbi8vXG4vLyBUaGlzIHJ1bnMgYXMgYSBzaWRlIGVmZmVjdCBvZiBpbXBvcnRpbmcgY29kZXZpYmUtY29yZSdzIGZldGNoLWhlbHBlcnMsXG4vLyB3aGljaCBoYXBwZW5zIGVhcmx5IGluIGV2ZXJ5IHBsdWdpbidzIHN0YXJ0dXAgcGF0aC4gRG9jdW1lbnRlZCBoZXJlXG4vLyBzbyBmdXR1cmUgbWFpbnRhaW5lcnMgdW5kZXJzdGFuZCB3aHkgdGhlcmUncyBhIHNpZGUgZWZmZWN0IG9uIGltcG9ydC5cbmlmIChpc1J1bm5pbmdJbldTTCgpKSB7XG4gIHRyeSB7XG4gICAgZG5zLnNldERlZmF1bHRSZXN1bHRPcmRlcignaXB2NGZpcnN0Jyk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIE9sZGVyIE5vZGUgdmVyc2lvbnMgKDwgMTguNikgZG9uJ3QgZXhwb3NlIHNldERlZmF1bHRSZXN1bHRPcmRlcjtcbiAgICAvLyBza2lwIHNpbGVudGx5LiBVc2VycyBvbiB0aG9zZSB2ZXJzaW9ucyBjYW4gc3RpbGwgc2V0IHRoZVxuICAgIC8vIE5PREVfT1BUSU9OUz1cIi0tZG5zLXJlc3VsdC1vcmRlcj1pcHY0Zmlyc3RcIiBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgIC8vIG1hbnVhbGx5IGlmIHRoZXkgaGl0IElQdjYgaXNzdWVzLlxuICB9XG59XG5cbi8qKlxuICogRGV0ZWN0IHdoZXRoZXIgd2UncmUgcnVubmluZyBpbnNpZGUgV1NMICgxIG9yIDIpLiBSZXR1cm5zIGZhbHNlIG9uIGFueVxuICogbm9uLUxpbnV4IHBsYXRmb3JtIG9yIGlmIC9wcm9jL3N5cy9rZXJuZWwvb3NyZWxlYXNlIGlzIG5vdCByZWFkYWJsZS5cbiAqIER1cGxpY2F0ZWQgZnJvbSBhdXRoLXNlcnZpY2UudHMgYXMgYSBtb2R1bGUtbGV2ZWwgaGVscGVyIHNvIGl0IGNhbiBydW5cbiAqIGF0IGltcG9ydCB0aW1lLCBiZWZvcmUgYW55IGNsYXNzIGlzIGluc3RhbnRpYXRlZC5cbiAqL1xuZnVuY3Rpb24gaXNSdW5uaW5nSW5XU0woKTogYm9vbGVhbiB7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtICE9PSAnbGludXgnKSByZXR1cm4gZmFsc2U7XG4gIHRyeSB7XG4gICAgY29uc3Qgb3NSZWxlYXNlID0gZnMucmVhZEZpbGVTeW5jKCcvcHJvYy9zeXMva2VybmVsL29zcmVsZWFzZScsICd1dGY4Jyk7XG4gICAgcmV0dXJuIC9taWNyb3NvZnR8d3NsL2kudGVzdChvc1JlbGVhc2UpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBXcmFwcyBmZXRjaCgpIGFuZCByZXdyaXRlcyBcImZldGNoIGZhaWxlZFwiIGVycm9ycyB0byBpbmNsdWRlIHRoZSB1bmRlcmx5aW5nXG4gKiBjYXVzZSBhbmQgYSB1c2VyLWFjdGlvbmFibGUgZGlhZ25vc3RpYyB0aXAgd2hlbiBwb3NzaWJsZS4gTm9uLW5ldHdvcmsgZXJyb3JzXG4gKiBhbmQgSFRUUCBlcnJvciByZXNwb25zZXMgKG5vbi0yeHgpIGFyZSBub3QgYWZmZWN0ZWQg4oCUIHRoZSBjYWxsZXIgc3RpbGxcbiAqIGhhbmRsZXMgcmVzcG9uc2Uub2sgY2hlY2tzIHRoZW1zZWx2ZXMuXG4gKlxuICogQHBhcmFtIHVybCBUaGUgVVJMIHRvIGZldGNoXG4gKiBAcGFyYW0gaW5pdCBTdGFuZGFyZCBmZXRjaCBpbml0IG9wdGlvbnNcbiAqIEBwYXJhbSBjb250ZXh0IE9wdGlvbmFsIHNob3J0IGxhYmVsIChlLmcuIFwidG9rZW4gZXhjaGFuZ2VcIikgZm9yIHRoZSBlcnJvciBtZXNzYWdlXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFdpdGhEaWFnbm9zdGljcyhcbiAgdXJsOiBzdHJpbmcsXG4gIGluaXQ/OiBhbnksXG4gIGNvbnRleHQ/OiBzdHJpbmdcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZmV0Y2godXJsLCBpbml0KTtcbiAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAvLyBOb2RlJ3MgdW5kaWNpIHdyYXBzIHJlYWwgZXJyb3JzIGluIGVyci5jYXVzZVxuICAgIGNvbnN0IGNhdXNlQ29kZTogc3RyaW5nIHwgdW5kZWZpbmVkID0gZXJyPy5jYXVzZT8uY29kZTtcbiAgICBjb25zdCBjYXVzZU1lc3NhZ2U6IHN0cmluZyB8IHVuZGVmaW5lZCA9IGVycj8uY2F1c2U/Lm1lc3NhZ2U7XG4gICAgY29uc3QgY2F1c2VTdW1tYXJ5ID0gY2F1c2VDb2RlIHx8IGNhdXNlTWVzc2FnZSB8fCBlcnI/Lm1lc3NhZ2UgfHwgJ3Vua25vd24nO1xuXG4gICAgY29uc3QgdGlwID0gZ2V0RGlhZ25vc3RpY1RpcChjYXVzZUNvZGUpO1xuICAgIGNvbnN0IGNvbnRleHRMYWJlbCA9IGNvbnRleHQgPyBgJHtjb250ZXh0fTogYCA6ICcnO1xuICAgIGNvbnN0IHBsYXRmb3JtSW5mbyA9IGBOb2RlICR7cHJvY2Vzcy52ZXJzaW9ufSBvbiAke3Byb2Nlc3MucGxhdGZvcm19YDtcblxuICAgIGNvbnN0IGRldGFpbExpbmVzOiBzdHJpbmdbXSA9IFtcbiAgICAgIGAke2NvbnRleHRMYWJlbH1DYW5ub3QgcmVhY2ggJHt1cmx9YCxcbiAgICAgIGAgIFVuZGVybHlpbmcgZXJyb3I6ICR7Y2F1c2VTdW1tYXJ5fWAsXG4gICAgXTtcbiAgICBpZiAodGlwKSB7XG4gICAgICBkZXRhaWxMaW5lcy5wdXNoKGAgIFN1Z2dlc3RlZCBmaXg6ICR7dGlwfWApO1xuICAgIH1cbiAgICBkZXRhaWxMaW5lcy5wdXNoKGAgIFBsYXRmb3JtOiAke3BsYXRmb3JtSW5mb31gKTtcblxuICAgIGNvbnN0IGRldGFpbGVkRXJyb3IgPSBuZXcgRXJyb3IoZGV0YWlsTGluZXMuam9pbignXFxuJykpO1xuICAgIC8vIFByZXNlcnZlIHRoZSBvcmlnaW5hbCBlcnJvciBhcyBjYXVzZSBzbyBjYWxsZXJzIGNhbiBzdGlsbCBpbnNwZWN0IGl0XG4gICAgKGRldGFpbGVkRXJyb3IgYXMgYW55KS5jYXVzZSA9IGVycjtcbiAgICB0aHJvdyBkZXRhaWxlZEVycm9yO1xuICB9XG59XG5cbi8qKlxuICogTWFwIGNvbW1vbiBOb2RlIG5ldHdvcmsgZXJyb3IgY29kZXMgdG8gdXNlci1hY3Rpb25hYmxlIGRpYWdub3N0aWMgaGludHMuXG4gKiBSZXR1cm5zIG51bGwgaWYgdGhlIGNvZGUgaXNuJ3Qgb25lIHdlIHJlY29nbml6ZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RGlhZ25vc3RpY1RpcChlcnJvckNvZGU/OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKCFlcnJvckNvZGUpIHJldHVybiBudWxsO1xuXG4gIHN3aXRjaCAoZXJyb3JDb2RlKSB7XG4gICAgY2FzZSAnRU5PVEZPVU5EJzpcbiAgICBjYXNlICdFQUlfQUdBSU4nOlxuICAgICAgcmV0dXJuICdETlMgcmVzb2x1dGlvbiBmYWlsZWQuIE9uIFdTTCBVYnVudHUsIGNoZWNrIC9ldGMvcmVzb2x2LmNvbmYsIG9yIHRyeSBydW5uaW5nIHdpdGggTk9ERV9PUFRJT05TPVwiLS1kbnMtcmVzdWx0LW9yZGVyPWlwdjRmaXJzdFwiLic7XG5cbiAgICBjYXNlICdFVElNRURPVVQnOlxuICAgIGNhc2UgJ0VDT05OUkVGVVNFRCc6XG4gICAgY2FzZSAnRUNPTk5SRVNFVCc6XG4gICAgY2FzZSAnRUhPU1RVTlJFQUNIJzpcbiAgICBjYXNlICdFTkVUVU5SRUFDSCc6XG4gICAgICByZXR1cm4gJ05ldHdvcmsgdW5yZWFjaGFibGUuIE9uIFdTTCBVYnVudHUsIHRyeSBOT0RFX09QVElPTlM9XCItLWRucy1yZXN1bHQtb3JkZXI9aXB2NGZpcnN0XCIgKFdTTFxcJ3MgSVB2NiBpcyBvZnRlbiBicm9rZW4pLiBJZiBiZWhpbmQgYSBjb3Jwb3JhdGUgcHJveHksIHNldCBIVFRQU19QUk9YWS4nO1xuXG4gICAgY2FzZSAnQ0VSVF9IQVNfRVhQSVJFRCc6XG4gICAgY2FzZSAnQ0VSVF9OT1RfWUVUX1ZBTElEJzpcbiAgICAgIHJldHVybiAnVExTIGNlcnRpZmljYXRlIHRpbWUgZXJyb3Ig4oCUIGxpa2VseSBzeXN0ZW0gY2xvY2sgZHJpZnQuIE9uIFdTTCwgcnVuIGBzdWRvIGh3Y2xvY2sgLXNgLCBvciBzaHV0IGRvd24gV1NMIGZyb20gUG93ZXJTaGVsbCB3aXRoIGB3c2wgLS1zaHV0ZG93bmAgYW5kIHJlc3RhcnQuJztcblxuICAgIGNhc2UgJ1VOQUJMRV9UT19HRVRfSVNTVUVSX0NFUlRfTE9DQUxMWSc6XG4gICAgY2FzZSAnU0VMRl9TSUdORURfQ0VSVF9JTl9DSEFJTic6XG4gICAgY2FzZSAnVU5BQkxFX1RPX1ZFUklGWV9MRUFGX1NJR05BVFVSRSc6XG4gICAgY2FzZSAnREVQVEhfWkVST19TRUxGX1NJR05FRF9DRVJUJzpcbiAgICAgIHJldHVybiAnQ29ycG9yYXRlIEhUVFBTIHByb3h5IGRldGVjdGVkIOKAlCB0aGUgVExTIGNlcnQgaXMgbm90IHRydXN0ZWQgYnkgTm9kZS4gU2V0IE5PREVfRVhUUkFfQ0FfQ0VSVFM9L3BhdGgvdG8vY29ycG9yYXRlLWNhLnBlbSwgb3IgY29uZmlndXJlIEhUVFBTX1BST1hZIGlmIGEgcHJveHkgaXMgcmVxdWlyZWQuJztcblxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuIl19
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-claude-plugin",
3
- "version": "1.0.8",
4
- "description": "Mobile companion for Claude Code - monitor and control your Claude Code sessions from your iPhone with CodeVibe",
3
+ "version": "1.0.10",
4
+ "description": "Mobile companion for Claude Code - monitor and control your Claude Code sessions from your phone with CodeVibe",
5
5
  "main": "dist/server.js",
6
6
  "bin": {
7
7
  "codevibe-claude": "./bin/codevibe-claude"
@@ -22,7 +22,7 @@
22
22
  "dev": "ts-node src/server.ts",
23
23
  "start": "node dist/server.js",
24
24
  "watch": "tsc --watch",
25
- "test": "echo \"Error: no test specified\" && exit 1"
25
+ "test": "jest --config jest.config.js --forceExit"
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
@@ -53,7 +53,7 @@
53
53
  "darwin"
54
54
  ],
55
55
  "dependencies": {
56
- "@quantiya/codevibe-core": "^1.0.2",
56
+ "@quantiya/codevibe-core": "^1.0.3",
57
57
  "dotenv": "^16.6.1",
58
58
  "express": "^5.1.0",
59
59
  "graphql": "^16.12.0",
@@ -70,9 +70,12 @@
70
70
  ],
71
71
  "devDependencies": {
72
72
  "@types/express": "^5.0.5",
73
+ "@types/jest": "^30.0.0",
73
74
  "@types/node": "^24.10.1",
74
75
  "@types/uuid": "^10.0.0",
75
76
  "@types/ws": "^8.18.1",
77
+ "jest": "^30.3.0",
78
+ "ts-jest": "^29.4.9",
76
79
  "ts-node": "^10.9.2",
77
80
  "typescript": "^5.9.3"
78
81
  },