stellar-drive 1.1.26 → 1.2.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.
- package/dist/bin/install-pwa.d.ts.map +1 -1
- package/dist/bin/install-pwa.js +745 -4
- package/dist/bin/install-pwa.js.map +1 -1
- package/dist/engine.d.ts +11 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +276 -27
- package/dist/engine.js.map +1 -1
- package/dist/entries/auth.d.ts +2 -0
- package/dist/entries/auth.d.ts.map +1 -1
- package/dist/entries/auth.js +10 -0
- package/dist/entries/auth.js.map +1 -1
- package/dist/entries/config.d.ts +5 -1
- package/dist/entries/config.d.ts.map +1 -1
- package/dist/entries/config.js +16 -1
- package/dist/entries/config.js.map +1 -1
- package/dist/entries/demo.d.ts +8 -0
- package/dist/entries/demo.d.ts.map +1 -0
- package/dist/entries/demo.js +7 -0
- package/dist/entries/demo.js.map +1 -0
- package/dist/entries/engine.d.ts +10 -0
- package/dist/entries/engine.d.ts.map +1 -0
- package/dist/entries/engine.js +10 -0
- package/dist/entries/engine.js.map +1 -0
- package/dist/entries/types.d.ts +1 -1
- package/dist/entries/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kit/server.d.ts.map +1 -1
- package/dist/kit/server.js +0 -14
- package/dist/kit/server.js.map +1 -1
- package/package.json +9 -1
package/dist/bin/install-pwa.js
CHANGED
|
@@ -206,7 +206,7 @@ function generatePackageJson(opts) {
|
|
|
206
206
|
},
|
|
207
207
|
dependencies: {
|
|
208
208
|
postgres: '^3.4.0',
|
|
209
|
-
'stellar-drive': '^1.
|
|
209
|
+
'stellar-drive': '^1.2.0'
|
|
210
210
|
},
|
|
211
211
|
type: 'module'
|
|
212
212
|
}, null, 2) + '\n');
|
|
@@ -2060,6 +2060,7 @@ function generateSetupPageSvelte(opts) {
|
|
|
2060
2060
|
import { setConfig } from 'stellar-drive/config';
|
|
2061
2061
|
import { isOnline } from 'stellar-drive/stores';
|
|
2062
2062
|
import { pollForNewServiceWorker } from 'stellar-drive/kit';
|
|
2063
|
+
import Reconfigure from './Reconfigure.svelte';
|
|
2063
2064
|
|
|
2064
2065
|
// =============================================================================
|
|
2065
2066
|
// Wizard State
|
|
@@ -2261,6 +2262,7 @@ function generateSetupPageSvelte(opts) {
|
|
|
2261
2262
|
|
|
2262
2263
|
<div class="setup-page">
|
|
2263
2264
|
<div class="setup-container">
|
|
2265
|
+
{#if isFirstSetup}
|
|
2264
2266
|
<!-- Header -->
|
|
2265
2267
|
<h1>Set Up ${opts.name}</h1>
|
|
2266
2268
|
<p class="subtitle">Configure ${opts.name} to connect to your own Supabase backend</p>
|
|
@@ -2395,7 +2397,7 @@ function generateSetupPageSvelte(opts) {
|
|
|
2395
2397
|
</div>
|
|
2396
2398
|
<div class="deploy-stage" class:active={deployStage === 'deploying'} class:done={deployStage === 'ready'}>
|
|
2397
2399
|
<span class="stage-icon">{#if deployStage === 'deploying'}○{:else if deployStage === 'ready'}✓{:else}•{/if}</span>
|
|
2398
|
-
Deploying to Vercel
|
|
2400
|
+
Deploying to Vercel... (might take a minute)
|
|
2399
2401
|
</div>
|
|
2400
2402
|
<div class="deploy-stage" class:active={deployStage === 'ready'}>
|
|
2401
2403
|
<span class="stage-icon">{#if deployStage === 'ready'}✓{:else}•{/if}</span>
|
|
@@ -2406,8 +2408,16 @@ function generateSetupPageSvelte(opts) {
|
|
|
2406
2408
|
|
|
2407
2409
|
{#if deployStage === 'ready'}
|
|
2408
2410
|
<div class="message message-success">
|
|
2409
|
-
Deployment complete!
|
|
2411
|
+
Deployment complete! Use the update prompt at the bottom of the screen to refresh.
|
|
2412
|
+
If it doesn't appear, click below.
|
|
2410
2413
|
</div>
|
|
2414
|
+
<button
|
|
2415
|
+
class="btn btn-secondary"
|
|
2416
|
+
onclick={() => (window.location.href = '/')}
|
|
2417
|
+
style="margin-top: 0.75rem;"
|
|
2418
|
+
>
|
|
2419
|
+
Manually refresh & go home
|
|
2420
|
+
</button>
|
|
2411
2421
|
{/if}
|
|
2412
2422
|
{/if}
|
|
2413
2423
|
</div>
|
|
@@ -2432,12 +2442,16 @@ function generateSetupPageSvelte(opts) {
|
|
|
2432
2442
|
</div>
|
|
2433
2443
|
|
|
2434
2444
|
<!-- Security notice (first-time setup only) -->
|
|
2435
|
-
{#if isFirstSetup}
|
|
2436
2445
|
<div class="security-notice">
|
|
2437
2446
|
<strong>Security:</strong> Your Supabase credentials are stored as environment variables
|
|
2438
2447
|
on Vercel and are never sent to any third-party service. The Vercel token is used once
|
|
2439
2448
|
and is not persisted.
|
|
2440
2449
|
</div>
|
|
2450
|
+
{:else}
|
|
2451
|
+
<!-- Reconfigure view for returning users -->
|
|
2452
|
+
<h1>Reconfigure ${opts.name}</h1>
|
|
2453
|
+
<p class="subtitle">Update your credentials and redeploy</p>
|
|
2454
|
+
<Reconfigure />
|
|
2441
2455
|
{/if}
|
|
2442
2456
|
</div>
|
|
2443
2457
|
</div>
|
|
@@ -2691,6 +2705,732 @@ function generateSetupPageSvelte(opts) {
|
|
|
2691
2705
|
</style>
|
|
2692
2706
|
`;
|
|
2693
2707
|
}
|
|
2708
|
+
/**
|
|
2709
|
+
* Generate the Reconfigure component for the setup page.
|
|
2710
|
+
*
|
|
2711
|
+
* Shown when `isFirstSetup: false` — a flat settings page where the
|
|
2712
|
+
* user can update Supabase credentials and redeploy without stepping
|
|
2713
|
+
* through the full wizard.
|
|
2714
|
+
*
|
|
2715
|
+
* @returns The Svelte component source for `src/routes/setup/Reconfigure.svelte`.
|
|
2716
|
+
*/
|
|
2717
|
+
function generateReconfigureSvelte(opts) {
|
|
2718
|
+
return `<!--
|
|
2719
|
+
@fileoverview Reconfigure settings page for ${opts.name}.
|
|
2720
|
+
|
|
2721
|
+
Shown when \\\`isFirstSetup: false\\\` — a flat settings page where the
|
|
2722
|
+
user can update Supabase credentials and redeploy without stepping
|
|
2723
|
+
through the full wizard.
|
|
2724
|
+
-->
|
|
2725
|
+
<script lang="ts">
|
|
2726
|
+
import { getConfig, setConfig } from 'stellar-drive/config';
|
|
2727
|
+
import { isOnline } from 'stellar-drive/stores';
|
|
2728
|
+
import { pollForNewServiceWorker, monitorSwLifecycle } from 'stellar-drive/kit';
|
|
2729
|
+
import { onMount } from 'svelte';
|
|
2730
|
+
import { browser } from '$app/environment';
|
|
2731
|
+
|
|
2732
|
+
// ===========================================================================
|
|
2733
|
+
// Form State
|
|
2734
|
+
// ===========================================================================
|
|
2735
|
+
|
|
2736
|
+
let supabaseUrl = $state('');
|
|
2737
|
+
let supabasePublishableKey = $state('');
|
|
2738
|
+
let vercelToken = $state('');
|
|
2739
|
+
|
|
2740
|
+
// Initial values for change detection
|
|
2741
|
+
let initialSupabaseUrl = $state('');
|
|
2742
|
+
let initialSupabaseKey = $state('');
|
|
2743
|
+
|
|
2744
|
+
// ===========================================================================
|
|
2745
|
+
// UI State
|
|
2746
|
+
// ===========================================================================
|
|
2747
|
+
|
|
2748
|
+
let loading = $state(true);
|
|
2749
|
+
let validating = $state(false);
|
|
2750
|
+
let validateError = $state<string | null>(null);
|
|
2751
|
+
let validateSuccess = $state(false);
|
|
2752
|
+
let validatedUrl = $state('');
|
|
2753
|
+
let validatedKey = $state('');
|
|
2754
|
+
let deploying = $state(false);
|
|
2755
|
+
let deployError = $state<string | null>(null);
|
|
2756
|
+
let deployStage = $state<'idle' | 'setting-env' | 'deploying' | 'ready'>('idle');
|
|
2757
|
+
|
|
2758
|
+
// ===========================================================================
|
|
2759
|
+
// Derived State
|
|
2760
|
+
// ===========================================================================
|
|
2761
|
+
|
|
2762
|
+
const supabaseChanged = $derived(
|
|
2763
|
+
supabaseUrl !== initialSupabaseUrl || supabasePublishableKey !== initialSupabaseKey
|
|
2764
|
+
);
|
|
2765
|
+
|
|
2766
|
+
const credentialsChanged = $derived(
|
|
2767
|
+
validateSuccess && (supabaseUrl !== validatedUrl || supabasePublishableKey !== validatedKey)
|
|
2768
|
+
);
|
|
2769
|
+
|
|
2770
|
+
const supabaseNeedsValidation = $derived(supabaseChanged && !validateSuccess);
|
|
2771
|
+
|
|
2772
|
+
const canDeploy = $derived(
|
|
2773
|
+
supabaseChanged &&
|
|
2774
|
+
!supabaseNeedsValidation &&
|
|
2775
|
+
!credentialsChanged &&
|
|
2776
|
+
!!vercelToken &&
|
|
2777
|
+
!deploying &&
|
|
2778
|
+
deployStage === 'idle'
|
|
2779
|
+
);
|
|
2780
|
+
|
|
2781
|
+
// ===========================================================================
|
|
2782
|
+
// Effects
|
|
2783
|
+
// ===========================================================================
|
|
2784
|
+
|
|
2785
|
+
$effect(() => {
|
|
2786
|
+
if (credentialsChanged) {
|
|
2787
|
+
validateSuccess = false;
|
|
2788
|
+
validateError = null;
|
|
2789
|
+
}
|
|
2790
|
+
});
|
|
2791
|
+
|
|
2792
|
+
// ===========================================================================
|
|
2793
|
+
// Lifecycle
|
|
2794
|
+
// ===========================================================================
|
|
2795
|
+
|
|
2796
|
+
onMount(() => {
|
|
2797
|
+
if (!browser) return;
|
|
2798
|
+
|
|
2799
|
+
const config = getConfig();
|
|
2800
|
+
if (config) {
|
|
2801
|
+
supabaseUrl = config.supabaseUrl || '';
|
|
2802
|
+
supabasePublishableKey = config.supabasePublishableKey || '';
|
|
2803
|
+
initialSupabaseUrl = supabaseUrl;
|
|
2804
|
+
initialSupabaseKey = supabasePublishableKey;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
loading = false;
|
|
2808
|
+
});
|
|
2809
|
+
|
|
2810
|
+
// ===========================================================================
|
|
2811
|
+
// Validation
|
|
2812
|
+
// ===========================================================================
|
|
2813
|
+
|
|
2814
|
+
async function handleValidate() {
|
|
2815
|
+
validateError = null;
|
|
2816
|
+
validateSuccess = false;
|
|
2817
|
+
validating = true;
|
|
2818
|
+
|
|
2819
|
+
try {
|
|
2820
|
+
const res = await fetch('/api/setup/validate', {
|
|
2821
|
+
method: 'POST',
|
|
2822
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2823
|
+
body: JSON.stringify({ supabaseUrl, supabasePublishableKey })
|
|
2824
|
+
});
|
|
2825
|
+
|
|
2826
|
+
const data = await res.json();
|
|
2827
|
+
|
|
2828
|
+
if (data.valid) {
|
|
2829
|
+
validateSuccess = true;
|
|
2830
|
+
validatedUrl = supabaseUrl;
|
|
2831
|
+
validatedKey = supabasePublishableKey;
|
|
2832
|
+
setConfig({ supabaseUrl, supabasePublishableKey, configured: true });
|
|
2833
|
+
} else {
|
|
2834
|
+
validateError = data.error || 'Validation failed';
|
|
2835
|
+
}
|
|
2836
|
+
} catch (e) {
|
|
2837
|
+
validateError = e instanceof Error ? e.message : 'Network error';
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
validating = false;
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
// ===========================================================================
|
|
2844
|
+
// Deployment
|
|
2845
|
+
// ===========================================================================
|
|
2846
|
+
|
|
2847
|
+
function pollForDeployment(): Promise<void> {
|
|
2848
|
+
return new Promise((resolve) => {
|
|
2849
|
+
let resolved = false;
|
|
2850
|
+
|
|
2851
|
+
const done = () => {
|
|
2852
|
+
if (resolved) return;
|
|
2853
|
+
resolved = true;
|
|
2854
|
+
stopPoll();
|
|
2855
|
+
stopMonitor();
|
|
2856
|
+
deployStage = 'ready';
|
|
2857
|
+
resolve();
|
|
2858
|
+
};
|
|
2859
|
+
|
|
2860
|
+
const stopMonitor = monitorSwLifecycle({ onUpdateAvailable: done });
|
|
2861
|
+
|
|
2862
|
+
const stopPoll = pollForNewServiceWorker({
|
|
2863
|
+
intervalMs: 3000,
|
|
2864
|
+
maxAttempts: 200,
|
|
2865
|
+
onFound: done
|
|
2866
|
+
});
|
|
2867
|
+
|
|
2868
|
+
if (typeof navigator !== 'undefined' && navigator.serviceWorker) {
|
|
2869
|
+
navigator.serviceWorker.addEventListener('controllerchange', done, { once: true });
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
setTimeout(() => {
|
|
2873
|
+
if (!resolved) done();
|
|
2874
|
+
}, 180_000);
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
async function handleDeploy() {
|
|
2879
|
+
deployError = null;
|
|
2880
|
+
deploying = true;
|
|
2881
|
+
deployStage = 'setting-env';
|
|
2882
|
+
|
|
2883
|
+
try {
|
|
2884
|
+
const res = await fetch('/api/setup/deploy', {
|
|
2885
|
+
method: 'POST',
|
|
2886
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2887
|
+
body: JSON.stringify({ supabaseUrl, supabasePublishableKey, vercelToken })
|
|
2888
|
+
});
|
|
2889
|
+
|
|
2890
|
+
const data = await res.json();
|
|
2891
|
+
|
|
2892
|
+
if (data.success) {
|
|
2893
|
+
deployStage = 'deploying';
|
|
2894
|
+
await pollForDeployment();
|
|
2895
|
+
} else {
|
|
2896
|
+
deployError = data.error || 'Deployment failed';
|
|
2897
|
+
deployStage = 'idle';
|
|
2898
|
+
}
|
|
2899
|
+
} catch (e) {
|
|
2900
|
+
deployError = e instanceof Error ? e.message : 'Network error';
|
|
2901
|
+
deployStage = 'idle';
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
deploying = false;
|
|
2905
|
+
}
|
|
2906
|
+
</script>
|
|
2907
|
+
|
|
2908
|
+
<div class="reconfigure-page">
|
|
2909
|
+
{#if loading}
|
|
2910
|
+
<div class="loading-state">
|
|
2911
|
+
<span class="loading-spinner"></span>
|
|
2912
|
+
Loading configuration...
|
|
2913
|
+
</div>
|
|
2914
|
+
{:else}
|
|
2915
|
+
<!-- Supabase Connection Card -->
|
|
2916
|
+
<section class="config-card">
|
|
2917
|
+
<div class="card-header">
|
|
2918
|
+
<h2>Supabase Connection</h2>
|
|
2919
|
+
{#if !supabaseChanged && initialSupabaseUrl}
|
|
2920
|
+
<span class="status-badge status-connected">Connected</span>
|
|
2921
|
+
{/if}
|
|
2922
|
+
</div>
|
|
2923
|
+
|
|
2924
|
+
<p class="card-description">
|
|
2925
|
+
Find these values in your Supabase dashboard under <strong>Settings > API</strong>.
|
|
2926
|
+
</p>
|
|
2927
|
+
|
|
2928
|
+
<div class="form-group">
|
|
2929
|
+
<label for="reconfig-supabase-url">Supabase URL</label>
|
|
2930
|
+
<input
|
|
2931
|
+
id="reconfig-supabase-url"
|
|
2932
|
+
type="url"
|
|
2933
|
+
placeholder="https://your-project.supabase.co"
|
|
2934
|
+
bind:value={supabaseUrl}
|
|
2935
|
+
autocomplete="off"
|
|
2936
|
+
spellcheck="false"
|
|
2937
|
+
/>
|
|
2938
|
+
</div>
|
|
2939
|
+
|
|
2940
|
+
<div class="form-group">
|
|
2941
|
+
<label for="reconfig-supabase-key">Supabase Publishable Key</label>
|
|
2942
|
+
<input
|
|
2943
|
+
id="reconfig-supabase-key"
|
|
2944
|
+
type="text"
|
|
2945
|
+
placeholder="eyJhbGciOiJIUzI1NiIs..."
|
|
2946
|
+
bind:value={supabasePublishableKey}
|
|
2947
|
+
autocomplete="off"
|
|
2948
|
+
spellcheck="false"
|
|
2949
|
+
/>
|
|
2950
|
+
<span class="input-hint"
|
|
2951
|
+
>This is your public (anon) key. Row-Level Security policies enforce access control.</span
|
|
2952
|
+
>
|
|
2953
|
+
</div>
|
|
2954
|
+
|
|
2955
|
+
<button
|
|
2956
|
+
class="btn btn-secondary"
|
|
2957
|
+
onclick={handleValidate}
|
|
2958
|
+
disabled={!supabaseUrl || !supabasePublishableKey || validating}
|
|
2959
|
+
>
|
|
2960
|
+
{#if validating}
|
|
2961
|
+
<span class="loading-spinner small"></span>
|
|
2962
|
+
Testing connection...
|
|
2963
|
+
{:else}
|
|
2964
|
+
Test Connection
|
|
2965
|
+
{/if}
|
|
2966
|
+
</button>
|
|
2967
|
+
|
|
2968
|
+
{#if validateError}
|
|
2969
|
+
<div class="message error">{validateError}</div>
|
|
2970
|
+
{/if}
|
|
2971
|
+
{#if validateSuccess && !credentialsChanged}
|
|
2972
|
+
<div class="message success">Connection successful — credentials are valid.</div>
|
|
2973
|
+
{/if}
|
|
2974
|
+
</section>
|
|
2975
|
+
|
|
2976
|
+
<!-- Deploy Section -->
|
|
2977
|
+
<section class="config-card">
|
|
2978
|
+
<div class="card-header">
|
|
2979
|
+
<h2>Deploy Changes</h2>
|
|
2980
|
+
</div>
|
|
2981
|
+
|
|
2982
|
+
{#if !$isOnline}
|
|
2983
|
+
<div class="message error">
|
|
2984
|
+
You are currently offline. Deployment requires an internet connection.
|
|
2985
|
+
</div>
|
|
2986
|
+
{/if}
|
|
2987
|
+
|
|
2988
|
+
<div class="form-group">
|
|
2989
|
+
<label for="reconfig-vercel-token">Vercel API Token</label>
|
|
2990
|
+
<input
|
|
2991
|
+
id="reconfig-vercel-token"
|
|
2992
|
+
type="password"
|
|
2993
|
+
placeholder="Paste your Vercel token"
|
|
2994
|
+
bind:value={vercelToken}
|
|
2995
|
+
autocomplete="off"
|
|
2996
|
+
disabled={deploying || deployStage !== 'idle'}
|
|
2997
|
+
/>
|
|
2998
|
+
<span class="input-hint">
|
|
2999
|
+
Create a token at
|
|
3000
|
+
<a href="https://vercel.com/account/tokens" target="_blank" rel="noopener noreferrer">
|
|
3001
|
+
vercel.com/account/tokens</a
|
|
3002
|
+
>. It is used once and never stored.
|
|
3003
|
+
</span>
|
|
3004
|
+
</div>
|
|
3005
|
+
|
|
3006
|
+
{#if deployStage === 'idle'}
|
|
3007
|
+
<button class="btn btn-primary" onclick={handleDeploy} disabled={!canDeploy}>
|
|
3008
|
+
{#if deploying}
|
|
3009
|
+
<span class="loading-spinner small"></span>
|
|
3010
|
+
Deploying...
|
|
3011
|
+
{:else}
|
|
3012
|
+
Deploy Changes
|
|
3013
|
+
{/if}
|
|
3014
|
+
</button>
|
|
3015
|
+
{/if}
|
|
3016
|
+
|
|
3017
|
+
{#if deployError}
|
|
3018
|
+
<div class="message error">{deployError}</div>
|
|
3019
|
+
{/if}
|
|
3020
|
+
|
|
3021
|
+
{#if deployStage !== 'idle'}
|
|
3022
|
+
<div class="deploy-steps">
|
|
3023
|
+
<div
|
|
3024
|
+
class="deploy-step"
|
|
3025
|
+
class:active={deployStage === 'setting-env'}
|
|
3026
|
+
class:complete={deployStage === 'deploying' || deployStage === 'ready'}
|
|
3027
|
+
>
|
|
3028
|
+
<div class="deploy-step-indicator">
|
|
3029
|
+
{#if deployStage === 'setting-env'}
|
|
3030
|
+
<span class="loading-spinner small"></span>
|
|
3031
|
+
{:else}
|
|
3032
|
+
<svg
|
|
3033
|
+
width="16"
|
|
3034
|
+
height="16"
|
|
3035
|
+
viewBox="0 0 24 24"
|
|
3036
|
+
fill="none"
|
|
3037
|
+
stroke="currentColor"
|
|
3038
|
+
stroke-width="3"
|
|
3039
|
+
stroke-linecap="round"
|
|
3040
|
+
stroke-linejoin="round"
|
|
3041
|
+
>
|
|
3042
|
+
<polyline points="20 6 9 17 4 12" />
|
|
3043
|
+
</svg>
|
|
3044
|
+
{/if}
|
|
3045
|
+
</div>
|
|
3046
|
+
<span>Setting environment variables...</span>
|
|
3047
|
+
</div>
|
|
3048
|
+
|
|
3049
|
+
<div
|
|
3050
|
+
class="deploy-step"
|
|
3051
|
+
class:active={deployStage === 'deploying'}
|
|
3052
|
+
class:complete={deployStage === 'ready'}
|
|
3053
|
+
>
|
|
3054
|
+
<div class="deploy-step-indicator">
|
|
3055
|
+
{#if deployStage === 'deploying'}
|
|
3056
|
+
<span class="loading-spinner small"></span>
|
|
3057
|
+
{:else if deployStage === 'ready'}
|
|
3058
|
+
<svg
|
|
3059
|
+
width="16"
|
|
3060
|
+
height="16"
|
|
3061
|
+
viewBox="0 0 24 24"
|
|
3062
|
+
fill="none"
|
|
3063
|
+
stroke="currentColor"
|
|
3064
|
+
stroke-width="3"
|
|
3065
|
+
stroke-linecap="round"
|
|
3066
|
+
stroke-linejoin="round"
|
|
3067
|
+
>
|
|
3068
|
+
<polyline points="20 6 9 17 4 12" />
|
|
3069
|
+
</svg>
|
|
3070
|
+
{:else}
|
|
3071
|
+
<div class="deploy-dot"></div>
|
|
3072
|
+
{/if}
|
|
3073
|
+
</div>
|
|
3074
|
+
<span>Deploying... (might take a bit)</span>
|
|
3075
|
+
</div>
|
|
3076
|
+
|
|
3077
|
+
<div class="deploy-step" class:active={deployStage === 'ready'}>
|
|
3078
|
+
<div class="deploy-step-indicator">
|
|
3079
|
+
{#if deployStage === 'ready'}
|
|
3080
|
+
<svg
|
|
3081
|
+
width="16"
|
|
3082
|
+
height="16"
|
|
3083
|
+
viewBox="0 0 24 24"
|
|
3084
|
+
fill="none"
|
|
3085
|
+
stroke="currentColor"
|
|
3086
|
+
stroke-width="3"
|
|
3087
|
+
stroke-linecap="round"
|
|
3088
|
+
stroke-linejoin="round"
|
|
3089
|
+
>
|
|
3090
|
+
<polyline points="20 6 9 17 4 12" />
|
|
3091
|
+
</svg>
|
|
3092
|
+
{:else}
|
|
3093
|
+
<div class="deploy-dot"></div>
|
|
3094
|
+
{/if}
|
|
3095
|
+
</div>
|
|
3096
|
+
<span>Ready</span>
|
|
3097
|
+
</div>
|
|
3098
|
+
</div>
|
|
3099
|
+
|
|
3100
|
+
{#if deployStage === 'ready'}
|
|
3101
|
+
<div class="message success">
|
|
3102
|
+
Deployment complete! Use the update prompt at the bottom of the screen to refresh. If it
|
|
3103
|
+
doesn't appear, click below.
|
|
3104
|
+
</div>
|
|
3105
|
+
<button
|
|
3106
|
+
class="btn btn-secondary"
|
|
3107
|
+
onclick={() => (window.location.href = '/')}
|
|
3108
|
+
style="margin-top: 0.75rem;"
|
|
3109
|
+
>
|
|
3110
|
+
Manually refresh & go home
|
|
3111
|
+
</button>
|
|
3112
|
+
{/if}
|
|
3113
|
+
{/if}
|
|
3114
|
+
</section>
|
|
3115
|
+
{/if}
|
|
3116
|
+
</div>
|
|
3117
|
+
|
|
3118
|
+
<style>
|
|
3119
|
+
/* ===========================================================================
|
|
3120
|
+
Layout
|
|
3121
|
+
=========================================================================== */
|
|
3122
|
+
|
|
3123
|
+
.reconfigure-page {
|
|
3124
|
+
max-width: 640px;
|
|
3125
|
+
width: 100%;
|
|
3126
|
+
display: flex;
|
|
3127
|
+
flex-direction: column;
|
|
3128
|
+
gap: 1.5rem;
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
.loading-state {
|
|
3132
|
+
display: flex;
|
|
3133
|
+
align-items: center;
|
|
3134
|
+
justify-content: center;
|
|
3135
|
+
gap: 0.75rem;
|
|
3136
|
+
padding: 3rem;
|
|
3137
|
+
font-size: 0.9375rem;
|
|
3138
|
+
color: var(--color-text-muted, #666);
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
/* ===========================================================================
|
|
3142
|
+
Config Card
|
|
3143
|
+
=========================================================================== */
|
|
3144
|
+
|
|
3145
|
+
.config-card {
|
|
3146
|
+
padding: 1.5rem;
|
|
3147
|
+
background: var(--color-surface, #fff);
|
|
3148
|
+
border: 1px solid var(--color-border, #e2e2e2);
|
|
3149
|
+
border-radius: 12px;
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
.card-header {
|
|
3153
|
+
display: flex;
|
|
3154
|
+
align-items: center;
|
|
3155
|
+
justify-content: space-between;
|
|
3156
|
+
margin-bottom: 1rem;
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
.card-header h2 {
|
|
3160
|
+
margin: 0;
|
|
3161
|
+
font-size: 1.0625rem;
|
|
3162
|
+
font-weight: 700;
|
|
3163
|
+
color: var(--color-text, #111);
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
.card-description {
|
|
3167
|
+
margin: 0 0 1rem;
|
|
3168
|
+
font-size: 0.875rem;
|
|
3169
|
+
color: var(--color-text-muted, #666);
|
|
3170
|
+
line-height: 1.6;
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
.card-description strong {
|
|
3174
|
+
color: var(--color-text, #111);
|
|
3175
|
+
font-weight: 600;
|
|
3176
|
+
}
|
|
3177
|
+
|
|
3178
|
+
/* ===========================================================================
|
|
3179
|
+
Status Badges
|
|
3180
|
+
=========================================================================== */
|
|
3181
|
+
|
|
3182
|
+
.status-badge {
|
|
3183
|
+
display: inline-flex;
|
|
3184
|
+
align-items: center;
|
|
3185
|
+
gap: 0.25rem;
|
|
3186
|
+
padding: 0.2rem 0.5rem;
|
|
3187
|
+
font-size: 0.6875rem;
|
|
3188
|
+
font-weight: 600;
|
|
3189
|
+
border-radius: 4px;
|
|
3190
|
+
letter-spacing: 0.02em;
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
.status-connected {
|
|
3194
|
+
background: var(--color-success-bg, #f0fdf4);
|
|
3195
|
+
color: var(--color-success, #16a34a);
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
/* ===========================================================================
|
|
3199
|
+
Form Elements
|
|
3200
|
+
=========================================================================== */
|
|
3201
|
+
|
|
3202
|
+
.form-group {
|
|
3203
|
+
display: flex;
|
|
3204
|
+
flex-direction: column;
|
|
3205
|
+
gap: 0.5rem;
|
|
3206
|
+
margin-bottom: 1rem;
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
.form-group label {
|
|
3210
|
+
font-weight: 700;
|
|
3211
|
+
color: var(--color-text-muted, #666);
|
|
3212
|
+
font-size: 0.6875rem;
|
|
3213
|
+
text-transform: uppercase;
|
|
3214
|
+
letter-spacing: 0.1em;
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
.form-group input {
|
|
3218
|
+
width: 100%;
|
|
3219
|
+
padding: 0.75rem 0.875rem;
|
|
3220
|
+
font-size: 0.9375rem;
|
|
3221
|
+
color: var(--color-text, #111);
|
|
3222
|
+
background: var(--color-bg, #fafafa);
|
|
3223
|
+
border: 1px solid var(--color-border, #e2e2e2);
|
|
3224
|
+
border-radius: 8px;
|
|
3225
|
+
transition: border-color 0.2s;
|
|
3226
|
+
font-family: inherit;
|
|
3227
|
+
box-sizing: border-box;
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3230
|
+
.form-group input:focus {
|
|
3231
|
+
outline: none;
|
|
3232
|
+
border-color: var(--color-primary, #3b82f6);
|
|
3233
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
|
|
3234
|
+
}
|
|
3235
|
+
|
|
3236
|
+
.form-group input:disabled {
|
|
3237
|
+
opacity: 0.6;
|
|
3238
|
+
cursor: not-allowed;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
.form-group input::placeholder {
|
|
3242
|
+
color: var(--color-text-muted, #999);
|
|
3243
|
+
opacity: 0.6;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
.input-hint {
|
|
3247
|
+
font-size: 0.75rem;
|
|
3248
|
+
color: var(--color-text-muted, #666);
|
|
3249
|
+
opacity: 0.7;
|
|
3250
|
+
line-height: 1.4;
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
.input-hint a {
|
|
3254
|
+
color: var(--color-primary, #3b82f6);
|
|
3255
|
+
text-decoration: none;
|
|
3256
|
+
border-bottom: 1px solid rgba(59, 130, 246, 0.3);
|
|
3257
|
+
transition: border-color 0.2s;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
.input-hint a:hover {
|
|
3261
|
+
border-bottom-color: var(--color-primary, #3b82f6);
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
/* ===========================================================================
|
|
3265
|
+
Messages
|
|
3266
|
+
=========================================================================== */
|
|
3267
|
+
|
|
3268
|
+
.message {
|
|
3269
|
+
padding: 0.875rem 1rem;
|
|
3270
|
+
border-radius: 8px;
|
|
3271
|
+
font-size: 0.875rem;
|
|
3272
|
+
font-weight: 500;
|
|
3273
|
+
line-height: 1.5;
|
|
3274
|
+
margin-top: 0.75rem;
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
.error {
|
|
3278
|
+
background: var(--color-error-bg, #fef2f2);
|
|
3279
|
+
color: var(--color-error, #dc2626);
|
|
3280
|
+
border: 1px solid rgba(220, 38, 38, 0.2);
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3283
|
+
.success {
|
|
3284
|
+
background: var(--color-success-bg, #f0fdf4);
|
|
3285
|
+
color: var(--color-success, #16a34a);
|
|
3286
|
+
border: 1px solid rgba(22, 163, 106, 0.2);
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
/* ===========================================================================
|
|
3290
|
+
Buttons
|
|
3291
|
+
=========================================================================== */
|
|
3292
|
+
|
|
3293
|
+
.btn {
|
|
3294
|
+
display: flex;
|
|
3295
|
+
align-items: center;
|
|
3296
|
+
justify-content: center;
|
|
3297
|
+
gap: 0.5rem;
|
|
3298
|
+
padding: 0.75rem 1.25rem;
|
|
3299
|
+
font-size: 0.9375rem;
|
|
3300
|
+
font-weight: 600;
|
|
3301
|
+
border-radius: 8px;
|
|
3302
|
+
cursor: pointer;
|
|
3303
|
+
transition: all 0.2s;
|
|
3304
|
+
border: none;
|
|
3305
|
+
font-family: inherit;
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3308
|
+
.btn-primary {
|
|
3309
|
+
background: var(--color-primary, #3b82f6);
|
|
3310
|
+
color: white;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
.btn-primary:hover:not(:disabled) {
|
|
3314
|
+
opacity: 0.9;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
.btn-secondary {
|
|
3318
|
+
background: var(--color-secondary, #6b7280);
|
|
3319
|
+
color: white;
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
.btn-secondary:hover:not(:disabled) {
|
|
3323
|
+
opacity: 0.9;
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
.btn:disabled {
|
|
3327
|
+
opacity: 0.5;
|
|
3328
|
+
cursor: not-allowed;
|
|
3329
|
+
}
|
|
3330
|
+
|
|
3331
|
+
/* ===========================================================================
|
|
3332
|
+
Loading Spinner
|
|
3333
|
+
=========================================================================== */
|
|
3334
|
+
|
|
3335
|
+
.loading-spinner {
|
|
3336
|
+
width: 18px;
|
|
3337
|
+
height: 18px;
|
|
3338
|
+
border: 2px solid rgba(0, 0, 0, 0.15);
|
|
3339
|
+
border-top-color: var(--color-primary, #3b82f6);
|
|
3340
|
+
border-radius: 50%;
|
|
3341
|
+
animation: spin 0.8s linear infinite;
|
|
3342
|
+
display: inline-block;
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3345
|
+
.loading-spinner.small {
|
|
3346
|
+
width: 14px;
|
|
3347
|
+
height: 14px;
|
|
3348
|
+
border-width: 2px;
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
@keyframes spin {
|
|
3352
|
+
to {
|
|
3353
|
+
transform: rotate(360deg);
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
|
|
3357
|
+
/* ===========================================================================
|
|
3358
|
+
Deploy Steps
|
|
3359
|
+
=========================================================================== */
|
|
3360
|
+
|
|
3361
|
+
.deploy-steps {
|
|
3362
|
+
display: flex;
|
|
3363
|
+
flex-direction: column;
|
|
3364
|
+
gap: 0.75rem;
|
|
3365
|
+
margin-top: 1rem;
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
.deploy-step {
|
|
3369
|
+
display: flex;
|
|
3370
|
+
align-items: center;
|
|
3371
|
+
gap: 0.75rem;
|
|
3372
|
+
font-size: 0.875rem;
|
|
3373
|
+
color: var(--color-text-muted, #999);
|
|
3374
|
+
opacity: 0.5;
|
|
3375
|
+
transition: all 0.3s;
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
.deploy-step.active {
|
|
3379
|
+
opacity: 1;
|
|
3380
|
+
color: var(--color-primary, #3b82f6);
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3383
|
+
.deploy-step.complete {
|
|
3384
|
+
opacity: 1;
|
|
3385
|
+
color: var(--color-success, #16a34a);
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
.deploy-step-indicator {
|
|
3389
|
+
width: 24px;
|
|
3390
|
+
height: 24px;
|
|
3391
|
+
display: flex;
|
|
3392
|
+
align-items: center;
|
|
3393
|
+
justify-content: center;
|
|
3394
|
+
flex-shrink: 0;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
.deploy-dot {
|
|
3398
|
+
width: 8px;
|
|
3399
|
+
height: 8px;
|
|
3400
|
+
background: var(--color-border, #ccc);
|
|
3401
|
+
border-radius: 50%;
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
/* ===========================================================================
|
|
3405
|
+
Responsive
|
|
3406
|
+
=========================================================================== */
|
|
3407
|
+
|
|
3408
|
+
@media (max-width: 640px) {
|
|
3409
|
+
.config-card {
|
|
3410
|
+
padding: 1.25rem;
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
.form-group input {
|
|
3414
|
+
font-size: 16px;
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3419
|
+
.loading-spinner {
|
|
3420
|
+
animation: none;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
.btn {
|
|
3424
|
+
transition: none;
|
|
3425
|
+
}
|
|
3426
|
+
|
|
3427
|
+
.deploy-step {
|
|
3428
|
+
transition: none;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
</style>
|
|
3432
|
+
`;
|
|
3433
|
+
}
|
|
2694
3434
|
/**
|
|
2695
3435
|
* Generate a minimal privacy policy page component.
|
|
2696
3436
|
*
|
|
@@ -5278,6 +6018,7 @@ export async function run() {
|
|
|
5278
6018
|
['src/routes/+error.svelte', generateErrorPage(opts)],
|
|
5279
6019
|
['src/routes/setup/+page.ts', generateSetupPageTs()],
|
|
5280
6020
|
['src/routes/setup/+page.svelte', generateSetupPageSvelte(opts)],
|
|
6021
|
+
['src/routes/setup/Reconfigure.svelte', generateReconfigureSvelte(opts)],
|
|
5281
6022
|
['src/routes/policy/+page.svelte', generatePolicyPage(opts)],
|
|
5282
6023
|
['src/routes/login/+page.svelte', generateLoginPage(opts)],
|
|
5283
6024
|
['src/routes/confirm/+page.svelte', generateConfirmPage(opts)],
|