stellar-drive 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +607 -0
- package/dist/actions/remoteChange.d.ts +204 -0
- package/dist/actions/remoteChange.d.ts.map +1 -0
- package/dist/actions/remoteChange.js +424 -0
- package/dist/actions/remoteChange.js.map +1 -0
- package/dist/actions/truncateTooltip.d.ts +56 -0
- package/dist/actions/truncateTooltip.d.ts.map +1 -0
- package/dist/actions/truncateTooltip.js +312 -0
- package/dist/actions/truncateTooltip.js.map +1 -0
- package/dist/auth/crypto.d.ts +41 -0
- package/dist/auth/crypto.d.ts.map +1 -0
- package/dist/auth/crypto.js +50 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/deviceVerification.d.ts +283 -0
- package/dist/auth/deviceVerification.d.ts.map +1 -0
- package/dist/auth/deviceVerification.js +575 -0
- package/dist/auth/deviceVerification.js.map +1 -0
- package/dist/auth/displayUtils.d.ts +98 -0
- package/dist/auth/displayUtils.d.ts.map +1 -0
- package/dist/auth/displayUtils.js +145 -0
- package/dist/auth/displayUtils.js.map +1 -0
- package/dist/auth/loginGuard.d.ts +134 -0
- package/dist/auth/loginGuard.d.ts.map +1 -0
- package/dist/auth/loginGuard.js +276 -0
- package/dist/auth/loginGuard.js.map +1 -0
- package/dist/auth/offlineCredentials.d.ts +105 -0
- package/dist/auth/offlineCredentials.d.ts.map +1 -0
- package/dist/auth/offlineCredentials.js +176 -0
- package/dist/auth/offlineCredentials.js.map +1 -0
- package/dist/auth/offlineSession.d.ts +96 -0
- package/dist/auth/offlineSession.d.ts.map +1 -0
- package/dist/auth/offlineSession.js +145 -0
- package/dist/auth/offlineSession.js.map +1 -0
- package/dist/auth/resolveAuthState.d.ts +85 -0
- package/dist/auth/resolveAuthState.d.ts.map +1 -0
- package/dist/auth/resolveAuthState.js +249 -0
- package/dist/auth/resolveAuthState.js.map +1 -0
- package/dist/auth/singleUser.d.ts +498 -0
- package/dist/auth/singleUser.d.ts.map +1 -0
- package/dist/auth/singleUser.js +1282 -0
- package/dist/auth/singleUser.js.map +1 -0
- package/dist/bin/commands.d.ts +14 -0
- package/dist/bin/commands.d.ts.map +1 -0
- package/dist/bin/commands.js +68 -0
- package/dist/bin/commands.js.map +1 -0
- package/dist/bin/install-pwa.d.ts +41 -0
- package/dist/bin/install-pwa.d.ts.map +1 -0
- package/dist/bin/install-pwa.js +4594 -0
- package/dist/bin/install-pwa.js.map +1 -0
- package/dist/config.d.ts +249 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +395 -0
- package/dist/config.js.map +1 -0
- package/dist/conflicts.d.ts +306 -0
- package/dist/conflicts.d.ts.map +1 -0
- package/dist/conflicts.js +807 -0
- package/dist/conflicts.js.map +1 -0
- package/dist/crdt/awareness.d.ts +128 -0
- package/dist/crdt/awareness.d.ts.map +1 -0
- package/dist/crdt/awareness.js +284 -0
- package/dist/crdt/awareness.js.map +1 -0
- package/dist/crdt/channel.d.ts +165 -0
- package/dist/crdt/channel.d.ts.map +1 -0
- package/dist/crdt/channel.js +522 -0
- package/dist/crdt/channel.js.map +1 -0
- package/dist/crdt/config.d.ts +58 -0
- package/dist/crdt/config.d.ts.map +1 -0
- package/dist/crdt/config.js +123 -0
- package/dist/crdt/config.js.map +1 -0
- package/dist/crdt/helpers.d.ts +104 -0
- package/dist/crdt/helpers.d.ts.map +1 -0
- package/dist/crdt/helpers.js +116 -0
- package/dist/crdt/helpers.js.map +1 -0
- package/dist/crdt/offline.d.ts +58 -0
- package/dist/crdt/offline.d.ts.map +1 -0
- package/dist/crdt/offline.js +130 -0
- package/dist/crdt/offline.js.map +1 -0
- package/dist/crdt/persistence.d.ts +65 -0
- package/dist/crdt/persistence.d.ts.map +1 -0
- package/dist/crdt/persistence.js +171 -0
- package/dist/crdt/persistence.js.map +1 -0
- package/dist/crdt/provider.d.ts +109 -0
- package/dist/crdt/provider.d.ts.map +1 -0
- package/dist/crdt/provider.js +543 -0
- package/dist/crdt/provider.js.map +1 -0
- package/dist/crdt/store.d.ts +111 -0
- package/dist/crdt/store.d.ts.map +1 -0
- package/dist/crdt/store.js +158 -0
- package/dist/crdt/store.js.map +1 -0
- package/dist/crdt/types.d.ts +281 -0
- package/dist/crdt/types.d.ts.map +1 -0
- package/dist/crdt/types.js +26 -0
- package/dist/crdt/types.js.map +1 -0
- package/dist/data.d.ts +502 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +862 -0
- package/dist/data.js.map +1 -0
- package/dist/database.d.ts +153 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +325 -0
- package/dist/database.js.map +1 -0
- package/dist/debug.d.ts +87 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +135 -0
- package/dist/debug.js.map +1 -0
- package/dist/demo.d.ts +131 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +168 -0
- package/dist/demo.js.map +1 -0
- package/dist/deviceId.d.ts +47 -0
- package/dist/deviceId.d.ts.map +1 -0
- package/dist/deviceId.js +106 -0
- package/dist/deviceId.js.map +1 -0
- package/dist/diagnostics.d.ts +292 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +378 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/engine.d.ts +230 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +2636 -0
- package/dist/engine.js.map +1 -0
- package/dist/entries/actions.d.ts +16 -0
- package/dist/entries/actions.d.ts.map +1 -0
- package/dist/entries/actions.js +29 -0
- package/dist/entries/actions.js.map +1 -0
- package/dist/entries/auth.d.ts +19 -0
- package/dist/entries/auth.d.ts.map +1 -0
- package/dist/entries/auth.js +50 -0
- package/dist/entries/auth.js.map +1 -0
- package/dist/entries/config.d.ts +15 -0
- package/dist/entries/config.d.ts.map +1 -0
- package/dist/entries/config.js +20 -0
- package/dist/entries/config.js.map +1 -0
- package/dist/entries/crdt.d.ts +32 -0
- package/dist/entries/crdt.d.ts.map +1 -0
- package/dist/entries/crdt.js +52 -0
- package/dist/entries/crdt.js.map +1 -0
- package/dist/entries/kit.d.ts +22 -0
- package/dist/entries/kit.d.ts.map +1 -0
- package/dist/entries/kit.js +58 -0
- package/dist/entries/kit.js.map +1 -0
- package/dist/entries/stores.d.ts +22 -0
- package/dist/entries/stores.d.ts.map +1 -0
- package/dist/entries/stores.js +57 -0
- package/dist/entries/stores.js.map +1 -0
- package/dist/entries/types.d.ts +23 -0
- package/dist/entries/types.d.ts.map +1 -0
- package/dist/entries/types.js +12 -0
- package/dist/entries/types.js.map +1 -0
- package/dist/entries/utils.d.ts +12 -0
- package/dist/entries/utils.d.ts.map +1 -0
- package/dist/entries/utils.js +42 -0
- package/dist/entries/utils.js.map +1 -0
- package/dist/entries/vite.d.ts +20 -0
- package/dist/entries/vite.d.ts.map +1 -0
- package/dist/entries/vite.js +26 -0
- package/dist/entries/vite.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +234 -0
- package/dist/index.js.map +1 -0
- package/dist/kit/auth.d.ts +80 -0
- package/dist/kit/auth.d.ts.map +1 -0
- package/dist/kit/auth.js +75 -0
- package/dist/kit/auth.js.map +1 -0
- package/dist/kit/confirm.d.ts +111 -0
- package/dist/kit/confirm.d.ts.map +1 -0
- package/dist/kit/confirm.js +169 -0
- package/dist/kit/confirm.js.map +1 -0
- package/dist/kit/loads.d.ts +187 -0
- package/dist/kit/loads.d.ts.map +1 -0
- package/dist/kit/loads.js +208 -0
- package/dist/kit/loads.js.map +1 -0
- package/dist/kit/server.d.ts +175 -0
- package/dist/kit/server.d.ts.map +1 -0
- package/dist/kit/server.js +297 -0
- package/dist/kit/server.js.map +1 -0
- package/dist/kit/sw.d.ts +176 -0
- package/dist/kit/sw.d.ts.map +1 -0
- package/dist/kit/sw.js +320 -0
- package/dist/kit/sw.js.map +1 -0
- package/dist/queue.d.ts +306 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +925 -0
- package/dist/queue.js.map +1 -0
- package/dist/realtime.d.ts +280 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +1031 -0
- package/dist/realtime.js.map +1 -0
- package/dist/runtime/runtimeConfig.d.ts +110 -0
- package/dist/runtime/runtimeConfig.d.ts.map +1 -0
- package/dist/runtime/runtimeConfig.js +260 -0
- package/dist/runtime/runtimeConfig.js.map +1 -0
- package/dist/schema.d.ts +150 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +891 -0
- package/dist/schema.js.map +1 -0
- package/dist/stores/authState.d.ts +204 -0
- package/dist/stores/authState.d.ts.map +1 -0
- package/dist/stores/authState.js +336 -0
- package/dist/stores/authState.js.map +1 -0
- package/dist/stores/factories.d.ts +140 -0
- package/dist/stores/factories.d.ts.map +1 -0
- package/dist/stores/factories.js +157 -0
- package/dist/stores/factories.js.map +1 -0
- package/dist/stores/network.d.ts +48 -0
- package/dist/stores/network.d.ts.map +1 -0
- package/dist/stores/network.js +261 -0
- package/dist/stores/network.js.map +1 -0
- package/dist/stores/remoteChanges.d.ts +417 -0
- package/dist/stores/remoteChanges.d.ts.map +1 -0
- package/dist/stores/remoteChanges.js +626 -0
- package/dist/stores/remoteChanges.js.map +1 -0
- package/dist/stores/sync.d.ts +165 -0
- package/dist/stores/sync.d.ts.map +1 -0
- package/dist/stores/sync.js +275 -0
- package/dist/stores/sync.js.map +1 -0
- package/dist/supabase/auth.d.ts +219 -0
- package/dist/supabase/auth.d.ts.map +1 -0
- package/dist/supabase/auth.js +459 -0
- package/dist/supabase/auth.js.map +1 -0
- package/dist/supabase/client.d.ts +88 -0
- package/dist/supabase/client.d.ts.map +1 -0
- package/dist/supabase/client.js +313 -0
- package/dist/supabase/client.js.map +1 -0
- package/dist/supabase/validate.d.ts +118 -0
- package/dist/supabase/validate.d.ts.map +1 -0
- package/dist/supabase/validate.js +208 -0
- package/dist/supabase/validate.js.map +1 -0
- package/dist/sw/build/vite-plugin.d.ts +149 -0
- package/dist/sw/build/vite-plugin.d.ts.map +1 -0
- package/dist/sw/build/vite-plugin.js +517 -0
- package/dist/sw/build/vite-plugin.js.map +1 -0
- package/dist/sw/sw.js +664 -0
- package/dist/types.d.ts +363 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +85 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +156 -0
- package/dist/utils.js.map +1 -0
- package/package.json +117 -0
- package/src/components/DeferredChangesBanner.svelte +477 -0
- package/src/components/DemoBanner.svelte +110 -0
- package/src/components/SyncStatus.svelte +1732 -0
package/dist/kit/auth.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Auth hydration helper for the root layout component.
|
|
3
|
+
*
|
|
4
|
+
* This module bridges the gap between SvelteKit's server-side load data and
|
|
5
|
+
* the client-side reactive auth store (`authState`). When the root layout
|
|
6
|
+
* receives auth-related data from a load function, this helper inspects the
|
|
7
|
+
* `authMode` discriminator and calls the corresponding `authState.set*()`
|
|
8
|
+
* setter so that every downstream component gets reactive access to the
|
|
9
|
+
* current authentication state without needing to know the hydration details.
|
|
10
|
+
*
|
|
11
|
+
* @module kit/auth
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```svelte
|
|
15
|
+
* <!-- +layout.svelte -->
|
|
16
|
+
* <script lang="ts">
|
|
17
|
+
* import { hydrateAuthState } from 'stellar-drive/kit/auth';
|
|
18
|
+
* let { data } = $props();
|
|
19
|
+
* $effect(() => { hydrateAuthState(data); });
|
|
20
|
+
* </script>
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @see {@link authState} for the reactive store being hydrated
|
|
24
|
+
* @see {@link resolveAuthState} in `auth/resolveAuthState.ts` for how auth
|
|
25
|
+
* state is determined on the server/load side
|
|
26
|
+
*/
|
|
27
|
+
import { authState } from '../stores/authState.js';
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// PUBLIC API
|
|
30
|
+
// =============================================================================
|
|
31
|
+
/**
|
|
32
|
+
* Reads layout load data (`{ authMode, session, offlineProfile }`) and calls
|
|
33
|
+
* the appropriate `authState.set*()` method to hydrate the client-side
|
|
34
|
+
* reactive auth store.
|
|
35
|
+
*
|
|
36
|
+
* The function acts as a switchboard: it inspects `authMode` and delegates to
|
|
37
|
+
* the matching setter on the `authState` store. This keeps the root layout
|
|
38
|
+
* component free of branching logic and ensures a single source of truth for
|
|
39
|
+
* how layout data maps to reactive state.
|
|
40
|
+
*
|
|
41
|
+
* Call this from a Svelte 5 `$effect()` in your root `+layout.svelte` so it
|
|
42
|
+
* re-runs whenever the layout data changes (e.g. after a login or logout):
|
|
43
|
+
*
|
|
44
|
+
* @param layoutData - The auth-related subset of root layout load data.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* // In +layout.svelte
|
|
49
|
+
* $effect(() => { hydrateAuthState(data); });
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @see {@link AuthLayoutData} for the expected shape of `layoutData`
|
|
53
|
+
* @see {@link authState} for the store methods being invoked
|
|
54
|
+
*/
|
|
55
|
+
export function hydrateAuthState(layoutData) {
|
|
56
|
+
/* Supabase mode requires both the mode flag AND a valid session object;
|
|
57
|
+
if the session is null the user has been logged out server-side. */
|
|
58
|
+
if (layoutData.authMode === 'demo') {
|
|
59
|
+
authState.setDemoAuth();
|
|
60
|
+
}
|
|
61
|
+
else if (layoutData.authMode === 'supabase' && layoutData.session) {
|
|
62
|
+
authState.setSupabaseAuth(layoutData.session);
|
|
63
|
+
}
|
|
64
|
+
else if (layoutData.authMode === 'offline' && layoutData.offlineProfile) {
|
|
65
|
+
/* Offline mode requires a locally-stored profile to be present;
|
|
66
|
+
without it we fall through to the unauthenticated state. */
|
|
67
|
+
authState.setOfflineAuth(layoutData.offlineProfile);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
/* Catch-all: covers 'none' mode as well as edge cases where the mode
|
|
71
|
+
flag is set but the corresponding payload is missing. */
|
|
72
|
+
authState.setNoAuth();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/kit/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAqCnD,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAA0B;IACzD;0EACsE;IACtE,IAAI,UAAU,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACnC,SAAS,CAAC,WAAW,EAAE,CAAC;IAC1B,CAAC;SAAM,IAAI,UAAU,CAAC,QAAQ,KAAK,UAAU,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACpE,SAAS,CAAC,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;QAC1E;sEAC8D;QAC9D,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN;mEAC2D;QAC3D,SAAS,CAAC,SAAS,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Email confirmation helpers for the `/confirm` route.
|
|
3
|
+
*
|
|
4
|
+
* This module extracts the OTP verification, device trust, error translation,
|
|
5
|
+
* and cross-tab broadcast logic so that the scaffolded confirmation page can
|
|
6
|
+
* focus purely on UI rendering. It handles the full lifecycle of an email
|
|
7
|
+
* confirmation link click:
|
|
8
|
+
*
|
|
9
|
+
* 1. Verify the OTP token hash with Supabase
|
|
10
|
+
* 2. Trust the originating device (for device-verification flows)
|
|
11
|
+
* 3. Translate raw Supabase errors into user-friendly messages
|
|
12
|
+
* 4. Broadcast the confirmation to other open tabs via BroadcastChannel
|
|
13
|
+
* 5. Attempt to auto-close the confirmation tab
|
|
14
|
+
*
|
|
15
|
+
* @module kit/confirm
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // In /confirm/+page.svelte onMount
|
|
20
|
+
* const result = await handleEmailConfirmation(tokenHash, type);
|
|
21
|
+
* if (result.success) {
|
|
22
|
+
* await broadcastAuthConfirmed('auth-channel', type);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @see {@link verifyOtp} in `supabase/auth.ts` for the underlying OTP call
|
|
27
|
+
* @see {@link trustPendingDevice} in `auth/deviceVerification.ts` for device trust logic
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Result of an email confirmation attempt.
|
|
31
|
+
*
|
|
32
|
+
* Provides a simple success/failure discriminator with an optional
|
|
33
|
+
* user-friendly error message when the confirmation fails.
|
|
34
|
+
*/
|
|
35
|
+
export interface ConfirmResult {
|
|
36
|
+
/** Whether the OTP verification completed successfully. */
|
|
37
|
+
success: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* A user-facing error message explaining why confirmation failed.
|
|
40
|
+
* Only present when `success` is `false`.
|
|
41
|
+
*/
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Handles the full email confirmation flow: verifies the OTP token hash,
|
|
46
|
+
* optionally trusts the pending device, and translates Supabase error
|
|
47
|
+
* messages into user-friendly strings.
|
|
48
|
+
*
|
|
49
|
+
* The function normalizes the `type` parameter before passing it to Supabase
|
|
50
|
+
* (e.g. `'magiclink'` maps to `'email'` for OTP verification purposes) and
|
|
51
|
+
* applies a tiered error classification to produce contextual error messages.
|
|
52
|
+
*
|
|
53
|
+
* @param tokenHash - The `token_hash` extracted from the confirmation URL
|
|
54
|
+
* query parameters (provided by Supabase in the email link).
|
|
55
|
+
* @param type - The verification type from Supabase, indicating what kind
|
|
56
|
+
* of email action triggered the confirmation. One of:
|
|
57
|
+
* - `'signup'` — new account registration
|
|
58
|
+
* - `'email'` — email change or device verification
|
|
59
|
+
* - `'email_change'` — explicit email address change
|
|
60
|
+
* - `'magiclink'` — passwordless login link
|
|
61
|
+
*
|
|
62
|
+
* @returns A promise resolving to `{ success: true }` on successful
|
|
63
|
+
* verification, or `{ success: false, error: string }` on failure
|
|
64
|
+
* with a translated error message.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const result = await handleEmailConfirmation(tokenHash, 'signup');
|
|
69
|
+
* if (!result.success) {
|
|
70
|
+
* showError(result.error);
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @see {@link ConfirmResult} for the return type shape
|
|
75
|
+
* @see {@link verifyOtp} for the underlying Supabase OTP verification
|
|
76
|
+
*/
|
|
77
|
+
export declare function handleEmailConfirmation(tokenHash: string, type: 'signup' | 'email' | 'email_change' | 'magiclink'): Promise<ConfirmResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Broadcasts an auth confirmation event via `BroadcastChannel` so other
|
|
80
|
+
* open tabs (e.g. the login page that initiated the email flow) can detect
|
|
81
|
+
* the completed authentication and update their UI accordingly.
|
|
82
|
+
*
|
|
83
|
+
* After broadcasting, the function waits briefly for the receiving tab to
|
|
84
|
+
* process the message, then attempts to auto-close this confirmation tab.
|
|
85
|
+
* If the browser blocks `window.close()` (common for tabs not opened via
|
|
86
|
+
* `window.open()`), the function returns `'can_close'` so the UI can show
|
|
87
|
+
* a "you may close this tab" message instead.
|
|
88
|
+
*
|
|
89
|
+
* @param channelName - The `BroadcastChannel` name. Must match the channel
|
|
90
|
+
* name used by the login page listener.
|
|
91
|
+
* @param type - The verification type to include in the broadcast
|
|
92
|
+
* message payload, so the receiver knows which flow
|
|
93
|
+
* completed.
|
|
94
|
+
*
|
|
95
|
+
* @returns A promise resolving to one of:
|
|
96
|
+
* - `'closed'` — tab was successfully closed (caller won't see this)
|
|
97
|
+
* - `'can_close'` — broadcast sent but tab could not auto-close
|
|
98
|
+
* - `'no_broadcast'` — BroadcastChannel API not available (SSR or old browser)
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const status = await broadcastAuthConfirmed('stellar-auth', 'signup');
|
|
103
|
+
* if (status === 'can_close') {
|
|
104
|
+
* showMessage('You can close this tab.');
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel}
|
|
109
|
+
*/
|
|
110
|
+
export declare function broadcastAuthConfirmed(channelName: string, type: string): Promise<'closed' | 'can_close' | 'no_broadcast'>;
|
|
111
|
+
//# sourceMappingURL=confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../src/kit/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,cAAc,GAAG,WAAW,GACtD,OAAO,CAAC,aAAa,CAAC,CA4CxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC,CA+BlD"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Email confirmation helpers for the `/confirm` route.
|
|
3
|
+
*
|
|
4
|
+
* This module extracts the OTP verification, device trust, error translation,
|
|
5
|
+
* and cross-tab broadcast logic so that the scaffolded confirmation page can
|
|
6
|
+
* focus purely on UI rendering. It handles the full lifecycle of an email
|
|
7
|
+
* confirmation link click:
|
|
8
|
+
*
|
|
9
|
+
* 1. Verify the OTP token hash with Supabase
|
|
10
|
+
* 2. Trust the originating device (for device-verification flows)
|
|
11
|
+
* 3. Translate raw Supabase errors into user-friendly messages
|
|
12
|
+
* 4. Broadcast the confirmation to other open tabs via BroadcastChannel
|
|
13
|
+
* 5. Attempt to auto-close the confirmation tab
|
|
14
|
+
*
|
|
15
|
+
* @module kit/confirm
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // In /confirm/+page.svelte onMount
|
|
20
|
+
* const result = await handleEmailConfirmation(tokenHash, type);
|
|
21
|
+
* if (result.success) {
|
|
22
|
+
* await broadcastAuthConfirmed('auth-channel', type);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @see {@link verifyOtp} in `supabase/auth.ts` for the underlying OTP call
|
|
27
|
+
* @see {@link trustPendingDevice} in `auth/deviceVerification.ts` for device trust logic
|
|
28
|
+
*/
|
|
29
|
+
import { verifyOtp } from '../supabase/auth.js';
|
|
30
|
+
import { trustPendingDevice } from '../auth/deviceVerification.js';
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// PUBLIC API
|
|
33
|
+
// =============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Handles the full email confirmation flow: verifies the OTP token hash,
|
|
36
|
+
* optionally trusts the pending device, and translates Supabase error
|
|
37
|
+
* messages into user-friendly strings.
|
|
38
|
+
*
|
|
39
|
+
* The function normalizes the `type` parameter before passing it to Supabase
|
|
40
|
+
* (e.g. `'magiclink'` maps to `'email'` for OTP verification purposes) and
|
|
41
|
+
* applies a tiered error classification to produce contextual error messages.
|
|
42
|
+
*
|
|
43
|
+
* @param tokenHash - The `token_hash` extracted from the confirmation URL
|
|
44
|
+
* query parameters (provided by Supabase in the email link).
|
|
45
|
+
* @param type - The verification type from Supabase, indicating what kind
|
|
46
|
+
* of email action triggered the confirmation. One of:
|
|
47
|
+
* - `'signup'` — new account registration
|
|
48
|
+
* - `'email'` — email change or device verification
|
|
49
|
+
* - `'email_change'` — explicit email address change
|
|
50
|
+
* - `'magiclink'` — passwordless login link
|
|
51
|
+
*
|
|
52
|
+
* @returns A promise resolving to `{ success: true }` on successful
|
|
53
|
+
* verification, or `{ success: false, error: string }` on failure
|
|
54
|
+
* with a translated error message.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* const result = await handleEmailConfirmation(tokenHash, 'signup');
|
|
59
|
+
* if (!result.success) {
|
|
60
|
+
* showError(result.error);
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @see {@link ConfirmResult} for the return type shape
|
|
65
|
+
* @see {@link verifyOtp} for the underlying Supabase OTP verification
|
|
66
|
+
*/
|
|
67
|
+
export async function handleEmailConfirmation(tokenHash, type) {
|
|
68
|
+
try {
|
|
69
|
+
/* Supabase's verifyOtp does not accept 'magiclink' as a type;
|
|
70
|
+
it expects 'email' for both magic link and email verification flows. */
|
|
71
|
+
const otpType = type === 'magiclink' ? 'email' : type;
|
|
72
|
+
const { error } = await verifyOtp(tokenHash, otpType);
|
|
73
|
+
/* For device-verification OTPs (email or magiclink), trust the device
|
|
74
|
+
that initiated the confirmation so it won't be challenged again. */
|
|
75
|
+
if (!error && (type === 'email' || type === 'magiclink')) {
|
|
76
|
+
await trustPendingDevice();
|
|
77
|
+
}
|
|
78
|
+
if (error) {
|
|
79
|
+
/* Tiered error classification: check for common Supabase error patterns
|
|
80
|
+
and translate them to actionable user-facing messages rather than
|
|
81
|
+
exposing raw API error strings. */
|
|
82
|
+
const errorLower = error.toLowerCase();
|
|
83
|
+
if (errorLower.includes('already') ||
|
|
84
|
+
errorLower.includes('confirmed') ||
|
|
85
|
+
errorLower.includes('used')) {
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
error: 'This email has already been confirmed. You can sign in to your account.'
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else if (errorLower.includes('expired') || errorLower.includes('invalid')) {
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
error: 'This confirmation link has expired. Please request a new one from the login page.'
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/* Unrecognized error pattern — pass through the raw message as a
|
|
98
|
+
last resort; this should be rare in production. */
|
|
99
|
+
return { success: false, error };
|
|
100
|
+
}
|
|
101
|
+
return { success: true };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
/* Catch network failures, unexpected exceptions, etc. The user sees
|
|
105
|
+
a generic message rather than a stack trace. */
|
|
106
|
+
return { success: false, error: 'An unexpected error occurred. Please try again.' };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Broadcasts an auth confirmation event via `BroadcastChannel` so other
|
|
111
|
+
* open tabs (e.g. the login page that initiated the email flow) can detect
|
|
112
|
+
* the completed authentication and update their UI accordingly.
|
|
113
|
+
*
|
|
114
|
+
* After broadcasting, the function waits briefly for the receiving tab to
|
|
115
|
+
* process the message, then attempts to auto-close this confirmation tab.
|
|
116
|
+
* If the browser blocks `window.close()` (common for tabs not opened via
|
|
117
|
+
* `window.open()`), the function returns `'can_close'` so the UI can show
|
|
118
|
+
* a "you may close this tab" message instead.
|
|
119
|
+
*
|
|
120
|
+
* @param channelName - The `BroadcastChannel` name. Must match the channel
|
|
121
|
+
* name used by the login page listener.
|
|
122
|
+
* @param type - The verification type to include in the broadcast
|
|
123
|
+
* message payload, so the receiver knows which flow
|
|
124
|
+
* completed.
|
|
125
|
+
*
|
|
126
|
+
* @returns A promise resolving to one of:
|
|
127
|
+
* - `'closed'` — tab was successfully closed (caller won't see this)
|
|
128
|
+
* - `'can_close'` — broadcast sent but tab could not auto-close
|
|
129
|
+
* - `'no_broadcast'` — BroadcastChannel API not available (SSR or old browser)
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const status = await broadcastAuthConfirmed('stellar-auth', 'signup');
|
|
134
|
+
* if (status === 'can_close') {
|
|
135
|
+
* showMessage('You can close this tab.');
|
|
136
|
+
* }
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel}
|
|
140
|
+
*/
|
|
141
|
+
export async function broadcastAuthConfirmed(channelName, type) {
|
|
142
|
+
/* Guard against SSR and browsers lacking BroadcastChannel support
|
|
143
|
+
(notably some older mobile browsers). */
|
|
144
|
+
if (typeof window === 'undefined' || !('BroadcastChannel' in window)) {
|
|
145
|
+
return 'no_broadcast';
|
|
146
|
+
}
|
|
147
|
+
const channel = new BroadcastChannel(channelName);
|
|
148
|
+
channel.postMessage({
|
|
149
|
+
type: 'AUTH_CONFIRMED',
|
|
150
|
+
verificationType: type
|
|
151
|
+
});
|
|
152
|
+
/* Give the original tab time to process the message before closing
|
|
153
|
+
the channel — 500ms is sufficient for the receiver's event loop
|
|
154
|
+
to fire the handler and update its state. */
|
|
155
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
156
|
+
channel.close();
|
|
157
|
+
/* Attempt to close this confirmation tab — browsers generally only
|
|
158
|
+
allow window.close() for tabs opened programmatically via
|
|
159
|
+
window.open(), so this may silently fail. */
|
|
160
|
+
try {
|
|
161
|
+
window.close();
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* Browser policy may block window.close() — expected behavior */
|
|
165
|
+
}
|
|
166
|
+
/* If execution reaches here, the tab is still open (close was blocked) */
|
|
167
|
+
return 'can_close';
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/kit/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAuBnE,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,SAAiB,EACjB,IAAuD;IAEvD,IAAI,CAAC;QACH;kFAC0E;QAC1E,MAAM,OAAO,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,OAA8C,CAAC,CAAC;QAE7F;8EACsE;QACtE,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,WAAW,CAAC,EAAE,CAAC;YACzD,MAAM,kBAAkB,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV;;iDAEqC;YACrC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YACvC,IACE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAC9B,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAChC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3B,CAAC;gBACD,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,yEAAyE;iBACjF,CAAC;YACJ,CAAC;iBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5E,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,mFAAmF;iBAC3F,CAAC;YACJ,CAAC;YACD;iEACqD;YACrD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACnC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP;0DACkD;QAClD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iDAAiD,EAAE,CAAC;IACtF,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,IAAY;IAEZ;+CAC2C;IAC3C,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,kBAAkB,IAAI,MAAM,CAAC,EAAE,CAAC;QACrE,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAElD,OAAO,CAAC,WAAW,CAAC;QAClB,IAAI,EAAE,gBAAgB;QACtB,gBAAgB,EAAE,IAAI;KACvB,CAAC,CAAC;IAEH;;mDAE+C;IAC/C,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB;;mDAE+C;IAC/C,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IAED,0EAA0E;IAC1E,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview SvelteKit load function helpers.
|
|
3
|
+
*
|
|
4
|
+
* This module extracts orchestration logic from layout and page load functions
|
|
5
|
+
* so that scaffolded routes can be thin wrappers around these helpers. Each
|
|
6
|
+
* exported function encapsulates a specific load concern:
|
|
7
|
+
*
|
|
8
|
+
* - `resolveRootLayout` — full app initialization sequence (config,
|
|
9
|
+
* auth, sync engine startup)
|
|
10
|
+
* - `resolveProtectedLayout` — auth guard for protected route groups
|
|
11
|
+
* - `resolveSetupAccess` — access control for the `/setup` wizard
|
|
12
|
+
*
|
|
13
|
+
* By centralizing this logic in the engine, consuming apps avoid duplicating
|
|
14
|
+
* the initialization ordering and redirect logic across their route tree.
|
|
15
|
+
*
|
|
16
|
+
* @module kit/loads
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // In +layout.ts (root)
|
|
21
|
+
* import { resolveRootLayout } from 'stellar-drive/kit/loads';
|
|
22
|
+
* export async function load({ url }) {
|
|
23
|
+
* return resolveRootLayout(url);
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @see {@link initConfig} for runtime configuration bootstrap
|
|
28
|
+
* @see {@link resolveAuthState} for auth mode determination
|
|
29
|
+
* @see {@link startSyncEngine} for offline-first sync initialization
|
|
30
|
+
*/
|
|
31
|
+
import type { AuthStateResult } from '../auth/resolveAuthState.js';
|
|
32
|
+
/**
|
|
33
|
+
* Data returned by `resolveRootLayout`.
|
|
34
|
+
*
|
|
35
|
+
* Extends the base auth state with an optional `singleUserSetUp` flag
|
|
36
|
+
* indicating whether the app has completed initial configuration.
|
|
37
|
+
*/
|
|
38
|
+
export interface RootLayoutData extends AuthStateResult {
|
|
39
|
+
/**
|
|
40
|
+
* Indicates whether the single-user setup wizard has been completed.
|
|
41
|
+
* When `false` and no config exists, the app should redirect to `/setup`.
|
|
42
|
+
*/
|
|
43
|
+
singleUserSetUp?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Data returned by `resolveProtectedLayout`.
|
|
47
|
+
*
|
|
48
|
+
* A narrowed subset of auth state fields needed by protected route groups
|
|
49
|
+
* to render authenticated content.
|
|
50
|
+
*/
|
|
51
|
+
export interface ProtectedLayoutData {
|
|
52
|
+
/** The Supabase session, or `null` if using offline/no auth. */
|
|
53
|
+
session: AuthStateResult['session'];
|
|
54
|
+
/** The active authentication mode discriminator. */
|
|
55
|
+
authMode: AuthStateResult['authMode'];
|
|
56
|
+
/** The offline profile credentials, if in offline mode. */
|
|
57
|
+
offlineProfile: AuthStateResult['offlineProfile'];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Data returned by `resolveSetupAccess`.
|
|
61
|
+
*
|
|
62
|
+
* Tells the setup page whether this is a first-time configuration
|
|
63
|
+
* (public access) or a reconfiguration (authenticated users only).
|
|
64
|
+
*/
|
|
65
|
+
export interface SetupAccessData {
|
|
66
|
+
/**
|
|
67
|
+
* `true` when no configuration exists yet — the setup page should
|
|
68
|
+
* render the full first-time wizard without requiring authentication.
|
|
69
|
+
*/
|
|
70
|
+
isFirstSetup: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Orchestrates the root layout load sequence, which is the critical
|
|
74
|
+
* initialization path that runs on every page load:
|
|
75
|
+
*
|
|
76
|
+
* 1. Calls the app's `initEngine` function (for database schema setup)
|
|
77
|
+
* 2. Runs `initConfig()` — loads runtime config from storage; if no
|
|
78
|
+
* config exists and the user is not already on `/setup`, returns a
|
|
79
|
+
* blank state so the layout can redirect to the setup wizard
|
|
80
|
+
* 3. Resolves auth state — determines whether the user is authenticated
|
|
81
|
+
* via Supabase, offline credentials, or not at all
|
|
82
|
+
* 4. Starts the sync engine if the user is authenticated, enabling
|
|
83
|
+
* offline-first data synchronization
|
|
84
|
+
*
|
|
85
|
+
* @param url - The current page URL object. Only `pathname` is
|
|
86
|
+
* inspected, to detect whether the user is already
|
|
87
|
+
* on the `/setup` page.
|
|
88
|
+
* @param _initEngineFn - (Optional) The app's `initEngine()` call, executed
|
|
89
|
+
* before config init. Typically already called at
|
|
90
|
+
* module scope in the browser; this parameter exists
|
|
91
|
+
* for explicit invocation in SSR contexts.
|
|
92
|
+
*
|
|
93
|
+
* @returns Layout data containing session, auth mode, offline profile,
|
|
94
|
+
* and setup status. The consuming layout uses these to hydrate
|
|
95
|
+
* the auth store and conditionally render the app shell.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* // +layout.ts
|
|
100
|
+
* export async function load({ url }) {
|
|
101
|
+
* return resolveRootLayout(url);
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @see {@link RootLayoutData} for the return type shape
|
|
106
|
+
* @see {@link initConfig} for config bootstrapping details
|
|
107
|
+
* @see {@link resolveAuthState} for auth resolution logic
|
|
108
|
+
*/
|
|
109
|
+
export declare function resolveRootLayout(url: {
|
|
110
|
+
pathname: string;
|
|
111
|
+
}, _initEngineFn?: () => void): Promise<RootLayoutData>;
|
|
112
|
+
/**
|
|
113
|
+
* Auth guard for protected routes. Resolves auth state and, if the user
|
|
114
|
+
* is unauthenticated, computes a redirect URL to the login page with a
|
|
115
|
+
* `redirect` query parameter so the user can be sent back after login.
|
|
116
|
+
*
|
|
117
|
+
* The caller is responsible for performing the actual redirect (typically
|
|
118
|
+
* via SvelteKit's `throw redirect(302, redirectUrl)`), since this helper
|
|
119
|
+
* is framework-agnostic in its return value.
|
|
120
|
+
*
|
|
121
|
+
* @param url - The current page URL object with `pathname` and `search`
|
|
122
|
+
* properties, used to construct the post-login return URL.
|
|
123
|
+
*
|
|
124
|
+
* @returns An object containing:
|
|
125
|
+
* - `data` — the auth state payload for the layout
|
|
126
|
+
* - `redirectUrl` — a login URL string if unauthenticated, or `null`
|
|
127
|
+
* if the user is authenticated and should proceed normally.
|
|
128
|
+
* When non-null, the caller should `throw redirect(302, redirectUrl)`.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* // /(protected)/+layout.ts
|
|
133
|
+
* import { redirect } from '@sveltejs/kit';
|
|
134
|
+
* import { resolveProtectedLayout } from 'stellar-drive/kit/loads';
|
|
135
|
+
*
|
|
136
|
+
* export async function load({ url }) {
|
|
137
|
+
* const { data, redirectUrl } = await resolveProtectedLayout(url);
|
|
138
|
+
* if (redirectUrl) throw redirect(302, redirectUrl);
|
|
139
|
+
* return data;
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* @see {@link ProtectedLayoutData} for the return data shape
|
|
144
|
+
* @see {@link resolveAuthState} for the underlying auth resolution
|
|
145
|
+
*/
|
|
146
|
+
export declare function resolveProtectedLayout(url: {
|
|
147
|
+
pathname: string;
|
|
148
|
+
search: string;
|
|
149
|
+
}): Promise<{
|
|
150
|
+
data: ProtectedLayoutData;
|
|
151
|
+
redirectUrl: string | null;
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* Setup page guard implementing a two-tier access model:
|
|
155
|
+
*
|
|
156
|
+
* - **Unconfigured app** (first-time setup): public access, no auth required.
|
|
157
|
+
* Returns `{ isFirstSetup: true }`.
|
|
158
|
+
* - **Configured app** (reconfiguration): any authenticated user may access.
|
|
159
|
+
* Unauthenticated users are redirected to `/login`.
|
|
160
|
+
*
|
|
161
|
+
* @returns An object containing:
|
|
162
|
+
* - `data` — setup access info (`{ isFirstSetup }`)
|
|
163
|
+
* - `redirectUrl` — a redirect path if the user lacks access, or `null`
|
|
164
|
+
* if access is granted. When non-null, the caller should
|
|
165
|
+
* `throw redirect(302, redirectUrl)`.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* // /setup/+page.ts
|
|
170
|
+
* import { redirect } from '@sveltejs/kit';
|
|
171
|
+
* import { resolveSetupAccess } from 'stellar-drive/kit/loads';
|
|
172
|
+
*
|
|
173
|
+
* export async function load() {
|
|
174
|
+
* const { data, redirectUrl } = await resolveSetupAccess();
|
|
175
|
+
* if (redirectUrl) throw redirect(302, redirectUrl);
|
|
176
|
+
* return data;
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* @see {@link SetupAccessData} for the return data shape
|
|
181
|
+
* @see {@link getConfig} for checking whether config exists
|
|
182
|
+
*/
|
|
183
|
+
export declare function resolveSetupAccess(): Promise<{
|
|
184
|
+
data: SetupAccessData;
|
|
185
|
+
redirectUrl: string | null;
|
|
186
|
+
}>;
|
|
187
|
+
//# sourceMappingURL=loads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loads.d.ts","sourceRoot":"","sources":["../../src/kit/loads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAMnE;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IAEpC,oDAAoD;IACpD,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAEtC,2DAA2D;IAC3D,cAAc,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;CACnD;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EACzB,aAAa,CAAC,EAAE,MAAM,IAAI,GACzB,OAAO,CAAC,cAAc,CAAC,CAmCzB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAgBrE;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC,CAqBD"}
|