Skip to content

Commit

Permalink
Add positional parameters to Auth hooks (#76)
Browse files Browse the repository at this point in the history
* make auth parameter positional

* add cannot delete another user warning

* rewrite document for positional parameters

* refactor parameters

* rewrite docs for positional parameters

* refactor positional parameters

* rewrite docs for positional parameters

* refactor positional parameters

* rewrite docs for positional parameters

* refactor positional parameters

* rewrite docs for positional parameters

* refactor positional parameters

* rewrite docs for positional parameters

* fix useUser parameters

* fix linting issue

* fix useUser parameters

* fix linting issue
  • Loading branch information
erayerdin authored Feb 17, 2024
1 parent 672eb3b commit cd9dd9d
Show file tree
Hide file tree
Showing 19 changed files with 93 additions and 94 deletions.
12 changes: 8 additions & 4 deletions docs/hooks/useDeleteUser.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ tags:
`useDeleteUser` hook is used to delete the currently signed-in user. A very simple example would be:

```typescript
const { dispatch } = useDeleteUser({ auth });
const { dispatch } = useDeleteUser(auth);
await dispatch();
```

!!! warning
`useDeleteUser`, as mentioned, can only delete the currently signed-in user from the client side. Due to security reasons, you cannot delete any other user. If you want to delete another user, use Firebase Auth from Firebase Console or Firebase Functions.

!!! warning
`useDeleteUser` is lazy by default and will not do anything until you use `dispatch` function.

You can also get the state[^unauthorized] of deletion process.

```typescript
const { state, dispatch } = useDeleteUser({ auth });
const { state, dispatch } = useDeleteUser(auth);
await dispatch();
// `state` is "ready" | "loading" | "anonymous"
```
Expand All @@ -30,7 +33,7 @@ By default, `"anonymous"` state includes both real anonymous and Firebase-handle

```typescript
// assuming user is Firebase-handled anon
const { dispatch } = useDeleteUser({ auth, includeFirebaseAnon: true });
const { dispatch } = useDeleteUser(auth, { includeFirebaseAnon: true });
await dispatch(); // this will delete anonymous user
```

Expand All @@ -41,7 +44,8 @@ Input parameters for `useDeleteUser` hook is as follows:
| Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. || - |
| `includeFirebaseAnon` | `boolean` | Enable deleting Firebase-handled anonymous users. || `false` |
| `options` | `Object` | Options for the operation. || See below. |
| `options.includeFirebaseAnon` | `boolean` | Enable deleting Firebase-handled anonymous users. || `false` |

## Return Type

Expand Down
4 changes: 2 additions & 2 deletions docs/hooks/useSendEmailVerification.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:
`useSendEmailVerification` hook is used to send email verification to a user. A very simple example would be:

```typescript
const { dispatch } = useSendEmailVerification({ auth });
const { dispatch } = useSendEmailVerification(auth);
await dispatch();
```

Expand All @@ -18,7 +18,7 @@ await dispatch();
You can also get the state of the process.

```typescript
const { state, dispatch } = useSendEmailVerification({ auth });
const { state, dispatch } = useSendEmailVerification(auth);
await dispatch();
// `state` is "ready" | "loading" | "done" | "anonymous"
```
Expand Down
8 changes: 4 additions & 4 deletions docs/hooks/useSignIn.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:
`useSignIn` hook is used to sign in a user. A very simple example would be:

```typescript
const { dispatch } = useSignIn({ auth });
const { dispatch } = useSignIn(auth);
await dispatch({
type: "classic",
email,
Expand All @@ -22,7 +22,7 @@ await dispatch({
You can also get the state[^unauthorized] of sign-in process.

```typescript
const { state, dispatch } = useSignIn({ auth });
const { state, dispatch } = useSignIn(auth);
await dispatch({
type: "classic",
email,
Expand All @@ -37,7 +37,7 @@ await dispatch({
`dispatch` function will return an instance of [`UserCredential` | `undefined`][UserCredentialDocRef].

```typescript
const { state, dispatch } = useSignIn({ auth });
const { state, dispatch } = useSignIn(auth);
const credential = await dispatch({
type: "classic",
email,
Expand Down Expand Up @@ -116,7 +116,7 @@ You will need `actionCodeSettings`. You can see [this section in Firebase Auth d
If `type` is something else, you need to provide an implementation of `AuthProvider`. An example for Google sign-in looks as such:

```typescript
const { state, dispatch } = useSignIn({ auth });
const { state, dispatch } = useSignIn(auth);
const provider = new GoogleAuthProvider();
await dispatch({
type: "google",
Expand Down
19 changes: 10 additions & 9 deletions docs/hooks/useSignOut.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:
`useSignOut` hook is used to sign out currently signed-in user. A very simple example would be:

```typescript
const { dispatch } = useSignOut({ auth });
const { dispatch } = useSignOut(auth);
await dispatch();
```

Expand All @@ -18,7 +18,7 @@ await dispatch();
You can also get the state[^done] of sign-out process.

```typescript
const { state, dispatch } = useSignOut({ auth });
const { state, dispatch } = useSignOut(auth);
await dispatch();
// `state` is "ready" | "loading" | "anonymous"
```
Expand All @@ -33,7 +33,7 @@ const onError = (error: Error) => {
// do something with error
}

const { dispatch } = useSignOut({ auth, onError });
const { dispatch } = useSignOut(auth, { onError });
await dispatch();
```

Expand All @@ -47,12 +47,12 @@ In Firebase, there are two types of anonymity: Firebase-handled anonymous users
const onlyRealAnon = true;

// User is really anonymous
const { state } = useSignOut({ auth }); // state: "anonymous"
const { state } = useSignOut({ auth, onlyRealAnon }); // state: "anonymous"
const { state } = useSignOut(auth); // state: "anonymous"
const { state } = useSignOut(auth, { onlyRealAnon }); // state: "anonymous"

// User is anonymous in Firebase Auth records
const { state } = useSignOut({ auth }); // state: "anonymous"
const { state } = useSignOut({ auth, onlyRealAnon }); // state: "ready"
const { state } = useSignOut(auth); // state: "anonymous"
const { state } = useSignOut(auth, { onlyRealAnon }); // state: "ready"
```

## Input Parameters
Expand All @@ -62,8 +62,9 @@ Input parameters for `useSignOut` hook is as follows:
| Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. || - |
| `onError` | `(error: Error) => void` | A function to handle errors. || Throws error. |
| `onlyRealAnon` | `boolean` | Consider the user anonymous only if they are `null`. || `false` (which also considers Firebase-handled anonymous users) |
| `options` | `Object` | Options for the process. || See below. |
| `options.onError` | `(error: Error) => void` | A function to handle errors. || Throws error. |
| `options.onlyRealAnon` | `boolean` | Consider the user anonymous only if they are `null`. || `false` (which also considers Firebase-handled anonymous users) |

## Return Type

Expand Down
4 changes: 2 additions & 2 deletions docs/hooks/useSignUp.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:
`useSignUp` hook is used to create a user with email and password. A very simple example would be:

```typescript
const { dispatch } = useSignUp({ auth });
const { dispatch } = useSignUp(auth);
await dispatch(email, password);
```

Expand All @@ -18,7 +18,7 @@ await dispatch(email, password);
You can also get the state[^unauthorized] of sign-up process.

```typescript
const { state, dispatch } = useSignUp({ auth });
const { state, dispatch } = useSignUp(auth);
await dispatch();
// `state` is "ready" | "loading" | "authenticated"
```
Expand Down
7 changes: 4 additions & 3 deletions docs/hooks/useUser.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:
`useUser` hook is used to get the currently signed-in user. A very simple example would be:

```typescript
const user = useUser({ auth });
const user = useUser(auth);
```

!!! warning
Expand All @@ -35,8 +35,9 @@ Input parameters for `useUser` hook is as follows:
| Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. || - |
| `onError` | `(error: Error) => void` or `undefined` | A function to handle errors. || `undefined` |
| `onChange` | `() => void` or `undefined` | A function to run after state changes. || `undefined` |
| `options` | `Object` | Options for the process. || See below. |
| `options.onError` | `(error: Error) => void` or `undefined` | A function to handle errors. || `undefined` |
| `options.onChange` | `() => void` or `undefined` | A function to run after state changes. || `undefined` |

## Return Type

Expand Down
2 changes: 1 addition & 1 deletion src/auth/AuthorizationZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const AuthorizationZone = ({
onSuccess,
onFailure = () => <></>,
}: AuthorizationZoneProps) => {
const user = useUser({ auth });
const user = useUser(auth);
const [success, setSuccess] = useState(false);

useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/auth/SignOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const SignOut = ({
onLoading,
onAnonymous,
}: SignOutProps) => {
const { state, dispatch } = useSignOut({ auth, onlyRealAnon });
const { state, dispatch } = useSignOut(auth, { onlyRealAnon });

switch (state) {
case "ready":
Expand Down
12 changes: 6 additions & 6 deletions src/auth/useDeleteUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe("when real anon, useDeleteUser hook", () => {
});

it("should have anonymous state", async () => {
const { result } = renderHook(() => useDeleteUser({ auth }));
const { result } = renderHook(() => useDeleteUser(auth));
const { state } = result.current;
expect(state).toBe("anonymous");
});
Expand All @@ -45,14 +45,14 @@ describe("when anon, useDeleteUser hook", () => {
});

it("should have anonymous state", async () => {
const { result } = renderHook(() => useDeleteUser({ auth }));
const { result } = renderHook(() => useDeleteUser(auth));
const { state } = result.current;
expect(state).toBe("anonymous");
});

it("should have ready state if includeFirebaseAnon", async () => {
const { result } = renderHook(() =>
useDeleteUser({ auth, includeFirebaseAnon: true }),
useDeleteUser(auth, { includeFirebaseAnon: true }),
);
const { state } = result.current;
expect(state).toBe("ready");
Expand Down Expand Up @@ -88,13 +88,13 @@ describe("when authed, useDeleteUser hook", () => {
});

it("should have ready state", async () => {
const { result } = renderHook(() => useDeleteUser({ auth }));
const { result } = renderHook(() => useDeleteUser(auth));
const { state } = result.current;
expect(state).toBe("ready");
});

it("should delete user", async () => {
const { result } = renderHook(() => useDeleteUser({ auth }));
const { result } = renderHook(() => useDeleteUser(auth));
const { dispatch } = result.current;
await dispatch();
await sleep(100);
Expand All @@ -103,7 +103,7 @@ describe("when authed, useDeleteUser hook", () => {
});

it("should have loading state while dispatching", async () => {
const { result } = renderHook(() => useDeleteUser({ auth }));
const { result } = renderHook(() => useDeleteUser(auth));
const { dispatch } = result.current;
dispatch();
await sleep(1);
Expand Down
15 changes: 8 additions & 7 deletions src/auth/useDeleteUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { Auth, deleteUser, signOut } from "firebase/auth";
import { useEffect, useState } from "react";
import { useUser } from ".";

type UseDeleteUserParams = {
auth: Auth;
type UseDeleteUserOptions = {
includeFirebaseAnon?: boolean;
};

Expand All @@ -19,11 +18,13 @@ type UseDeleteUser = {
dispatch: UseDeleteUserDispatcher;
};

export const useDeleteUser = ({
auth,
includeFirebaseAnon = false,
}: UseDeleteUserParams): UseDeleteUser => {
const user = useUser({ auth });
export const useDeleteUser = (
auth: Auth,
{ includeFirebaseAnon }: UseDeleteUserOptions = {
includeFirebaseAnon: false,
},
): UseDeleteUser => {
const user = useUser(auth);
const [state, setState] = useState<UseDeleteUserState>("ready");

useEffect(() => {
Expand Down
12 changes: 4 additions & 8 deletions src/auth/useSendEmailVerification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import { ActionCodeSettings, Auth, sendEmailVerification } from "firebase/auth";
import { useEffect, useState } from "react";
import { useUser } from ".";

type UseSendEmailVerificationParams = {
auth: Auth;
};

type UseSendEmailVerificationState = "ready" | "loading" | "done" | "anonymous";
type UseSendEmailVerificationDispatcher = (
actionCodeSettings?: ActionCodeSettings,
Expand All @@ -20,10 +16,10 @@ type UseSendEmailVerification = {
dispatch: UseSendEmailVerificationDispatcher;
};

export const useSendEmailVerification = ({
auth,
}: UseSendEmailVerificationParams): UseSendEmailVerification => {
const user = useUser({ auth });
export const useSendEmailVerification = (
auth: Auth,
): UseSendEmailVerification => {
const user = useUser(auth);
const [state, setState] = useState<UseSendEmailVerificationState>("ready");

useEffect(() => {
Expand Down
8 changes: 4 additions & 4 deletions src/auth/useSignIn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("when authed, useSignIn hook", () => {
});

it("should have authenticated state", async () => {
const { result } = renderHook(() => useSignIn({ auth }));
const { result } = renderHook(() => useSignIn(auth));
const { state } = result.current;
expect(state).toBe("authenticated");
});
Expand All @@ -46,7 +46,7 @@ describe("when anon, useSignIn hook", () => {
await signOut(auth);

// test
const { result } = renderHook(() => useSignIn({ auth }));
const { result } = renderHook(() => useSignIn(auth));
const { state } = result.current;
expect(state).toBe("ready");
});
Expand All @@ -56,7 +56,7 @@ describe("when anon, useSignIn hook", () => {
const credential = await signInAnonymously(auth);

// test
const { result } = renderHook(() => useSignIn({ auth }));
const { result } = renderHook(() => useSignIn(auth));
const { state } = result.current;
expect(state).toBe("ready");

Expand All @@ -70,7 +70,7 @@ describe("when anon, useSignIn hook", () => {
const email = generateEmail("dispatchemail");
await createUserWithEmailAndPassword(auth, email, password);

const { result } = renderHook(() => useSignIn({ auth }));
const { result } = renderHook(() => useSignIn(auth));
const { dispatch } = result.current;

const credential = await dispatch({ type: "classic", email, password });
Expand Down
8 changes: 2 additions & 6 deletions src/auth/useSignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ import { ActionCodeSettings } from "firebase/auth";
import { useEffect, useState } from "react";
import { useUser } from ".";

type UseSignInParams = {
auth: Auth;
};

type UseSignInState = "ready" | "loading" | "authenticated" | "awaiting";
type UseSignInDispatcher = (
params:
Expand Down Expand Up @@ -62,8 +58,8 @@ type UseSignIn = {
dispatch: UseSignInDispatcher;
};

export const useSignIn = ({ auth }: UseSignInParams): UseSignIn => {
const user = useUser({ auth });
export const useSignIn = (auth: Auth): UseSignIn => {
const user = useUser(auth);
const [state, setState] = useState<UseSignInState>("ready");

useEffect(() => {
Expand Down
Loading

0 comments on commit cd9dd9d

Please sign in to comment.