Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@better-auth-kit/legal-consent": "workspace:*",
"@better-auth-kit/waitlist": "workspace:*",
"@better-auth-kit/reverify": "workspace:*",
"@faker-js/faker": "^9.5.1",
"@hookform/resolvers": "^4.1.3",
"@radix-ui/react-accordion": "^1.2.1",
Expand Down
21 changes: 21 additions & 0 deletions apps/docs/src/app/components/email/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use client";

import { Button } from "@/components/ui/button";
import { authClient } from "@/lib/auth-client";

export default function Page() {
const session = authClient.useSession();

return (
<div className="w-full h-full relative flex justify-center items-center pr-[var(--fd-sidebar-width)] bg-gradient-to-br from-fd-border/10 to-fd-border/50">
<Button
onClick={async () => {
console.log(session.data?.user.email);
authClient.reverify.sendEmail();
}}
>
Send Verification Email
</Button>
</div>
);
}
3 changes: 2 additions & 1 deletion apps/docs/src/lib/auth-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import {
usernameClient,
} from "better-auth/client/plugins";
import { waitlistClient } from "@better-auth-kit/waitlist";
import { nextCookies } from "better-auth/next-js";
import { reverifyClient } from "@better-auth-kit/reverify/client";

export const authClient = createAuthClient({
plugins: [
waitlistClient(),
apiKeyClient(),
usernameClient(),
emailOTPClient(),
reverifyClient(),
],
});
43 changes: 32 additions & 11 deletions apps/docs/src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { apiKey, openAPI, organization, username } from "better-auth/plugins";
import { nextCookies } from "better-auth/next-js";
import Database from "better-sqlite3";
import { legalConsent } from "@better-auth-kit/legal-consent";
import { reverify } from "@better-auth-kit/reverify";

