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'],
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ Two processes: the API on `:3000` and the worker SPA on `:5173`.
|
||||
From the repo root:
|
||||
|
||||
```bash
|
||||
yarn workspace @solelog/api db:migrate # apply migrations (creates ./.tmp DB on first run)
|
||||
yarn workspace @solelog/api db:migrate # apply migrations (creates ./data/app.db on first run)
|
||||
yarn workspace @solelog/api db:seed # idempotent: seeds the reference activities
|
||||
yarn workspace @solelog/api start # Hono server on http://localhost:3000
|
||||
```
|
||||
@@ -58,10 +58,14 @@ connected to the same Wi-Fi:
|
||||
```
|
||||
|
||||
(On Windows PowerShell: `$env:VITE_API_URL='http://<PC-LAN-IP>:3000'; yarn workspace @solelog/worker dev`.)
|
||||
4. Add that origin (`http://<PC-LAN-IP>:5173`) to the API's CORS `origin` list
|
||||
(`apps/api/src/app.ts`) **and** to better-auth `trustedOrigins` (`apps/api/src/auth.ts`), then
|
||||
restart the API — otherwise the cross-origin sign-in is blocked and the SPA cannot read the
|
||||
`set-auth-token` response header.
|
||||
4. Allow that origin on the API by setting `CORS_ORIGINS` when you start it — **no code edit**:
|
||||
|
||||
```bash
|
||||
CORS_ORIGINS=http://localhost:5173,http://<PC-LAN-IP>:5173 yarn workspace @solelog/api start
|
||||
```
|
||||
|
||||
(PowerShell: `$env:CORS_ORIGINS='http://localhost:5173,http://<PC-LAN-IP>:5173'; yarn workspace @solelog/api start`.)
|
||||
Otherwise the cross-origin sign-in is blocked and the SPA cannot read the `set-auth-token` header.
|
||||
|
||||
No firewall punch-through, VPN, or tunnel is involved — just the LAN.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user