コンテンツにスキップ

ストア & イベント

@authrim/sveltekit は状態管理に2つの相補的メカニズムを使用します:

  • Svelteストア — UI描画のためのリアクティブな Readable ストア
  • イベント — 副作用やカスタムロジックのための型付きイベントエミッター

ストアは公開 Readable 値です。SDKは認証操作と発火されたイベントからストアを更新します。アプリケーションコードからストアへ直接書き込まないでください。

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?.name ?? $user?.email}</p>
{:else}
<p>サインインしていません</p>
{/if}
ストア説明
sessionReadable<Session | null>現在のセッションオブジェクト
userReadable<User | null>現在のユーザーオブジェクト
isAuthenticatedReadable<boolean>session !== null から導出
loadingStateReadable<AuthLoadingState>現在のローディング状態
errorReadable<AuthError | null>最後の認証エラー
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.name ?? payload.user.email);
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 }セッションのtimeout/revocation連携向けの予約イベント
token:refreshed{ session }browser-token更新連携向けの予約イベント
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 };
}

コンポーネントでのイベント使用

Section titled “コンポーネントでのイベント使用”
<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>

組み込みクライアントは、ログイン/ログアウト/エラー/session-changeイベントに応じてストアを更新します:

イベントストア更新
auth:loginsession ← payload.session, user ← payload.user, loadingState'idle', errornull
auth:logoutsessionnull, usernull, loadingState'idle', errornull
auth:errorerror ← payload.error, loadingState'idle'
session:changedsession ← payload.session, user ← payload.user

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 が<br>最初のレンダリング前に設定
    Provider->>Provider: onMount: 任意のcheckOnMountセッション取得

これにより $isAuthenticated が最初のレンダリングで正しい値を持ちます。server-mediatedモードでmount時にブラウザからセッション取得するかどうかは serverSession.checkOnMount で明示します。