102 lines
3.2 KiB
TypeScript
102 lines
3.2 KiB
TypeScript
import { defineConfig, loadEnv } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import path from 'path'
|
|
import fs from 'fs'
|
|
|
|
/** Same default as server when `server/.env` has no PORT (see repo root `mailflow.dev.port.json`). */
|
|
function readMailflowDevPort(): string {
|
|
const f = path.resolve(__dirname, '../mailflow.dev.port.json')
|
|
try {
|
|
const j = JSON.parse(fs.readFileSync(f, 'utf8')) as { port?: number }
|
|
if (j.port != null && Number.isFinite(Number(j.port))) return String(j.port)
|
|
} catch {
|
|
/* missing or invalid */
|
|
}
|
|
return '3030'
|
|
}
|
|
|
|
/** Align Vite proxy with server/.env PORT (client/.env does not load server PORT). */
|
|
function readBackendPortFromServerEnv(): string {
|
|
const envFile = path.resolve(__dirname, '../server/.env')
|
|
try {
|
|
let text = fs.readFileSync(envFile, 'utf8')
|
|
if (text.charCodeAt(0) === 0xfeff) text = text.slice(1)
|
|
for (const line of text.split(/\r?\n/)) {
|
|
if (/^\s*#/.test(line)) continue
|
|
const noComment = line.split('#')[0]?.trim() || ''
|
|
const m = /^\s*PORT\s*=\s*"?(\d+)"?/i.exec(noComment)
|
|
if (m) return m[1]
|
|
}
|
|
} catch {
|
|
/* no server/.env */
|
|
}
|
|
return readMailflowDevPort()
|
|
}
|
|
|
|
/** Origin only (no trailing /api) — matches client api.ts / VITE_DEV_BACKEND_ORIGIN contract. */
|
|
function stripTrailingApiFromOrigin(o: string): string {
|
|
let s = o.replace(/\/$/, '')
|
|
while (s.endsWith('/api')) {
|
|
s = s.slice(0, -4).replace(/\/+$/, '')
|
|
}
|
|
return s
|
|
}
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig(({ mode }) => {
|
|
const env = loadEnv(mode, __dirname, '')
|
|
const appwriteDevOrigin = (env.APPWRITE_DEV_ORIGIN || '').replace(/\/$/, '')
|
|
const defaultApiOrigin = `http://127.0.0.1:${readBackendPortFromServerEnv()}`
|
|
// 127.0.0.1 avoids Windows localhost → IPv6 (::1) vs backend listening on IPv4-only
|
|
const apiDevTarget = stripTrailingApiFromOrigin(env.VITE_DEV_API_ORIGIN || defaultApiOrigin)
|
|
|
|
const proxy: Record<
|
|
string,
|
|
{ target: string; changeOrigin: boolean; secure?: boolean }
|
|
> = {
|
|
'/api': {
|
|
target: apiDevTarget,
|
|
changeOrigin: true,
|
|
},
|
|
'/stripe': {
|
|
target: apiDevTarget,
|
|
changeOrigin: true,
|
|
},
|
|
}
|
|
|
|
// Dev: Browser → localhost:5173/v1/* → Appwrite (umgeht CORS, wenn die Console nur z. B. webklar.com erlaubt)
|
|
if (mode === 'development' && appwriteDevOrigin) {
|
|
proxy['/v1'] = {
|
|
target: appwriteDevOrigin,
|
|
changeOrigin: true,
|
|
secure: true,
|
|
}
|
|
}
|
|
|
|
return {
|
|
// Browser ruft Express direkt an (CORS) — vermeidet 404, wenn der Vite-/api-Proxy nicht greift
|
|
define:
|
|
mode === 'development'
|
|
? {
|
|
'import.meta.env.VITE_DEV_BACKEND_ORIGIN': JSON.stringify(apiDevTarget),
|
|
}
|
|
: {},
|
|
plugins: [react(), tailwindcss()],
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src'),
|
|
},
|
|
},
|
|
server: {
|
|
host: true,
|
|
port: 5173,
|
|
// Wenn 5173 schon belegt ist, nicht still auf einen anderen Port wechseln — sonst öffnet man oft noch die alte URL und bekommt für /api 404.
|
|
strictPort: true,
|
|
proxy,
|
|
},
|
|
// `vite preview` hat standardmäßig keinen Dev-Proxy — sonst wäre /api ein 404.
|
|
preview: { proxy },
|
|
}
|
|
})
|