Added basic shack creation.

This commit is contained in:
DebaucheryLibrarian 2023-06-03 23:32:50 +02:00
parent bc9fec207b
commit de757efc6e
23 changed files with 274 additions and 216 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
node_modules/ node_modules/
dist/ dist/
config/ config/
log/
!config/default.js !config/default.js
assets/js/config/ assets/js/config/
!assets/js/config/default.js !assets/js/config/default.js

View File

@ -26,3 +26,61 @@
2023-05-29 00:35:22 info [server] Server running at 0.0.0.0:7477 2023-05-29 00:35:22 info [server] Server running at 0.0.0.0:7477
2023-05-29 00:42:59 info [redis] Redis module initialized 2023-05-29 00:42:59 info [redis] Redis module initialized
2023-05-29 00:42:59 info [server] Server running at 0.0.0.0:7477 2023-05-29 00:42:59 info [server] Server running at 0.0.0.0:7477
2023-05-29 00:55:18 info [redis] Redis module initialized
2023-05-29 00:55:18 info [server] Server running at 0.0.0.0:7477
2023-05-29 02:07:51 info [redis] Redis module initialized
2023-05-29 02:07:51 info [server] Server running at 0.0.0.0:7477
2023-05-29 02:08:43 info [redis] Redis module initialized
2023-05-29 02:08:43 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:17:42 info [redis] Redis module initialized
2023-05-29 16:17:43 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:18:29 info [redis] Redis module initialized
2023-05-29 16:18:29 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:18:40 info [redis] Redis module initialized
2023-05-29 16:18:40 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:20:45 info [redis] Redis module initialized
2023-05-29 16:20:45 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:26:36 info [redis] Redis module initialized
2023-05-29 16:26:36 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:27:24 info [redis] Redis module initialized
2023-05-29 16:27:25 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:28:06 info [redis] Redis module initialized
2023-05-29 16:28:07 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:28:49 info [redis] Redis module initialized
2023-05-29 16:28:49 info [server] Server running at 0.0.0.0:7477
2023-05-29 16:28:52 warn [error] Failed to fulfill request to /: [vite-plugin-ssr@0.4.126][Wrong Usage] pageContext.httpResponse.body can't be used because the render() hook defined by /renderer/_default.page.server.js > `export { render }` provides a Readable Node.js Stream. Use `pageContext.httpResponse.pipe()` or `pageContext.httpResponse.getBody()` instead. See https://vite-plugin-ssr.com/stream for more information.
2023-05-29 16:28:52 error [error] Error: [vite-plugin-ssr@0.4.126][Wrong Usage] pageContext.httpResponse.body can't be used because the render() hook defined by /renderer/_default.page.server.js > `export { render }` provides a Readable Node.js Stream. Use `pageContext.httpResponse.pipe()` or `pageContext.httpResponse.getBody()` instead. See https://vite-plugin-ssr.com/stream for more information.
at get body [as body] (/home/niels/Projects/shack/node_modules/vite-plugin-ssr/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js:51:41)
at defaultHandler (file:///home/niels/Projects/shack/src/web/default.js:19:4)
2023-05-29 16:42:10 warn [error] Failed to fulfill request to /: [vite-plugin-ssr@0.4.126][Wrong Usage] pageContext.httpResponse.body can't be used because the render() hook defined by /renderer/_default.page.server.js > `export { render }` provides a Readable Node.js Stream. Use `pageContext.httpResponse.pipe()` or `pageContext.httpResponse.getBody()` instead. See https://vite-plugin-ssr.com/stream for more information.
2023-05-29 16:42:10 error [error] Error: [vite-plugin-ssr@0.4.126][Wrong Usage] pageContext.httpResponse.body can't be used because the render() hook defined by /renderer/_default.page.server.js > `export { render }` provides a Readable Node.js Stream. Use `pageContext.httpResponse.pipe()` or `pageContext.httpResponse.getBody()` instead. See https://vite-plugin-ssr.com/stream for more information.
at get body [as body] (/home/niels/Projects/shack/node_modules/vite-plugin-ssr/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js:51:41)
at defaultHandler (file:///home/niels/Projects/shack/src/web/default.js:19:4)
2023-05-29 16:43:01 info [redis] Redis module initialized
2023-05-29 16:43:01 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:00:19 info [redis] Redis module initialized
2023-05-29 17:00:20 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:00:45 info [redis] Redis module initialized
2023-05-29 17:00:45 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:01:19 info [redis] Redis module initialized
2023-05-29 17:01:19 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:03:49 info [redis] Redis module initialized
2023-05-29 17:03:49 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:14:16 info [redis] Redis module initialized
2023-05-29 17:14:17 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:15:52 info [redis] Redis module initialized
2023-05-29 17:15:52 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:27:43 info [redis] Redis module initialized
2023-05-29 17:27:44 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:29:14 info [redis] Redis module initialized
2023-05-29 17:29:14 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:29:33 info [redis] Redis module initialized
2023-05-29 17:29:33 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:32:52 info [redis] Redis module initialized
2023-05-29 17:32:52 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:37:32 info [redis] Redis module initialized
2023-05-29 17:37:32 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:45:26 info [redis] Redis module initialized
2023-05-29 17:45:26 info [server] Server running at 0.0.0.0:7477
2023-05-29 17:49:05 info [redis] Redis module initialized
2023-05-29 17:49:05 info [server] Server running at 0.0.0.0:7477

28
package-lock.json generated
View File

@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "shack",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@babel/cli": "^7.21.5", "@babel/cli": "^7.21.5",
@ -21,6 +22,7 @@
"config": "^3.3.9", "config": "^3.3.9",
"connect-redis": "^7.1.0", "connect-redis": "^7.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"error-stack-parser": "^2.1.4",
"eslint": "^8.41.0", "eslint": "^8.41.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-vue": "^9.14.0", "eslint-plugin-vue": "^9.14.0",
@ -3530,6 +3532,14 @@
"url": "https://github.com/fb55/entities?sponsor=1" "url": "https://github.com/fb55/entities?sponsor=1"
} }
}, },
"node_modules/error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"dependencies": {
"stackframe": "^1.3.4"
}
},
"node_modules/errors": { "node_modules/errors": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz", "resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz",
@ -6808,6 +6818,11 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
},
"node_modules/statuses": { "node_modules/statuses": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@ -10228,6 +10243,14 @@
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
}, },
"error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"requires": {
"stackframe": "^1.3.4"
}
},
"errors": { "errors": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz", "resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz",
@ -12564,6 +12587,11 @@
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
}, },
"stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
},
"statuses": { "statuses": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",

View File

@ -3,6 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"description": "Shack is a self-hosted social news aggregate", "description": "Shack is a self-hosted social news aggregate",
"main": "src/web/server.js", "main": "src/web/server.js",
"type": "module",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitea.unknown.name/DebaucheryLibrarian/shack" "url": "https://gitea.unknown.name/DebaucheryLibrarian/shack"
@ -17,7 +18,7 @@
"dev": "npm run server", "dev": "npm run server",
"prod": "npm run build && npm run server:prod", "prod": "npm run build && npm run server:prod",
"build": "vite build", "build": "vite build",
"server": "node ./src/web/server", "server": "node --experimental-specifier-resolution=node ./src/web/server",
"server:prod": "cross-env NODE_ENV=production node ./src/web/server", "server:prod": "cross-env NODE_ENV=production node ./src/web/server",
"migrate-make": "knex-migrate generate", "migrate-make": "knex-migrate generate",
"migrate": "knex-migrate up", "migrate": "knex-migrate up",
@ -38,6 +39,7 @@
"config": "^3.3.9", "config": "^3.3.9",
"connect-redis": "^7.1.0", "connect-redis": "^7.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"error-stack-parser": "^2.1.4",
"eslint": "^8.41.0", "eslint": "^8.41.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-vue": "^9.14.0", "eslint-plugin-vue": "^9.14.0",

View File

@ -21,5 +21,22 @@
class="link" class="link"
>Sign up</a></li> >Sign up</a></li>
</ul> </ul>
<ul>
<li
v-for="shelf in shelves"
:key="shelf.id"
><a
:href="`/s/${shelf.slug}`"
class="link"
>{{ shelf.slug }}</a></li>
</ul>
</div> </div>
</template> </template>
<script setup>
import { usePageContext } from '../../renderer/usePageContext';
const { pageData } = usePageContext();
const { shelves } = pageData;
</script>

View File

@ -1,71 +0,0 @@
<template>
<div class="content">
<a
href="/"
class="link"
>Go back home</a>
<h3>{{ shuck }}</h3>
<form
class="form compose"
@submit.prevent="submitPost"
>
<div class="form-row">
<input
v-model="title"
placeholder="Title"
class="input"
>
</div>
<div class="form-row">
<input
v-model="link"
class="input"
placeholder="Link"
>
</div>
<div class="form-row">
<textarea
v-model="body"
placeholder="Body"
class="input body"
/>
</div>
<div class="form-actions">
<button class="button button-submit">Post</button>
</div>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
const shuck = 'Eratic';
// const route = useRoute();
// const res = await useFetch(`/api/shucks/${route.params.id}/posts`);
const title = ref();
const link = ref();
const body = ref();
async function submitPost() {
console.log('POST', link.value);
/*
await useFetch(`/api/shucks/${route.params.id}/posts`, {
method: 'post',
body: {
title,
link,
body,
},
});
*/
}
</script>

View File

@ -1,35 +1,20 @@
import { renderToString as renderToString_ } from '@vue/server-renderer'; // import { renderToString as renderToString_ } from '@vue/server-renderer';
import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr/server'; import { renderToNodeStream } from '@vue/server-renderer';
import { escapeInject } from 'vite-plugin-ssr/server';
import { createApp } from './app'; import { createApp } from './app';
import { useUser } from '../stores/user'; import { useUser } from '../stores/user';
import logoUrl from './logo.svg'; import logoUrl from './logo.svg';
async function renderToString(app) {
let err;
// Workaround: renderToString_() swallows errors in production, see https://github.com/vuejs/core/issues/7876
app.config.errorHandler = (err_) => { // eslint-disable-line no-param-reassign
err = err_;
};
const appHtml = await renderToString_(app);
if (err) {
throw err;
}
return appHtml;
}
async function render(pageContext) { async function render(pageContext) {
const appHtml = await renderToString(pageContext.app);
// See https://vite-plugin-ssr.com/head // See https://vite-plugin-ssr.com/head
const { documentProps } = pageContext.exports; const { documentProps } = pageContext.exports;
const title = (documentProps && documentProps.title) || 'shack'; const title = (documentProps && documentProps.title) || 'shack';
const desc = (documentProps && documentProps.description) || 'Shack'; const desc = (documentProps && documentProps.description) || 'Shack';
const { app, store } = createApp(pageContext);
const stream = renderToNodeStream(app);
const documentHtml = escapeInject` const documentHtml = escapeInject`
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -41,40 +26,26 @@ async function render(pageContext) {
<title>${title}</title> <title>${title}</title>
</head> </head>
<body> <body>
<div id="app">${dangerouslySkipEscape(appHtml)}</div> <div id="app">${stream}</div>
</body> </body>
</html> </html>
`; `;
return {
documentHtml,
};
}
async function onBeforeRender(pageContext) {
if (!pageContext.Page) {
throw new Error('My render() hook expects pageContext.Page to be defined');
}
const { app, store } = createApp(pageContext);
const userStore = useUser(); const userStore = useUser();
userStore.user = pageContext.session.user; userStore.user = pageContext.session.user;
return { return {
documentHtml,
pageContext: { pageContext: {
app,
initialState: store.state.value, initialState: store.state.value,
pageData: { enableEagerStreaming: true,
user: pageContext.session.user,
},
}, },
}; };
} }
export { export {
render, render,
onBeforeRender,
}; };
export const passToClient = ['urlPathname', 'initialState', 'pageData']; export const passToClient = ['urlPathname', 'initialState', 'pageData', 'pageProps'];

View File

@ -1,14 +1,24 @@
<template> <template>
<div class="content">
<div v-if="is404"> <div v-if="is404">
<h1>404 Page Not Found</h1> <h1>404 Page Not Found</h1>
<p>This page could not be found.</p>
<p v-if="errorInfo">{{ errorInfo }}</p>
<p v-else>This page could not be found.</p>
</div> </div>
<div v-else> <div v-else>
<h1>500 Internal Error</h1> <h1>500 Internal Error</h1>
<p>Something went wrong.</p>
<p v-if="errorInfo">{{ errorInfo }}</p>
<p v-else>Something went wrong.</p>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps(['is404']) import { usePageContext } from './usePageContext';
const { pageProps } = usePageContext();
const { is404, errorInfo } = pageProps;
</script> </script>

View File

@ -49,7 +49,7 @@ const { user } = storeToRefs(userStore);
async function logout() { async function logout() {
await del('/api/session'); await del('/api/session');
window.location.reload(); window.location.href = '/account/login';
} }
</script> </script>

View File

@ -4,7 +4,7 @@
"parserOptions": { "parserOptions": {
"parser": "@babel/eslint-parser", "parser": "@babel/eslint-parser",
"ecmaVersion": 2019, "ecmaVersion": 2019,
"sourceType": "script", "sourceType": "module",
"requireConfigFile": false "requireConfigFile": false
}, },
"rules": { "rules": {

View File

@ -1,5 +1,5 @@
// const config = require('config'); // import config from 'config';
const yargs = require('yargs'); import yargs from 'yargs';
const { argv } = yargs const { argv } = yargs
.command('npm start') .command('npm start')
@ -8,4 +8,4 @@ const { argv } = yargs
type: 'string', type: 'string',
}); });
module.exports = argv; export default argv;

