refactor: remove user prefix from endpoints (#358)

This commit is contained in:
Bereket Engida
2024-10-28 12:33:59 +03:00
committed by GitHub
parent 463d7944f6
commit 1c7606d61e
23 changed files with 68 additions and 75 deletions

View File

@@ -24,7 +24,7 @@ import {
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { PasswordInput } from "@/components/ui/password-input";
import { client, signOut, user, useSession } from "@/lib/auth-client";
import { client, signOut, useSession } from "@/lib/auth-client";
import { Session } from "@/lib/auth-types";
import { MobileIcon } from "@radix-ui/react-icons";
import {
@@ -180,7 +180,7 @@ export default function UserCard(props: {
className="text-red-500 opacity-80 cursor-pointer text-xs border-muted-foreground border-red-600 underline "
onClick={async () => {
setIsTerminating(session.id);
const res = await client.user.revokeSession({
const res = await client.revokeSession({
id: session.id,
});
@@ -497,7 +497,7 @@ function ChangePassword() {
return;
}
setLoading(true);
const res = await user.changePassword({
const res = await client.changePassword({
newPassword: newPassword,
currentPassword: currentPassword,
revokeOtherSessions: signOutDevices,
@@ -610,7 +610,7 @@ function EditUserDialog(props: { session: Session | null }) {
disabled={isLoading}
onClick={async () => {
setIsLoading(true);
await user.update({
await client.updateUser({
image: image ? await convertImageToBase64(image) : undefined,
name: name ? name : undefined,
fetchOptions: {

View File

@@ -33,7 +33,6 @@ export const {
signIn,
signOut,
useSession,
user,
organization,
useListOrganizations,
useActiveOrganization,

View File

@@ -64,7 +64,7 @@ The `listSessions` function returns a list of sessions that are active for the u
```ts title="client.ts"
import { authClient } from "@/lib/client"
const sessions = await authClient.user.listSessions()
const sessions = await authClient.listSessions()
```
### Revoke Session
@@ -74,7 +74,7 @@ When a user signs out of a device, the session is automatically ended. However,
To end a session, use the `revokeSession` function. Just pass the session ID as a parameter.
```ts title="client.ts"
await authClient.user.revokeSession({
await authClient.revokeSession({
id: session.id,
})
```
@@ -84,7 +84,7 @@ await authClient.user.revokeSession({
To revoke all sessions, you can use the `revokeSessions` function.
```ts title="client.ts"
await authClient.user.revokeSessions()
await authClient.revokeSessions()
```
### Revoking Sessions on Password Change
@@ -92,7 +92,7 @@ await authClient.user.revokeSessions()
You can revoke all sessions when the user changes their password by passing `revokeOtherSessions` true on `changePAssword` function.
```ts title="auth.ts"
await authClient.user.changePassword({
await authClient.changePassword({
newPassword: newPassword,
currentPassword: currentPassword,
revokeOtherSessions: signOutDevices,

View File

@@ -25,7 +25,7 @@ The user table can be extended by plugins to store additional data. When a plugi
To update user information, you can use the `updateUser` function provided by the client. The `updateUser` function takes an object with the following properties:
```ts
await authClient.user.update({
await authClient.updateUser({
image: "https://example.com/image.jpg",
name: "John Doe",
})
@@ -66,7 +66,7 @@ export const auth = betterAuth({
Once enabled, use the `changeEmail` function on the client to update a users email. The user must verify their current email before changing it.
```ts
await authClient.user.changeEmail({
await authClient.changeEmail({
newEmail: "new-email@email.com",
callbackURL: "/dashboard", //to redirect after verification
});
@@ -83,7 +83,7 @@ After verification, the new email is updated in the user table, and a confirmati
Password of a user isn't stored in the user table. Instead, it's stored in the account table. To change the password of a user, you can use the `changePassword` function provided by the client. The `changePassword` function takes an object with the following properties:
```ts
await authClient.user.changePassword({
await authClient.changePassword({
newPassword: "newPassword123",
currentPassword: "oldPassword123",
revokeOtherSessions: true, // revoke all other sessions the user is signed into
@@ -95,7 +95,7 @@ await authClient.user.changePassword({
If a user was registered using oAuth or other providers, they won't have a password. In this case, you can use the `setPassword` function to set a password for the user. This will create a new credential account with the password.
```ts
await authClient.user.setPassword({
await authClient.setPassword({
password,
});
```
@@ -125,7 +125,7 @@ The account table stores the authentication data of the user. The account table
To list user accounts you can use `client.user.listAccounts` method. Which will return all accounts associated with a user.
```ts
const accounts = await authClient.user.listAccounts();
const accounts = await authClient.listAccounts();
```
### Account Linking
@@ -165,7 +165,7 @@ Users already signed in can manually link their account to additional social pro
- **Linking Social Accounts:** Use the `user.linkSocial` method on the client to link a social provider to the user's account.
```ts
await client.user.linkSocial({
await client.linkSocial({
provider: "google", // Provider to link
callbackURL: "/callback" // Callback URL after linking completes
});

View File

@@ -58,7 +58,7 @@ Now you can make authenticated API calls:
```ts title="client.ts"
// This request is automatically authenticated
const { data } = await authClient.user.listSessions();
const { data } = await authClient.listSessions();
```
### 4. Per-Request Token (Optional)
@@ -66,7 +66,7 @@ const { data } = await authClient.user.listSessions();
You can also provide the token for individual requests:
```ts title="client.ts"
const { data } = await authClient.user.listSessions({
const { data } = await authClient.listSessions({
fetchOptions: {
headers: {
Authorization: `Bearer ${token}`

View File

@@ -3,16 +3,11 @@ import {
signOut,
twoFactorActions,
useListPasskeys,
userActions,
useSession,
revokeSession,
updateUser,
} from "@/libs/auth-client";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "./ui/card";
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
import { UAParser } from "ua-parser-js";
import { Image, ImageFallback, ImageRoot } from "./ui/image";
import type { Session, User } from "better-auth/types";
@@ -109,7 +104,7 @@ export function UserCard(props: {
<button
class="text-red-500 opacity-80 cursor-pointer text-xs border-muted-foreground border-red-600 underline "
onClick={async () => {
const res = await userActions.revokeSession({
const res = await revokeSession({
id: activeSession.id,
});
@@ -216,7 +211,7 @@ function EditUserDialog(props: { user?: User }) {
<Button
onClick={async () => {
setIsLoading(true);
await userActions.update({
await updateUser({
image: image()
? await convertImageToBase64(image()!)
: undefined,

View File

@@ -8,9 +8,12 @@ export const {
signUp,
passkey: passkeyActions,
useListPasskeys,
user: userActions,
twoFactor: twoFactorActions,
$Infer,
updateUser,
changePassword,
revokeSession,
revokeSessions,
} = createAuthClient({
baseURL:
process.env.NODE_ENV === "development"

View File

@@ -180,7 +180,7 @@ export default function UserCard(props: {
className="text-red-500 opacity-80 cursor-pointer text-xs border-muted-foreground border-red-600 underline "
onClick={async () => {
setIsTerminating(session.id);
const res = await client.user.revokeSession({
const res = await client.revokeSession({
id: session.id,
});
@@ -497,7 +497,7 @@ function ChangePassword() {
return;
}
setLoading(true);
const res = await user.changePassword({
const res = await client.changePassword({
newPassword: newPassword,
currentPassword: currentPassword,
revokeOtherSessions: signOutDevices,
@@ -610,7 +610,7 @@ function EditUserDialog(props: { session: Session | null }) {
disabled={isLoading}
onClick={async () => {
setIsLoading(true);
await user.update({
await client.updateUser({
image: image ? await convertImageToBase64(image) : undefined,
name: name ? name : undefined,
fetchOptions: {

View File

@@ -4,7 +4,6 @@ import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
import { Button } from "~/components/ui/button";
import {
Card,
CardDescription,
CardContent,
CardFooter,
CardHeader,
@@ -84,7 +83,7 @@ export default function UserCard() {
useState<boolean>(false);
const { data: activeSessions } = useSWR("/sessions", async () => {
return (await authClient.user.listSessions()).data;
return (await authClient.listSessions()).data;
});
return (
<Card>
@@ -174,7 +173,7 @@ export default function UserCard() {
className="text-red-500 opacity-80 cursor-pointer text-xs border-muted-foreground border-red-600 underline "
onClick={async () => {
setIsTerminating(activeSession.id);
const res = await authClient.user.revokeSession({
const res = await authClient.revokeSession({
id: activeSession.id,
});
@@ -453,7 +452,7 @@ function ChangePassword() {
return;
}
setLoading(true);
const res = await authClient.user.changePassword({
const res = await authClient.changePassword({
newPassword: newPassword,
currentPassword: currentPassword,
revokeOtherSessions: signOutDevices,
@@ -564,7 +563,7 @@ function EditUserDialog(props: { session: Session | null }) {
disabled={isLoading}
onClick={async () => {
setIsLoading(true);
await authClient.user.update({
await authClient.updateUser({
image: image ? await convertImageToBase64(image) : undefined,
name: name ? name : undefined,
fetchOptions: {

View File

@@ -58,7 +58,7 @@ describe("account", async () => {
});
const { headers } = await signInWithTestUser();
it("should list all accounts", async () => {
const accounts = await client.user.listAccounts({
const accounts = await client.listAccounts({
fetchOptions: {
headers,
},
@@ -67,7 +67,7 @@ describe("account", async () => {
});
it("should link account", async () => {
const linkAccountRes = await client.user.linkSocial(
const linkAccountRes = await client.linkSocial(
{
provider: "google",
callbackURL: "/callback",
@@ -110,7 +110,7 @@ describe("account", async () => {
},
});
const { headers: headers2 } = await signInWithTestUser();
const accounts = await client.user.listAccounts({
const accounts = await client.listAccounts({
fetchOptions: { headers: headers2 },
});
expect(accounts.data?.length).toBe(2);
@@ -118,7 +118,7 @@ describe("account", async () => {
it("shouldn't link existing account", async () => {
const { headers: headers2 } = await signInWithTestUser();
const linkAccountRes = await client.user.linkSocial(
const linkAccountRes = await client.linkSocial(
{
provider: "google",
callbackURL: "/callback",

View File

@@ -2,15 +2,12 @@ import { z } from "zod";
import { createAuthEndpoint } from "../call";
import { socialProviderList } from "../../social-providers";
import { APIError } from "better-call";
import { generateState, parseState, type OAuth2Tokens } from "../../oauth2";
import { generateState } from "../../oauth2";
import { generateCodeVerifier } from "oslo/oauth2";
import { HIDE_METADATA, logger } from "../../utils";
import { compareHash } from "../../crypto/hash";
import { getSessionFromCtx, sessionMiddleware } from "./session";
import { userSchema } from "../../db/schema";
import { sessionMiddleware } from "./session";
export const listUserAccounts = createAuthEndpoint(
"/user/list-accounts",
"/list-accounts",
{
method: "GET",
use: [sessionMiddleware],
@@ -25,7 +22,7 @@ export const listUserAccounts = createAuthEndpoint(
);
export const linkSocialAccount = createAuthEndpoint(
"/user/link-social",
"/link-social",
{
method: "POST",
requireHeaders: true,

View File

@@ -201,7 +201,7 @@ describe("session", async () => {
},
);
const response = await client.user.listSessions({
const response = await client.listSessions({
fetchOptions: {
headers,
},
@@ -227,7 +227,7 @@ describe("session", async () => {
onSuccess: sessionSetter(headers2),
},
});
await client.user.revokeSession({
await client.revokeSession({
fetchOptions: {
headers,
},
@@ -239,7 +239,7 @@ describe("session", async () => {
},
});
expect(session.data).toBeNull();
const revokeRes = await client.user.revokeSessions({
const revokeRes = await client.revokeSessions({
fetchOptions: {
headers: headers2,
},
@@ -324,7 +324,7 @@ describe("session storage", async () => {
},
});
expect(session.data).not.toBeNull();
const res = await client.user.revokeSession({
const res = await client.revokeSession({
fetchOptions: {
headers,
},

View File

@@ -184,7 +184,7 @@ export const sessionMiddleware = createAuthMiddleware(async (ctx) => {
*/
export const listSessions = <Option extends BetterAuthOptions>() =>
createAuthEndpoint(
"/user/list-sessions",
"/list-sessions",
{
method: "GET",
use: [sessionMiddleware],
@@ -207,7 +207,7 @@ export const listSessions = <Option extends BetterAuthOptions>() =>
* revoke a single session
*/
export const revokeSession = createAuthEndpoint(
"/user/revoke-session",
"/revoke-session",
{
method: "POST",
body: z.object({
@@ -242,7 +242,7 @@ export const revokeSession = createAuthEndpoint(
* revoke all user sessions
*/
export const revokeSessions = createAuthEndpoint(
"/user/revoke-sessions",
"/revoke-sessions",
{
method: "POST",
use: [sessionMiddleware],

View File

@@ -35,7 +35,7 @@ describe("updateUser", async () => {
}
it("should update the user's name", async () => {
const updated = await client.user.update({
const updated = await client.updateUser({
name: "newName",
fetchOptions: {
headers,
@@ -46,7 +46,7 @@ describe("updateUser", async () => {
it("should update user email", async () => {
const newEmail = "new-email@email.com";
const res = await client.user.changeEmail({
const res = await client.changeEmail({
newEmail,
fetchOptions: {
headers: headers,
@@ -68,7 +68,7 @@ describe("updateUser", async () => {
},
],
});
await client.user.changeEmail({
await client.changeEmail({
newEmail: "new-email-2@email.com",
fetchOptions: {
headers: headers,
@@ -86,7 +86,7 @@ describe("updateUser", async () => {
it("should update the user's password", async () => {
const newEmail = "new-email@email.com";
const updated = await client.user.changePassword({
const updated = await client.changePassword({
newPassword: "newPassword",
currentPassword: testUser.password,
revokeOtherSessions: true,
@@ -109,7 +109,7 @@ describe("updateUser", async () => {
it("should revoke other sessions", async () => {
const newHeaders = new Headers();
await client.user.changePassword({
await client.changePassword({
newPassword: "newPassword",
currentPassword: testUser.password,
revokeOtherSessions: true,
@@ -169,7 +169,7 @@ describe("updateUser", async () => {
});
expect(res?.newField).toBe("new");
const updated = await client.user.update({
const updated = await client.updateUser({
name: "newName",
fetchOptions: {
headers,

View File

@@ -1,6 +1,6 @@
import { z, ZodObject, ZodOptional, ZodString } from "zod";
import { createAuthEndpoint } from "../call";
import { alphabet, generateRandomString } from "../../crypto/random";
import { deleteSessionCookie, setSessionCookie } from "../../cookies";
import { sessionMiddleware } from "./session";
import { APIError } from "better-call";
@@ -11,7 +11,7 @@ import { parseUserInput } from "../../db/schema";
export const updateUser = <O extends BetterAuthOptions>() =>
createAuthEndpoint(
"/user/update",
"/update-user",
{
method: "POST",
body: z.record(z.string(), z.any()) as unknown as ZodObject<{
@@ -67,7 +67,7 @@ export const updateUser = <O extends BetterAuthOptions>() =>
);
export const changePassword = createAuthEndpoint(
"/user/change-password",
"/change-password",
{
method: "POST",
body: z.object({
@@ -154,7 +154,7 @@ export const changePassword = createAuthEndpoint(
);
export const setPassword = createAuthEndpoint(
"/user/set-password",
"/set-password",
{
method: "POST",
body: z.object({
@@ -211,7 +211,7 @@ export const setPassword = createAuthEndpoint(
);
export const deleteUser = createAuthEndpoint(
"/user/delete",
"/delete-user",
{
method: "POST",
body: z.object({
@@ -250,7 +250,7 @@ export const deleteUser = createAuthEndpoint(
);
export const changeEmail = createAuthEndpoint(
"/user/change-email",
"/change-email",
{
method: "POST",
query: z

View File

@@ -35,7 +35,7 @@ export const getClientConfig = <O extends ClientOptions>(options?: O) => {
let pluginsAtoms = {} as Record<string, Atom<any>>;
let pluginPathMethods: Record<string, "POST" | "GET"> = {
"/sign-out": "POST",
"/user/revoke-sessions": "POST",
"/revoke-sessions": "POST",
};
const atomListeners: AtomListener[] = [
{
@@ -43,7 +43,7 @@ export const getClientConfig = <O extends ClientOptions>(options?: O) => {
matcher(path) {
return (
path === "/sign-out" ||
path === "/user/update" ||
path === "/update-user" ||
path.startsWith("/sign-in") ||
path.startsWith("/sign-up")
);

View File

@@ -114,7 +114,7 @@ export type InferRoute<API, COpts extends ClientOptions> = API extends {
]
: [
Prettify<
T["path"] extends `/user/update`
T["path"] extends `/update-user`
? InferUserUpdateCtx<COpts>
: InferCtx<C>
>?,

View File

@@ -80,7 +80,7 @@ describe("db", async () => {
});
expect(res.data?.user.email).toBe("test@email.com");
const { headers } = await signInWithTestUser();
const res2 = await client.user.update(
const res2 = await client.updateUser(
{
name: "New Name",
},

View File

@@ -102,7 +102,7 @@ describe("additionalFields", async () => {
onSuccess: sessionSetter(headers),
},
);
const res = await client.user.update({
const res = await client.updateUser({
name: "test",
newField: "updated-field",
fetchOptions: {

View File

@@ -117,7 +117,7 @@ export const admin = (options?: AdminOptions) => {
after: [
{
matcher(context) {
return context.path === "/user/list-sessions";
return context.path === "/list-sessions";
},
handler: createAuthMiddleware(async (ctx) => {
const returned = ctx.context.returned;

View File

@@ -26,7 +26,7 @@ describe("bearer", async () => {
});
it("should list session", async () => {
const sessions = await client.user.listSessions({
const sessions = await client.listSessions({
fetchOptions: {
headers: {
authorization: `Bearer ${token}`,

View File

@@ -177,7 +177,7 @@ describe("phone auth flow", async () => {
},
headers,
});
const changedEmailRes = await client.user.changeEmail({
const changedEmailRes = await client.changeEmail({
newEmail,
fetchOptions: {
headers,

View File

@@ -38,7 +38,7 @@ describe("username", async (it) => {
expect(res.data?.session).toBeDefined();
});
it("should update username", async () => {
const res = await client.user.update({
const res = await client.updateUser({
username: "new-username-2",
fetchOptions: {
headers,