@authrim/setup 0.1.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 (78) hide show
  1. package/README.md +303 -0
  2. package/dist/__tests__/config.test.d.ts +5 -0
  3. package/dist/__tests__/config.test.d.ts.map +1 -0
  4. package/dist/__tests__/config.test.js +115 -0
  5. package/dist/__tests__/config.test.js.map +1 -0
  6. package/dist/__tests__/keys.test.d.ts +5 -0
  7. package/dist/__tests__/keys.test.d.ts.map +1 -0
  8. package/dist/__tests__/keys.test.js +87 -0
  9. package/dist/__tests__/keys.test.js.map +1 -0
  10. package/dist/__tests__/naming.test.d.ts +5 -0
  11. package/dist/__tests__/naming.test.d.ts.map +1 -0
  12. package/dist/__tests__/naming.test.js +84 -0
  13. package/dist/__tests__/naming.test.js.map +1 -0
  14. package/dist/cli/commands/config.d.ts +13 -0
  15. package/dist/cli/commands/config.d.ts.map +1 -0
  16. package/dist/cli/commands/config.js +231 -0
  17. package/dist/cli/commands/config.js.map +1 -0
  18. package/dist/cli/commands/deploy.d.ts +21 -0
  19. package/dist/cli/commands/deploy.d.ts.map +1 -0
  20. package/dist/cli/commands/deploy.js +304 -0
  21. package/dist/cli/commands/deploy.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts +14 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -0
  24. package/dist/cli/commands/init.js +1248 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/core/admin.d.ts +64 -0
  27. package/dist/core/admin.d.ts.map +1 -0
  28. package/dist/core/admin.js +247 -0
  29. package/dist/core/admin.js.map +1 -0
  30. package/dist/core/cloudflare.d.ts +157 -0
  31. package/dist/core/cloudflare.d.ts.map +1 -0
  32. package/dist/core/cloudflare.js +452 -0
  33. package/dist/core/cloudflare.js.map +1 -0
  34. package/dist/core/config.d.ts +891 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +208 -0
  37. package/dist/core/config.js.map +1 -0
  38. package/dist/core/deploy.d.ts +81 -0
  39. package/dist/core/deploy.d.ts.map +1 -0
  40. package/dist/core/deploy.js +389 -0
  41. package/dist/core/deploy.js.map +1 -0
  42. package/dist/core/keys.d.ts +111 -0
  43. package/dist/core/keys.d.ts.map +1 -0
  44. package/dist/core/keys.js +287 -0
  45. package/dist/core/keys.js.map +1 -0
  46. package/dist/core/lock.d.ts +220 -0
  47. package/dist/core/lock.d.ts.map +1 -0
  48. package/dist/core/lock.js +230 -0
  49. package/dist/core/lock.js.map +1 -0
  50. package/dist/core/naming.d.ts +151 -0
  51. package/dist/core/naming.d.ts.map +1 -0
  52. package/dist/core/naming.js +209 -0
  53. package/dist/core/naming.js.map +1 -0
  54. package/dist/core/source.d.ts +68 -0
  55. package/dist/core/source.d.ts.map +1 -0
  56. package/dist/core/source.js +285 -0
  57. package/dist/core/source.js.map +1 -0
  58. package/dist/core/wrangler.d.ts +87 -0
  59. package/dist/core/wrangler.d.ts.map +1 -0
  60. package/dist/core/wrangler.js +398 -0
  61. package/dist/core/wrangler.js.map +1 -0
  62. package/dist/index.d.ts +11 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +117 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/web/api.d.ts +21 -0
  67. package/dist/web/api.d.ts.map +1 -0
  68. package/dist/web/api.js +423 -0
  69. package/dist/web/api.js.map +1 -0
  70. package/dist/web/server.d.ts +12 -0
  71. package/dist/web/server.d.ts.map +1 -0
  72. package/dist/web/server.js +112 -0
  73. package/dist/web/server.js.map +1 -0
  74. package/dist/web/ui.d.ts +7 -0
  75. package/dist/web/ui.d.ts.map +1 -0
  76. package/dist/web/ui.js +765 -0
  77. package/dist/web/ui.js.map +1 -0
  78. package/package.json +61 -0
