From be75efaf47f5f6fa515f5d911bbaa3b97be3a2dc Mon Sep 17 00:00:00 2001 From: Bereket Engida Date: Sat, 31 Aug 2024 20:53:56 +0300 Subject: [PATCH] feat: changes in api --- dev/bc-fe/hono/db.sqlite | Bin 110592 -> 69632 bytes dev/bc-fe/react/src/App.tsx | 68 +++++++++++++++- dev/bc-fe/react/src/lib/auth.ts | 9 ++- packages/better-auth/src/api/index.ts | 12 +-- .../better-auth/src/api/routes/sign-in.ts | 5 +- .../better-auth/src/api/routes/sign-up.ts | 4 +- packages/better-auth/src/client/base.ts | 23 ++++-- .../better-auth/src/client/client.test.ts | 8 +- .../src/client/create-client-plugin.ts | 3 +- .../better-auth/src/client/fetch-plugins.ts | 1 - packages/better-auth/src/client/proxy.ts | 8 +- packages/better-auth/src/client/type.ts | 7 +- .../better-auth/src/plugins/bearer/index.ts | 4 +- .../plugins/two-factor/backup-codes/index.ts | 2 +- .../src/plugins/two-factor/client.ts | 36 ++++++++- .../src/plugins/two-factor/index.ts | 75 +++++++++++++++--- .../src/plugins/two-factor/otp/index.ts | 3 +- .../src/plugins/two-factor/totp/index.ts | 2 +- ...-fa-middleware.ts => verify-middleware.ts} | 70 +--------------- .../better-auth/src/plugins/username/index.ts | 25 ++++-- packages/better-auth/src/types/plugins.ts | 24 +++--- 21 files changed, 249 insertions(+), 140 deletions(-) rename packages/better-auth/src/plugins/two-factor/{two-fa-middleware.ts => verify-middleware.ts} (58%) diff --git a/dev/bc-fe/hono/db.sqlite b/dev/bc-fe/hono/db.sqlite index a0bf2dde417a7170e643abbf9f4932b92e591d71..ce459eab41b859fa91e2424299151f3a4880b63f 100644 GIT binary patch delta 1834 zcma)*O-$Qn7{_hwKuqksrBgd?1sXoaIzfW{+WDNaDWw6L#36|xfF+XtmZWXWF<2=}rDA4Fs)suVQGJ8}`d-%~v_~hb zS5UkDmi0Fj=om4ClJ&QVQ52=>LiaPvWy1CX0nq-VJxqN^y-WT@enJA`A_qr~21+je-bKmJbVd8!9*DO_|b|&bWYnwRk8~xC=(z3FS^CzqN^7xmIP85tF zV5Htd_kw+G9wm8xfIpfHZ6=*6!9_)x+DqgorqeMsetWW7+Y41ZyPOnGm*}bThA&=B z&GU=NxkM&a4f#AFHKfQXR*}=2;dHhn<)q^7dS}$+X0#$|}sM?lnoA%uBiXswh_!C8uT^PNCox z0$v$e{S3Gvj3?TqLK$ap@(=;n>e fjLYZuh^-}T-CvdDOtw@p4Z?8akJ~9e`TN%Y*(dtP literal 110592 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 {session.user.name}

+

+ {session.user.username} +

{session.user.email}

@@ -58,6 +61,7 @@ function App() { }}> Continue with github + ) @@ -73,6 +77,7 @@ export default App; function SignUp() { const [email, setEmail] = useState("") const [name, setName] = useState("") + const [username, setUsername] = useState("") const [password, setPassword] = useState("") return (
setName(e.target.value)} /> + setUsername(e.target.value)} + /> setPassword(e.target.value)} />
) +} + + + +function SignIn() { + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + return ( +
+ setEmail(e.target.value)} + /> + + setPassword(e.target.value)} + /> + +
+ ) } \ No newline at end of file diff --git a/dev/bc-fe/react/src/lib/auth.ts b/dev/bc-fe/react/src/lib/auth.ts index 2e7d688a55..c9ad1c643e 100644 --- a/dev/bc-fe/react/src/lib/auth.ts +++ b/dev/bc-fe/react/src/lib/auth.ts @@ -1,7 +1,12 @@ import { createAuthClient } from "better-auth/react"; -import { twoFactorClient } from "better-auth/client"; +import { twoFactorClient, usernameClient } from "better-auth/client"; export const auth = createAuthClient({ baseURL: "http://localhost:3000/api/auth", - authPlugins: [twoFactorClient], + authPlugins: [ + twoFactorClient({ + twoFactorPage: "/two-factor", + }), + usernameClient, + ], }); diff --git a/packages/better-auth/src/api/index.ts b/packages/better-auth/src/api/index.ts index 56b9281cd1..94f48ac06f 100644 --- a/packages/better-auth/src/api/index.ts +++ b/packages/better-auth/src/api/index.ts @@ -10,14 +10,14 @@ import { getSession, resetPassword, sendVerificationEmail, - signInCredential, + signInEmail, signInOAuth, signOut, verifyEmail, } from "./routes"; import { getCSRFToken } from "./routes/csrf"; import { ok, welcome } from "./routes/ok"; -import { signUpCredential } from "./routes/sign-up"; +import { signUpEmail } from "./routes/sign-up"; import { error } from "./routes/error"; import type { z, ZodAny, ZodObject, ZodOptional, ZodString } from "zod"; @@ -85,8 +85,8 @@ export const router = ( getCSRFToken, getSession: typedSession, signOut, - signUpCredential, - signInCredential, + signUpEmail, + signInEmail, forgetPassword, resetPassword, verifyEmail, @@ -136,10 +136,10 @@ export const router = ( for (const hook of plugin.hooks.after) { const match = hook.matcher(context); if (match) { - const hookRes = await hook.handler({ - ...context, + const obj = Object.assign(context, { returned: endpointRes, }); + const hookRes = await hook.handler(obj); if (hookRes && "response" in hookRes) { response = hookRes.response as any; } diff --git a/packages/better-auth/src/api/routes/sign-in.ts b/packages/better-auth/src/api/routes/sign-in.ts index ed3341aab8..5d8d0032e5 100644 --- a/packages/better-auth/src/api/routes/sign-in.ts +++ b/packages/better-auth/src/api/routes/sign-in.ts @@ -39,7 +39,6 @@ export const signInOAuth = createAuthEndpoint( if (!provider) { throw new APIError("NOT_FOUND"); } - const cookie = c.context.authCookies; const currentURL = c.query?.currentURL ? new URL(c.query?.currentURL) @@ -78,8 +77,8 @@ export const signInOAuth = createAuthEndpoint( }, ); -export const signInCredential = createAuthEndpoint( - "/sign-in/email-password", +export const signInEmail = createAuthEndpoint( + "/sign-in/email", { method: "POST", body: z.object({ diff --git a/packages/better-auth/src/api/routes/sign-up.ts b/packages/better-auth/src/api/routes/sign-up.ts index 6c21e5b81f..f8682d0b28 100644 --- a/packages/better-auth/src/api/routes/sign-up.ts +++ b/packages/better-auth/src/api/routes/sign-up.ts @@ -3,8 +3,8 @@ import { Argon2id } from "oslo/password"; import { z } from "zod"; import { createAuthEndpoint } from "../call"; -export const signUpCredential = createAuthEndpoint( - "/sign-up/credential", +export const signUpEmail = createAuthEndpoint( + "/sign-up/email", { method: "POST", body: z.object({ diff --git a/packages/better-auth/src/client/base.ts b/packages/better-auth/src/client/base.ts index fe57a0af7a..2d31191f27 100644 --- a/packages/better-auth/src/client/base.ts +++ b/packages/better-auth/src/client/base.ts @@ -28,15 +28,25 @@ export const createAuthClient = ( : {}) & Auth["api"] : Auth["api"]; + /** + * used for plugins only + */ + const $baseFetch = createFetch({ + ...options, + baseURL: getBaseURL(options?.baseURL).withPath, + }); const $fetch = createFetch({ method: "GET", ...options, baseURL: getBaseURL(options?.baseURL).withPath, plugins: [ + ...(options?.plugins || []), + ...(options?.authPlugins + ?.flatMap((plugin) => plugin($baseFetch).fetchPlugins) + .filter((plugin) => plugin !== undefined) || []), + ...(options?.csrfPlugin !== false ? [csrfPlugin] : []), redirectPlugin, addCurrentURL, - ...(options?.csrfPlugin !== false ? [csrfPlugin] : []), - ...(options?.plugins || []), ], }); @@ -121,11 +131,10 @@ export const createAuthClient = ( atom: "$activeOrgSignal", }, { - matcher: (path) => path === "/sign-out", - atom: "$sessionSignal", - }, - { - matcher: (path) => path.startsWith("/sign-up"), + matcher: (path) => + path === "/sign-out" || + path.startsWith("/sign-up") || + path.startsWith("/sign-in"), atom: "$sessionSignal", }, ...pluginProxySignals, diff --git a/packages/better-auth/src/client/client.test.ts b/packages/better-auth/src/client/client.test.ts index 749bf812cd..ab2cc2c944 100644 --- a/packages/better-auth/src/client/client.test.ts +++ b/packages/better-auth/src/client/client.test.ts @@ -30,7 +30,13 @@ describe("client path to object", async () => { client.$atoms.$session; const client2 = createReactClient({ - authPlugins: [organization, twoFactorClient, usernameClient], + authPlugins: [ + organization, + twoFactorClient({ + twoFactorPage: "/two-factor", + }), + usernameClient, + ], }); }); }); diff --git a/packages/better-auth/src/client/create-client-plugin.ts b/packages/better-auth/src/client/create-client-plugin.ts index f142a6392b..16626933ba 100644 --- a/packages/better-auth/src/client/create-client-plugin.ts +++ b/packages/better-auth/src/client/create-client-plugin.ts @@ -1,4 +1,4 @@ -import type { BetterFetch } from "@better-fetch/fetch"; +import type { BetterFetch, BetterFetchPlugin } from "@better-fetch/fetch"; import type { Endpoint } from "better-call"; import type { AuthProxySignal } from "./proxy"; import type { Atom, PreinitializedWritableAtom } from "nanostores"; @@ -25,6 +25,7 @@ export const createClientPlugin = () => { atoms?: Record>; integrations?: Integrations; pathMethods?: Record; + fetchPlugins?: BetterFetchPlugin[]; }, ) => { return ($fetch: BetterFetch) => { diff --git a/packages/better-auth/src/client/fetch-plugins.ts b/packages/better-auth/src/client/fetch-plugins.ts index 1dfb3f29ec..2ce822d53e 100644 --- a/packages/better-auth/src/client/fetch-plugins.ts +++ b/packages/better-auth/src/client/fetch-plugins.ts @@ -7,7 +7,6 @@ export const redirectPlugin = { hooks: { onSuccess(context) { if (context.data?.url && context.data?.redirect) { - console.log("redirecting to", context.data.url); window.location.href = context.data.url; } }, diff --git a/packages/better-auth/src/client/proxy.ts b/packages/better-auth/src/client/proxy.ts index c6baebcbc1..544aef2359 100644 --- a/packages/better-auth/src/client/proxy.ts +++ b/packages/better-auth/src/client/proxy.ts @@ -64,12 +64,18 @@ export function createDynamicPathProxy>( body: method === "GET" ? undefined : body, query: query, method, - onSuccess() { + async onSuccess(context) { const signal = $signal?.find((s) => s.matcher(routePath)); if (!signal) return; const signalAtom = $signals?.[signal.atom]; if (!signalAtom) return; signalAtom.set(!signalAtom.get()); + /** + * call if options.onSuccess + * is passed since we are + * overriding onSuccess + */ + await options?.onSuccess?.(context); }, }); }, diff --git a/packages/better-auth/src/client/type.ts b/packages/better-auth/src/client/type.ts index f7db5f290e..b3121f21f5 100644 --- a/packages/better-auth/src/client/type.ts +++ b/packages/better-auth/src/client/type.ts @@ -1,4 +1,8 @@ -import type { BetterFetch, BetterFetchOption } from "@better-fetch/fetch"; +import type { + BetterFetch, + BetterFetchOption, + BetterFetchPlugin, +} from "@better-fetch/fetch"; import type { Auth } from "../auth"; import type { UnionToIntersection } from "../types/helper"; import type { useAuthStore as reactStore } from "./react"; @@ -30,6 +34,7 @@ export type AuthPlugin = ($fetch: BetterFetch) => { preact?: (useStore: typeof preactStore) => Record; }; pathMethods?: Record; + fetchPlugins?: BetterFetchPlugin[]; }; export interface ClientOptions extends BetterFetchOption { /** diff --git a/packages/better-auth/src/plugins/bearer/index.ts b/packages/better-auth/src/plugins/bearer/index.ts index 19ceed8cd0..a9a7774021 100644 --- a/packages/better-auth/src/plugins/bearer/index.ts +++ b/packages/better-auth/src/plugins/bearer/index.ts @@ -19,7 +19,7 @@ export const bearer = () => { ?.startsWith("Bearer ") || false ); }, - handler: createAuthMiddleware(async (ctx) => { + handler: async (ctx) => { const token = ctx.request?.headers .get("authorization") ?.replace("Bearer ", ""); @@ -38,7 +38,7 @@ export const bearer = () => { ctx.context.authCookies.sessionToken.name }=${signedToken.replace("=", "")}`, ); - }), + }, }, ], }, diff --git a/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts b/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts index f12cc0546a..f3cc0a7685 100644 --- a/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts +++ b/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { createAuthEndpoint } from "../../../api/call"; import { sessionMiddleware } from "../../../api/middlewares/session"; import { symmetricDecrypt, symmetricEncrypt } from "../../../crypto"; -import { verifyTwoFactorMiddleware } from "../two-fa-middleware"; +import { verifyTwoFactorMiddleware } from "../verify-middleware"; import type { TwoFactorProvider, UserWithTwoFactor } from "../types"; export interface BackupCodeOptions { diff --git a/packages/better-auth/src/plugins/two-factor/client.ts b/packages/better-auth/src/plugins/two-factor/client.ts index 263f7c299f..34926504b8 100644 --- a/packages/better-auth/src/plugins/two-factor/client.ts +++ b/packages/better-auth/src/plugins/two-factor/client.ts @@ -1,8 +1,21 @@ import { createClientPlugin } from "../../client/create-client-plugin"; import type { twoFactor as twoFa } from "../../plugins/two-factor"; -export const twoFactorClient = createClientPlugin>()( - ($fetch) => { +export const twoFactorClient = ( + options: { + twoFactorPage: string; + /** + * Redirect to the two factor page. If twoFactorPage + * is not set this will redirect to the root path. + * @default true + */ + redirect?: boolean; + } = { + redirect: true, + twoFactorPage: "/", + }, +) => { + return createClientPlugin>()(($fetch) => { return { id: "two-factor", authProxySignal: [ @@ -18,6 +31,21 @@ export const twoFactorClient = createClientPlugin>()( "/two-factor/enable": "POST", "/two-factor/send-otp": "POST", }, + fetchPlugins: [ + { + id: "two-factor", + name: "two-factor", + hooks: { + async onSuccess(context) { + if (context.data?.twoFactorRedirect) { + if (options.redirect) { + window.location.href = options.twoFactorPage; + } + } + }, + }, + }, + ], }; - }, -); + }); +}; diff --git a/packages/better-auth/src/plugins/two-factor/index.ts b/packages/better-auth/src/plugins/two-factor/index.ts index 95e6e9f5c8..6bf597e578 100644 --- a/packages/better-auth/src/plugins/two-factor/index.ts +++ b/packages/better-auth/src/plugins/two-factor/index.ts @@ -1,17 +1,15 @@ import { alphabet, generateRandomString } from "oslo/crypto"; import { z } from "zod"; -import { createAuthEndpoint } from "../../api/call"; +import { createAuthEndpoint, createAuthMiddleware } from "../../api/call"; import { sessionMiddleware } from "../../api/middlewares/session"; -import { symmetricEncrypt } from "../../crypto"; +import { hs256, symmetricEncrypt } from "../../crypto"; import type { BetterAuthPlugin } from "../../types/plugins"; import { backupCode2fa, generateBackupCodes } from "./backup-codes"; import { otp2fa } from "./otp"; import { totp2fa } from "./totp"; -import { - twoFactorMiddleware, - verifyTwoFactorMiddleware, -} from "./two-fa-middleware"; + import type { TwoFactorOptions, UserWithTwoFactor } from "./types"; +import type { Session } from "../../adapters/schema"; export const twoFactor = (options: O) => { const totp = totp2fa({ @@ -86,12 +84,65 @@ export const twoFactor = (options: O) => { ), }, options: options, - middlewares: [ - { - path: "/sign-in/credential", - middleware: twoFactorMiddleware(options), - }, - ], + hooks: { + after: [ + { + matcher(context) { + return ( + context.path === "/sign-in/email" || + context.path === "/sign-in/username" + ); + }, + handler: createAuthMiddleware(async (ctx) => { + const returned = (await (ctx as any).returned) as Response; + if (returned?.status !== 200) { + return; + } + const response = (await returned.json()) as { + user: UserWithTwoFactor; + session: Session; + }; + if (!response.user.twoFactorEnabled) { + return; + } + /** + * remove the session cookie. It's set by the sign in credential + */ + ctx.setCookie(ctx.context.authCookies.sessionToken.name, "", { + path: "/", + sameSite: "lax", + httpOnly: true, + secure: false, + maxAge: 0, + }); + const hash = await hs256(ctx.context.secret, response.session.id); + /** + * We set the user id and the session + * id as a hash. Later will fetch for + * sessions with the user id compare + * the hash and set that as session. + */ + await ctx.setSignedCookie( + "better-auth.two-factor", + `${response.session.userId}!${hash}`, + ctx.context.secret, + ctx.context.authCookies.sessionToken.options, + ); + const res = new Response( + JSON.stringify({ + twoFactorRedirect: true, + }), + { + headers: ctx.responseHeader, + }, + ); + return { + response: res, + }; + }), + }, + ], + }, schema: { user: { fields: { diff --git a/packages/better-auth/src/plugins/two-factor/otp/index.ts b/packages/better-auth/src/plugins/two-factor/otp/index.ts index f39130990b..8619154293 100644 --- a/packages/better-auth/src/plugins/two-factor/otp/index.ts +++ b/packages/better-auth/src/plugins/two-factor/otp/index.ts @@ -3,9 +3,8 @@ import { generateRandomInteger } from "oslo/crypto"; import { generateHOTP } from "oslo/otp"; import { z } from "zod"; import { createAuthEndpoint } from "../../../api/call"; -import { sessionMiddleware } from "../../../api/middlewares/session"; import { OTP_RANDOM_NUMBER_COOKIE_NAME } from "../constant"; -import { verifyTwoFactorMiddleware } from "../two-fa-middleware"; +import { verifyTwoFactorMiddleware } from "../verify-middleware"; import type { TwoFactorProvider, UserWithTwoFactor } from "../types"; export interface OTPOptions { diff --git a/packages/better-auth/src/plugins/two-factor/totp/index.ts b/packages/better-auth/src/plugins/two-factor/totp/index.ts index 9cd1bb4fe7..ce6c95c8bc 100644 --- a/packages/better-auth/src/plugins/two-factor/totp/index.ts +++ b/packages/better-auth/src/plugins/two-factor/totp/index.ts @@ -6,7 +6,7 @@ import { createAuthEndpoint } from "../../../api/call"; import { sessionMiddleware } from "../../../api/middlewares/session"; import { symmetricDecrypt } from "../../../crypto"; import type { BackupCodeOptions } from "../backup-codes"; -import { verifyTwoFactorMiddleware } from "../two-fa-middleware"; +import { verifyTwoFactorMiddleware } from "../verify-middleware"; import type { TwoFactorProvider, UserWithTwoFactor } from "../types"; export type TOTPOptions = { diff --git a/packages/better-auth/src/plugins/two-factor/two-fa-middleware.ts b/packages/better-auth/src/plugins/two-factor/verify-middleware.ts similarity index 58% rename from packages/better-auth/src/plugins/two-factor/two-fa-middleware.ts rename to packages/better-auth/src/plugins/two-factor/verify-middleware.ts index ffd1650005..3f77c6599a 100644 --- a/packages/better-auth/src/plugins/two-factor/two-fa-middleware.ts +++ b/packages/better-auth/src/plugins/two-factor/verify-middleware.ts @@ -1,11 +1,9 @@ import { APIError } from "better-call"; -import { z } from "zod"; import type { Session } from "../../adapters/schema"; import { createAuthMiddleware } from "../../api/call"; -import { signInCredential } from "../../api/routes"; import { hs256 } from "../../crypto"; import { TWO_FACTOR_COOKIE_NAME } from "./constant"; -import type { TwoFactorOptions, UserWithTwoFactor } from "./types"; +import type { UserWithTwoFactor } from "./types"; export const verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => { const cookie = await ctx.getSignedCookie( @@ -107,69 +105,3 @@ export const verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => { message: "invalid two factor authentication", }); }); - -export const twoFactorMiddleware = (options: TwoFactorOptions) => - createAuthMiddleware( - { - body: z.object({ - email: z.string().email(), - password: z.string(), - /** - * Callback URL to - * redirect to after - * the user has signed in. - */ - callbackURL: z.string().optional(), - }), - }, - async (ctx) => { - //@ts-ignore - const signIn = await signInCredential({ - ...ctx, - body: ctx.body, - }); - if (!signIn?.user) { - return new Response(null, { - status: 401, - }); - } - const user = signIn.user as UserWithTwoFactor; - if (!user.twoFactorEnabled) { - return new Response(JSON.stringify(signIn), { - headers: ctx.responseHeader, - }); - } - /** - * remove the session cookie. It's set by the sign in credential - */ - ctx.setCookie(ctx.context.authCookies.sessionToken.name, "", { - path: "/", - sameSite: "lax", - httpOnly: true, - secure: false, - maxAge: 0, - }); - const hash = await hs256(ctx.context.secret, signIn.session.id); - /** - * We set the user id and the session - * id as a hash. Later will fetch for - * sessions with the user id compare - * the hash and set that as session. - */ - await ctx.setSignedCookie( - "better-auth.two-factor", - `${signIn.session.userId}!${hash}`, - ctx.context.secret, - ctx.context.authCookies.sessionToken.options, - ); - return new Response( - JSON.stringify({ - url: options.twoFactorURL || ctx.body.callbackURL || "/", - redirect: true, - }), - { - headers: ctx.responseHeader, - }, - ); - }, - ); diff --git a/packages/better-auth/src/plugins/username/index.ts b/packages/better-auth/src/plugins/username/index.ts index d8aa9a80fc..440d2ff700 100644 --- a/packages/better-auth/src/plugins/username/index.ts +++ b/packages/better-auth/src/plugins/username/index.ts @@ -4,14 +4,14 @@ import type { BetterAuthPlugin } from "../../types/plugins"; import { Argon2id } from "oslo/password"; import { APIError } from "better-call"; import type { Account, User } from "../../adapters/schema"; -import { signUpCredential } from "../../api/routes/sign-up"; +import { signUpEmail } from "../../api/routes/sign-up"; export const username = () => { return { id: "username", endpoints: { signInUsername: createAuthEndpoint( - "/sign-in/username-password", + "/sign-in/username", { method: "POST", body: z.object({ @@ -102,7 +102,7 @@ export const username = () => { { method: "POST", body: z.object({ - username: z.string().min(3).max(20).optional(), + username: z.string().min(3).max(20), name: z.string(), email: z.string().email(), password: z.string(), @@ -111,7 +111,11 @@ export const username = () => { }), }, async (ctx) => { - const res = await signUpCredential(ctx); + const res = await signUpEmail({ + ...ctx, + //@ts-expect-error + _flag: undefined, + }); if (!res) { return ctx.json(null, { status: 400, @@ -121,9 +125,14 @@ export const username = () => { }, }); } - await ctx.context.internalAdapter.updateUserByEmail(res.user.email, { - username: ctx.body.username, - }); + const updatedUser = + await ctx.context.internalAdapter.updateUserByEmail( + res.user.email, + { + username: ctx.body.username, + }, + ); + console.log(updatedUser); return ctx.json(res); }, ), @@ -135,6 +144,8 @@ export const username = () => { username: { type: "string", required: false, + unique: true, + returned: true, }, }, }, diff --git a/packages/better-auth/src/types/plugins.ts b/packages/better-auth/src/types/plugins.ts index e944387dfc..e9483e114b 100644 --- a/packages/better-auth/src/types/plugins.ts +++ b/packages/better-auth/src/types/plugins.ts @@ -26,23 +26,19 @@ export type BetterAuthPlugin = { hooks?: { before?: { matcher: (context: GenericEndpointContext) => boolean; - handler: Endpoint< - (context: GenericEndpointContext) => Promise; - }> - >; + handler: (context: GenericEndpointContext) => Promise; + }>; }[]; after?: { matcher: (context: GenericEndpointContext) => boolean; - handler: Endpoint< - ( - context: GenericEndpointContext & { - returned: EndpointResponse; - }, - ) => Promise - >; + handler: ( + context: GenericEndpointContext & { + returned: EndpointResponse; + }, + ) => Promise; }[]; }; /**