mirror of
https://dev.azure.com/tstanciu94/PhantomMind/_git/Bitip
synced 2025-10-13 01:52:19 +03:00
- Changed main entry point from `index.js` to `server.js` in package.json. - Created a new `app.ts` file to encapsulate Express app configuration. - Removed old `index.ts` file and moved server logic to `server.ts`. - Updated nodemon configurations to point to the new `server.ts`. - Added new middleware for API key authentication with public endpoint support. - Modified validators to accept any string for IPs, allowing handlers to determine validity. - Added integration tests for batch lookup and health endpoints. - Implemented unit tests for error handling and validation middleware. - Updated `tsup` and `vitest` configurations to reflect new entry points and testing setup.
104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
// Copyright (c) 2025 Tudor Stanciu
|
|
|
|
import express from 'express';
|
|
import cors from 'cors';
|
|
import helmet from 'helmet';
|
|
import compression from 'compression';
|
|
import path from 'path';
|
|
import apiRoutes from './routes/api';
|
|
import apiKeyAuth from './middleware/auth';
|
|
import dynamicRateLimit from './middleware/rateLimit';
|
|
import { errorHandler } from './middleware/errorHandler';
|
|
import config from './services/config';
|
|
import logger from './services/logger';
|
|
import { generateRuntimeConfig } from './services/runtimeConfig';
|
|
import { healthCheckHandler } from './handlers/healthHandler';
|
|
import { paths } from './utils/paths';
|
|
|
|
/**
|
|
* Creates and configures the Express application
|
|
* This factory function allows the app to be created without starting the server
|
|
* Useful for testing and modular architecture
|
|
*/
|
|
export const createApp = (): express.Express => {
|
|
const app = express();
|
|
|
|
// Security middleware
|
|
app.use(
|
|
helmet({
|
|
contentSecurityPolicy: config.enableHttpsSecurity
|
|
? {
|
|
directives: {
|
|
defaultSrc: ["'self'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
|
|
scriptSrc: ["'self'"],
|
|
imgSrc: ["'self'", 'data:', 'https:'],
|
|
connectSrc: ["'self'"],
|
|
fontSrc: ["'self'"],
|
|
objectSrc: ["'none'"],
|
|
mediaSrc: ["'self'"],
|
|
frameSrc: ["'none'"],
|
|
},
|
|
}
|
|
: false,
|
|
strictTransportSecurity: config.enableHttpsSecurity,
|
|
crossOriginOpenerPolicy: config.enableHttpsSecurity,
|
|
crossOriginResourcePolicy: config.enableHttpsSecurity,
|
|
originAgentCluster: false, // Disable Origin-Agent-Cluster header to avoid browser warnings
|
|
})
|
|
);
|
|
|
|
app.use(
|
|
cors({
|
|
origin: process.env.NODE_ENV === 'production' ? false : true,
|
|
credentials: true,
|
|
})
|
|
);
|
|
|
|
app.use(compression());
|
|
app.use(express.json({ limit: '10mb' }));
|
|
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
|
|
// Request logging
|
|
app.use((req, res, next) => {
|
|
logger.debug('Incoming request', {
|
|
method: req.method,
|
|
path: req.path,
|
|
ip: req.ip,
|
|
userAgent: req.headers['user-agent'],
|
|
});
|
|
next();
|
|
});
|
|
|
|
// Apply base path if configured
|
|
const basePath = config.basePath.endsWith('/')
|
|
? config.basePath.slice(0, -1)
|
|
: config.basePath;
|
|
|
|
// Serve static frontend files
|
|
const frontendPath = paths.frontendDir;
|
|
|
|
// Generate runtime configuration (env.js) at startup
|
|
generateRuntimeConfig(frontendPath, basePath);
|
|
|
|
// Health check endpoint at root (always accessible for Docker HEALTHCHECK)
|
|
app.get('/api/health', healthCheckHandler);
|
|
|
|
// API routes with authentication and rate limiting
|
|
app.use(`${basePath}/api`, apiKeyAuth, dynamicRateLimit, apiRoutes);
|
|
|
|
// Serve static frontend files
|
|
app.use(basePath, express.static(frontendPath));
|
|
|
|
// Fallback to index.html for client-side routing (Express 5 syntax)
|
|
// Named wildcard required in path-to-regexp v8: /*path matches any path
|
|
app.get(`${basePath}/*path`, (_req, res): void => {
|
|
res.sendFile(path.join(frontendPath, 'index.html'));
|
|
});
|
|
|
|
// Global error handler (must be last middleware)
|
|
app.use(errorHandler);
|
|
|
|
return app;
|
|
};
|