package/dist/web/ui.js ADDED
@@ -0,0 +1,765 @@
1
+ /**
2
+ * HTML Template for Authrim Setup Web UI
3
+ *
4
+ * A simple, self-contained UI for the setup wizard.
5
+ */
6
+ export function getHtmlTemplate(sessionToken) {
7
+ // Escape token for safe embedding in JavaScript
8
+ const safeToken = sessionToken ? sessionToken.replace(/['"\\]/g, '') : '';
9
+ return `<!DOCTYPE html>
10
+ <html lang="en">
11
+ <head>
12
+ <meta charset="UTF-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
14
+ <title>Authrim Setup</title>
15
+ <style>
16
+ :root {
17
+ --primary: #2563eb;
18
+ --primary-dark: #1d4ed8;
19
+ --success: #10b981;
20
+ --error: #ef4444;
21
+ --warning: #f59e0b;
22
+ --bg: #f8fafc;
23
+ --card-bg: #ffffff;
24
+ --text: #1e293b;
25
+ --text-muted: #64748b;
26
+ --border: #e2e8f0;
27
+ }
28
+
29
+ * {
30
+ margin: 0;
31
+ padding: 0;
32
+ box-sizing: border-box;
33
+ }
34
+
35
+ body {
36
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
37
+ background: var(--bg);
38
+ color: var(--text);
39
+ line-height: 1.6;
40
+ min-height: 100vh;
41
+ }
42
+
43
+ .container {
44
+ max-width: 800px;
45
+ margin: 0 auto;
46
+ padding: 2rem;
47
+ }
48
+
49
+ header {
50
+ text-align: center;
51
+ margin-bottom: 2rem;
52
+ }
53
+
54
+ h1 {
55
+ font-size: 2rem;
56
+ color: var(--primary);
57
+ margin-bottom: 0.5rem;
58
+ }
59
+
60
+ .subtitle {
61
+ color: var(--text-muted);
62
+ }
63
+
64
+ .card {
65
+ background: var(--card-bg);
66
+ border-radius: 12px;
67
+ padding: 1.5rem;
68
+ margin-bottom: 1.5rem;
69
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
70
+ }
71
+
72
+ .card-title {
73
+ font-size: 1.25rem;
74
+ font-weight: 600;
75
+ margin-bottom: 1rem;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 0.5rem;
79
+ }
80
+
81
+ .status-badge {
82
+ font-size: 0.75rem;
83
+ padding: 0.25rem 0.5rem;
84
+ border-radius: 9999px;
85
+ font-weight: 500;
86
+ }
87
+
88
+ .status-pending { background: var(--border); color: var(--text-muted); }
89
+ .status-running { background: #dbeafe; color: var(--primary); }
90
+ .status-success { background: #d1fae5; color: var(--success); }
91
+ .status-error { background: #fee2e2; color: var(--error); }
92
+
93
+ .form-group {
94
+ margin-bottom: 1rem;
95
+ }
96
+
97
+ label {
98
+ display: block;
99
+ font-weight: 500;
100
+ margin-bottom: 0.5rem;
101
+ }
102
+
103
+ input[type="text"],
104
+ input[type="password"],
105
+ select {
106
+ width: 100%;
107
+ padding: 0.75rem;
108
+ border: 1px solid var(--border);
109
+ border-radius: 8px;
110
+ font-size: 1rem;
111
+ transition: border-color 0.2s;
112
+ }
113
+
114
+ input:focus,
115
+ select:focus {
116
+ outline: none;
117
+ border-color: var(--primary);
118
+ }
119
+
120
+ .checkbox-group {
121
+ display: flex;
122
+ flex-wrap: wrap;
123
+ gap: 1rem;
124
+ }
125
+
126
+ .checkbox-item {
127
+ display: flex;
128
+ align-items: center;
129
+ gap: 0.5rem;
130
+ }
131
+
132
+ button {
133
+ padding: 0.75rem 1.5rem;
134
+ border-radius: 8px;
135
+ font-size: 1rem;
136
+ font-weight: 500;
137
+ cursor: pointer;
138
+ transition: all 0.2s;
139
+ border: none;
140
+ }
141
+
142
+ .btn-primary {
143
+ background: var(--primary);
144
+ color: white;
145
+ }
146
+
147
+ .btn-primary:hover:not(:disabled) {
148
+ background: var(--primary-dark);
149
+ }
150
+
151
+ .btn-primary:disabled {
152
+ opacity: 0.6;
153
+ cursor: not-allowed;
154
+ }
155
+
156
+ .btn-secondary {
157
+ background: var(--border);
158
+ color: var(--text);
159
+ }
160
+
161
+ .btn-secondary:hover {
162
+ background: #cbd5e1;
163
+ }
164
+
165
+ .button-group {
166
+ display: flex;
167
+ gap: 1rem;
168
+ margin-top: 1.5rem;
169
+ }
170
+
171
+ .progress-log {
172
+ background: #1e293b;
173
+ border-radius: 8px;
174
+ padding: 1rem;
175
+ max-height: 300px;
176
+ overflow-y: auto;
177
+ font-family: 'Monaco', 'Menlo', monospace;
178
+ font-size: 0.875rem;
179
+ }
180
+
181
+ .progress-log pre {
182
+ color: #e2e8f0;
183
+ white-space: pre-wrap;
184
+ word-break: break-word;
185
+ }
186
+
187
+ .step-indicator {
188
+ display: flex;
189
+ justify-content: center;
190
+ gap: 0.5rem;
191
+ margin-bottom: 2rem;
192
+ }
193
+
194
+ .step {
195
+ width: 40px;
196
+ height: 40px;
197
+ border-radius: 50%;
198
+ display: flex;
199
+ align-items: center;
200
+ justify-content: center;
201
+ font-weight: 600;
202
+ font-size: 0.875rem;
203
+ }
204
+
205
+ .step-active {
206
+ background: var(--primary);
207
+ color: white;
208
+ }
209
+
210
+ .step-complete {
211
+ background: var(--success);
212
+ color: white;
213
+ }
214
+
215
+ .step-pending {
216
+ background: var(--border);
217
+ color: var(--text-muted);
218
+ }
219
+
220
+ .step-connector {
221
+ width: 40px;
222
+ height: 2px;
223
+ background: var(--border);
224
+ align-self: center;
225
+ }
226
+
227
+ .alert {
228
+ padding: 1rem;
229
+ border-radius: 8px;
230
+ margin-bottom: 1rem;
231
+ }
232
+
233
+ .alert-success { background: #d1fae5; color: #065f46; }
234
+ .alert-error { background: #fee2e2; color: #991b1b; }
235
+ .alert-warning { background: #fef3c7; color: #92400e; }
236
+ .alert-info { background: #dbeafe; color: #1e40af; }
237
+
238
+ .url-display {
239
+ background: var(--bg);
240
+ padding: 1rem;
241
+ border-radius: 8px;
242
+ margin-top: 1rem;
243
+ }
244
+
245
+ .url-item {
246
+ display: flex;
247
+ gap: 0.5rem;
248
+ margin-bottom: 0.5rem;
249
+ }
250
+
251
+ .url-label {
252
+ font-weight: 500;
253
+ min-width: 100px;
254
+ }
255
+
256
+ .url-value {
257
+ color: var(--primary);
258
+ }
259
+
260
+ .hidden { display: none; }
261
+ </style>
262
+ </head>
263
+ <body>
264
+ <div class="container">
265
+ <header>
266
+ <h1>🔐 Authrim Setup</h1>
267
+ <p class="subtitle">OIDC Provider on Cloudflare Workers</p>
268
+ </header>
269
+
270
+ <div class="step-indicator">
271
+ <div class="step step-active" id="step-1">1</div>
272
+ <div class="step-connector"></div>
273
+ <div class="step step-pending" id="step-2">2</div>
274
+ <div class="step-connector"></div>
275
+ <div class="step step-pending" id="step-3">3</div>
276
+ <div class="step-connector"></div>
277
+ <div class="step step-pending" id="step-4">4</div>
278
+ </div>
279
+
280
+ <!-- Step 1: Prerequisites -->
281
+ <div id="section-prerequisites" class="card">
282
+ <h2 class="card-title">
283
+ Prerequisites
284
+ <span class="status-badge status-running" id="prereq-status">Checking...</span>
285
+ </h2>
286
+ <div id="prereq-content">
287
+ <p>Checking system requirements...</p>
288
+ </div>
289
+ </div>
290
+
291
+ <!-- Step 2: Configuration -->
292
+ <div id="section-config" class="card hidden">
293
+ <h2 class="card-title">Configuration</h2>
294
+
295
+ <div class="form-group">
296
+ <label for="env">Environment</label>
297
+ <select id="env">
298
+ <option value="prod">Production (prod)</option>
299
+ <option value="staging">Staging</option>
300
+ <option value="dev">Development (dev)</option>
301
+ </select>
302
+ </div>
303
+
304
+ <div class="form-group">
305
+ <label for="domain">Custom Domain (optional)</label>
306
+ <input type="text" id="domain" placeholder="auth.example.com">
307
+ <small style="color: var(--text-muted)">Leave empty to use workers.dev / pages.dev</small>
308
+ </div>
309
+
310
+ <h3 style="margin: 1.5rem 0 1rem; font-size: 1rem;">Components</h3>
311
+ <div class="checkbox-group">
312
+ <label class="checkbox-item">
313
+ <input type="checkbox" id="comp-api" checked disabled>
314
+ API (required)
315
+ </label>
316
+ <label class="checkbox-item">
317
+ <input type="checkbox" id="comp-login-ui" checked>
318
+ Login UI
319
+ </label>
320
+ <label class="checkbox-item">
321
+ <input type="checkbox" id="comp-admin-ui" checked>
322
+ Admin UI
323
+ </label>
324
+ <label class="checkbox-item">
325
+ <input type="checkbox" id="comp-saml">
326
+ SAML IdP
327
+ </label>
328
+ <label class="checkbox-item">
329
+ <input type="checkbox" id="comp-vc">
330
+ Verifiable Credentials
331
+ </label>
332
+ </div>
333
+
334
+ <div class="button-group">
335
+ <button class="btn-primary" id="btn-configure">Continue</button>
336
+ </div>
337
+ </div>
338
+
339
+ <!-- Step 3: Provisioning -->
340
+ <div id="section-provision" class="card hidden">
341
+ <h2 class="card-title">
342
+ Resource Provisioning
343
+ <span class="status-badge status-pending" id="provision-status">Ready</span>
344
+ </h2>
345
+
346
+ <p style="margin-bottom: 1rem;">The following resources will be created:</p>
347
+ <ul style="margin-left: 1.5rem; margin-bottom: 1rem;">
348
+ <li>2 D1 Databases (core, PII)</li>
349
+ <li>8 KV Namespaces</li>
350
+ <li>RSA Key Pair for JWT signing</li>
351
+ </ul>
352
+
353
+ <div class="progress-log hidden" id="provision-log">
354
+ <pre id="provision-output"></pre>
355
+ </div>
356
+
357
+ <div class="button-group">
358
+ <button class="btn-secondary" id="btn-back-config">Back</button>
359
+ <button class="btn-primary" id="btn-provision">Create Resources</button>
360
+ </div>
361
+ </div>
362
+
363
+ <!-- Step 4: Deployment -->
364
+ <div id="section-deploy" class="card hidden">
365
+ <h2 class="card-title">
366
+ Deployment
367
+ <span class="status-badge status-pending" id="deploy-status">Ready</span>
368
+ </h2>
369
+
370
+ <p style="margin-bottom: 1rem;">Ready to deploy Authrim workers to Cloudflare.</p>
371
+
372
+ <div class="progress-log hidden" id="deploy-log">
373
+ <pre id="deploy-output"></pre>
374
+ </div>
375
+
376
+ <div class="button-group">
377
+ <button class="btn-secondary" id="btn-back-provision">Back</button>
378
+ <button class="btn-primary" id="btn-deploy">Deploy</button>
379
+ </div>
380
+ </div>
381
+
382
+ <!-- Complete -->
383
+ <div id="section-complete" class="card hidden">
384
+ <h2 class="card-title" style="color: var(--success);">
385
+ Setup Complete!
386
+ </h2>
387
+
388
+ <p>Authrim has been successfully deployed.</p>
389
+
390
+ <div class="url-display" id="urls">
391
+ <!-- URLs will be inserted here -->
392
+ </div>
393
+
394
+ <div class="alert alert-info" style="margin-top: 1rem;">
395
+ <strong>Next Steps:</strong>
396
+ <ol style="margin-left: 1.5rem; margin-top: 0.5rem;">
397
+ <li>Visit the Admin UI to create your first client</li>
398
+ <li>Configure your application to use the OIDC endpoints</li>
399
+ </ol>
400
+ </div>
401
+ </div>
402
+ </div>
403
+
404
+ <script>
405
+ // Session token for API authentication (embedded by server)
406
+ const SESSION_TOKEN = '${safeToken}';
407
+
408
+ // State
409
+ let currentStep = 1;
410
+ let config = {};
411
+
412
+ // Elements
413
+ const steps = {
414
+ 1: document.getElementById('step-1'),
415
+ 2: document.getElementById('step-2'),
416
+ 3: document.getElementById('step-3'),
417
+ 4: document.getElementById('step-4'),
418
+ };
419
+
420
+ const sections = {
421
+ prerequisites: document.getElementById('section-prerequisites'),
422
+ config: document.getElementById('section-config'),
423
+ provision: document.getElementById('section-provision'),
424
+ deploy: document.getElementById('section-deploy'),
425
+ complete: document.getElementById('section-complete'),
426
+ };
427
+
428
+ // API helpers (with session token authentication)
429
+ async function api(endpoint, options = {}) {
430
+ const response = await fetch('/api' + endpoint, {
431
+ headers: {
432
+ 'Content-Type': 'application/json',
433
+ 'X-Session-Token': SESSION_TOKEN,
434
+ },
435
+ ...options,
436
+ body: options.body ? JSON.stringify(options.body) : undefined,
437
+ });
438
+ return response.json();
439
+ }
440
+
441
+ // Step navigation
442
+ function setStep(step) {
443
+ currentStep = step;
444
+ for (let i = 1; i <= 4; i++) {
445
+ const el = steps[i];
446
+ el.className = 'step ' + (i < step ? 'step-complete' : i === step ? 'step-active' : 'step-pending');
447
+ }
448
+ }
449
+
450
+ function showSection(name) {
451
+ Object.values(sections).forEach(s => s.classList.add('hidden'));
452
+ sections[name].classList.remove('hidden');
453
+ }
454
+
455
+ // Safe DOM element creation helpers
456
+ function createAlert(type, content) {
457
+ const div = document.createElement('div');
458
+ div.className = 'alert alert-' + type;
459
+ if (typeof content === 'string') {
460
+ div.textContent = content;
461
+ } else {
462
+ div.appendChild(content);
463
+ }
464
+ return div;
465
+ }
466
+
467
+ function createUrlItem(label, url) {
468
+ const div = document.createElement('div');
469
+ div.className = 'url-item';
470
+
471
+ const labelSpan = document.createElement('span');
472
+ labelSpan.className = 'url-label';
473
+ labelSpan.textContent = label;
474
+
475
+ const link = document.createElement('a');
476
+ link.href = url;
477
+ link.target = '_blank';
478
+ link.className = 'url-value';
479
+ link.textContent = url;
480
+
481
+ div.appendChild(labelSpan);
482
+ div.appendChild(link);
483
+ return div;
484
+ }
485
+
486
+ // Check prerequisites
487
+ async function checkPrerequisites() {
488
+ const prereqStatus = document.getElementById('prereq-status');
489
+ const prereqContent = document.getElementById('prereq-content');
490
+
491
+ try {
492
+ const result = await api('/prerequisites');
493
+
494
+ // Clear existing content
495
+ prereqContent.textContent = '';
496
+
497
+ if (!result.wranglerInstalled) {
498
+ prereqStatus.textContent = 'Error';
499
+ prereqStatus.className = 'status-badge status-error';
500
+
501
+ const alertDiv = document.createElement('div');
502
+ alertDiv.className = 'alert alert-error';
503
+
504
+ const title = document.createElement('strong');
505
+ title.textContent = 'Wrangler not installed';
506
+ alertDiv.appendChild(title);
507
+
508
+ const para = document.createElement('p');
509
+ para.textContent = 'Please install wrangler first:';
510
+ alertDiv.appendChild(para);
511
+
512
+ const code = document.createElement('code');
513
+ code.style.display = 'block';
514
+ code.style.marginTop = '0.5rem';
515
+ code.textContent = 'npm install -g wrangler';
516
+ alertDiv.appendChild(code);
517
+
518
+ prereqContent.appendChild(alertDiv);
519
+ return false;
520
+ }
521
+
522
+ if (!result.auth.isLoggedIn) {
523
+ prereqStatus.textContent = 'Login Required';
524
+ prereqStatus.className = 'status-badge status-warning';
525
+
526
+ const alertDiv = document.createElement('div');
527
+ alertDiv.className = 'alert alert-warning';
528
+
529
+ const title = document.createElement('strong');
530
+ title.textContent = 'Not logged in to Cloudflare';
531
+ alertDiv.appendChild(title);
532
+
533
+ const para1 = document.createElement('p');
534
+ para1.textContent = 'Please run this command in your terminal:';
535
+ alertDiv.appendChild(para1);
536
+
537
+ const code = document.createElement('code');
538
+ code.style.display = 'block';
539
+ code.style.marginTop = '0.5rem';
540
+ code.textContent = 'wrangler login';
541
+ alertDiv.appendChild(code);
542
+
543
+ const para2 = document.createElement('p');
544
+ para2.style.marginTop = '0.5rem';
545
+ para2.textContent = 'Then refresh this page.';
546
+ alertDiv.appendChild(para2);
547
+
548
+ prereqContent.appendChild(alertDiv);
549
+ return false;
550
+ }
551
+
552
+ prereqStatus.textContent = 'Ready';
553
+ prereqStatus.className = 'status-badge status-success';
554
+
555
+ const alertDiv = document.createElement('div');
556
+ alertDiv.className = 'alert alert-success';
557
+
558
+ const p1 = document.createElement('p');
559
+ p1.textContent = 'Wrangler installed';
560
+ alertDiv.appendChild(p1);
561
+
562
+ const p2 = document.createElement('p');
563
+ p2.textContent = 'Logged in as ' + (result.auth.email || 'Unknown');
564
+ alertDiv.appendChild(p2);
565
+
566
+ prereqContent.appendChild(alertDiv);
567
+
568
+ const buttonGroup = document.createElement('div');
569
+ buttonGroup.className = 'button-group';
570
+
571
+ const btn = document.createElement('button');
572
+ btn.className = 'btn-primary';
573
+ btn.textContent = 'Start Setup';
574
+ btn.addEventListener('click', startSetup);
575
+ buttonGroup.appendChild(btn);
576
+
577
+ prereqContent.appendChild(buttonGroup);
578
+
579
+ return true;
580
+ } catch (error) {
581
+ prereqStatus.textContent = 'Error';
582
+ prereqStatus.className = 'status-badge status-error';
583
+ prereqContent.textContent = '';
584
+ prereqContent.appendChild(createAlert('error', 'Error checking prerequisites: ' + error.message));
585
+ return false;
586
+ }
587
+ }
588
+
589
+ // Start setup
590
+ function startSetup() {
591
+ setStep(2);
592
+ showSection('config');
593
+ }
594
+
595
+ // Configure
596
+ document.getElementById('btn-configure').addEventListener('click', async () => {
597
+ const env = document.getElementById('env').value;
598
+ const domain = document.getElementById('domain').value;
599
+
600
+ config = {
601
+ env,
602
+ domain: domain || null,
603
+ components: {
604
+ api: true,
605
+ loginUi: document.getElementById('comp-login-ui').checked,
606
+ adminUi: document.getElementById('comp-admin-ui').checked,
607
+ saml: document.getElementById('comp-saml').checked,
608
+ vc: document.getElementById('comp-vc').checked,
609
+ },
610
+ };
611
+
612
+ // Create default config
613
+ await api('/config/default', {
614
+ method: 'POST',
615
+ body: { env, domain },
616
+ });
617
+
618
+ setStep(3);
619
+ showSection('provision');
620
+ });
621
+
622
+ document.getElementById('btn-back-config').addEventListener('click', () => {
623
+ setStep(2);
624
+ showSection('config');
625
+ });
626
+
627
+ // Provision
628
+ document.getElementById('btn-provision').addEventListener('click', async () => {
629
+ const btn = document.getElementById('btn-provision');
630
+ const status = document.getElementById('provision-status');
631
+ const log = document.getElementById('provision-log');
632
+ const output = document.getElementById('provision-output');
633
+
634
+ btn.disabled = true;
635
+ status.textContent = 'Running...';
636
+ status.className = 'status-badge status-running';
637
+ log.classList.remove('hidden');
638
+ output.textContent = '';
639
+
640
+ try {
641
+ // Generate keys
642
+ output.textContent += 'Generating cryptographic keys...\\n';
643
+ await api('/keys/generate', {
644
+ method: 'POST',
645
+ body: { keyId: config.env + '-key-' + Date.now() },
646
+ });
647
+ output.textContent += 'Keys generated\\n\\n';
648
+
649
+ // Provision resources
650
+ output.textContent += 'Provisioning Cloudflare resources...\\n';
651
+ const result = await api('/provision', {
652
+ method: 'POST',
653
+ body: { env: config.env },
654
+ });
655
+
656
+ if (result.success) {
657
+ output.textContent += '\\nProvisioning complete!\\n';
658
+ status.textContent = 'Complete';
659
+ status.className = 'status-badge status-success';
660
+
661
+ setStep(4);
662
+ setTimeout(() => showSection('deploy'), 1000);
663
+ } else {
664
+ throw new Error(result.error);
665
+ }
666
+ } catch (error) {
667
+ output.textContent += '\\nError: ' + error.message + '\\n';
668
+ status.textContent = 'Error';
669
+ status.className = 'status-badge status-error';
670
+ btn.disabled = false;
671
+ }
672
+ });
673
+
674
+ document.getElementById('btn-back-provision').addEventListener('click', () => {
675
+ setStep(3);
676
+ showSection('provision');
677
+ });
678
+
679
+ // Deploy
680
+ document.getElementById('btn-deploy').addEventListener('click', async () => {
681
+ const btn = document.getElementById('btn-deploy');
682
+ const status = document.getElementById('deploy-status');
683
+ const log = document.getElementById('deploy-log');
684
+ const output = document.getElementById('deploy-output');
685
+
686
+ btn.disabled = true;
687
+ status.textContent = 'Deploying...';
688
+ status.className = 'status-badge status-running';
689
+ log.classList.remove('hidden');
690
+ output.textContent = 'Starting deployment...\\n\\n';
691
+
692
+ try {
693
+ // Generate wrangler configs first
694
+ output.textContent += 'Generating wrangler.toml files...\\n';
695
+ await api('/wrangler/generate', {
696
+ method: 'POST',
697
+ body: { env: config.env },
698
+ });
699
+ output.textContent += 'Config files generated\\n\\n';
700
+
701
+ // Start deployment
702
+ output.textContent += 'Deploying workers...\\n';
703
+
704
+ // Poll for status updates
705
+ const pollInterval = setInterval(async () => {
706
+ const statusResult = await api('/deploy/status');
707
+ if (statusResult.progress.length > 0) {
708
+ output.textContent = statusResult.progress.join('\\n') + '\\n';
709
+ }
710
+ }, 1000);
711
+
712
+ const result = await api('/deploy', {
713
+ method: 'POST',
714
+ body: {
715
+ env: config.env,
716
+ dryRun: false,
717
+ },
718
+ });
719
+
720
+ clearInterval(pollInterval);
721
+
722
+ if (result.success) {
723
+ output.textContent += '\\nDeployment complete!\\n';
724
+ status.textContent = 'Complete';
725
+ status.className = 'status-badge status-success';
726
+
727
+ // Show completion
728
+ showComplete();
729
+ } else {
730
+ throw new Error(result.error || 'Deployment failed');
731
+ }
732
+ } catch (error) {
733
+ output.textContent += '\\nError: ' + error.message + '\\n';
734
+ status.textContent = 'Error';
735
+ status.className = 'status-badge status-error';
736
+ btn.disabled = false;
737
+ }
738
+ });
739
+
740
+ // Show completion
741
+ function showComplete() {
742
+ const urlsEl = document.getElementById('urls');
743
+ const env = config.env;
744
+ const domain = config.domain;
745
+
746
+ const apiUrl = domain ? 'https://' + domain : 'https://' + env + '-ar-router.workers.dev';
747
+ const loginUrl = domain ? 'https://' + domain + '/login' : 'https://' + env + '-ar-ui.pages.dev';
748
+ const adminUrl = domain ? 'https://' + domain + '/admin' : 'https://' + env + '-ar-ui.pages.dev/admin';
749
+
750
+ // Clear and rebuild URLs section safely
751
+ urlsEl.textContent = '';
752
+ urlsEl.appendChild(createUrlItem('API (Issuer):', apiUrl));
753
+ urlsEl.appendChild(createUrlItem('Login UI:', loginUrl));
754
+ urlsEl.appendChild(createUrlItem('Admin UI:', adminUrl));
755
+
756
+ showSection('complete');
757
+ }
758
+
759
+ // Initialize
760
+ checkPrerequisites();
761
+ </script>
762
+ </body>
763
+ </html>`;
764
+ }
765
+ //# sourceMappingURL=ui.js.map