traxxx-web/src/web/server.js

185 lines
4.6 KiB
JavaScript

import config from 'config';
import path from 'path';
import express from 'express';
import boolParser from 'express-query-boolean';
import Router from 'express-promise-router';
import session from 'express-session';
import RedisStore from 'connect-redis';
import compression from 'compression';
import cookie from 'cookie';
import redis from '../redis.js';
import errorHandler from './error.js';
import consentHandler from './consent.js';
import { scenesRouter } from './scenes.js';
import { actorsRouter } from './actors.js';
import { fetchMoviesApi } from './movies.js';
import { fetchEntitiesApi } from './entities.js';
import { fetchTagsApi } from './tags.js';
import { graphqlApi } from './graphql.js';
import mainHandler from './main.js';
import {
setUserApi,
loginApi,
logoutApi,
signupApi,
fetchUserKeysApi,
createKeyApi,
removeUserKeyApi,
flushUserKeysApi,
} from './auth.js';
import { router as userRouter } from './users.js';
import { router as stashesRouter } from './stashes.js';
import {
fetchAlertsApi,
createAlertApi,
removeAlertApi,
fetchNotificationsApi,
updateNotificationApi,
updateNotificationsApi,
} from './alerts.js';
import initLogger from '../logger.js';
const logger = initLogger();
const isProduction = process.env.NODE_ENV === 'production';
export default async function initServer() {
const app = express();
const router = Router();
app.use(compression());
app.disable('x-powered-by');
router.use(boolParser());
router.use('/', express.static('public'));
router.use('/', express.static('static'));
router.use('/media', express.static(config.media.path));
router.use((req, res, next) => {
if (req.headers.cookie) {
const cookies = cookie.parse(req.headers.cookie);
/* eslint-disable no-param-reassign */
req.cookies = cookies;
req.tagFilter = cookies.tags ? JSON.parse(cookies.tags) : [];
/* eslint-enable no-param-reassign */
}
next();
});
router.use(express.json());
const redisStore = new RedisStore({
client: redis,
prefix: 'traxxx:session:',
});
router.use(session({
...config.web.session,
store: redisStore,
}));
router.use(setUserApi);
// Vite integration
if (isProduction) {
app.enable('trust proxy');
// In production, we need to serve our static assets ourselves.
// (In dev, Vite's middleware serves our static assets.)
const sirv = (await import('sirv')).default;
router.use(sirv('dist/client'));
} else {
// We instantiate Vite's development server and integrate its middleware to our server.
// ⚠️ We instantiate it only in development. (It isn't needed in production and it
// would unnecessarily bloat our production server.)
const vite = await import('vite');
const viteDevMiddleware = (
await vite.createServer({
// root,
server: { middlewareMode: true },
})
).middlewares;
router.use(viteDevMiddleware);
}
router.get('/consent', (req, res) => {
res.sendFile(path.join(import.meta.dirname, '../../assets/consent.html'));
});
// SESSION
router.post('/api/session', loginApi);
router.delete('/api/session', logoutApi);
// USERS
router.post('/api/users', signupApi);
router.get('/api/users/:userId/notifications', fetchNotificationsApi);
router.patch('/api/users/:userId/notifications', updateNotificationsApi);
router.patch('/api/users/:userId/notifications/:notificationId', updateNotificationApi);
// API KEYS
router.get('/api/me/keys', fetchUserKeysApi);
router.post('/api/keys', createKeyApi);
router.delete('/api/me/keys/:keyIdentifier', removeUserKeyApi);
router.delete('/api/me/keys', flushUserKeysApi);
// ALERTS
router.get('/api/alerts', fetchAlertsApi);
router.post('/api/alerts', createAlertApi);
router.delete('/api/alerts/:alertId', removeAlertApi);
router.use(userRouter);
router.use(stashesRouter);
router.use(scenesRouter);
router.use(actorsRouter);
// MOVIES
router.get('/api/movies', fetchMoviesApi);
// ENTITIES
router.get('/api/entities', fetchEntitiesApi);
// TAGS
router.get('/api/tags', fetchTagsApi);
if (config.apiAccess.graphqlEnabled) {
router.post('/graphql', graphqlApi);
}
router.use(consentHandler);
router.use((req, res, next) => {
/* eslint-disable no-param-reassign */
res.set('Accept-CH', 'Sec-CH-Prefers-Color-Scheme');
res.set('Vary', 'Sec-CH-Prefers-Color-Scheme');
res.set('Critical-CH', 'Sec-CH-Prefers-Color-Scheme');
/* eslint-enable no-param-reassign */
next();
});
router.get('*', mainHandler);
router.use(errorHandler);
app.use(router);
const port = process.env.PORT || config.web.port || 3000;
app.listen(port);
logger.info(`Server running at http://localhost:${port}`);
}