@daveyplate/better-auth-persistent
Version:
Persistent session management for Better Auth
85 lines (75 loc) • 2.56 kB
text/typescript
import type { BetterFetchError } from "@better-fetch/fetch"
import { persistentAtom } from "@nanostores/persistent"
import type { Session, User } from "better-auth"
import { computed, task } from "nanostores"
import SuperJSON from "superjson"
import { $authClient } from "./auth-client-store"
import { $persistentSession } from "./persistent-session"
import type { AuthClient } from "./types/auth-client"
type DeviceSession = { session: Session; user: User }
type DeviceSessionsResult = {
data: DeviceSession[] | null
isPending: boolean
error: BetterFetchError | null
}
export const emptyResponse = {
data: null,
isPending: true,
isRefetching: true,
error: null,
refetch: undefined
}
const $persistentSessions = persistentAtom<DeviceSessionsResult>(
"device-sessions",
emptyResponse,
{
encode: SuperJSON.stringify,
decode: SuperJSON.parse
}
)
export const $freshSessions = computed(
[$authClient, $persistentSession],
(authClient, persistentSession) =>
task(async () => {
if (!authClient) return emptyResponse
if (!persistentSession.data) return emptyResponse
try {
const deviceSessions = await (
authClient as AuthClient
).multiSession.listDeviceSessions({
fetchOptions: { throw: true }
})
return {
data: deviceSessions,
isPending: false,
isRefetching: false,
error: null,
refetch: undefined
}
} catch (error) {
return {
data: null,
isPending: false,
isRefetching: false,
error: error as BetterFetchError,
refetch: undefined
}
}
})
)
export const $deviceSessions = computed(
[$persistentSession, $persistentSessions, $freshSessions],
(persistentSession, persistentSessions, freshSessions) => {
if (persistentSession.isPending) return emptyResponse
if (!freshSessions) return persistentSessions
if (!persistentSession.data) {
$persistentSessions.set(emptyResponse)
} else if (
freshSessions.data ||
(!persistentSessions.data && freshSessions.error)
) {
$persistentSessions.set(freshSessions)
}
return $persistentSessions.get()
}
)