diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index 74548e7..e64e029 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -1,8 +1,10 @@ import { Hono } from 'hono'; import { health } from './routes/health'; +import { auth } from './auth'; export function createApp(): Hono { const app = new Hono(); app.route('/', health); + app.on(['POST', 'GET'], '/api/auth/*', (c) => auth.handler(c.req.raw)); return app; } diff --git a/apps/api/src/auth.ts b/apps/api/src/auth.ts new file mode 100644 index 0000000..86cf5ba --- /dev/null +++ b/apps/api/src/auth.ts @@ -0,0 +1,18 @@ +import { betterAuth } from 'better-auth'; +import { drizzleAdapter } from 'better-auth/adapters/drizzle'; +import { bearer } from 'better-auth/plugins'; +import { db } from './db/client'; +import * as schema from './db/schema'; +import { env } from './env'; + +export const auth = betterAuth({ + secret: env.BETTER_AUTH_SECRET, + baseURL: env.BETTER_AUTH_URL, + trustedOrigins: [env.BETTER_AUTH_URL, 'http://localhost:3000'], + database: drizzleAdapter(db, { provider: 'sqlite', schema }), + emailAndPassword: { + enabled: true, + requireEmailVerification: false, + }, + plugins: [bearer()], +}); diff --git a/apps/api/test/auth.test.ts b/apps/api/test/auth.test.ts new file mode 100644 index 0000000..f915ffa --- /dev/null +++ b/apps/api/test/auth.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect } from 'vitest'; +import { createApp } from '../src/app'; + +const json = { 'content-type': 'application/json' }; + +describe('auth', () => { + it('signs a user up and signs them in, returning a bearer token', async () => { + const app = createApp(); + const creds = { email: 'worker@example.com', password: 'sterk-wachtwoord-123', name: 'Worker' }; + + const signup = await app.request('/api/auth/sign-up/email', { + method: 'POST', + headers: json, + body: JSON.stringify(creds), + }); + expect(signup.status).toBe(200); + + const signin = await app.request('/api/auth/sign-in/email', { + method: 'POST', + headers: json, + body: JSON.stringify({ email: creds.email, password: creds.password }), + }); + expect(signin.status).toBe(200); + + const token = signin.headers.get('set-auth-token'); + expect(token).toBeTruthy(); + }); +});