export const auth = betterAuth({
database: new Database("./test.db"),
trustedOrigins: ["http://localhost:3000"],
emailAndPassword: {
enabled: true,
},
Expand All @@ -25,27 +27,46 @@ export const auth = betterAuth({
// },
// },
// }),
reverify({
email: {
enabled: true,
sendReverificationEmail(params, ctx) {
if (params.type === "link") {
console.log(
`Send reverification link to ${params.user.email} with url ${params.url}`,
);
} else if (params.type === "otp") {
console.log(
`Send reverification otp to ${params.user.email} with code ${params.code}`,
);
}
},
},
}),
organization(),
openAPI(),
apiKey(),
username(),
nextCookies(),
],
emailVerification: {
sendVerificationEmail: async ({ user, url, token }, request) => {
console.log(
`Send verification email to ${user.email} with url ${url} and token ${token}`,
);
},
},
databaseHooks: {
user: {
create: {
after: async (user, ctx) => {
//@ts-ignore - erroring because `getActiveOrganization` is not defined
const organization = await getActiveOrganization(user.id);
if (!organization) {
auth.api.createOrganization({
body: {
name: "My Organization",
slug: "my-organization",
userId: user.id,
},
});
}
// auth.api.createOrganization({
// body: {
// name: "My Organization",
// slug: "my-organization",
// userId: user.id,
// },
// });
},
},
},
Expand Down
15 changes: 14 additions & 1 deletion bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"version": "0.0.0",
"dependencies": {
"@better-auth-kit/legal-consent": "workspace:*",
"@better-auth-kit/reverify": "workspace:*",
"@better-auth-kit/waitlist": "workspace:*",
"@faker-js/faker": "^9.5.1",
"@hookform/resolvers": "^4.1.3",
Expand Down Expand Up @@ -133,9 +134,19 @@
"@types/prompts": "^2.4.9",
},
},
"packages/internal/utils": {
"name": "@better-auth-kit/internal-utils",
"version": "0.0.1",
"dependencies": {
"bun-plugin-dts": "^0.3.0",
},
"devDependencies": {
"@types/bun": "1.2.4",
},
},
"packages/libraries/seed": {
"name": "@better-auth-kit/seed",
"version": "1.0.2",
"version": "1.0.3",
"dependencies": {
"better-auth": "^1.2.4",
"chalk": "^5.4.1",
Expand Down Expand Up @@ -307,6 +318,8 @@

"@better-auth-kit/convex": ["@better-auth-kit/convex@workspace:packages/adapters/convex"],

"@better-auth-kit/internal-utils": ["@better-auth-kit/internal-utils@workspace:packages/internal/utils"],

"@better-auth-kit/legal-consent": ["@better-auth-kit/legal-consent@workspace:packages/plugins/legal-consent"],

"@better-auth-kit/reverify": ["@better-auth-kit/reverify@workspace:packages/plugins/reverify"],
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"packages/cli",
"packages/plugins/*",
"packages/libraries/*",
"packages/adapters/*"
"packages/adapters/*",
"packages/internal/*"
],
"dependencies": {
"@daveyplate/better-auth-ui": "^1.2.19"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/reverify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}
},
"scripts": {
"dev": "bun build --entrypoints ./src/index.ts --outdir ./dist --target node --format esm --sourcemap=external --minify --packages external --watch",
"dev": "bun build --entrypoints ./src/index.ts ./src/client.ts --outdir ./dist --target node --format esm --sourcemap=external --minify --packages external --watch",
"build": "bun build.ts",
"test": "vitest"
},
Expand Down
5 changes: 4 additions & 1 deletion packages/plugins/reverify/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import type { reverify } from "./index";

type ReverifyPlugin = typeof reverify;

export const reverifyClientPlugin = () => {
export const reverifyClient = () => {
return {
id: "reverify",
$InferServerPlugin: {} as ReturnType<ReverifyPlugin>,
pathMethods: {
"/reverify/password": "POST",
"/reverify/send-email": "POST",
"/reverify/verify-email-otp": "POST",
"/reverify/is-verified": "GET",
},
} satisfies BetterAuthClientPlugin;
};
64 changes: 20 additions & 44 deletions packages/plugins/reverify/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,32 @@
import type { BetterAuthPlugin } from "better-auth";
import {
APIError,
createAuthEndpoint,
sessionMiddleware,
} from "better-auth/api";
import { z } from "zod";
import { reverifyPassword } from "./routes/password";
import { reverifyEmail } from "./routes/email";
import { isVerified } from "./routes/isVerified";
import { emailreverification } from "./schema";
import { mergeSchema } from "better-auth/db";
import type { ReverifyOptions } from "./types";
export * from "./types";

export const ERROR_CODES = {
NO_SESSION: "No session found.",
} as const;

export const reverify = () => {
export const reverify = <EmailEnabled extends boolean = false>(
options: ReverifyOptions<EmailEnabled> = {},
) => {
const { email } = options;

return {
id: "reverify",
endpoints: {
reverifyPassword: createAuthEndpoint(
"/reverify/password",
{
method: "POST",
use: [sessionMiddleware],
body: z.object({
password: z.string(),
}),
},
async (ctx) => {
const session = ctx.context.session;

if (!session) {
throw new APIError("UNAUTHORIZED", {
message: ERROR_CODES.NO_SESSION,
});
}
let validPassword = false;
try {
validPassword = await ctx.context.password.checkPassword(
session.user.id,
ctx,
);
} catch (error: unknown) {
console.error(error);
if (
error instanceof APIError &&
error?.body?.code === "INVALID_PASSWORD"
) {
return ctx.json({ valid: false });
}
throw error;
}

return ctx.json({ valid: validPassword });
},
),
reverifyPassword,
isVerified,
...reverifyEmail<EmailEnabled>({ email }),
},
schema: {
...(email?.enabled
? mergeSchema(emailreverification, options?.email?.schema)
: {}),
},
} satisfies BetterAuthPlugin;
};
Loading