This commit is contained in:
giancarlo
2024-03-24 02:23:22 +08:00
parent 648d77b430
commit bce3479368
589 changed files with 37067 additions and 9596 deletions

View File

@@ -0,0 +1,26 @@
import { useQuery } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
import { useFactorsMutationKey } from './use-user-factors-mutation-key';
function useFetchAuthFactors() {
const client = useSupabase();
const queryKey = useFactorsMutationKey();
const queryFn = async () => {
const { data, error } = await client.auth.mfa.listFactors();
if (error) {
throw error;
}
return data;
};
return useQuery({
queryKey,
queryFn,
});
}
export default useFetchAuthFactors;

View File

@@ -0,0 +1,40 @@
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
interface Params {
email: string;
redirectTo: string;
}
/**
* @name useRequestResetPassword
* @description Requests a password reset for a user. This function will
* trigger a password reset email to be sent to the user's email address.
* After the user clicks the link in the email, they will be redirected to
* /password-reset where their password can be updated.
*/
export function useRequestResetPassword() {
const client = useSupabase();
const mutationKey = ['auth', 'reset-password'];
const mutationFn = async (params: Params) => {
const { error, data } = await client.auth.resetPasswordForEmail(
params.email,
{
redirectTo: params.redirectTo,
},
);
if (error) {
throw error;
}
return data;
};
return useMutation({
mutationFn,
mutationKey,
});
}

View File

@@ -0,0 +1,33 @@
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
interface Credentials {
email: string;
password: string;
}
export function useSignInWithEmailPassword() {
const client = useSupabase();
const mutationKey = ['auth', 'sign-in-with-email-password'];
const mutationFn = async (credentials: Credentials) => {
const response = await client.auth.signInWithPassword(credentials);
if (response.error) {
throw response.error.message;
}
const user = response.data?.user;
const identities = user?.identities ?? [];
// if the user has no identities, it means that the email is taken
if (identities.length === 0) {
throw new Error('User already registered');
}
return response.data;
};
return useMutation({ mutationKey, mutationFn });
}

View File

@@ -0,0 +1,46 @@
import type {
AuthError,
SignInWithPasswordlessCredentials,
} from '@supabase/gotrue-js';
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
export function useSignInWithOtp() {
const client = useSupabase();
const mutationKey = ['auth', 'sign-in-with-otp'];
const mutationFn = async (credentials: SignInWithPasswordlessCredentials) => {
const result = await client.auth.signInWithOtp(credentials);
if (result.error) {
if (shouldIgnoreError(result.error)) {
console.warn(
`Ignoring error during development: ${result.error.message}`,
);
return {} as never;
}
throw result.error.message;
}
return result.data;
};
return useMutation({
mutationFn,
mutationKey,
});
}
export default useSignInWithOtp;
function shouldIgnoreError(error: AuthError) {
return isSmsProviderNotSetupError(error);
}
function isSmsProviderNotSetupError(error: AuthError) {
return error.message.includes(`sms Provider could not be found`);
}

View File

@@ -0,0 +1,25 @@
import type { SignInWithOAuthCredentials } from '@supabase/gotrue-js';
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
export function useSignInWithProvider() {
const client = useSupabase();
const mutationKey = ['auth', 'sign-in-with-provider'];
const mutationFn = async (credentials: SignInWithOAuthCredentials) => {
const response = await client.auth.signInWithOAuth(credentials);
if (response.error) {
throw response.error.message;
}
return response.data;
};
return useMutation({
mutationFn,
mutationKey,
});
}

View File

@@ -0,0 +1,16 @@
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
import { useRevalidateUserSession } from './use-user-session';
export function useSignOut() {
const client = useSupabase();
const revalidateUserSession = useRevalidateUserSession();
return useMutation({
mutationFn: async () => {
await client.auth.signOut();
await revalidateUserSession();
},
});
}

View File

@@ -0,0 +1,44 @@
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
interface Credentials {
email: string;
password: string;
emailRedirectTo: string;
}
export function useSignUpWithEmailAndPassword() {
const client = useSupabase();
const mutationKey = ['auth', 'sign-up-with-email-password'];
const mutationFn = async (params: Credentials) => {
const { emailRedirectTo, ...credentials } = params;
const response = await client.auth.signUp({
...credentials,
options: {
emailRedirectTo,
},
});
if (response.error) {
throw response.error.message;
}
const user = response.data?.user;
const identities = user?.identities ?? [];
// if the user has no identities, it means that the email is taken
if (identities.length === 0) {
throw new Error('User already registered');
}
return response.data;
};
return useMutation({
mutationKey,
mutationFn,
});
}

View File

@@ -0,0 +1,8 @@
import { useMemo } from 'react';
import { getSupabaseBrowserClient } from '../clients/browser.client';
import { Database } from '../database.types';
export function useSupabase<Schema = Database>() {
return useMemo(() => getSupabaseBrowserClient<Schema>(), []);
}

View File

@@ -0,0 +1,31 @@
import type { UserAttributes } from '@supabase/gotrue-js';
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
type Params = UserAttributes & { redirectTo: string };
export function useUpdateUser() {
const client = useSupabase();
const mutationKey = ['auth', 'update-user'];
const mutationFn = async (attributes: Params) => {
const { redirectTo, ...params } = attributes;
const response = await client.auth.updateUser(params, {
emailRedirectTo: redirectTo,
});
if (response.error) {
throw response.error;
}
return response.data;
};
return useMutation({
mutationKey,
mutationFn,
});
}

View File

@@ -0,0 +1,8 @@
import { useUserSession } from './use-user-session';
export function useFactorsMutationKey() {
const user = useUserSession();
const userId = user?.data?.user.id;
return ['mfa-factors', userId];
}

View File

@@ -0,0 +1,34 @@
import { useCallback } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
const queryKey = ['supabase:session'];
export function useUserSession() {
const supabase = useSupabase();
const queryFn = async () => {
const { data, error } = await supabase.auth.getSession();
console.log(data, error);
if (error) {
throw error;
}
return data.session;
};
return useQuery({ queryKey, queryFn });
}
export function useRevalidateUserSession() {
const client = useQueryClient();
return useCallback(
() =>
client.invalidateQueries({
queryKey,
}),
[client],
);
}

View File

@@ -0,0 +1,27 @@
import { useQuery } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
export function useUser() {
const client = useSupabase();
const queryKey = ['user'];
const queryFn = async () => {
const response = await client.auth.getUser();
if (response.error) {
return Promise.reject(response.error);
}
if (response.data?.user) {
return response.data.user;
}
return Promise.reject('Unexpected result format');
};
return useQuery({
queryFn,
queryKey,
});
}

View File

@@ -0,0 +1,26 @@
import type { VerifyOtpParams } from '@supabase/gotrue-js';
import { useMutation } from '@tanstack/react-query';
import { useSupabase } from './use-supabase';
export function useVerifyOtp() {
const client = useSupabase();
const mutationKey = ['verify-otp'];
const mutationFn = async (params: VerifyOtpParams) => {
const { data, error } = await client.auth.verifyOtp(params);
if (error) {
throw error;
}
return data;
};
return useMutation({
mutationFn,
mutationKey,
});
}