config: migrate from nestjs to tasks and websocket server in docker (#316)

* feat: make tasks script run in docker

* feat: make websocket server work in docker

* fix: format issue

* fix: broken lockfile

* fix: non matching typescript versions
This commit is contained in:
Meier Lukas
2024-04-07 11:32:29 +02:00
committed by GitHub
parent 35ca732744
commit 669c6c8955
14 changed files with 173 additions and 68 deletions

View File

@@ -4,7 +4,8 @@
"exports": {
".": "./src/index.ts",
"./client": "./src/client.ts",
"./server": "./src/server.ts"
"./server": "./src/server.ts",
"./websocket": "./src/websocket.ts"
},
"private": true,
"main": "./index.ts",
@@ -12,12 +13,10 @@
"license": "MIT",
"type": "module",
"scripts": {
"dev": "pnpm with-env tsx ./src/wssDevServer.ts",
"clean": "rm -rf .turbo node_modules",
"lint": "eslint .",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit",
"with-env": "dotenv -e ../../.env --"
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@homarr/auth": "workspace:^0.1.0",
@@ -30,14 +29,12 @@
"@homarr/validation": "workspace:^0.1.0",
"@trpc/client": "next",
"@trpc/server": "next",
"superjson": "2.2.1",
"ws": "^8.16.0"
"superjson": "2.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.5.10",
"eslint": "^8.57.0",
"prettier": "^3.2.5",
"typescript": "^5.4.4"

View File

@@ -0,0 +1,2 @@
export { appRouter } from "./root";
export { createTRPCContext } from "./trpc";

View File

@@ -1,64 +0,0 @@
import { applyWSSHandler } from "@trpc/server/adapters/ws";
import { WebSocketServer } from "ws";
import { getSessionFromToken, sessionTokenCookieName } from "@homarr/auth";
import { parseCookies } from "@homarr/common";
import { db } from "@homarr/db";
import { logger } from "@homarr/log";
import { appRouter } from "./root";
import { createTRPCContext } from "./trpc";
const wss = new WebSocketServer({
port: 3001,
});
const handler = applyWSSHandler({
wss,
router: appRouter,
createContext: async ({ req }) => {
try {
const headers = Object.entries(req.headers).map(
([key, value]) =>
[key, typeof value === "string" ? value : value?.[0]] as [
string,
string,
],
);
const nextHeaders = new Headers(headers);
const store = parseCookies(nextHeaders.get("cookie") ?? "");
const sessionToken = store[sessionTokenCookieName];
const session = await getSessionFromToken(db, sessionToken);
return createTRPCContext({
headers: nextHeaders,
session,
});
} catch (error) {
logger.error(error);
return createTRPCContext({
headers: new Headers(),
session: null,
});
}
},
});
wss.on("connection", (websocket, incomingMessage) => {
logger.info(
` Connection (${wss.clients.size}) ${incomingMessage.method} ${incomingMessage.url}`,
);
websocket.once("close", (code, reason) => {
logger.info(
` Connection (${wss.clients.size}) ${code} ${reason.toString()}`,
);
});
});
logger.info("✅ WebSocket Server listening on ws://localhost:3001");
process.on("SIGTERM", () => {
logger.info("SIGTERM");
handler.broadcastReconnectNotification();
wss.close();
});

View File

@@ -36,6 +36,7 @@ export const createConfiguration = (isCredentialsRequest: boolean) =>
session: sessionCallback,
signIn: createSignInCallback(adapter, isCredentialsRequest),
},
secret: "secret-is-not-defined-yet", // TODO: This should be added later
session: {
strategy: "database",
maxAge: sessionMaxAgeInSeconds,

View File

@@ -4,7 +4,7 @@ import { migrate } from "drizzle-orm/better-sqlite3/migrator";
const migrationsFolder = process.argv[2] ?? "./migrations";
const sqlite = new Database(process.env.DB_URL.replace("file:", ""));
const sqlite = new Database(process.env.DB_URL?.replace("file:", ""));
const db = drizzle(sqlite);

View File

@@ -13,11 +13,12 @@
"types": "./index.ts",
"license": "MIT",
"scripts": {
"build": "esbuild migrate.ts --bundle --platform=node --outfile=migrate.cjs",
"clean": "rm -rf .turbo node_modules",
"lint": "eslint .",
"format": "prettier --check . --ignore-path ../../.gitignore",
"migration:generate": "drizzle-kit generate:sqlite",
"migration:run": "node ./migrate.mjs",
"migration:run": "tsx ./migrate.ts",
"push": "drizzle-kit push:sqlite",
"studio": "drizzle-kit studio",
"typecheck": "tsc --noEmit"

View File

@@ -27,7 +27,7 @@ export class RedisTransport extends Transport {
this.redis
.publish(
"logging",
"pubSub:logging",
superjson.stringify({
message: info.message,
timestamp: info.timestamp,

View File

@@ -37,7 +37,7 @@ export const createSubPubChannel = <TData>(name: string) => {
);
});
subscriber.on("message", (channel, message) => {
if (channel !== channelName) return;
if (channel !== channelName) return; // TODO: check if this is necessary - it should be handled by the redis client
callback(superjson.parse(message));
});