feat(api): drive CORS + trusted origins from CORS_ORIGINS env
Phone/LAN testing previously required editing both app.ts (cors origin) and auth.ts (better-auth trustedOrigins). Now both read env.WEB_ORIGINS, parsed from a comma-separated CORS_ORIGINS env var (default http://localhost:5173). To test from a phone, set CORS_ORIGINS to include the LAN origin and restart the API — no code edit. Documented in .env.example. Also fixed the worker README (db:migrate creates ./data/app.db, not ./.tmp; phone step now uses CORS_ORIGINS). API tests 36/36 green; typecheck clean.
This commit is contained in:
@@ -2,3 +2,8 @@ DATABASE_URL=file:./data/app.db
|
||||
BETTER_AUTH_SECRET=change-me-to-a-long-random-string
|
||||
BETTER_AUTH_URL=http://localhost:3000
|
||||
PORT=3000
|
||||
|
||||
# Comma-separated browser origins allowed for CORS + better-auth (the worker SPA).
|
||||
# Add your phone's LAN origin to test on a device — no code edit needed, e.g.:
|
||||
# CORS_ORIGINS=http://localhost:5173,http://192.168.1.50:5173
|
||||
CORS_ORIGINS=http://localhost:5173
|
||||
|
||||
@@ -5,13 +5,14 @@ import { me } from './routes/me';
|
||||
import { activitiesRoutes } from './routes/activities';
|
||||
import { sessionsRoutes } from './routes/sessions';
|
||||
import { auth } from './auth';
|
||||
import { env } from './env';
|
||||
|
||||
export function createApp(): Hono {
|
||||
const app = new Hono();
|
||||
app.use(
|
||||
'/api/*',
|
||||
cors({
|
||||
origin: ['http://localhost:5173'],
|
||||
origin: env.WEB_ORIGINS,
|
||||
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowHeaders: ['Content-Type', 'Authorization'],
|
||||
exposeHeaders: ['set-auth-token'], // so the SPA can read the bearer token on sign-in
|
||||
|
||||
@@ -8,7 +8,7 @@ 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', 'http://localhost:5173'],
|
||||
trustedOrigins: [env.BETTER_AUTH_URL, 'http://localhost:3000', ...env.WEB_ORIGINS],
|
||||
database: drizzleAdapter(db, { provider: 'sqlite', schema }),
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
const webOrigins = process.env.CORS_ORIGINS?.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
export const env = {
|
||||
DATABASE_URL: process.env.DATABASE_URL ?? 'file:./data/app.db',
|
||||
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET ?? 'dev-insecure-secret-change-me',
|
||||
BETTER_AUTH_URL: process.env.BETTER_AUTH_URL ?? 'http://localhost:3000',
|
||||
PORT: Number(process.env.PORT ?? 3000),
|
||||
// Browser origins allowed for CORS + better-auth trustedOrigins. Set CORS_ORIGINS to a
|
||||
// comma-separated list (e.g. "http://localhost:5173,http://192.168.1.50:5173") to let a
|
||||
// phone on the LAN reach the API — no code edit needed. Defaults to the local Vite origin.
|
||||
WEB_ORIGINS: webOrigins && webOrigins.length ? webOrigins : ['http://localhost:5173'],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user