View File

@ -9,4 +9,4 @@ class HttpError extends Error {
} }
} }
module.exports = { HttpError }; export { HttpError };

View File

@ -1,7 +1,7 @@
const config = require('config'); import config from 'config';
const knex = require('knex'); import knex from 'knex';
module.exports = knex({ export default knex({
client: 'pg', client: 'pg',
connection: config.database, connection: config.database,
// performance overhead, don't use asyncStackTraces in production // performance overhead, don't use asyncStackTraces in production

View File

@ -1,13 +1,14 @@
const util = require('util'); import util from 'util';
const path = require('path'); import path from 'path';
const winston = require('winston'); import * as winston from 'winston';
import 'winston-daily-rotate-file';
require('winston-daily-rotate-file'); import stackParser from 'error-stack-parser';
// import args from './args'; // import args from './args';
module.exports = function initLogger(filepath) { export default function initLogger(customLabel) {
const contextLabel = path.basename(filepath, '.js'); const filepath = stackParser.parse(new Error())[1]?.fileName;
const contextLabel = customLabel || path.basename(filepath, '.js');
return winston.createLogger({ return winston.createLogger({
format: winston.format.combine( format: winston.format.combine(
@ -32,4 +33,4 @@ module.exports = function initLogger(filepath) {
}), }),
], ],
}); });
}; }

View File

@ -1,6 +1,9 @@
const config = require('config'); import config from 'config';
const redis = require('redis'); import redis from 'redis';
const logger = require('./logger')(__filename);
import initLogger from './logger';
const logger = initLogger();
const client = redis.createClient({ const client = redis.createClient({
socket: config.redis, socket: config.redis,
@ -9,6 +12,4 @@ const client = redis.createClient({
client.connect(); client.connect();
logger.info('Redis module initialized'); logger.info('Redis module initialized');
module.exports = { export { client };
client,
};

View File

@ -1,17 +1,54 @@
const knex = require('./knex'); import knex from './knex';
async function createShelf(shelf) { function curateDatabaseShelf(shelf) {
console.log('create', shelf); if (!shelf) {
return null;
}
const shelfEntry = await knex('shelves').insert({ return {
id: shelf.id,
slug: shelf.slug, slug: shelf.slug,
}); };
}
async function fetchShelf(shelfId) {
const shelfEntry = await knex('shelves')
.where((builder) => {
const id = Number(shelfId);
if (Number.isNaN(id)) {
builder.where('slug', shelfId);
return;
}
builder.where('id', shelfId);
})
.first();
return curateDatabaseShelf(shelfEntry);
}
async function fetchShelves({ limit = 10 } = {}) {
const shelfEntries = await knex('shelves').limit(limit);
return shelfEntries.map((shelfEntry) => curateDatabaseShelf(shelfEntry));
}
async function createShelf(shelf, user) {
const shelfEntry = await knex('shelves')
.insert({
slug: shelf.slug,
founder_id: user.id,
})
.returning('*');
console.log('entry', shelfEntry); console.log('entry', shelfEntry);
return true; return curateDatabaseShelf(shelfEntry);
} }
module.exports = { export {
fetchShelf,
fetchShelves,
createShelf, createShelf,
}; };

View File

@ -1,12 +1,13 @@
const config = require('config'); import config from 'config';
const util = require('util'); import util from 'util';
const crypto = require('crypto'); import crypto from 'crypto';
const bhttp = require('bhttp'); import bhttp from 'bhttp';
const logger = require('./logger')(__filename); import initLogger from './logger';
const { HttpError } = require('./errors'); import { HttpError } from './errors';
const knex = require('./knex'); import knex from './knex';
const logger = initLogger();
const scrypt = util.promisify(crypto.scrypt); const scrypt = util.promisify(crypto.scrypt);
function curateDatabaseUser(user) { function curateDatabaseUser(user) {
@ -141,7 +142,7 @@ async function createUser(credentials, context) {
} }
} }
module.exports = { export {
createUser, createUser,
login, login,
}; };

View File

@ -1,6 +1,6 @@
const { renderPage } = require('vite-plugin-ssr/server'); import { renderPage } from 'vite-plugin-ssr/server';
async function initDefaultHandler() { export default async function initDefaultHandler() {
async function defaultHandler(req, res, next) { async function defaultHandler(req, res, next) {
const pageContextInit = { const pageContextInit = {
urlOriginal: req.originalUrl, urlOriginal: req.originalUrl,
@ -16,9 +16,13 @@ async function initDefaultHandler() {
} }
const { const {
body, statusCode, contentType, earlyHints, statusCode, contentType, earlyHints,
} = httpResponse; } = httpResponse;
const body = await httpResponse.getBody();
console.log(pageContext.pageData);
if (res.writeEarlyHints) { if (res.writeEarlyHints) {
res.writeEarlyHints({ link: earlyHints.map((e) => e.earlyHintLink) }); res.writeEarlyHints({ link: earlyHints.map((e) => e.earlyHintLink) });
} }
@ -28,5 +32,3 @@ async function initDefaultHandler() {
return defaultHandler; return defaultHandler;
} }
module.exports = initDefaultHandler;

View File

@ -1,6 +1,8 @@
const logger = require('../logger')(__filename); import initLogger from '../logger';
function errorHandler(error, req, res, _next) { const logger = initLogger();
export default function errorHandler(error, req, res, _next) {
logger.warn(`Failed to fulfill request to ${req.path}: ${error.message}`); logger.warn(`Failed to fulfill request to ${req.path}: ${error.message}`);
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
@ -18,5 +20,3 @@ function errorHandler(error, req, res, _next) {
res.status(500).send('Something didn\'t quite go as expected... Our apologies for the inconvenience.'); res.status(500).send('Something didn\'t quite go as expected... Our apologies for the inconvenience.');
} }
module.exports = errorHandler;

View File

@ -1,6 +1,6 @@
const IPCIDR = require('ip-cidr'); import IPCIDR from 'ip-cidr';
function setIp(req, res, next) { export default function setIp(req, res, next) {
const ip = req.headers['x-forwarded-for'] const ip = req.headers['x-forwarded-for']
? req.headers['x-forwarded-for'].split(',')[0] ? req.headers['x-forwarded-for'].split(',')[0]
: req.connection.remoteAddress; : req.connection.remoteAddress;
@ -14,5 +14,3 @@ function setIp(req, res, next) {
next(); next();
} }
module.exports = setIp;

View File

@ -1,32 +1,31 @@
// Note that this file isn't processed by Vite, see https://github.com/brillout/vite-plugin-ssr/issues/562 import config from 'config';
const config = require('config'); import express from 'express';
const express = require('express'); import Router from 'express-promise-router';
const Router = require('express-promise-router'); import bodyParser from 'body-parser';
const session = require('express-session'); import session from 'express-session';
const RedisStore = require('connect-redis').default; import RedisStore from 'connect-redis';
const bodyParser = require('body-parser'); import compression from 'compression';
const compression = require('compression'); import sirv from 'sirv';
const sirv = require('sirv'); import * as vite from 'vite';
const vite = require('vite');
const logger = require('../logger')(__filename); import { client as redis } from '../redis';
const redis = require('../redis').client;
const initDefaultHandler = require('./default'); import initLogger from '../logger';
import initDefaultHandler from './default';
import setIp from './ip';
import errorHandler from './error';
const setIp = require('./ip'); import {
const errorHandler = require('./error'); setUser,
const {
login, login,
logout, logout,
fetchUser, fetchUser,
createUser, createUser,
} = require('./users'); } from './users';
const { createShelf } = require('./shelves'); import { createShelf } from './shelves';
const root = `${__dirname}/../..`; const logger = initLogger();
async function startServer() { async function startServer() {
const app = express(); const app = express();
@ -38,16 +37,17 @@ async function startServer() {
app.disable('x-powered-by'); app.disable('x-powered-by');
app.set('trust proxy', 1); app.set('trust proxy', 1);
router.use(session({ ...config.web.session, store: sessionStore }));
router.use(setIp);
router.use(bodyParser.json({ strict: false }));
app.use(compression()); app.use(compression());
router.use(session({ ...config.web.session, store: sessionStore }));
router.use(setIp);
router.use(setUser);
router.use(bodyParser.json({ strict: false }));
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
app.use(sirv(`${root}/dist/client`)); app.use(sirv('dist/client'));
} else { } else {
const viteDevMiddleware = (await vite.createServer({ const viteDevMiddleware = (await vite.createServer({
root,
server: { middlewareMode: true }, server: { middlewareMode: true },
})).middlewares; })).middlewares;

View File

@ -1,13 +1,11 @@
const { createShelf } = require('../shelves'); import { createShelf } from '../shelves';
async function createShelfApi(req) { async function createShelfApi(req) {
console.log('create shelf', req.body); const shelf = await createShelf(req.body, req.user);
const shelf = await createShelf(req.body);
return shelf; return shelf;
} }
module.exports = { export {
createShelf: createShelfApi, createShelfApi as createShelf,
}; };

View File

@ -1,7 +1,10 @@
const { import { login, createUser } from '../users';
login,
createUser, async function setUser(req, res, next) {
} = require('../users'); req.user = req.session.user; // eslint-disable-line no-param-reassign
next();
}
async function fetchUserApi(req, res) { async function fetchUserApi(req, res) {
res.send(req.session.user); res.send(req.session.user);
@ -25,9 +28,10 @@ async function createUserApi(req, res) {
res.send(user); res.send(user);
} }
module.exports = { export {
login: loginApi, setUser,
logout: logoutApi, loginApi as login,
fetchUser: fetchUserApi, logoutApi as logout,
createUser: createUserApi, fetchUserApi as fetchUser,
createUserApi as createUser,
}; };