useAuthClient.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { createAuthClient } from "better-auth/client"
  2. import { adminClient, inferAdditionalFields } from "better-auth/client/plugins"
  3. import { additionalFields } from "#shared/utils/auth/additionalFields.js"
  4. import {
  5. ac,
  6. admin as adminRole,
  7. user as userRole
  8. } from "#shared/utils/auth/permissions.js"
  9. export default function useAuthClient() {
  10. const headers = import.meta.server ? useRequestHeaders() : undefined
  11. const authClient = createAuthClient({
  12. fetchOptions: { headers },
  13. plugins: [
  14. adminClient({ ac, roles: { admin: adminRole, user: userRole } }),
  15. inferAdditionalFields(additionalFields)
  16. ]
  17. })
  18. const session = useState("auth:session", () => null)
  19. const user = useState("auth:user", () => null)
  20. const isSignedIn = computed(() => !!session.value)
  21. const fetchingSession = import.meta.server
  22. ? ref(false)
  23. : useState("auth:fetchingSession", () => false)
  24. async function signIn({ email, password, rememberMe, redirectTo } = {}) {
  25. // noinspection JSUnresolvedReference
  26. const result = await authClient.signIn.email({
  27. email,
  28. password,
  29. rememberMe
  30. })
  31. if (redirectTo) {
  32. await navigateTo(redirectTo)
  33. } else {
  34. const route = useRoute()
  35. if (route.name === "characterView") {
  36. await navigateTo({ name: "characterEdit", params: route.params })
  37. }
  38. }
  39. return result
  40. }
  41. async function signOut({ redirectTo } = {}) {
  42. // noinspection JSUnresolvedReference
  43. const result = await authClient.signOut()
  44. session.value = null
  45. user.value = null
  46. if (redirectTo) {
  47. await navigateTo(redirectTo)
  48. } else {
  49. const route = useRoute()
  50. if (route.name === "characterEdit") {
  51. await navigateTo({ name: "characterView", params: route.params })
  52. } else {
  53. // noinspection JSUnresolvedReference
  54. if (
  55. _includes(route.meta?.middleware, "signed-in") ||
  56. _includes(route.meta?.middleware, "admin")
  57. ) {
  58. await navigateTo({ name: "characters" })
  59. }
  60. }
  61. }
  62. return result
  63. }
  64. async function fetchSession() {
  65. if (fetchingSession.value) {
  66. console.log("[useAuthClient] [fetchSession] already fetching session")
  67. return
  68. }
  69. fetchingSession.value = true
  70. // noinspection JSUnresolvedReference
  71. const { data } = await authClient.getSession({ fetchOptions: { headers } })
  72. session.value = data?.session || null
  73. user.value = data?.user || null
  74. fetchingSession.value = false
  75. return data
  76. }
  77. if (import.meta.client) {
  78. authClient.$store.listen("$sessionSignal", async (signal) => {
  79. if (!signal) {
  80. return
  81. }
  82. await fetchSession()
  83. })
  84. }
  85. // noinspection JSUnresolvedReference
  86. return {
  87. session,
  88. user,
  89. isSignedIn,
  90. signIn,
  91. signUp: authClient.signUp,
  92. signOut,
  93. fetchSession,
  94. authClient
  95. }
  96. }