Initial push

This commit is contained in:
2026-03-08 15:49:34 +01:00
parent 8da12bb7d1
commit 47127f276d
101 changed files with 13844 additions and 8 deletions

108
lib/auth/index.ts Normal file
View File

@@ -0,0 +1,108 @@
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { organization } from "better-auth/plugins";
import { magicLink } from "better-auth/plugins/magic-link";
import { db } from "@/lib/db";
import * as schema from "@/lib/db/schema";
const isProduction = process.env.NODE_ENV === "production";
export const auth = betterAuth({
// -------------------------------------------------------------------------
// Core
// -------------------------------------------------------------------------
secret: process.env.BETTER_AUTH_SECRET!,
baseURL: process.env.BETTER_AUTH_URL ?? "http://localhost:3000",
// -------------------------------------------------------------------------
// Database adapter (Drizzle + bun:sqlite)
// -------------------------------------------------------------------------
database: drizzleAdapter(db, {
provider: "sqlite",
schema: {
users: schema.users,
sessions: schema.sessions,
accounts: schema.accounts,
verifications: schema.verifications,
},
usePlural: false,
}),
// -------------------------------------------------------------------------
// Custom user fields
// -------------------------------------------------------------------------
user: {
additionalFields: {
role: {
type: "string",
required: false,
defaultValue: "moderator",
input: false, // Not settable by the user directly
},
},
},
// -------------------------------------------------------------------------
// Email + password authentication
// -------------------------------------------------------------------------
emailAndPassword: {
enabled: true,
requireEmailVerification: false,
minPasswordLength: 8,
maxPasswordLength: 128,
},
// -------------------------------------------------------------------------
// Plugins
// -------------------------------------------------------------------------
plugins: [
// Organization / role support
organization(),
// Magic link — used for invitation acceptance flows
magicLink({
expiresIn: 60 * 60, // 1 hour
disableSignUp: true, // magic links are only for invited users
sendMagicLink: async ({ email, url, token }) => {
// Delegate to the application's email module. The email module is
// responsible for importing and calling Resend (or whichever mailer
// is configured). We do a dynamic import so that this file does not
// pull in email dependencies at auth-initialisation time on the edge.
const { sendMagicLinkEmail } = await import("@/lib/email/index");
await sendMagicLinkEmail({ email, url, token });
},
}),
],
// -------------------------------------------------------------------------
// Trusted origins — allow env-configured list plus localhost in dev
// -------------------------------------------------------------------------
trustedOrigins: process.env.BETTER_AUTH_TRUSTED_ORIGINS
? process.env.BETTER_AUTH_TRUSTED_ORIGINS.split(",").map((o) => o.trim())
: ["http://localhost:3000"],
// -------------------------------------------------------------------------
// Cookie / session security
// -------------------------------------------------------------------------
advanced: {
useSecureCookies: isProduction,
defaultCookieAttributes: {
httpOnly: true,
secure: isProduction,
sameSite: "strict",
path: "/",
},
},
});
// ---------------------------------------------------------------------------
// Type helpers for use across the application
// ---------------------------------------------------------------------------
export type Auth = typeof auth;
/** The server-side session type returned by auth.api.getSession */
export type Session = typeof auth.$Infer.Session.session;
/** The user type embedded in every session */
export type User = typeof auth.$Infer.Session.user;