@n24q02m/mcp-core 1.0.0-beta.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/build/auth/credential-form.d.ts +45 -0
  2. package/build/auth/credential-form.d.ts.map +1 -0
  3. package/build/auth/credential-form.js +668 -0
  4. package/build/auth/credential-form.js.map +1 -0
  5. package/build/auth/delegated-oauth-app.d.ts +53 -0
  6. package/build/auth/delegated-oauth-app.d.ts.map +1 -0
  7. package/build/auth/delegated-oauth-app.js +531 -0
  8. package/build/auth/delegated-oauth-app.js.map +1 -0
  9. package/build/auth/index.d.ts +10 -0
  10. package/build/auth/index.d.ts.map +1 -0
  11. package/build/auth/index.js +10 -0
  12. package/build/auth/index.js.map +1 -0
  13. package/build/auth/local-oauth-app.d.ts +83 -0
  14. package/build/auth/local-oauth-app.d.ts.map +1 -0
  15. package/build/auth/local-oauth-app.js +355 -0
  16. package/build/auth/local-oauth-app.js.map +1 -0
  17. package/build/auth/router.d.ts +18 -0
  18. package/build/auth/router.d.ts.map +1 -0
  19. package/build/auth/router.js +62 -0
  20. package/build/auth/router.js.map +1 -0
  21. package/build/auth/well-known.d.ts +4 -0
  22. package/build/auth/well-known.d.ts.map +1 -0
  23. package/build/auth/well-known.js +20 -0
  24. package/build/auth/well-known.js.map +1 -0
  25. package/build/index.d.ts +3 -1
  26. package/build/index.d.ts.map +1 -1
  27. package/build/index.js +5 -1
  28. package/build/index.js.map +1 -1
  29. package/build/relay/browser.d.ts.map +1 -1
  30. package/build/relay/browser.js +10 -0
  31. package/build/relay/browser.js.map +1 -1
  32. package/build/storage/config-file.d.ts +10 -0
  33. package/build/storage/config-file.d.ts.map +1 -1
  34. package/build/storage/config-file.js +20 -7
  35. package/build/storage/config-file.js.map +1 -1
  36. package/build/transport/local-server.d.ts +67 -0
  37. package/build/transport/local-server.d.ts.map +1 -0
  38. package/build/transport/local-server.js +131 -0
  39. package/build/transport/local-server.js.map +1 -0
  40. package/package.json +5 -1
