ストア & イベント
概要
@authrim/sveltekit は状態管理に2つの相補的メカニズムを使用します:
- Svelteストア — UI描画のためのリアクティブな
Readableストア - イベント — 副作用やカスタムロジックのための型付きイベントエミッター
イベントが真のデータソースです。ストアはイベントから自動更新(投影)されます — ストアへの直接書き込みは行いません。
ストア
auth.stores でストアにアクセス:
<script lang="ts"> import { getAuthContext } from '@authrim/sveltekit';
const auth = getAuthContext(); const { session, user, isAuthenticated, loadingState, error } = auth.stores;</script>
{#if $isAuthenticated} <p>こんにちは、{$user?.displayName}</p>{:else} <p>サインインしていません</p>{/if}ストアリファレンス
| ストア | 型 | 説明 |
|---|---|---|
session | Readable<Session | null> | 現在のセッションオブジェクト |
user | Readable<User | null> | 現在のユーザーオブジェクト |
isAuthenticated | Readable<boolean> | session !== null から導出 |
loadingState | Readable<AuthLoadingState> | 現在のローディング状態 |
error | Readable<AuthError | null> | 最後の認証エラー |
AuthLoadingState
type AuthLoadingState = | 'idle' // 安定 — 処理なし | 'initializing' // 初回セッション確認 | 'authenticating' // ログイン/サインアップ中 | 'refreshing' // セッション更新中 | 'signing_out'; // サインアウト中'idle' が安定状態です。操作が完了(成功またはエラー)すると、常に 'idle' に戻ります。
ローディング状態の例
<script lang="ts"> import { getAuthContext } from '@authrim/sveltekit';
const auth = getAuthContext(); const { loadingState, error } = auth.stores;</script>
{#if $loadingState === 'authenticating'} <div class="overlay">サインイン中...</div>{:else if $loadingState === 'signing_out'} <div class="overlay">サインアウト中...</div>{/if}
{#if $error} <div class="alert" role="alert"> <p>{$error.message}</p> <code>{$error.code}</code> </div>{/if}ストアエラー型
interface AuthError { code: string; // エラーコード(例:'AR003001') message: string; // 人間可読なメッセージ details?: unknown; // 追加メタデータ}イベント
auth.on() で認証イベントを購読。解除関数を返します。
const unsubscribe = auth.on('auth:login', (payload) => { console.log('ログイン:', payload.user.displayName); console.log('方式:', payload.method); // 'passkey' | 'emailCode' | 'social'});
// クリーンアップunsubscribe();イベントリファレンス
| イベント | ペイロード | トリガー |
|---|---|---|
auth:login | { session, user, method } | ユーザーがログインに成功 |
auth:logout | { redirectUri? } | ユーザーがサインアウト |
auth:error | { error: AuthError } | 認証エラー発生 |
session:changed | { session, user } | セッションまたはユーザーデータが変更 |
session:expired | { reason } | セッションが無効化 |
token:refreshed | { session } | トークンの更新に成功 |
イベントペイロード型
interface AuthEventPayloads { 'auth:login': { session: Session; user: User; method: 'passkey' | 'emailCode' | 'social'; }; 'auth:logout': { redirectUri?: string }; 'auth:error': { error: AuthError }; 'session:changed': { session: Session | null; user: User | null }; 'session:expired': { reason: 'timeout' | 'revoked' | 'logout' }; 'token:refreshed': { session: Session };}コンポーネントでのイベント使用
<script lang="ts"> import { onMount, onDestroy } from 'svelte'; import { getAuthContext } from '@authrim/sveltekit'; import { goto } from '$app/navigation';
const auth = getAuthContext();
let unsubscribes: (() => void)[] = [];
onMount(() => { unsubscribes.push( auth.on('auth:login', () => { goto('/dashboard'); }), auth.on('session:expired', ({ reason }) => { if (reason === 'revoked') { goto('/login?reason=session-revoked'); } }), ); });
onDestroy(() => { unsubscribes.forEach(fn => fn()); });</script>イベント → ストア投影
イベントは自動的にストアを更新します。手動での同期は不要です:
| イベント | ストア更新 |
|---|---|
auth:login | session ← payload.session, user ← payload.user, loadingState ← 'idle', error ← null |
auth:logout | session ← null, user ← null, loadingState ← 'idle', error ← null |
auth:error | error ← payload.error, loadingState ← 'idle' |
session:changed | session ← payload.session, user ← payload.user |
SSR同期
AuthProvider でSSRデータを使用する場合、初期セッションは同期的に(最初のレンダリング前に)設定され、ハイドレーションの不一致を防ぎます:
sequenceDiagram
participant Server as サーバー (hooks)
participant Layout as +layout.svelte
participant Provider as AuthProvider
participant Stores as Svelte Stores
Server->>Layout: SSR認証データ
Layout->>Provider: initialSession, initialUser
Provider->>Stores: _syncFromSSR()(同期的)
Note over Stores: session & user が
最初のレンダリング前に設定
Provider->>Provider: onMount: バックグラウンドで再検証
これにより $isAuthenticated が最初のレンダリングで正しい値を持ち、未認証コンテンツのフラッシュが発生しません。