231 lines
5.9 KiB
JavaScript
231 lines
5.9 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 { fetchEntitiesApi } from './entities.js';
|
|
import { fetchTagsApi } from './tags.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 {
|
|
fetchAlertsApi,
|
|
createAlertApi,
|
|
removeAlertApi,
|
|
fetchNotificationsApi,
|
|
updateNotificationApi,
|
|
updateNotificationsApi,
|
|
} from './alerts.js';
|
|
|
|
import { fetchUnseenNotificationsCount } 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);
|
|
}
|
|
|
|
// SESSION
|
|
router.post('/api/session', loginApi);
|
|
router.delete('/api/session', logoutApi);
|
|
|
|
// USERS
|
|
router.get('/api/users/:userId', fetchUserApi);
|
|
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);
|
|
|
|
// 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);
|
|
|
|
// ALERTS
|
|
router.get('/api/alerts', fetchAlertsApi);
|
|
router.post('/api/alerts', createAlertApi);
|
|
router.delete('/api/alerts/:alertId', removeAlertApi);
|
|
|
|
// SCENES
|
|
router.get('/api/scenes', fetchScenesApi);
|
|
|
|
// ACTORS
|
|
router.get('/api/actors', fetchActorsApi);
|
|
|
|
// MOVIES
|
|
router.get('/api/movies', fetchMoviesApi);
|
|
|
|
// ENTITIES
|
|
router.get('/api/entities', fetchEntitiesApi);
|
|
|
|
// TAGS
|
|
router.get('/api/tags', fetchTagsApi);
|
|
|
|
router.get('*', async (req, res, next) => {
|
|
const unseenNotifications = await fetchUnseenNotificationsCount(req.user);
|
|
|
|
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,
|
|
},
|
|
meta: {
|
|
unseenNotifications,
|
|
},
|
|
};
|
|
|
|
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}`);
|
|
}
|