@authrim/setup 0.1.52 → 0.1.58
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/dist/core/admin.d.ts +1 -1
- package/dist/core/admin.js +3 -3
- package/dist/core/admin.js.map +1 -1
- package/dist/core/cloudflare.d.ts +15 -0
- package/dist/core/cloudflare.d.ts.map +1 -1
- package/dist/core/cloudflare.js +99 -2
- package/dist/core/cloudflare.js.map +1 -1
- package/dist/core/deploy.d.ts.map +1 -1
- package/dist/core/deploy.js.map +1 -1
- package/dist/core/naming.d.ts +1 -1
- package/dist/core/naming.js +1 -1
- package/dist/core/source.js.map +1 -1
- package/dist/core/wrangler.d.ts.map +1 -1
- package/dist/core/wrangler.js +50 -20
- package/dist/core/wrangler.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +3 -2
- package/dist/web/api.js.map +1 -1
- package/dist/web/server.js +1 -1
- package/dist/web/server.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +154 -14
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/web/ui.js
CHANGED
|
@@ -452,6 +452,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
452
452
|
|
|
453
453
|
.url-value {
|
|
454
454
|
color: var(--primary);
|
|
455
|
+
word-break: break-all;
|
|
456
|
+
overflow-wrap: break-word;
|
|
455
457
|
}
|
|
456
458
|
|
|
457
459
|
.file-input-wrapper {
|
|
@@ -496,6 +498,37 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
496
498
|
|
|
497
499
|
.hidden { display: none; }
|
|
498
500
|
|
|
501
|
+
/* Modal styles */
|
|
502
|
+
.modal {
|
|
503
|
+
position: fixed;
|
|
504
|
+
top: 0;
|
|
505
|
+
left: 0;
|
|
506
|
+
right: 0;
|
|
507
|
+
bottom: 0;
|
|
508
|
+
z-index: 1000;
|
|
509
|
+
display: flex;
|
|
510
|
+
align-items: center;
|
|
511
|
+
justify-content: center;
|
|
512
|
+
}
|
|
513
|
+
.modal.hidden { display: none; }
|
|
514
|
+
.modal-backdrop {
|
|
515
|
+
position: absolute;
|
|
516
|
+
top: 0;
|
|
517
|
+
left: 0;
|
|
518
|
+
right: 0;
|
|
519
|
+
bottom: 0;
|
|
520
|
+
background: rgba(0, 0, 0, 0.5);
|
|
521
|
+
}
|
|
522
|
+
.modal-content {
|
|
523
|
+
position: relative;
|
|
524
|
+
background: var(--card-bg);
|
|
525
|
+
border-radius: 12px;
|
|
526
|
+
padding: 1.5rem;
|
|
527
|
+
max-width: 450px;
|
|
528
|
+
width: 90%;
|
|
529
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
|
530
|
+
}
|
|
531
|
+
|
|
499
532
|
/* Resource preview styles */
|
|
500
533
|
.resource-preview {
|
|
501
534
|
background: var(--bg);
|
|
@@ -1146,9 +1179,9 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1146
1179
|
Authrim uses two separate D1 databases to isolate personal data from application data.
|
|
1147
1180
|
</p>
|
|
1148
1181
|
|
|
1149
|
-
<
|
|
1150
|
-
|
|
1151
|
-
</
|
|
1182
|
+
<p style="margin-bottom: 1.5rem; font-size: 0.85rem; color: var(--text-muted);">
|
|
1183
|
+
Note: Database region cannot be changed after creation.
|
|
1184
|
+
</p>
|
|
1152
1185
|
|
|
1153
1186
|
<div class="database-config-stack">
|
|
1154
1187
|
<!-- Core Database (Non-PII) -->
|
|
@@ -1274,7 +1307,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1274
1307
|
<h2 class="card-title">📧 Email Provider</h2>
|
|
1275
1308
|
|
|
1276
1309
|
<p style="margin-bottom: 1rem; color: var(--text-muted);">
|
|
1277
|
-
|
|
1310
|
+
Used for sending Mail OTP and email address verification.
|
|
1278
1311
|
You can configure this later if you prefer.
|
|
1279
1312
|
</p>
|
|
1280
1313
|
|
|
@@ -1283,7 +1316,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1283
1316
|
<input type="radio" name="email-setup-choice" value="later" checked>
|
|
1284
1317
|
<span style="display: flex; flex-direction: column; gap: 0.25rem;">
|
|
1285
1318
|
<strong>Configure later</strong>
|
|
1286
|
-
<small style="color: var(--text-muted);">Skip for now
|
|
1319
|
+
<small style="color: var(--text-muted);">Skip for now and configure later.</small>
|
|
1287
1320
|
</span>
|
|
1288
1321
|
</label>
|
|
1289
1322
|
<label class="radio-item" style="padding: 0.75rem; border: 1px solid var(--border); border-radius: 8px; margin-top: 0.5rem;">
|
|
@@ -1405,7 +1438,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1405
1438
|
|
|
1406
1439
|
<div class="button-group">
|
|
1407
1440
|
<button class="btn-secondary" id="btn-back-provision">Back</button>
|
|
1408
|
-
<button class="btn-primary" id="btn-deploy">Deploy</button>
|
|
1441
|
+
<button class="btn-primary" id="btn-deploy">Start Deploy</button>
|
|
1409
1442
|
</div>
|
|
1410
1443
|
</div>
|
|
1411
1444
|
|
|
@@ -1513,6 +1546,14 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1513
1546
|
</div>
|
|
1514
1547
|
<div class="resource-list" id="detail-r2-list"></div>
|
|
1515
1548
|
</div>
|
|
1549
|
+
|
|
1550
|
+
<!-- Pages Projects -->
|
|
1551
|
+
<div class="resource-section" id="detail-pages-section">
|
|
1552
|
+
<div class="resource-section-title">
|
|
1553
|
+
📄 Pages Projects <span class="count" id="detail-pages-count">(0)</span>
|
|
1554
|
+
</div>
|
|
1555
|
+
<div class="resource-list" id="detail-pages-list"></div>
|
|
1556
|
+
</div>
|
|
1516
1557
|
</div>
|
|
1517
1558
|
|
|
1518
1559
|
<div class="button-group">
|
|
@@ -1578,6 +1619,14 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1578
1619
|
<small id="delete-r2-count">(0 buckets)</small>
|
|
1579
1620
|
</span>
|
|
1580
1621
|
</label>
|
|
1622
|
+
|
|
1623
|
+
<label class="checkbox-item delete-option">
|
|
1624
|
+
<input type="checkbox" id="delete-pages" checked>
|
|
1625
|
+
<span>
|
|
1626
|
+
<strong>Pages Projects</strong>
|
|
1627
|
+
<small id="delete-pages-count">(0 projects)</small>
|
|
1628
|
+
</span>
|
|
1629
|
+
</label>
|
|
1581
1630
|
</div>
|
|
1582
1631
|
</div>
|
|
1583
1632
|
|
|
@@ -1594,6 +1643,22 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
1594
1643
|
</div>
|
|
1595
1644
|
</div>
|
|
1596
1645
|
|
|
1646
|
+
<!-- Save Config Modal -->
|
|
1647
|
+
<div id="save-config-modal" class="modal hidden">
|
|
1648
|
+
<div class="modal-backdrop"></div>
|
|
1649
|
+
<div class="modal-content">
|
|
1650
|
+
<h3 style="margin: 0 0 1rem 0;">💾 Save Configuration?</h3>
|
|
1651
|
+
<p style="color: var(--text-muted); margin-bottom: 1.5rem;">
|
|
1652
|
+
Would you like to save your configuration to a file before proceeding?
|
|
1653
|
+
This allows you to resume setup later or use the same settings for another deployment.
|
|
1654
|
+
</p>
|
|
1655
|
+
<div class="button-group" style="justify-content: flex-end;">
|
|
1656
|
+
<button class="btn-secondary" id="modal-skip-save">Skip</button>
|
|
1657
|
+
<button class="btn-primary" id="modal-save-config">Save Configuration</button>
|
|
1658
|
+
</div>
|
|
1659
|
+
</div>
|
|
1660
|
+
</div>
|
|
1661
|
+
|
|
1597
1662
|
<script>
|
|
1598
1663
|
// Session token for API authentication (embedded by server)
|
|
1599
1664
|
const SESSION_TOKEN = '${safeToken}';
|
|
@@ -2371,10 +2436,47 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2371
2436
|
};
|
|
2372
2437
|
}
|
|
2373
2438
|
|
|
2374
|
-
//
|
|
2439
|
+
// Show save config modal before proceeding
|
|
2440
|
+
const modal = document.getElementById('save-config-modal');
|
|
2441
|
+
modal.classList.remove('hidden');
|
|
2442
|
+
});
|
|
2443
|
+
|
|
2444
|
+
// Modal handlers
|
|
2445
|
+
document.getElementById('modal-skip-save').addEventListener('click', () => {
|
|
2446
|
+
document.getElementById('save-config-modal').classList.add('hidden');
|
|
2447
|
+
proceedToProvision();
|
|
2448
|
+
});
|
|
2449
|
+
|
|
2450
|
+
document.getElementById('modal-save-config').addEventListener('click', async () => {
|
|
2451
|
+
const modal = document.getElementById('save-config-modal');
|
|
2452
|
+
const btn = document.getElementById('modal-save-config');
|
|
2453
|
+
btn.disabled = true;
|
|
2454
|
+
btn.textContent = 'Saving...';
|
|
2455
|
+
|
|
2456
|
+
try {
|
|
2457
|
+
await saveConfigToFile();
|
|
2458
|
+
modal.classList.add('hidden');
|
|
2459
|
+
btn.disabled = false;
|
|
2460
|
+
btn.textContent = 'Save Configuration';
|
|
2461
|
+
proceedToProvision();
|
|
2462
|
+
} catch (error) {
|
|
2463
|
+
alert('Failed to save configuration: ' + error.message);
|
|
2464
|
+
btn.disabled = false;
|
|
2465
|
+
btn.textContent = 'Save Configuration';
|
|
2466
|
+
}
|
|
2467
|
+
});
|
|
2468
|
+
|
|
2469
|
+
// Close modal on backdrop click
|
|
2470
|
+
document.querySelector('.modal-backdrop').addEventListener('click', () => {
|
|
2471
|
+
document.getElementById('save-config-modal').classList.add('hidden');
|
|
2472
|
+
proceedToProvision();
|
|
2473
|
+
});
|
|
2474
|
+
|
|
2475
|
+
function proceedToProvision() {
|
|
2476
|
+
updateResourcePreview(config.env);
|
|
2375
2477
|
setStep(6);
|
|
2376
2478
|
showSection('provision');
|
|
2377
|
-
}
|
|
2479
|
+
}
|
|
2378
2480
|
|
|
2379
2481
|
// Provision
|
|
2380
2482
|
document.getElementById('btn-provision').addEventListener('click', async () => {
|
|
@@ -2595,7 +2697,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2595
2697
|
method: 'POST',
|
|
2596
2698
|
body: {
|
|
2597
2699
|
env: config.env,
|
|
2598
|
-
baseUrl:
|
|
2700
|
+
baseUrl: apiUrl, // Setup page is served by ar-auth worker (API)
|
|
2599
2701
|
keysDir: '.keys',
|
|
2600
2702
|
},
|
|
2601
2703
|
});
|
|
@@ -2685,6 +2787,12 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2685
2787
|
const setupItem = createUrlItem('Admin Setup:', result.setupUrl);
|
|
2686
2788
|
setupItem.querySelector('a').style.fontWeight = 'bold';
|
|
2687
2789
|
urlsEl.appendChild(setupItem);
|
|
2790
|
+
|
|
2791
|
+
// Add warning about one-time use and time limit
|
|
2792
|
+
const setupNote = document.createElement('div');
|
|
2793
|
+
setupNote.style.cssText = 'margin-top: 0.5rem; margin-bottom: 0.5rem; padding: 0.5rem 0.75rem; background: #fef3c7; border-radius: 0.375rem; font-size: 0.85rem; color: #92400e;';
|
|
2794
|
+
setupNote.innerHTML = '⚠️ This URL can only be used <strong>once</strong> and expires in <strong>1 hour</strong>.';
|
|
2795
|
+
urlsEl.appendChild(setupNote);
|
|
2688
2796
|
} else {
|
|
2689
2797
|
// Show debug info when setup URL is missing
|
|
2690
2798
|
const debugDiv = document.createElement('div');
|
|
@@ -2739,6 +2847,23 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2739
2847
|
};
|
|
2740
2848
|
}
|
|
2741
2849
|
|
|
2850
|
+
// Get human-readable label for database region
|
|
2851
|
+
function getRegionLabel(location, jurisdiction) {
|
|
2852
|
+
if (jurisdiction === 'eu') {
|
|
2853
|
+
return 'EU Jurisdiction';
|
|
2854
|
+
}
|
|
2855
|
+
const labels = {
|
|
2856
|
+
'auto': 'Automatic',
|
|
2857
|
+
'wnam': 'North America (West)',
|
|
2858
|
+
'enam': 'North America (East)',
|
|
2859
|
+
'weur': 'Europe (West)',
|
|
2860
|
+
'eeur': 'Europe (East)',
|
|
2861
|
+
'apac': 'Asia Pacific',
|
|
2862
|
+
'oc': 'Oceania',
|
|
2863
|
+
};
|
|
2864
|
+
return labels[location] || 'Automatic';
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2742
2867
|
function updateResourcePreview(env) {
|
|
2743
2868
|
const resources = getResourceNames(env);
|
|
2744
2869
|
|
|
@@ -2750,11 +2875,21 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
2750
2875
|
kvList.innerHTML = '';
|
|
2751
2876
|
keysList.innerHTML = '';
|
|
2752
2877
|
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2878
|
+
// Get region info from config
|
|
2879
|
+
const coreRegion = config.database?.core || { location: 'auto', jurisdiction: 'none' };
|
|
2880
|
+
const piiRegion = config.database?.pii || { location: 'auto', jurisdiction: 'none' };
|
|
2881
|
+
|
|
2882
|
+
// D1 databases with region info
|
|
2883
|
+
const coreDbName = env + '-authrim-core-db';
|
|
2884
|
+
const piiDbName = env + '-authrim-pii-db';
|
|
2885
|
+
|
|
2886
|
+
const coreLi = document.createElement('li');
|
|
2887
|
+
coreLi.innerHTML = coreDbName + ' <span style="color: var(--text-muted); font-size: 0.85em;">(' + getRegionLabel(coreRegion.location, coreRegion.jurisdiction) + ')</span>';
|
|
2888
|
+
d1List.appendChild(coreLi);
|
|
2889
|
+
|
|
2890
|
+
const piiLi = document.createElement('li');
|
|
2891
|
+
piiLi.innerHTML = piiDbName + ' <span style="color: var(--text-muted); font-size: 0.85em;">(' + getRegionLabel(piiRegion.location, piiRegion.jurisdiction) + ')</span>';
|
|
2892
|
+
d1List.appendChild(piiLi);
|
|
2758
2893
|
|
|
2759
2894
|
resources.kv.forEach(name => {
|
|
2760
2895
|
const li = document.createElement('li');
|
|
@@ -3024,10 +3159,12 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3024
3159
|
renderResourceList('detail-kv-list', 'detail-kv-count', env.kv, 'name', 'kv');
|
|
3025
3160
|
renderResourceList('detail-queues-list', 'detail-queues-count', env.queues, 'name', 'queue');
|
|
3026
3161
|
renderResourceList('detail-r2-list', 'detail-r2-count', env.r2, 'name', 'r2');
|
|
3162
|
+
renderResourceList('detail-pages-list', 'detail-pages-count', env.pages || [], 'name', 'pages');
|
|
3027
3163
|
|
|
3028
3164
|
// Hide empty sections
|
|
3029
3165
|
document.getElementById('detail-queues-section').style.display = env.queues.length === 0 ? 'none' : 'block';
|
|
3030
3166
|
document.getElementById('detail-r2-section').style.display = env.r2.length === 0 ? 'none' : 'block';
|
|
3167
|
+
document.getElementById('detail-pages-section').style.display = (env.pages || []).length === 0 ? 'none' : 'block';
|
|
3031
3168
|
|
|
3032
3169
|
showSection('envDetail');
|
|
3033
3170
|
|
|
@@ -3195,6 +3332,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3195
3332
|
document.getElementById('delete-kv-count').textContent = '(' + env.kv.length + ' namespaces)';
|
|
3196
3333
|
document.getElementById('delete-queues-count').textContent = '(' + env.queues.length + ' queues)';
|
|
3197
3334
|
document.getElementById('delete-r2-count').textContent = '(' + env.r2.length + ' buckets)';
|
|
3335
|
+
document.getElementById('delete-pages-count').textContent = '(' + (env.pages || []).length + ' projects)';
|
|
3198
3336
|
|
|
3199
3337
|
// Reset checkboxes
|
|
3200
3338
|
document.getElementById('delete-workers').checked = true;
|
|
@@ -3202,6 +3340,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3202
3340
|
document.getElementById('delete-kv').checked = true;
|
|
3203
3341
|
document.getElementById('delete-queues').checked = true;
|
|
3204
3342
|
document.getElementById('delete-r2').checked = true;
|
|
3343
|
+
document.getElementById('delete-pages').checked = true;
|
|
3205
3344
|
|
|
3206
3345
|
// Reset UI state
|
|
3207
3346
|
document.getElementById('delete-log').classList.add('hidden');
|
|
@@ -3260,6 +3399,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
|
|
|
3260
3399
|
deleteKV: document.getElementById('delete-kv').checked,
|
|
3261
3400
|
deleteQueues: document.getElementById('delete-queues').checked,
|
|
3262
3401
|
deleteR2: document.getElementById('delete-r2').checked,
|
|
3402
|
+
deletePages: document.getElementById('delete-pages').checked,
|
|
3263
3403
|
};
|
|
3264
3404
|
|
|
3265
3405
|
// Poll for progress
|
package/dist/web/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,eAAe,CAAC,YAAqB,EAAE,UAAoB;IACzE,gDAAgD;IAChD,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAErD,OAAO
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,eAAe,CAAC,YAAqB,EAAE,UAAoB;IACzE,gDAAgD;IAChD,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAErD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAqnDoB,SAAS;0BACZ,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6wDhC,CAAC;AACT,CAAC"}
|