tayyabimam's picture
Fresh build completely clean of binaries
35ac985
Raw
History Blame Contribute Delete
2.81 kB
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import path from 'path';
import { fileURLToPath } from 'url';
import { keysRouter } from './routes/keys.js';
import { modelsRouter } from './routes/models.js';
import { proxyRouter } from './routes/proxy.js';
import { fallbackRouter } from './routes/fallback.js';
import { analyticsRouter } from './routes/analytics.js';
import { healthRouter } from './routes/health.js';
import { settingsRouter } from './routes/settings.js';
import { errorHandler } from './middleware/errorHandler.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DEFAULT_DASHBOARD_ORIGINS = [
'http://localhost:5173',
'http://127.0.0.1:5173',
'http://[::1]:5173',
];
function getAllowedCorsOrigins() {
const configuredOrigins = (process.env.DASHBOARD_ORIGINS ?? '')
.split(',')
.map(origin => origin.trim())
.filter(Boolean);
return new Set([...DEFAULT_DASHBOARD_ORIGINS, ...configuredOrigins]);
}
export function createApp() {
const app = express();
const allowedCorsOrigins = getAllowedCorsOrigins();
// CSP intentionally disabled — the SPA bundles inline styles and the OG
// image is loaded from the same origin; enabling helmet's default CSP
// breaks the React build's hashed-asset loader. HSTS off because this is
// a single-user local proxy, served over HTTP on localhost. Both should
// stay disabled unless someone serves the proxy over HTTPS publicly
// (which is also not a supported deployment — see README).
app.use(helmet({ contentSecurityPolicy: false, hsts: false }));
app.use(cors({
origin(origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) {
callback(null, !origin || allowedCorsOrigins.has(origin));
},
}));
app.use(express.json({ limit: '1mb' }));
// API routes
app.use('/api/keys', keysRouter);
app.use('/api/models', modelsRouter);
app.use('/api/fallback', fallbackRouter);
app.use('/api/analytics', analyticsRouter);
app.use('/api/health', healthRouter);
app.use('/api/settings', settingsRouter);
// OpenAI-compatible proxy
app.use('/v1', proxyRouter);
// Health check
app.get('/api/ping', (_req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Error handler (for API routes)
app.use(errorHandler);
// Serve client static files (after API error handler)
const clientDist = path.resolve(__dirname, '../../client/dist');
app.use(express.static(clientDist));
// SPA fallback — serve index.html for non-API routes
app.use((req, res, next) => {
if (req.path.startsWith('/api/') || req.path.startsWith('/v1/')) {
next();
return;
}
res.sendFile(path.join(clientDist, 'index.html'));
});
return app;
}