@authrim/setup 0.1.61 → 0.1.63
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.
- package/README.md +51 -480
- package/dist/core/wrangler.d.ts.map +1 -1
- package/dist/core/wrangler.js +6 -3
- package/dist/core/wrangler.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +42 -3
- package/dist/web/api.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +411 -51
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/web/ui.js
CHANGED
|
@@ -382,6 +382,77 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
382
382
|
word-break: break-word;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
+
/* Progress UI Components */
|
|
386
|
+
.progress-container {
|
|
387
|
+
margin: 1rem 0;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.progress-status {
|
|
391
|
+
display: flex;
|
|
392
|
+
align-items: center;
|
|
393
|
+
gap: 0.75rem;
|
|
394
|
+
margin-bottom: 0.75rem;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.progress-status .spinner {
|
|
398
|
+
width: 20px;
|
|
399
|
+
height: 20px;
|
|
400
|
+
border: 2px solid #e2e8f0;
|
|
401
|
+
border-top-color: var(--primary);
|
|
402
|
+
border-radius: 50%;
|
|
403
|
+
animation: spin 0.8s linear infinite;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
@keyframes spin {
|
|
407
|
+
to { transform: rotate(360deg); }
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.progress-bar-wrapper {
|
|
411
|
+
background: #e2e8f0;
|
|
412
|
+
border-radius: 4px;
|
|
413
|
+
height: 8px;
|
|
414
|
+
overflow: hidden;
|
|
415
|
+
margin-bottom: 0.5rem;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.progress-bar {
|
|
419
|
+
height: 100%;
|
|
420
|
+
background: var(--primary);
|
|
421
|
+
border-radius: 4px;
|
|
422
|
+
transition: width 0.3s ease;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.progress-text {
|
|
426
|
+
font-size: 0.875rem;
|
|
427
|
+
color: var(--text-muted);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.log-toggle {
|
|
431
|
+
display: flex;
|
|
432
|
+
align-items: center;
|
|
433
|
+
gap: 0.5rem;
|
|
434
|
+
padding: 0.5rem 0.75rem;
|
|
435
|
+
background: #f1f5f9;
|
|
436
|
+
border: 1px solid var(--border);
|
|
437
|
+
border-radius: 6px;
|
|
438
|
+
cursor: pointer;
|
|
439
|
+
font-size: 0.875rem;
|
|
440
|
+
color: var(--text-muted);
|
|
441
|
+
margin-top: 1rem;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.log-toggle:hover {
|
|
445
|
+
background: #e2e8f0;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.log-toggle .arrow {
|
|
449
|
+
transition: transform 0.2s;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.log-toggle.open .arrow {
|
|
453
|
+
transform: rotate(90deg);
|
|
454
|
+
}
|
|
455
|
+
|
|
385
456
|
.step-indicator {
|
|
386
457
|
display: flex;
|
|
387
458
|
justify-content: center;
|
|
@@ -998,7 +1069,19 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
998
1069
|
|
|
999
1070
|
<div id="config-preview-section" class="hidden">
|
|
1000
1071
|
<h3 style="font-size: 1rem; margin-bottom: 0.5rem;">Configuration Preview</h3>
|
|
1001
|
-
<div class="config-preview" id="config-preview"></div>
|
|
1072
|
+
<div class="config-preview" id="config-preview-content"></div>
|
|
1073
|
+
</div>
|
|
1074
|
+
|
|
1075
|
+
<div id="config-validation-error" class="hidden" style="margin-top: 1rem; padding: 1rem; background: #fee2e2; border: 1px solid #fca5a5; border-radius: 8px;">
|
|
1076
|
+
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem;">
|
|
1077
|
+
<span style="font-size: 1.25rem;">⚠️</span>
|
|
1078
|
+
<strong style="color: #b91c1c;">Configuration Validation Failed</strong>
|
|
1079
|
+
</div>
|
|
1080
|
+
<ul id="config-validation-errors" style="margin: 0; padding-left: 1.5rem; color: #991b1b; font-size: 0.875rem;"></ul>
|
|
1081
|
+
</div>
|
|
1082
|
+
|
|
1083
|
+
<div id="config-validation-success" class="hidden" style="margin-top: 1rem; padding: 0.75rem 1rem; background: #d1fae5; border: 1px solid #6ee7b7; border-radius: 8px;">
|
|
1084
|
+
<span style="color: #065f46;">✓ Configuration is valid</span>
|
|
1002
1085
|
</div>
|
|
1003
1086
|
|
|
1004
1087
|
<div class="button-group">
|
|
@@ -1403,6 +1486,23 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1403
1486
|
</div>
|
|
1404
1487
|
</div>
|
|
1405
1488
|
|
|
1489
|
+
<!-- Progress UI (shown during provisioning) -->
|
|
1490
|
+
<div id="provision-progress-ui" class="progress-container hidden">
|
|
1491
|
+
<div class="progress-status">
|
|
1492
|
+
<div class="spinner" id="provision-spinner"></div>
|
|
1493
|
+
<span id="provision-current-task">Initializing...</span>
|
|
1494
|
+
</div>
|
|
1495
|
+
<div class="progress-bar-wrapper">
|
|
1496
|
+
<div class="progress-bar" id="provision-progress-bar" style="width: 0%"></div>
|
|
1497
|
+
</div>
|
|
1498
|
+
<div class="progress-text" id="provision-progress-text">0 / 0 resources</div>
|
|
1499
|
+
|
|
1500
|
+
<div class="log-toggle" id="provision-log-toggle">
|
|
1501
|
+
<span class="arrow">▶</span>
|
|
1502
|
+
<span>Show detailed log</span>
|
|
1503
|
+
</div>
|
|
1504
|
+
</div>
|
|
1505
|
+
|
|
1406
1506
|
<div class="progress-log hidden" id="provision-log">
|
|
1407
1507
|
<pre id="provision-output"></pre>
|
|
1408
1508
|
</div>
|
|
@@ -1431,7 +1531,24 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1431
1531
|
<span class="status-badge status-pending" id="deploy-status">Ready</span>
|
|
1432
1532
|
</h2>
|
|
1433
1533
|
|
|
1434
|
-
<p style="margin-bottom: 1rem;">Ready to deploy Authrim workers to Cloudflare.</p>
|
|
1534
|
+
<p id="deploy-ready-text" style="margin-bottom: 1rem;">Ready to deploy Authrim workers to Cloudflare.</p>
|
|
1535
|
+
|
|
1536
|
+
<!-- Progress UI (shown during deployment) -->
|
|
1537
|
+
<div id="deploy-progress-ui" class="progress-container hidden">
|
|
1538
|
+
<div class="progress-status">
|
|
1539
|
+
<div class="spinner" id="deploy-spinner"></div>
|
|
1540
|
+
<span id="deploy-current-task">Initializing...</span>
|
|
1541
|
+
</div>
|
|
1542
|
+
<div class="progress-bar-wrapper">
|
|
1543
|
+
<div class="progress-bar" id="deploy-progress-bar" style="width: 0%"></div>
|
|
1544
|
+
</div>
|
|
1545
|
+
<div class="progress-text" id="deploy-progress-text">0 / 0 components</div>
|
|
1546
|
+
|
|
1547
|
+
<div class="log-toggle" id="deploy-log-toggle">
|
|
1548
|
+
<span class="arrow">▶</span>
|
|
1549
|
+
<span>Show detailed log</span>
|
|
1550
|
+
</div>
|
|
1551
|
+
</div>
|
|
1435
1552
|
|
|
1436
1553
|
<div class="progress-log hidden" id="deploy-log">
|
|
1437
1554
|
<pre id="deploy-output"></pre>
|
|
@@ -1507,6 +1624,31 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1507
1624
|
<code id="detail-env-name" style="background: var(--bg); padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 1rem;"></code>
|
|
1508
1625
|
</h2>
|
|
1509
1626
|
|
|
1627
|
+
<!-- Admin Setup Section -->
|
|
1628
|
+
<div id="admin-setup-section" class="hidden" style="margin-bottom: 1.5rem; padding: 1rem; background: #fef3c7; border-radius: 8px; border: 1px solid #fcd34d;">
|
|
1629
|
+
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;">
|
|
1630
|
+
<span style="font-size: 1.5rem;">⚠️</span>
|
|
1631
|
+
<div>
|
|
1632
|
+
<div style="font-weight: 600; color: #92400e;">Admin Account Not Configured</div>
|
|
1633
|
+
<div style="font-size: 0.875rem; color: #a16207;">Initial administrator has not been set up for this environment.</div>
|
|
1634
|
+
</div>
|
|
1635
|
+
</div>
|
|
1636
|
+
<button class="btn-primary" id="btn-start-admin-setup" style="margin-top: 0.5rem;">
|
|
1637
|
+
🔐 Start Admin Account Setup with Passkey
|
|
1638
|
+
</button>
|
|
1639
|
+
<div id="admin-setup-result" class="hidden" style="margin-top: 1rem; padding: 0.75rem; background: white; border-radius: 6px;">
|
|
1640
|
+
<div style="font-weight: 500; margin-bottom: 0.5rem;">Setup URL Generated:</div>
|
|
1641
|
+
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
|
1642
|
+
<input type="text" id="admin-setup-url" readonly style="flex: 1; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">
|
|
1643
|
+
<button class="btn-secondary" id="btn-copy-setup-url" style="white-space: nowrap;">📋 Copy</button>
|
|
1644
|
+
<a id="btn-open-setup-url" href="#" target="_blank" class="btn-primary" style="text-decoration: none; white-space: nowrap;">🔗 Open</a>
|
|
1645
|
+
</div>
|
|
1646
|
+
<div style="font-size: 0.75rem; color: #6b7280; margin-top: 0.5rem;">
|
|
1647
|
+
This URL is valid for 1 hour. Open it in a browser to register the first admin account.
|
|
1648
|
+
</div>
|
|
1649
|
+
</div>
|
|
1650
|
+
</div>
|
|
1651
|
+
|
|
1510
1652
|
<div id="detail-resources">
|
|
1511
1653
|
<!-- Workers -->
|
|
1512
1654
|
<div class="resource-section">
|
|
@@ -1557,31 +1699,6 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1557
1699
|
</div>
|
|
1558
1700
|
</div>
|
|
1559
1701
|
|
|
1560
|
-
<!-- Admin Setup Section -->
|
|
1561
|
-
<div id="admin-setup-section" class="resource-section hidden" style="margin-top: 1.5rem; padding: 1rem; background: #fef3c7; border-radius: 8px; border: 1px solid #fcd34d;">
|
|
1562
|
-
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;">
|
|
1563
|
-
<span style="font-size: 1.5rem;">⚠️</span>
|
|
1564
|
-
<div>
|
|
1565
|
-
<div style="font-weight: 600; color: #92400e;">Admin Account Not Configured</div>
|
|
1566
|
-
<div style="font-size: 0.875rem; color: #a16207;">Initial administrator has not been set up for this environment.</div>
|
|
1567
|
-
</div>
|
|
1568
|
-
</div>
|
|
1569
|
-
<button class="btn-primary" id="btn-start-admin-setup" style="margin-top: 0.5rem;">
|
|
1570
|
-
🔐 Start Admin Account Setup with Passkey
|
|
1571
|
-
</button>
|
|
1572
|
-
<div id="admin-setup-result" class="hidden" style="margin-top: 1rem; padding: 0.75rem; background: white; border-radius: 6px;">
|
|
1573
|
-
<div style="font-weight: 500; margin-bottom: 0.5rem;">Setup URL Generated:</div>
|
|
1574
|
-
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
|
1575
|
-
<input type="text" id="admin-setup-url" readonly style="flex: 1; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">
|
|
1576
|
-
<button class="btn-secondary" id="btn-copy-setup-url" style="white-space: nowrap;">📋 Copy</button>
|
|
1577
|
-
<a id="btn-open-setup-url" href="#" target="_blank" class="btn-primary" style="text-decoration: none; white-space: nowrap;">🔗 Open</a>
|
|
1578
|
-
</div>
|
|
1579
|
-
<div style="font-size: 0.75rem; color: #6b7280; margin-top: 0.5rem;">
|
|
1580
|
-
This URL is valid for 1 hour. Open it in a browser to register the first admin account.
|
|
1581
|
-
</div>
|
|
1582
|
-
</div>
|
|
1583
|
-
</div>
|
|
1584
|
-
|
|
1585
1702
|
<div class="button-group">
|
|
1586
1703
|
<button class="btn-secondary" id="btn-back-env-detail">← Back to List</button>
|
|
1587
1704
|
<button class="btn-danger" id="btn-delete-from-detail">🗑️ Delete Environment...</button>
|
|
@@ -1603,6 +1720,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1603
1720
|
Environment: <code id="delete-env-name" style="background: var(--bg); padding: 0.25rem 0.5rem; border-radius: 4px;"></code>
|
|
1604
1721
|
</h3>
|
|
1605
1722
|
|
|
1723
|
+
<div id="delete-options-section">
|
|
1606
1724
|
<p style="margin-bottom: 1rem; color: var(--text-muted);">Select resources to delete:</p>
|
|
1607
1725
|
|
|
1608
1726
|
<div class="delete-options">
|
|
@@ -1654,6 +1772,24 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1654
1772
|
</span>
|
|
1655
1773
|
</label>
|
|
1656
1774
|
</div>
|
|
1775
|
+
</div>
|
|
1776
|
+
</div>
|
|
1777
|
+
|
|
1778
|
+
<!-- Progress UI (shown during deletion) -->
|
|
1779
|
+
<div id="delete-progress-ui" class="progress-container hidden">
|
|
1780
|
+
<div class="progress-status">
|
|
1781
|
+
<div class="spinner" id="delete-spinner"></div>
|
|
1782
|
+
<span id="delete-current-task">Initializing...</span>
|
|
1783
|
+
</div>
|
|
1784
|
+
<div class="progress-bar-wrapper">
|
|
1785
|
+
<div class="progress-bar" id="delete-progress-bar" style="width: 0%"></div>
|
|
1786
|
+
</div>
|
|
1787
|
+
<div class="progress-text" id="delete-progress-text">0 / 0 resources</div>
|
|
1788
|
+
|
|
1789
|
+
<div class="log-toggle" id="delete-log-toggle">
|
|
1790
|
+
<span class="arrow">▶</span>
|
|
1791
|
+
<span>Show detailed log</span>
|
|
1792
|
+
</div>
|
|
1657
1793
|
</div>
|
|
1658
1794
|
|
|
1659
1795
|
<div class="progress-log hidden" id="delete-log">
|
|
@@ -1758,6 +1894,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1758
1894
|
function showSection(name) {
|
|
1759
1895
|
Object.values(sections).forEach(s => s.classList.add('hidden'));
|
|
1760
1896
|
sections[name].classList.remove('hidden');
|
|
1897
|
+
window.scrollTo(0, 0);
|
|
1761
1898
|
}
|
|
1762
1899
|
|
|
1763
1900
|
// Auto-scroll helper for progress logs
|
|
@@ -1767,6 +1904,106 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1767
1904
|
}
|
|
1768
1905
|
}
|
|
1769
1906
|
|
|
1907
|
+
// Log toggle functionality
|
|
1908
|
+
function setupLogToggle(toggleId, logId) {
|
|
1909
|
+
const toggle = document.getElementById(toggleId);
|
|
1910
|
+
const log = document.getElementById(logId);
|
|
1911
|
+
if (toggle && log) {
|
|
1912
|
+
toggle.addEventListener('click', () => {
|
|
1913
|
+
const isHidden = log.classList.contains('hidden');
|
|
1914
|
+
if (isHidden) {
|
|
1915
|
+
log.classList.remove('hidden');
|
|
1916
|
+
toggle.classList.add('open');
|
|
1917
|
+
toggle.querySelector('span:last-child').textContent = 'Hide detailed log';
|
|
1918
|
+
} else {
|
|
1919
|
+
log.classList.add('hidden');
|
|
1920
|
+
toggle.classList.remove('open');
|
|
1921
|
+
toggle.querySelector('span:last-child').textContent = 'Show detailed log';
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
// Setup all log toggles
|
|
1928
|
+
setupLogToggle('deploy-log-toggle', 'deploy-log');
|
|
1929
|
+
setupLogToggle('provision-log-toggle', 'provision-log');
|
|
1930
|
+
setupLogToggle('delete-log-toggle', 'delete-log');
|
|
1931
|
+
|
|
1932
|
+
// Progress UI update helper
|
|
1933
|
+
function updateProgressUI(prefix, current, total, currentTask) {
|
|
1934
|
+
const progressBar = document.getElementById(prefix + '-progress-bar');
|
|
1935
|
+
const progressText = document.getElementById(prefix + '-progress-text');
|
|
1936
|
+
const currentTaskEl = document.getElementById(prefix + '-current-task');
|
|
1937
|
+
|
|
1938
|
+
if (progressBar && total > 0) {
|
|
1939
|
+
const percent = Math.round((current / total) * 100);
|
|
1940
|
+
progressBar.style.width = percent + '%';
|
|
1941
|
+
}
|
|
1942
|
+
if (progressText) {
|
|
1943
|
+
progressText.textContent = current + ' / ' + total + ' ' + (prefix === 'deploy' ? 'components' : 'resources');
|
|
1944
|
+
}
|
|
1945
|
+
if (currentTaskEl && currentTask) {
|
|
1946
|
+
currentTaskEl.textContent = currentTask;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
// Parse progress message to extract current task
|
|
1951
|
+
function parseProgressMessage(message) {
|
|
1952
|
+
// Match patterns like "Deploying xxx...", "Creating xxx...", "Deleting xxx..."
|
|
1953
|
+
if (message.includes('Deploying ')) {
|
|
1954
|
+
const parts = message.split('Deploying ')[1];
|
|
1955
|
+
if (parts) {
|
|
1956
|
+
const name = parts.split('.')[0].split(' ')[0];
|
|
1957
|
+
if (name) return 'Deploying ' + name + '...';
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
if (message.includes('Creating ')) {
|
|
1962
|
+
const parts = message.split('Creating ')[1];
|
|
1963
|
+
if (parts) {
|
|
1964
|
+
const name = parts.split(' ')[0].split('.')[0];
|
|
1965
|
+
if (name) return 'Creating ' + name + '...';
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
if (message.includes('Deleting')) {
|
|
1970
|
+
const parts = message.split('Deleting')[1];
|
|
1971
|
+
if (parts) {
|
|
1972
|
+
const name = parts.trim().split(' ')[0].replace(':', '');
|
|
1973
|
+
if (name) return 'Deleting ' + name + '...';
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
if (message.includes('✓')) {
|
|
1978
|
+
const parts = message.split('✓')[1];
|
|
1979
|
+
if (parts) {
|
|
1980
|
+
const text = parts.trim().substring(0, 40);
|
|
1981
|
+
return '✓ ' + text;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
if (message.includes('Level ')) {
|
|
1986
|
+
const parts = message.split('Level ')[1];
|
|
1987
|
+
if (parts) {
|
|
1988
|
+
const num = parts.trim().split(' ')[0];
|
|
1989
|
+
if (num) return 'Deployment Level ' + num;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
if (message.includes('Generating')) {
|
|
1994
|
+
const parts = message.split('Generating')[1];
|
|
1995
|
+
if (parts) {
|
|
1996
|
+
const text = parts.trim().substring(0, 30);
|
|
1997
|
+
return 'Generating ' + text + '...';
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
if (message.includes('Uploading')) return 'Uploading secrets...';
|
|
2002
|
+
if (message.toLowerCase().includes('building')) return 'Building packages...';
|
|
2003
|
+
|
|
2004
|
+
return null;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
1770
2007
|
// Safe DOM element creation helpers
|
|
1771
2008
|
function createAlert(type, content) {
|
|
1772
2009
|
const div = document.createElement('div');
|
|
@@ -1955,23 +2192,76 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1955
2192
|
});
|
|
1956
2193
|
|
|
1957
2194
|
// Load config handlers
|
|
1958
|
-
document.getElementById('config-file').addEventListener('change', (e) => {
|
|
2195
|
+
document.getElementById('config-file').addEventListener('change', async (e) => {
|
|
1959
2196
|
const file = e.target.files[0];
|
|
1960
2197
|
if (!file) return;
|
|
1961
2198
|
|
|
1962
2199
|
document.getElementById('config-file-name').textContent = file.name;
|
|
1963
2200
|
|
|
2201
|
+
// Reset validation display
|
|
2202
|
+
document.getElementById('config-validation-error').classList.add('hidden');
|
|
2203
|
+
document.getElementById('config-validation-success').classList.add('hidden');
|
|
2204
|
+
document.getElementById('config-preview-section').classList.add('hidden');
|
|
2205
|
+
document.getElementById('btn-load-config').disabled = true;
|
|
2206
|
+
|
|
1964
2207
|
const reader = new FileReader();
|
|
1965
|
-
reader.onload = (event) => {
|
|
2208
|
+
reader.onload = async (event) => {
|
|
2209
|
+
let rawConfig;
|
|
1966
2210
|
try {
|
|
1967
|
-
|
|
1968
|
-
document.getElementById('config-preview').textContent = JSON.stringify(loadedConfig, null, 2);
|
|
1969
|
-
document.getElementById('config-preview-section').classList.remove('hidden');
|
|
1970
|
-
document.getElementById('btn-load-config').disabled = false;
|
|
2211
|
+
rawConfig = JSON.parse(event.target.result);
|
|
1971
2212
|
} catch (err) {
|
|
1972
|
-
|
|
2213
|
+
document.getElementById('config-validation-error').classList.remove('hidden');
|
|
2214
|
+
const errorList = document.getElementById('config-validation-errors');
|
|
2215
|
+
while (errorList.firstChild) errorList.removeChild(errorList.firstChild);
|
|
2216
|
+
const li = document.createElement('li');
|
|
2217
|
+
li.textContent = 'Invalid JSON: ' + err.message;
|
|
2218
|
+
errorList.appendChild(li);
|
|
2219
|
+
loadedConfig = null;
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
// Show preview
|
|
2224
|
+
document.getElementById('config-preview-content').textContent = JSON.stringify(rawConfig, null, 2);
|
|
2225
|
+
document.getElementById('config-preview-section').classList.remove('hidden');
|
|
2226
|
+
|
|
2227
|
+
// Validate via API
|
|
2228
|
+
try {
|
|
2229
|
+
const response = await api('/config/validate', {
|
|
2230
|
+
method: 'POST',
|
|
2231
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2232
|
+
body: JSON.stringify(rawConfig),
|
|
2233
|
+
});
|
|
2234
|
+
|
|
2235
|
+
if (response.valid) {
|
|
2236
|
+
loadedConfig = response.config;
|
|
2237
|
+
document.getElementById('config-validation-success').classList.remove('hidden');
|
|
2238
|
+
document.getElementById('btn-load-config').disabled = false;
|
|
2239
|
+
} else {
|
|
2240
|
+
document.getElementById('config-validation-error').classList.remove('hidden');
|
|
2241
|
+
const errorList = document.getElementById('config-validation-errors');
|
|
2242
|
+
while (errorList.firstChild) errorList.removeChild(errorList.firstChild);
|
|
2243
|
+
|
|
2244
|
+
if (response.errors) {
|
|
2245
|
+
for (const err of response.errors) {
|
|
2246
|
+
const li = document.createElement('li');
|
|
2247
|
+
li.textContent = (err.path ? err.path + ': ' : '') + err.message;
|
|
2248
|
+
errorList.appendChild(li);
|
|
2249
|
+
}
|
|
2250
|
+
} else if (response.error) {
|
|
2251
|
+
const li = document.createElement('li');
|
|
2252
|
+
li.textContent = response.error;
|
|
2253
|
+
errorList.appendChild(li);
|
|
2254
|
+
}
|
|
2255
|
+
loadedConfig = null;
|
|
2256
|
+
}
|
|
2257
|
+
} catch (err) {
|
|
2258
|
+
document.getElementById('config-validation-error').classList.remove('hidden');
|
|
2259
|
+
const errorList = document.getElementById('config-validation-errors');
|
|
2260
|
+
while (errorList.firstChild) errorList.removeChild(errorList.firstChild);
|
|
2261
|
+
const li = document.createElement('li');
|
|
2262
|
+
li.textContent = 'Validation request failed: ' + err.message;
|
|
2263
|
+
errorList.appendChild(li);
|
|
1973
2264
|
loadedConfig = null;
|
|
1974
|
-
document.getElementById('btn-load-config').disabled = true;
|
|
1975
2265
|
}
|
|
1976
2266
|
};
|
|
1977
2267
|
reader.readAsText(file);
|
|
@@ -2056,14 +2346,13 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2056
2346
|
// Trigger env input to update preview/default labels
|
|
2057
2347
|
document.getElementById('env').dispatchEvent(new Event('input'));
|
|
2058
2348
|
|
|
2059
|
-
//
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
}
|
|
2349
|
+
// Show configuration screen for review/editing
|
|
2350
|
+
// User can modify settings before proceeding to provision
|
|
2351
|
+
setupMode = 'custom'; // Enable all options for editing
|
|
2352
|
+
document.getElementById('advanced-options').classList.remove('hidden');
|
|
2353
|
+
setStep(2);
|
|
2354
|
+
showSection('config');
|
|
2355
|
+
updatePreview();
|
|
2067
2356
|
});
|
|
2068
2357
|
|
|
2069
2358
|
// Configuration handlers
|
|
@@ -2514,16 +2803,23 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2514
2803
|
const resourcePreview = document.getElementById('resource-preview');
|
|
2515
2804
|
const keysSavedInfo = document.getElementById('keys-saved-info');
|
|
2516
2805
|
const keysPath = document.getElementById('keys-path');
|
|
2806
|
+
const progressUI = document.getElementById('provision-progress-ui');
|
|
2517
2807
|
|
|
2518
2808
|
btn.disabled = true;
|
|
2809
|
+
btn.classList.add('hidden');
|
|
2519
2810
|
btnGotoDeploy.classList.add('hidden');
|
|
2520
2811
|
status.textContent = 'Running...';
|
|
2521
2812
|
status.className = 'status-badge status-running';
|
|
2522
|
-
|
|
2813
|
+
progressUI.classList.remove('hidden');
|
|
2814
|
+
log.classList.add('hidden'); // Log is hidden by default, toggled via button
|
|
2523
2815
|
resourcePreview.classList.add('hidden');
|
|
2524
2816
|
keysSavedInfo.classList.add('hidden');
|
|
2525
2817
|
output.textContent = '';
|
|
2526
2818
|
|
|
2819
|
+
let provisionCompleted = 0;
|
|
2820
|
+
const totalResources = 8; // D1 Core, D1 PII, KV Settings, KV Cache, KV Tokens, R2 (optional), Queues (optional), Keys
|
|
2821
|
+
updateProgressUI('provision', 0, totalResources, 'Initializing...');
|
|
2822
|
+
|
|
2527
2823
|
// Start polling for progress
|
|
2528
2824
|
let lastProgressLength = 0;
|
|
2529
2825
|
provisionPollInterval = setInterval(async () => {
|
|
@@ -2534,6 +2830,16 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2534
2830
|
const newMessages = statusResult.progress.slice(lastProgressLength);
|
|
2535
2831
|
newMessages.forEach(msg => {
|
|
2536
2832
|
output.textContent += msg + '\\n';
|
|
2833
|
+
// Update progress UI based on message content
|
|
2834
|
+
const taskInfo = parseProgressMessage(msg);
|
|
2835
|
+
if (taskInfo) {
|
|
2836
|
+
updateProgressUI('provision', provisionCompleted, totalResources, taskInfo);
|
|
2837
|
+
}
|
|
2838
|
+
// Count completed items (lines with checkmark)
|
|
2839
|
+
if (msg.includes('✓') || msg.includes('✅')) {
|
|
2840
|
+
provisionCompleted++;
|
|
2841
|
+
updateProgressUI('provision', provisionCompleted, totalResources, taskInfo || ('Completed ' + provisionCompleted + ' items'));
|
|
2842
|
+
}
|
|
2537
2843
|
});
|
|
2538
2844
|
lastProgressLength = statusResult.progress.length;
|
|
2539
2845
|
scrollToBottom(log);
|
|
@@ -2585,6 +2891,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2585
2891
|
}
|
|
2586
2892
|
|
|
2587
2893
|
if (result.success) {
|
|
2894
|
+
// Final progress update
|
|
2895
|
+
updateProgressUI('provision', totalResources, totalResources, '✅ Provisioning complete!');
|
|
2588
2896
|
output.textContent += '\\n✅ Provisioning complete!\\n';
|
|
2589
2897
|
scrollToBottom(log);
|
|
2590
2898
|
status.textContent = 'Complete';
|
|
@@ -2598,6 +2906,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2598
2906
|
|
|
2599
2907
|
// Update buttons
|
|
2600
2908
|
btn.textContent = 'Re-provision (Delete & Create)';
|
|
2909
|
+
btn.classList.remove('hidden');
|
|
2601
2910
|
btn.disabled = false;
|
|
2602
2911
|
btnGotoDeploy.classList.remove('hidden');
|
|
2603
2912
|
} else {
|
|
@@ -2614,6 +2923,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2614
2923
|
scrollToBottom(log);
|
|
2615
2924
|
status.textContent = 'Error';
|
|
2616
2925
|
status.className = 'status-badge status-error';
|
|
2926
|
+
btn.classList.remove('hidden');
|
|
2617
2927
|
btn.disabled = false;
|
|
2618
2928
|
resourcePreview.classList.remove('hidden');
|
|
2619
2929
|
}
|
|
@@ -2642,13 +2952,21 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2642
2952
|
const status = document.getElementById('deploy-status');
|
|
2643
2953
|
const log = document.getElementById('deploy-log');
|
|
2644
2954
|
const output = document.getElementById('deploy-output');
|
|
2955
|
+
const progressUI = document.getElementById('deploy-progress-ui');
|
|
2956
|
+
const readyText = document.getElementById('deploy-ready-text');
|
|
2645
2957
|
|
|
2646
2958
|
btn.disabled = true;
|
|
2959
|
+
btn.classList.add('hidden');
|
|
2647
2960
|
status.textContent = 'Deploying...';
|
|
2648
2961
|
status.className = 'status-badge status-running';
|
|
2649
|
-
|
|
2962
|
+
readyText.classList.add('hidden');
|
|
2963
|
+
progressUI.classList.remove('hidden');
|
|
2964
|
+
log.classList.add('hidden'); // Log is hidden by default, toggled via button
|
|
2650
2965
|
output.textContent = 'Starting deployment...\\n\\n';
|
|
2651
|
-
|
|
2966
|
+
|
|
2967
|
+
let completedCount = 0;
|
|
2968
|
+
const totalComponents = 10; // Approximate total components
|
|
2969
|
+
updateProgressUI('deploy', 0, totalComponents, 'Initializing...');
|
|
2652
2970
|
|
|
2653
2971
|
try {
|
|
2654
2972
|
// Generate wrangler configs first
|
|
@@ -2666,10 +2984,25 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2666
2984
|
scrollToBottom(log);
|
|
2667
2985
|
|
|
2668
2986
|
// Poll for status updates
|
|
2987
|
+
let lastProgressLength = 0;
|
|
2669
2988
|
const pollInterval = setInterval(async () => {
|
|
2670
2989
|
const statusResult = await api('/deploy/status');
|
|
2671
|
-
if (statusResult.progress && statusResult.progress.length >
|
|
2672
|
-
|
|
2990
|
+
if (statusResult.progress && statusResult.progress.length > lastProgressLength) {
|
|
2991
|
+
const newMessages = statusResult.progress.slice(lastProgressLength);
|
|
2992
|
+
newMessages.forEach(msg => {
|
|
2993
|
+
output.textContent += msg + '\\n';
|
|
2994
|
+
// Update progress UI based on message content
|
|
2995
|
+
const taskInfo = parseProgressMessage(msg);
|
|
2996
|
+
if (taskInfo) {
|
|
2997
|
+
updateProgressUI('deploy', completedCount, totalComponents, taskInfo);
|
|
2998
|
+
}
|
|
2999
|
+
// Count completed items (lines with checkmark)
|
|
3000
|
+
if (msg.includes('✓') || msg.includes('✅')) {
|
|
3001
|
+
completedCount++;
|
|
3002
|
+
updateProgressUI('deploy', completedCount, totalComponents, taskInfo || ('Completed ' + completedCount + ' items'));
|
|
3003
|
+
}
|
|
3004
|
+
});
|
|
3005
|
+
lastProgressLength = statusResult.progress.length;
|
|
2673
3006
|
scrollToBottom(log);
|
|
2674
3007
|
}
|
|
2675
3008
|
}, 1000);
|
|
@@ -2685,6 +3018,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2685
3018
|
clearInterval(pollInterval);
|
|
2686
3019
|
|
|
2687
3020
|
if (result.success) {
|
|
3021
|
+
// Final progress update
|
|
3022
|
+
updateProgressUI('deploy', totalComponents, totalComponents, '✓ Deployment complete!');
|
|
2688
3023
|
output.textContent += '\\n✓ Deployment complete!\\n';
|
|
2689
3024
|
scrollToBottom(log);
|
|
2690
3025
|
|
|
@@ -3446,9 +3781,11 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3446
3781
|
document.getElementById('delete-pages').checked = true;
|
|
3447
3782
|
|
|
3448
3783
|
// Reset UI state
|
|
3784
|
+
document.getElementById('delete-options-section').classList.remove('hidden');
|
|
3449
3785
|
document.getElementById('delete-log').classList.add('hidden');
|
|
3450
3786
|
document.getElementById('delete-result').classList.add('hidden');
|
|
3451
|
-
document.getElementById('delete-result').
|
|
3787
|
+
document.getElementById('delete-result').textContent = '';
|
|
3788
|
+
document.getElementById('btn-confirm-delete').classList.remove('hidden');
|
|
3452
3789
|
document.getElementById('btn-confirm-delete').disabled = false;
|
|
3453
3790
|
|
|
3454
3791
|
showSection('envDelete');
|
|
@@ -3572,9 +3909,13 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3572
3909
|
const log = document.getElementById('delete-log');
|
|
3573
3910
|
const output = document.getElementById('delete-output');
|
|
3574
3911
|
const result = document.getElementById('delete-result');
|
|
3912
|
+
const progressUI = document.getElementById('delete-progress-ui');
|
|
3575
3913
|
|
|
3576
3914
|
btn.disabled = true;
|
|
3577
|
-
|
|
3915
|
+
btn.classList.add('hidden');
|
|
3916
|
+
document.getElementById('delete-options-section').classList.add('hidden');
|
|
3917
|
+
progressUI.classList.remove('hidden');
|
|
3918
|
+
log.classList.add('hidden'); // Log is hidden by default, toggled via button
|
|
3578
3919
|
result.classList.add('hidden');
|
|
3579
3920
|
output.textContent = '';
|
|
3580
3921
|
|
|
@@ -3587,6 +3928,11 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3587
3928
|
deletePages: document.getElementById('delete-pages').checked,
|
|
3588
3929
|
};
|
|
3589
3930
|
|
|
3931
|
+
// Count selected options for progress tracking
|
|
3932
|
+
let deleteCompleted = 0;
|
|
3933
|
+
const totalToDelete = Object.values(deleteOptions).filter(v => v).length;
|
|
3934
|
+
updateProgressUI('delete', 0, totalToDelete, 'Starting deletion...');
|
|
3935
|
+
|
|
3590
3936
|
// Poll for progress
|
|
3591
3937
|
let lastProgressLength = 0;
|
|
3592
3938
|
const pollInterval = setInterval(async () => {
|
|
@@ -3596,9 +3942,19 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3596
3942
|
const newMessages = statusResult.progress.slice(lastProgressLength);
|
|
3597
3943
|
newMessages.forEach(msg => {
|
|
3598
3944
|
output.textContent += msg + '\\n';
|
|
3945
|
+
// Update progress UI based on message content
|
|
3946
|
+
const taskInfo = parseProgressMessage(msg);
|
|
3947
|
+
if (taskInfo) {
|
|
3948
|
+
updateProgressUI('delete', deleteCompleted, totalToDelete, taskInfo);
|
|
3949
|
+
}
|
|
3950
|
+
// Count completed items (lines with checkmark)
|
|
3951
|
+
if (msg.includes('✓') || msg.includes('✅') || msg.includes('Deleted')) {
|
|
3952
|
+
deleteCompleted++;
|
|
3953
|
+
updateProgressUI('delete', deleteCompleted, totalToDelete, taskInfo || ('Deleted ' + deleteCompleted + ' items'));
|
|
3954
|
+
}
|
|
3599
3955
|
});
|
|
3600
3956
|
lastProgressLength = statusResult.progress.length;
|
|
3601
|
-
log
|
|
3957
|
+
scrollToBottom(log);
|
|
3602
3958
|
}
|
|
3603
3959
|
} catch (e) {}
|
|
3604
3960
|
}, 500);
|
|
@@ -3619,6 +3975,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3619
3975
|
result.classList.remove('hidden');
|
|
3620
3976
|
|
|
3621
3977
|
if (deleteResult.success) {
|
|
3978
|
+
// Final progress update
|
|
3979
|
+
updateProgressUI('delete', totalToDelete, totalToDelete, '✅ Deletion complete!');
|
|
3622
3980
|
result.textContent = '';
|
|
3623
3981
|
result.appendChild(createAlert('success', '✅ Environment deleted successfully!'));
|
|
3624
3982
|
|
|
@@ -3630,6 +3988,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3630
3988
|
} else {
|
|
3631
3989
|
result.textContent = '';
|
|
3632
3990
|
result.appendChild(createAlert('error', '❌ Some errors occurred: ' + (deleteResult.errors || []).join(', ')));
|
|
3991
|
+
btn.classList.remove('hidden');
|
|
3633
3992
|
btn.disabled = false;
|
|
3634
3993
|
}
|
|
3635
3994
|
} catch (error) {
|
|
@@ -3637,6 +3996,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3637
3996
|
result.classList.remove('hidden');
|
|
3638
3997
|
result.textContent = '';
|
|
3639
3998
|
result.appendChild(createAlert('error', '❌ Error: ' + error.message));
|
|
3999
|
+
btn.classList.remove('hidden');
|
|
3640
4000
|
btn.disabled = false;
|
|
3641
4001
|
}
|
|
3642
4002
|
});
|