traxxx-web/src/web/server.js

196 lines
5.0 KiB
JavaScript

import config from 'config';
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 { renderPage } from 'vike/server'; // eslint-disable-line import/extensions
// import root from './root.js';
import redis from '../redis.js';
import errorHandler from './error.js';
import { fetchScenesApi } from './scenes.js';
import { fetchActorsApi } from './actors.js';
import { fetchMoviesApi } from './movies.js';
import {
setUserApi,
loginApi,
logoutApi,
signupApi,
} from './auth.js';
import {
fetchUserApi,
} from './users.js';
import {
createStashApi,
removeStashApi,
stashActorApi,
stashSceneApi,
stashMovieApi,
unstashActorApi,
unstashSceneApi,
unstashMovieApi,
updateStashApi,
} from './stashes.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) => {
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);
}
// SESSION
router.post('/api/session', loginApi);
router.delete('/api/session', logoutApi);
// USERS
router.get('/api/users/:userId', fetchUserApi);
router.post('/api/users', signupApi);
// STASHES
router.post('/api/stashes', createStashApi);
router.patch('/api/stashes/:stashId', updateStashApi);
router.delete('/api/stashes/:stashId', removeStashApi);
router.post('/api/stashes/:stashId/actors', stashActorApi);
router.post('/api/stashes/:stashId/scenes', stashSceneApi);
router.post('/api/stashes/:stashId/movies', stashMovieApi);
router.delete('/api/stashes/:stashId/actors/:actorId', unstashActorApi);
router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashSceneApi);
router.delete('/api/stashes/:stashId/movies/:movieId', unstashMovieApi);
// SCENES
router.get('/api/scenes', fetchScenesApi);
// ACTORS
router.get('/api/actors', fetchActorsApi);
// MOVIES
router.get('/api/movies', fetchMoviesApi);
router.get('*', async (req, res, next) => {
const pageContextInit = {
urlOriginal: req.originalUrl,
urlQuery: req.query, // vike's own query does not apply boolean parser
headers: req.headers,
cookies: req.cookies,
tagFilter: req.tagFilter,
user: req.user && {
id: req.user.id,
username: req.user.username,
email: req.user.email,
avatar: req.user.avatar,
stashes: req.user.stashes,
primaryStash: req.user.primaryStash,
},
env: {
allowLogin: config.auth.login,
allowSignup: config.auth.signup,
maxMatches: config.database.manticore.maxMatches,
maxAggregateSize: config.database.manticore.maxAggregateSize,
media: config.media,
},
};
const pageContext = await renderPage(pageContextInit);
const { httpResponse } = pageContext;
if (pageContext.errorWhileRendering) {
console.error(pageContext.errorWhileRendering);
}
if (!httpResponse) {
next();
return;
}
/*
if (res.writeEarlyHints) {
res.writeEarlyHints({ link: httpResponse.earlyHints.map((e) => e.earlyHintLink) });
}
*/
httpResponse.headers.forEach(([name, value]) => res.setHeader(name, value));
res.status(httpResponse.statusCode);
// For HTTP streams use httpResponse.pipe() instead, see https://vike.dev/stream
res.send(httpResponse.body);
});
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}`);
}