@@ -0,0 +1,668 @@
1
+ /**
2
+ * Credential form HTML renderer.
3
+ *
4
+ * Renders a dark-themed HTML form from a RelayConfigSchema.
5
+ * Used as the OAuth authorization page presented to the user during relay config.
6
+ *
7
+ * This is a TypeScript port of core-py's `credential_form.py`. CSS and embedded JS
8
+ * are kept verbatim so the rendered form has visual + behavioral parity between
9
+ * Python and TS servers.
10
+ */
11
+ function escapeHtml(value) {
12
+ return String(value ?? '')
13
+ .replace(/&/g, '&')
14
+ .replace(/</g, '&lt;')
15
+ .replace(/>/g, '&gt;')
16
+ .replace(/"/g, '&quot;')
17
+ .replace(/'/g, '&#39;');
18
+ }
19
+ function renderField(field) {
20
+ const key = escapeHtml(field.key ?? '');
21
+ const label = escapeHtml(field.label ?? '');
22
+ const fieldType = escapeHtml(field.type ?? 'text');
23
+ const placeholder = escapeHtml(field.placeholder ?? '');
24
+ const helpText = escapeHtml(field.helpText ?? '');
25
+ const helpUrl = escapeHtml(field.helpUrl ?? '');
26
+ const required = Boolean(field.required);
27
+ const requiredAttr = required ? ' required' : '';
28
+ const requiredBadge = required
29
+ ? '<span class="required-badge">Required</span>'
30
+ : '<span class="optional-badge">Optional</span>';
31
+ let helpHtml = '';
32
+ if (helpText) {
33
+ if (helpUrl) {
34
+ helpHtml = `<p class="help-text"><a href="${helpUrl}" target="_blank" rel="noopener noreferrer">${helpText}</a></p>`;
35
+ }
36
+ else {
37
+ helpHtml = `<p class="help-text">${helpText}</p>`;
38
+ }
39
+ }
40
+ return `
41
+ <div class="field-group">
42
+ <label for="field-${key}" class="field-label">
43
+ ${label}
44
+ ${requiredBadge}
45
+ </label>
46
+ <input
47
+ id="field-${key}"
48
+ name="${key}"
49
+ type="${fieldType}"
50
+ placeholder="${placeholder}"
51
+ class="field-input"
52
+ autocomplete="off"
53
+ autocorrect="off"
54
+ autocapitalize="off"
55
+ spellcheck="false"${requiredAttr}
56
+ />
57
+ ${helpHtml}
58
+ </div>`;
59
+ }
60
+ function renderCapability(cap) {
61
+ const label = escapeHtml(cap.label ?? '');
62
+ const priority = escapeHtml(cap.priority ?? '');
63
+ const description = escapeHtml(cap.description ?? '');
64
+ const priorityClass = priority ? `priority-${priority}` : 'priority-medium';
65
+ const descHtml = description ? `<p class="capability-desc">${description}</p>` : '';
66
+ return `
67
+ <li class="capability-item">
68
+ <div class="capability-header">
69
+ <span class="capability-label">${label}</span>
70
+ <span class="capability-priority ${priorityClass}">${priority}</span>
71
+ </div>
72
+ ${descHtml}
73
+ </li>`;
74
+ }
75
+ /**
76
+ * Render a dark-themed HTML credential form from a RelayConfigSchema.
77
+ *
78
+ * @param schema RelayConfigSchema with server metadata and field definitions.
79
+ * @param options.submitUrl URL the form POSTs to as JSON via fetch().
80
+ * @param options.pageTitle Optional browser tab title. Defaults to displayName.
81
+ * @returns Complete HTML document string, XSS-safe with all dynamic content escaped.
82
+ */
83
+ export function renderCredentialForm(schema, options) {
84
+ const displayName = escapeHtml(schema.displayName ?? schema.server ?? 'Configuration');
85
+ const server = escapeHtml(schema.server ?? '');
86
+ const description = escapeHtml(schema.description ?? '');
87
+ const title = options.pageTitle !== undefined ? escapeHtml(options.pageTitle) : displayName;
88
+ const submitUrlEscaped = escapeHtml(options.submitUrl);
89
+ const fields = schema.fields ?? [];
90
+ const capabilityInfo = schema.capabilityInfo ?? [];
91
+ const fieldsHtml = fields.map(renderField).join('');
92
+ let capabilitiesHtml = '';
93
+ if (capabilityInfo.length > 0) {
94
+ const itemsHtml = capabilityInfo.map(renderCapability).join('');
95
+ capabilitiesHtml = `
96
+ <section class="capabilities-section">
97
+ <h2 class="capabilities-title">Capabilities Requested</h2>
98
+ <ul class="capabilities-list">${itemsHtml}
99
+ </ul>
100
+ </section>`;
101
+ }
102
+ const descriptionHtml = description ? `<p class="server-description">${description}</p>` : '';
103
+ return `<!DOCTYPE html>
104
+ <html lang="en">
105
+ <head>
106
+ <meta charset="UTF-8" />
107
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
108
+ <title>${title}</title>
109
+ <style>
110
+ *, *::before, *::after {
111
+ box-sizing: border-box;
112
+ margin: 0;
113
+ padding: 0;
114
+ }
115
+
116
+ body {
117
+ background-color: #0f0f0f;
118
+ color: #e8e8e8;
119
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
120
+ font-size: 15px;
121
+ line-height: 1.6;
122
+ min-height: 100vh;
123
+ display: flex;
124
+ align-items: flex-start;
125
+ justify-content: center;
126
+ padding: 2rem 1rem;
127
+ }
128
+
129
+ .container {
130
+ width: 100%;
131
+ max-width: 480px;
132
+ }
133
+
134
+ .card {
135
+ background-color: #1a1a1a;
136
+ border: 1px solid #2a2a2a;
137
+ border-radius: 12px;
138
+ padding: 2rem;
139
+ margin-bottom: 1.25rem;
140
+ }
141
+
142
+ .server-header {
143
+ margin-bottom: 1.5rem;
144
+ }
145
+
146
+ .server-name {
147
+ font-size: 1.375rem;
148
+ font-weight: 600;
149
+ color: #ffffff;
150
+ margin-bottom: 0.375rem;
151
+ }
152
+
153
+ .server-id {
154
+ font-size: 0.8125rem;
155
+ color: #666;
156
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
157
+ margin-bottom: 0.5rem;
158
+ }
159
+
160
+ .server-description {
161
+ font-size: 0.9rem;
162
+ color: #999;
163
+ margin-top: 0.5rem;
164
+ }
165
+
166
+ .form-title {
167
+ font-size: 0.875rem;
168
+ font-weight: 500;
169
+ color: #aaa;
170
+ text-transform: uppercase;
171
+ letter-spacing: 0.05em;
172
+ margin-bottom: 1.25rem;
173
+ }
174
+
175
+ .field-group {
176
+ margin-bottom: 1.25rem;
177
+ }
178
+
179
+ .field-label {
180
+ display: flex;
181
+ align-items: center;
182
+ gap: 0.5rem;
183
+ font-size: 0.875rem;
184
+ font-weight: 500;
185
+ color: #ccc;
186
+ margin-bottom: 0.375rem;
187
+ }
188
+
189
+ .required-badge {
190
+ font-size: 0.6875rem;
191
+ font-weight: 500;
192
+ color: #f87171;
193
+ background-color: rgba(248, 113, 113, 0.1);
194
+ border: 1px solid rgba(248, 113, 113, 0.25);
195
+ border-radius: 4px;
196
+ padding: 0.1rem 0.4rem;
197
+ }
198
+
199
+ .optional-badge {
200
+ font-size: 0.6875rem;
201
+ font-weight: 400;
202
+ color: #666;
203
+ background-color: rgba(255, 255, 255, 0.04);
204
+ border: 1px solid #333;
205
+ border-radius: 4px;
206
+ padding: 0.1rem 0.4rem;
207
+ }
208
+
209
+ .field-input {
210
+ width: 100%;
211
+ background-color: #111;
212
+ border: 1px solid #2e2e2e;
213
+ border-radius: 8px;
214
+ color: #e8e8e8;
215
+ font-size: 0.9375rem;
216
+ padding: 0.625rem 0.875rem;
217
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
218
+ outline: none;
219
+ }
220
+
221
+ .field-input:focus {
222
+ border-color: #4a6fa5;
223
+ box-shadow: 0 0 0 3px rgba(74, 111, 165, 0.2);
224
+ }
225
+
226
+ .field-input::placeholder {
227
+ color: #555;
228
+ }
229
+
230
+ .help-text {
231
+ font-size: 0.8125rem;
232
+ color: #666;
233
+ margin-top: 0.375rem;
234
+ }
235
+
236
+ .help-text a {
237
+ color: #6c9bd2;
238
+ text-decoration: none;
239
+ }
240
+
241
+ .help-text a:hover {
242
+ text-decoration: underline;
243
+ }
244
+
245
+ .submit-btn {
246
+ width: 100%;
247
+ background-color: #4a6fa5;
248
+ border: none;
249
+ border-radius: 8px;
250
+ color: #fff;
251
+ cursor: pointer;
252
+ font-size: 0.9375rem;
253
+ font-weight: 500;
254
+ padding: 0.75rem 1.5rem;
255
+ transition: background-color 0.15s ease, opacity 0.15s ease;
256
+ margin-top: 0.5rem;
257
+ }
258
+
259
+ .submit-btn:hover {
260
+ background-color: #5a7fb5;
261
+ }
262
+
263
+ .submit-btn:disabled {
264
+ opacity: 0.5;
265
+ cursor: not-allowed;
266
+ }
267
+
268
+ .status-box {
269
+ display: none;
270
+ border-radius: 8px;
271
+ font-size: 0.875rem;
272
+ margin-top: 1rem;
273
+ padding: 0.75rem 1rem;
274
+ }
275
+
276
+ .status-box.success {
277
+ background-color: rgba(52, 199, 89, 0.1);
278
+ border: 1px solid rgba(52, 199, 89, 0.3);
279
+ color: #34c759;
280
+ }
281
+
282
+ .status-box.error {
283
+ background-color: rgba(248, 113, 113, 0.1);
284
+ border: 1px solid rgba(248, 113, 113, 0.3);
285
+ color: #f87171;
286
+ }
287
+
288
+ .capabilities-section {
289
+ margin-top: 0;
290
+ }
291
+
292
+ .capabilities-title {
293
+ font-size: 0.875rem;
294
+ font-weight: 500;
295
+ color: #aaa;
296
+ text-transform: uppercase;
297
+ letter-spacing: 0.05em;
298
+ margin-bottom: 0.875rem;
299
+ }
300
+
301
+ .capabilities-list {
302
+ list-style: none;
303
+ display: flex;
304
+ flex-direction: column;
305
+ gap: 0.625rem;
306
+ }
307
+
308
+ .capability-item {
309
+ background-color: #111;
310
+ border: 1px solid #2a2a2a;
311
+ border-radius: 8px;
312
+ padding: 0.75rem 1rem;
313
+ }
314
+
315
+ .capability-header {
316
+ display: flex;
317
+ align-items: center;
318
+ justify-content: space-between;
319
+ gap: 0.5rem;
320
+ margin-bottom: 0.25rem;
321
+ }
322
+
323
+ .capability-label {
324
+ font-size: 0.875rem;
325
+ font-weight: 500;
326
+ color: #ccc;
327
+ }
328
+
329
+ .capability-priority {
330
+ font-size: 0.6875rem;
331
+ font-weight: 500;
332
+ border-radius: 4px;
333
+ padding: 0.1rem 0.4rem;
334
+ text-transform: capitalize;
335
+ }
336
+
337
+ .priority-high {
338
+ color: #f87171;
339
+ background-color: rgba(248, 113, 113, 0.1);
340
+ border: 1px solid rgba(248, 113, 113, 0.25);
341
+ }
342
+
343
+ .priority-medium {
344
+ color: #fbbf24;
345
+ background-color: rgba(251, 191, 36, 0.1);
346
+ border: 1px solid rgba(251, 191, 36, 0.25);
347
+ }
348
+
349
+ .priority-low {
350
+ color: #6ee7b7;
351
+ background-color: rgba(110, 231, 183, 0.1);
352
+ border: 1px solid rgba(110, 231, 183, 0.25);
353
+ }
354
+
355
+ .capability-desc {
356
+ font-size: 0.8125rem;
357
+ color: #666;
358
+ }
359
+ </style>
360
+ </head>
361
+ <body>
362
+ <div class="container">
363
+ <div class="card">
364
+ <div class="server-header">
365
+ <h1 class="server-name">${displayName}</h1>
366
+ <div class="server-id">${server}</div>
367
+ ${descriptionHtml}
368
+ </div>
369
+
370
+ <p class="form-title">Enter your credentials</p>
371
+
372
+ <form id="credential-form" novalidate>
373
+ ${fieldsHtml}
374
+
375
+ <button type="submit" class="submit-btn" id="submit-btn">
376
+ Connect
377
+ </button>
378
+
379
+ <div class="status-box" id="status-box" role="alert"></div>
380
+ </form>
381
+ </div>
382
+ ${capabilitiesHtml}
383
+ </div>
384
+
385
+ <script>
386
+ (function () {
387
+ var form = document.getElementById("credential-form");
388
+ var submitBtn = document.getElementById("submit-btn");
389
+ var statusBox = document.getElementById("status-box");
390
+ var submitUrl = "${submitUrlEscaped}";
391
+
392
+ function showStatus(type, message) {
393
+ statusBox.className = "status-box " + type;
394
+ statusBox.textContent = message;
395
+ statusBox.style.display = "block";
396
+ }
397
+
398
+ // Derive /otp endpoint URL from submitUrl (replaces /authorize... with /otp).
399
+ function otpUrl() {
400
+ return submitUrl.replace(/\\/authorize.*/, "/otp");
401
+ }
402
+
403
+ // Render (or update in-place) a step-input UI for otp_required / password_required.
404
+ // ns: next_step object with { text, field, input_type, placeholder }.
405
+ // All textual content from ns is inserted via textContent (never innerHTML).
406
+ function showStepInput(ns) {
407
+ // Hide the original credential form after first transition.
408
+ if (form && form.style.display !== "none") {
409
+ form.style.display = "none";
410
+ }
411
+
412
+ // If a step container already exists, update it in-place (chained next_step).
413
+ var container = document.getElementById("step-container");
414
+ var promptEl, inputEl, buttonEl, errorEl;
415
+ if (container) {
416
+ promptEl = document.getElementById("step-prompt");
417
+ inputEl = document.getElementById("step-input");
418
+ buttonEl = document.getElementById("step-submit");
419
+ errorEl = document.getElementById("step-error");
420
+ errorEl.style.display = "none";
421
+ errorEl.textContent = "";
422
+ inputEl.value = "";
423
+ inputEl.disabled = false;
424
+ buttonEl.disabled = false;
425
+ buttonEl.textContent = "Verify";
426
+ } else {
427
+ // Build a fresh step-input container inside the card.
428
+ var card = form.parentNode;
429
+ container = document.createElement("div");
430
+ container.id = "step-container";
431
+
432
+ promptEl = document.createElement("p");
433
+ promptEl.id = "step-prompt";
434
+ promptEl.className = "form-title";
435
+ container.appendChild(promptEl);
436
+
437
+ var fieldGroup = document.createElement("div");
438
+ fieldGroup.className = "field-group";
439
+ inputEl = document.createElement("input");
440
+ inputEl.id = "step-input";
441
+ inputEl.className = "field-input";
442
+ inputEl.setAttribute("autocomplete", "off");
443
+ inputEl.setAttribute("autocorrect", "off");
444
+ inputEl.setAttribute("autocapitalize", "off");
445
+ inputEl.setAttribute("spellcheck", "false");
446
+ inputEl.setAttribute("aria-labelledby", "step-prompt");
447
+ fieldGroup.appendChild(inputEl);
448
+ container.appendChild(fieldGroup);
449
+
450
+ buttonEl = document.createElement("button");
451
+ buttonEl.type = "button";
452
+ buttonEl.id = "step-submit";
453
+ buttonEl.className = "submit-btn";
454
+ buttonEl.textContent = "Verify";
455
+ container.appendChild(buttonEl);
456
+
457
+ errorEl = document.createElement("div");
458
+ errorEl.id = "step-error";
459
+ errorEl.className = "status-box error";
460
+ errorEl.setAttribute("role", "alert");
461
+ errorEl.style.display = "none";
462
+ container.appendChild(errorEl);
463
+
464
+ card.appendChild(container);
465
+
466
+ // Submit handlers (attached once, read current field name from dataset).
467
+ buttonEl.addEventListener("click", function () {
468
+ submitStep();
469
+ });
470
+ inputEl.addEventListener("keydown", function (evt) {
471
+ if (evt.key === "Enter") {
472
+ evt.preventDefault();
473
+ submitStep();
474
+ }
475
+ });
476
+ }
477
+
478
+ // Populate prompt + input attributes via safe DOM APIs.
479
+ promptEl.textContent = ns.text || "";
480
+ inputEl.setAttribute("type", ns.input_type || "text");
481
+ inputEl.setAttribute("placeholder", ns.placeholder || "");
482
+ // Stash field name so submitStep can read it at click time.
483
+ inputEl.dataset.field = ns.field || "value";
484
+ inputEl.focus();
485
+ }
486
+
487
+ function submitStep() {
488
+ var inputEl = document.getElementById("step-input");
489
+ var buttonEl = document.getElementById("step-submit");
490
+ var errorEl = document.getElementById("step-error");
491
+ var fieldName = inputEl.dataset.field || "value";
492
+ var value = inputEl.value;
493
+ if (value.trim() === "") {
494
+ errorEl.textContent = "Please enter a value.";
495
+ errorEl.style.display = "block";
496
+ return;
497
+ }
498
+ errorEl.style.display = "none";
499
+ errorEl.textContent = "";
500
+ buttonEl.disabled = true;
501
+ buttonEl.textContent = "Verifying...";
502
+ inputEl.disabled = true;
503
+
504
+ var body = {};
505
+ body[fieldName] = value;
506
+
507
+ fetch(otpUrl(), {
508
+ method: "POST",
509
+ headers: { "Content-Type": "application/json" },
510
+ body: JSON.stringify(body),
511
+ })
512
+ .then(function (response) {
513
+ return response.json().then(function (data) {
514
+ if (data.ok) {
515
+ if (data.next_step && (data.next_step.type === "otp_required" || data.next_step.type === "password_required")) {
516
+ // Chain: update in place with new prompt/field/type.
517
+ showStepInput(data.next_step);
518
+ } else {
519
+ // Completed.
520
+ var container = document.getElementById("step-container");
521
+ while (container.firstChild) {
522
+ container.removeChild(container.firstChild);
523
+ }
524
+ var done = document.createElement("div");
525
+ done.className = "status-box success";
526
+ done.style.display = "block";
527
+ done.textContent = "Setup complete! You can close this tab.";
528
+ container.appendChild(done);
529
+ }
530
+ } else {
531
+ // Error: show message, re-enable input + button for retry, keep value.
532
+ errorEl.textContent = data.error || data.error_description || "Verification failed.";
533
+ errorEl.style.display = "block";
534
+ inputEl.disabled = false;
535
+ buttonEl.disabled = false;
536
+ buttonEl.textContent = "Verify";
537
+ inputEl.focus();
538
+ }
539
+ });
540
+ })
541
+ .catch(function (err) {
542
+ errorEl.textContent = "Network error: " + err.message;
543
+ errorEl.style.display = "block";
544
+ inputEl.disabled = false;
545
+ buttonEl.disabled = false;
546
+ buttonEl.textContent = "Verify";
547
+ });
548
+ }
549
+
550
+ form.addEventListener("submit", function (event) {
551
+ event.preventDefault();
552
+
553
+ var inputs = form.querySelectorAll(".field-input");
554
+ var payload = {};
555
+ var valid = true;
556
+
557
+ inputs.forEach(function (input) {
558
+ if (input.hasAttribute("required") && input.value.trim() === "") {
559
+ valid = false;
560
+ input.style.borderColor = "#f87171";
561
+ } else {
562
+ input.style.borderColor = "";
563
+ payload[input.name] = input.value;
564
+ }
565
+ });
566
+
567
+ if (!valid) {
568
+ showStatus("error", "Please fill in all required fields.");
569
+ return;
570
+ }
571
+
572
+ submitBtn.disabled = true;
573
+ submitBtn.textContent = "Connecting...";
574
+ statusBox.style.display = "none";
575
+
576
+ fetch(submitUrl, {
577
+ method: "POST",
578
+ headers: { "Content-Type": "application/json" },
579
+ body: JSON.stringify(payload),
580
+ })
581
+ .then(function (response) {
582
+ return response.json().then(function (data) {
583
+ if (data.ok) {
584
+ form.querySelectorAll(".field-input").forEach(function (i) {
585
+ i.disabled = true;
586
+ });
587
+ submitBtn.disabled = true;
588
+ submitBtn.textContent = "Connected";
589
+ if (data.next_step && data.next_step.type === "oauth_device_code") {
590
+ var ns = data.next_step;
591
+ statusBox.textContent = "";
592
+ var title = document.createElement("strong");
593
+ title.textContent = "API keys saved!";
594
+ statusBox.appendChild(title);
595
+ statusBox.appendChild(document.createElement("br"));
596
+ statusBox.appendChild(document.createElement("br"));
597
+ var label = document.createTextNode("Authorize Google Drive sync:");
598
+ statusBox.appendChild(label);
599
+ statusBox.appendChild(document.createElement("br"));
600
+ var link = document.createElement("a");
601
+ link.href = ns.verification_url;
602
+ link.target = "_blank";
603
+ link.rel = "noopener";
604
+ link.style.cssText = "color:#60a5fa;font-weight:bold";
605
+ link.textContent = ns.verification_url;
606
+ statusBox.appendChild(link);
607
+ statusBox.appendChild(document.createElement("br"));
608
+ statusBox.appendChild(document.createElement("br"));
609
+ var codeLabel = document.createTextNode("Enter code: ");
610
+ statusBox.appendChild(codeLabel);
611
+ var codeEl = document.createElement("strong");
612
+ codeEl.style.cssText = "font-size:1.2em;letter-spacing:0.1em";
613
+ codeEl.textContent = ns.user_code;
614
+ statusBox.appendChild(codeEl);
615
+ statusBox.appendChild(document.createElement("br"));
616
+ statusBox.appendChild(document.createElement("br"));
617
+ var waiting = document.createElement("span");
618
+ waiting.id = "gdrive-waiting";
619
+ waiting.style.color = "#888";
620
+ waiting.textContent = "Waiting for authorization...";
621
+ statusBox.appendChild(waiting);
622
+ statusBox.className = "status-box info";
623
+ statusBox.style.display = "block";
624
+ // Poll /setup-status until GDrive auth completes
625
+ var pollInterval = setInterval(function () {
626
+ fetch(submitUrl.replace(/\\/authorize.*/, "/setup-status"))
627
+ .then(function (r) { return r.json(); })
628
+ .then(function (s) {
629
+ if (s.gdrive === "complete") {
630
+ clearInterval(pollInterval);
631
+ var w = document.getElementById("gdrive-waiting");
632
+ if (w) {
633
+ w.style.color = "#34c759";
634
+ w.textContent = "Google Drive authorized! Setup complete. You can close this tab.";
635
+ }
636
+ }
637
+ })
638
+ .catch(function () {});
639
+ }, 3000);
640
+ } else if (data.next_step && (data.next_step.type === "otp_required" || data.next_step.type === "password_required")) {
641
+ // Multi-step auth: hide form, show step input UI.
642
+ statusBox.style.display = "none";
643
+ showStepInput(data.next_step);
644
+ } else if (data.next_step && data.next_step.type === "info") {
645
+ showStatus("success", data.next_step.message || "Setup saved. Additional steps may be required.");
646
+ } else {
647
+ var successMsg = data.message || "Connected successfully. You can close this window.";
648
+ showStatus("success", successMsg);
649
+ }
650
+ } else {
651
+ showStatus("error", data.error || data.error_description || "Request failed.");
652
+ submitBtn.disabled = false;
653
+ submitBtn.textContent = "Connect";
654
+ }
655
+ });
656
+ })
657
+ .catch(function (err) {
658
+ showStatus("error", "Network error: " + err.message);
659
+ submitBtn.disabled = false;
660
+ submitBtn.textContent = "Connect";
661
+ });
662
+ });
663
+ })();
664
+ </script>
665
+ </body>
666
+ </html>`;
667
+ }
668
+ //# sourceMappingURL=credential-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-form.js","sourceRoot":"","sources":["../../src/auth/credential-form.ts"],"names":[],"mappings":"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"}