refactor: use fastify vite for the dev server (#284)
* refactor: use fastify vite for the server by doing this we do not need to have local hacks for the routes. No local proxy needed. Everything just works. * fix: update the dockerfile build path * fix: update package.json * fix: fonts path
This commit is contained in:
parent
b20c472b94
commit
0c86efd56c
3
.gitignore
vendored
3
.gitignore
vendored
@ -122,4 +122,5 @@ prisma_test.js
|
||||
database/
|
||||
data/
|
||||
.vscode
|
||||
hemmelig.backup.db
|
||||
hemmelig.backup.db
|
||||
client/build/
|
||||
|
@ -25,8 +25,7 @@ FROM node:20-alpine
|
||||
|
||||
WORKDIR /home/node/hemmelig
|
||||
|
||||
RUN mkdir build
|
||||
COPY --from=0 /usr/src/app/build build/
|
||||
COPY --from=0 /usr/src/app/client/build client/build
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
|
2
cli.js
2
cli.js
@ -3,7 +3,7 @@
|
||||
import meow from 'meow';
|
||||
import fetch from 'node-fetch';
|
||||
import YAML from 'yaml';
|
||||
import { generateKey, encrypt } from './src/shared/helpers/crypto.js';
|
||||
import { encrypt, generateKey } from './shared/helpers/crypto.js';
|
||||
|
||||
// Adding this hack to make it work for pkg
|
||||
// https://github.com/vercel/pkg/issues/1291#issuecomment-1360586986
|
||||
|
@ -3,7 +3,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import HttpApi from 'i18next-http-backend';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import config from './client/config';
|
||||
import config from './config';
|
||||
|
||||
function getLanguage() {
|
||||
const language = config.get('settings.forcedLanguage');
|
@ -3,14 +3,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Thin.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Thin.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-ThinItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-ThinItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -18,14 +18,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-ExtraLight.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-ExtraLight.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-ExtraLightItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-ExtraLightItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -33,14 +33,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Light.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Light.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-LightItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-LightItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -48,14 +48,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Regular.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Regular.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Italic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Italic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -63,14 +63,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Medium.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Medium.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-MediumItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-MediumItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -78,14 +78,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-SemiBold.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-SemiBold.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-SemiBoldItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-SemiBoldItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -93,14 +93,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Bold.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Bold.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-BoldItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-BoldItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -108,14 +108,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-ExtraBold.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-ExtraBold.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-ExtraBoldItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-ExtraBoldItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -123,14 +123,14 @@
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-Black.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-Black.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Inter-BlackItalic.woff2') format('woff2');
|
||||
src: url('/static/fonts/Inter-BlackItalic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
html {
|
@ -5,9 +5,9 @@ import { Provider } from 'react-redux';
|
||||
import { LoadingOverlay } from '@mantine/core';
|
||||
import './i18n';
|
||||
|
||||
import HemmeligApplication from './client/app';
|
||||
import configureStore from './client/helpers/configureStore';
|
||||
import './client/index.css';
|
||||
import HemmeligApplication from './app';
|
||||
import configureStore from './helpers/configureStore';
|
||||
import './index.css';
|
||||
|
||||
const store = configureStore();
|
||||
|
@ -40,7 +40,7 @@ const SignOut = () => {
|
||||
<Image
|
||||
maw={240}
|
||||
radius="md"
|
||||
src="./secret_cat.png"
|
||||
src="./static/secret_cat.png"
|
||||
alt="Secret Cat"
|
||||
className={styles.image}
|
||||
/>
|
16
html.js
16
html.js
@ -5,10 +5,10 @@ export default `<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>Hemmelig.app - Paste a password, confidential message, or private data.</title>
|
||||
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="icon" href="/static/favicon.ico" />
|
||||
<link rel="shortcut icon" href="/static/favicon.ico" />
|
||||
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="manifest" href="/static/manifest.json" />
|
||||
<!-- Primary Meta Tags -->
|
||||
<meta name="title" content="Paste a password, confidential message, or private data." />
|
||||
<meta
|
||||
@ -27,10 +27,10 @@ export default `<!DOCTYPE html>
|
||||
property="og:description"
|
||||
content="Ensure your sensitive data remains encrypted, secure, and confidential."
|
||||
/>
|
||||
<meta property="og:image" content="/icons/icon-512x512.png" />
|
||||
<meta property="og:image" content="/static/icons/icon-512x512.png" />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:card" content="/static/summary_large_image" />
|
||||
<meta property="twitter:url" content="https://www.hemmelig.app/" />
|
||||
<meta
|
||||
property="twitter:title"
|
||||
@ -40,14 +40,14 @@ export default `<!DOCTYPE html>
|
||||
property="twitter:description"
|
||||
content="Ensure your sensitive data remains encrypted, secure, and confidential."
|
||||
/>
|
||||
<meta property="twitter:image" content="/icons/icon-512x512.png" />
|
||||
<meta property="twitter:image" content="/static/icons/icon-512x512.png" />
|
||||
|
||||
<meta name="theme-color" content="#231e23" />
|
||||
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link rel="apple-touch-icon" href="/icons/maskable-icon-192x192.png" />
|
||||
<link rel="apple-touch-icon" href="/static/icons/maskable-icon-192x192.png" />
|
||||
<script id="__secret_config">
|
||||
try {
|
||||
window.__SECRET_CONFIG = {{config}}
|
||||
@ -61,7 +61,7 @@ export default `<!DOCTYPE html>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="module" src="/src/index.jsx"></script>
|
||||
<script type="module" src="/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
1737
package-lock.json
generated
1737
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@ -9,14 +9,13 @@
|
||||
"test": "mocha tests/**/*.test.js --reporter nyan",
|
||||
"test-watch": "mocha --watch tests/**/*.test.js --reporter nyan",
|
||||
"build": "node pre.js && vite build",
|
||||
"dev": "concurrently \"npm run server-dev\" \"npm run client-dev\"",
|
||||
"server-dev": "prisma migrate dev && NODE_ENV=development node pre.js && NODE_ENV=development nodemon server.js",
|
||||
"client-dev": "NODE_ENV=development vite",
|
||||
"dev": "npm run server-dev",
|
||||
"server-dev": "prisma migrate dev && NODE_ENV=development node pre.js && NODE_ENV=development node server.js --dev",
|
||||
"docker-build": "docker build -t hemmelig .",
|
||||
"docker-run": "docker run -p 3000:3000 -d --name=hemmelig -v ./data/hemmelig/:/var/tmp/hemmelig/upload/files -v ./database/:/home/node/hemmelig/database/ hemmelig",
|
||||
"production-test": "npm run docker-build && npm run docker-run",
|
||||
"prepare": "husky install",
|
||||
"prettier": "prettier --write --ignore-unknown src/ prisma/",
|
||||
"prettier": "prettier --write --ignore-unknown server/ client/ shared/ prisma/",
|
||||
"publish-cli": "rm -rf dist/ && npx microbundle build --target node -i cli.js -o dist/ && npm publish",
|
||||
"pkg": "rm -rf dist/ bin/ && npx esbuild cli.js --bundle --platform=node --outfile=dist/cli.cjs --define:import.meta.url=__dirname && npx pkg dist/cli.cjs --targets=node18-linux-arm64 --output=bin/hemmelig"
|
||||
},
|
||||
@ -41,7 +40,8 @@
|
||||
"@fastify/helmet": "^9.1.0",
|
||||
"@fastify/jwt": "^7.2.3",
|
||||
"@fastify/multipart": "^7.1.1",
|
||||
"@fastify/static": "^6.5.0",
|
||||
"@fastify/static": "^6.12.0",
|
||||
"@fastify/vite": "^6.0.6",
|
||||
"@mantine/core": "^6.0.6",
|
||||
"@mantine/form": "^6.0.6",
|
||||
"@mantine/hooks": "^6.0.6",
|
||||
@ -75,7 +75,6 @@
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"buffer": "^6.0.3",
|
||||
"classcat": "^5.0.3",
|
||||
"concurrently": "^7.4.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"deepmerge": "^4.2.2",
|
||||
"dlv": "^1.1.3",
|
||||
|
4
pre.js
4
pre.js
@ -1,11 +1,11 @@
|
||||
import fs from 'fs';
|
||||
import config from 'config';
|
||||
import fs from 'fs';
|
||||
import template from 'y8';
|
||||
import html from './html.js';
|
||||
|
||||
// This is scripts that has to be run before the
|
||||
// frontend build process
|
||||
fs.writeFileSync(
|
||||
'index.html',
|
||||
'client/index.html',
|
||||
template(html, { config: `'${JSON.stringify(config.get('__client_config'))}';` })
|
||||
);
|
||||
|
154
server.js
154
server.js
@ -1,51 +1,94 @@
|
||||
// Boot scripts
|
||||
import('./src/server/bootstrap.js');
|
||||
import('./server/bootstrap.js');
|
||||
|
||||
import cookie from '@fastify/cookie';
|
||||
import cors from '@fastify/cors';
|
||||
import helmet from '@fastify/helmet';
|
||||
import jwt from '@fastify/jwt';
|
||||
import fstatic from '@fastify/static';
|
||||
import fastifyStatic from '@fastify/static';
|
||||
import FastifyVite from '@fastify/vite';
|
||||
import config from 'config';
|
||||
import importFastify from 'fastify';
|
||||
import fs from 'fs';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import template from 'y8';
|
||||
|
||||
import rateLimit from './src/server/plugins/rate-limit.js';
|
||||
import rateLimit from './server/plugins/rate-limit.js';
|
||||
|
||||
import adminDecorator from './src/server/decorators/admin.js';
|
||||
import allowedIp from './src/server/decorators/allowed-ip.js';
|
||||
import attachment from './src/server/decorators/attachment-upload.js';
|
||||
import jwtDecorator from './src/server/decorators/jwt.js';
|
||||
import userFeatures from './src/server/decorators/user-features.js';
|
||||
import adminDecorator from './server/decorators/admin.js';
|
||||
import allowedIp from './server/decorators/allowed-ip.js';
|
||||
import attachment from './server/decorators/attachment-upload.js';
|
||||
import jwtDecorator from './server/decorators/jwt.js';
|
||||
import userFeatures from './server/decorators/user-features.js';
|
||||
|
||||
import readCookieAllRoutesHandler from './src/server/prehandlers/cookie-all-routes.js';
|
||||
import disableUserAccountCreationHandler from './src/server/prehandlers/disable-user-account-creation.js';
|
||||
import disableUserHandler from './src/server/prehandlers/disable-users.js';
|
||||
import readOnlyHandler from './src/server/prehandlers/read-only.js';
|
||||
import restrictOrganizationEmailHandler from './src/server/prehandlers/restrict-organization-email.js';
|
||||
import readCookieAllRoutesHandler from './server/prehandlers/cookie-all-routes.js';
|
||||
import disableUserAccountCreationHandler from './server/prehandlers/disable-user-account-creation.js';
|
||||
import disableUserHandler from './server/prehandlers/disable-users.js';
|
||||
import readOnlyHandler from './server/prehandlers/read-only.js';
|
||||
import restrictOrganizationEmailHandler from './server/prehandlers/restrict-organization-email.js';
|
||||
|
||||
import accountRoute from './src/server/controllers/account.js';
|
||||
import adminSettingsRoute from './src/server/controllers/admin/settings.js';
|
||||
import usersRoute from './src/server/controllers/admin/users.js';
|
||||
import authenticationRoute from './src/server/controllers/authentication.js';
|
||||
import downloadRoute from './src/server/controllers/download.js';
|
||||
import healthzRoute from './src/server/controllers/healthz.js';
|
||||
import secretRoute from './src/server/controllers/secret.js';
|
||||
import statsRoute from './src/server/controllers/stats.js';
|
||||
import accountRoute from './server/controllers/account.js';
|
||||
import adminSettingsRoute from './server/controllers/admin/settings.js';
|
||||
import usersRoute from './server/controllers/admin/users.js';
|
||||
import authenticationRoute from './server/controllers/authentication.js';
|
||||
import downloadRoute from './server/controllers/download.js';
|
||||
import healthzRoute from './server/controllers/healthz.js';
|
||||
import secretRoute from './server/controllers/secret.js';
|
||||
import statsRoute from './server/controllers/stats.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const MAX_FILE_BYTES = 1024 * config.get('file.size') * 1000; // Example: 1024 * 2 * 1000 = 2 024 000 bytes
|
||||
|
||||
const staticPath = path.join(__dirname, !isDev ? 'client/build' : 'client');
|
||||
|
||||
const fastify = importFastify({
|
||||
logger: config.get('logger'),
|
||||
bodyLimit: MAX_FILE_BYTES,
|
||||
});
|
||||
|
||||
await fastify.register(FastifyVite, {
|
||||
root: import.meta.url,
|
||||
dev: process.argv.includes('--dev'),
|
||||
spa: true,
|
||||
});
|
||||
|
||||
fastify.register(fastifyStatic, {
|
||||
root: path.join(__dirname, 'public'),
|
||||
prefix: '/static/',
|
||||
});
|
||||
|
||||
fastify.register(fastifyStatic, {
|
||||
root: path.join(__dirname, 'public', 'locales'),
|
||||
prefix: '/locales/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
if (!isDev) {
|
||||
const script = template(
|
||||
`
|
||||
try {
|
||||
window.__SECRET_CONFIG = {{config}}
|
||||
} catch (e) {
|
||||
window.__SECRET_CONFIG = '';
|
||||
}
|
||||
`,
|
||||
{ config: `'${JSON.stringify(config.get('__client_config'))}';` }
|
||||
);
|
||||
|
||||
const index = staticPath + '/index.html';
|
||||
|
||||
const dom = new JSDOM(fs.readFileSync(index));
|
||||
dom.window.document.querySelector('#__secret_config').textContent = script;
|
||||
|
||||
fs.writeFileSync(index, dom.serialize());
|
||||
}
|
||||
|
||||
fastify.register(rateLimit, {
|
||||
prefix: '/api/',
|
||||
max: config.get('rateLimit.max'),
|
||||
@ -91,7 +134,21 @@ fastify.addHook('preHandler', disableUserAccountCreationHandler);
|
||||
fastify.addHook('preHandler', readOnlyHandler);
|
||||
fastify.addHook('preHandler', restrictOrganizationEmailHandler);
|
||||
|
||||
// Register our routes before the static content
|
||||
function serveIndex(_, reply) {
|
||||
return reply.html();
|
||||
}
|
||||
|
||||
fastify.get('/', serveIndex);
|
||||
fastify.get('/secret/*', serveIndex);
|
||||
fastify.get('/about', serveIndex);
|
||||
fastify.get('/privacy', serveIndex);
|
||||
fastify.get('/api-docs', serveIndex);
|
||||
fastify.get('/signin', serveIndex);
|
||||
fastify.get('/signup', serveIndex);
|
||||
fastify.get('/signout', serveIndex);
|
||||
fastify.get('/account*', serveIndex);
|
||||
fastify.get('/terms', serveIndex);
|
||||
fastify.get('/public*', serveIndex);
|
||||
|
||||
fastify.register(authenticationRoute, {
|
||||
prefix: '/api/authentication',
|
||||
@ -115,54 +172,9 @@ fastify.register(statsRoute, { prefix: '/api/stats' });
|
||||
fastify.register(healthzRoute, { prefix: '/api/healthz' });
|
||||
fastify.register(healthzRoute, { prefix: '/healthz' });
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const staticPath = path.join(__dirname, !isDev ? 'build' : '');
|
||||
|
||||
// Static frontend for the production build
|
||||
if (!isDev) {
|
||||
fastify.register(fstatic, {
|
||||
root: staticPath,
|
||||
route: '/*',
|
||||
});
|
||||
|
||||
const script = template(
|
||||
`
|
||||
try {
|
||||
window.__SECRET_CONFIG = {{config}}
|
||||
} catch (e) {
|
||||
window.__SECRET_CONFIG = '';
|
||||
}
|
||||
`,
|
||||
{ config: `'${JSON.stringify(config.get('__client_config'))}';` }
|
||||
);
|
||||
|
||||
const index = staticPath + '/index.html';
|
||||
|
||||
const dom = new JSDOM(fs.readFileSync(index));
|
||||
dom.window.document.querySelector('#__secret_config').textContent = script;
|
||||
|
||||
fs.writeFileSync(index, dom.serialize());
|
||||
|
||||
function serveIndex(_, res) {
|
||||
return res.sendFile('index.html');
|
||||
}
|
||||
|
||||
fastify.get('/secret/*', serveIndex);
|
||||
fastify.get('/about', serveIndex);
|
||||
fastify.get('/privacy', serveIndex);
|
||||
fastify.get('/api-docs', serveIndex);
|
||||
fastify.get('/signin', serveIndex);
|
||||
fastify.get('/signup', serveIndex);
|
||||
fastify.get('/signout', serveIndex);
|
||||
fastify.get('/account*', serveIndex);
|
||||
fastify.get('/terms', serveIndex);
|
||||
fastify.get('/public*', serveIndex);
|
||||
}
|
||||
|
||||
const startServer = async () => {
|
||||
try {
|
||||
await fastify.vite.ready();
|
||||
await fastify.listen({ port: config.get('port'), host: config.get('localHostname') });
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import { encrypt, decrypt, generateKey } from '../../../src/shared/helpers/crypto.js';
|
||||
import { decrypt, encrypt, generateKey } from '../../../shared/helpers/crypto.js';
|
||||
|
||||
const SECRET = 'MASTER_KEY=1337-super-secret';
|
||||
|
||||
@ -9,8 +9,8 @@ const RANDOM_KEY = generateKey();
|
||||
describe('Crypto', () => {
|
||||
describe('#encrypt(string)', () => {
|
||||
it('should encrypt, and decrypt a secret', async () => {
|
||||
const encrypted = await encrypt(SECRET, RANDOM_KEY);
|
||||
const decrypted = await decrypt(encrypted, RANDOM_KEY);
|
||||
const encrypted = encrypt(SECRET, RANDOM_KEY);
|
||||
const decrypted = decrypt(encrypted, RANDOM_KEY);
|
||||
|
||||
assert.equal(decrypted, SECRET);
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import { hash, compare } from '../../../src/server/helpers/password.js';
|
||||
import { compare, hash } from '../../../server/helpers/password.js';
|
||||
|
||||
const PASSWORD = 'suP3rL0ng!PssWrd';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import isValidTTL from '../../../src/server/helpers/validate-ttl.js';
|
||||
import isValidTTL from '../../../server/helpers/validate-ttl.js';
|
||||
|
||||
describe('Validate TTL', () => {
|
||||
describe('#isValidTTL(ttl)', () => {
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const path = fileURLToPath(import.meta.url);
|
||||
const root = resolve(dirname(path), 'client');
|
||||
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
root,
|
||||
build: {
|
||||
outDir: 'build',
|
||||
},
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3001,
|
||||
proxy: {
|
||||
'/api': 'http://0.0.0.0:3000',
|
||||
},
|
||||
},
|
||||
publicDir: 'public',
|
||||
plugins: [react({ jsxRuntime: 'classic' })],
|
||||
};
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user