Complete refractor - we do sexy code only

This commit is contained in:
2024-05-09 04:00:05 +02:00
parent ca88c085e6
commit 8356a83431
28 changed files with 449 additions and 492 deletions

View File

@ -0,0 +1,7 @@
import { Socket, Server } from "socket.io";
export default function user_connect(socket: Socket, io: Server) {
socket.on('disconnect', (data) => {
console.log(`---User ${socket.id} has disconnected.`);
});
}

View File

@ -0,0 +1,7 @@
import { Socket, Server } from "socket.io";
export default function player_connect(socket: Socket, io: Server) {
socket.on('player:connect', (data) => {
console.log(`---User ${socket.id} has joined.`);
});
}

View File

@ -0,0 +1,7 @@
import { Socket, Server } from "socket.io";
export default function player_map_load(socket: Socket, io: Server) {
socket.on('player:map:load', (data) => {
console.log(`---User ${socket.id} has requested map.`);
});
}

6
src/app/logo.txt Normal file
View File

@ -0,0 +1,6 @@
███╗░░██╗███████╗░██╗░░░░░░░██╗  ░██████╗░██╗░░░██╗███████╗░██████╗████████╗
████╗░██║██╔════╝░██║░░██╗░░██║  ██╔═══██╗██║░░░██║██╔════╝██╔════╝╚══██╔══╝
██╔██╗██║█████╗░░░╚██╗████╗██╔╝  ██║██╗██║██║░░░██║█████╗░░╚█████╗░░░░██║░░░
██║╚████║██╔══╝░░░░████╔═████║░  ╚██████╔╝██║░░░██║██╔══╝░░░╚═══██╗░░░██║░░░
██║░╚███║███████╗░░╚██╔╝░╚██╔╝░  ░╚═██╔═╝░╚██████╔╝███████╗██████╔╝░░░██║░░░
╚═╝░░╚══╝╚══════╝░░░╚═╝░░░╚═╝░░  ░░░╚═╝░░░░╚═════╝░╚══════╝╚═════╝░░░░╚═╝░░░

View File

@ -0,0 +1,15 @@
import { Map } from '@prisma/client';
import prisma from '../utilities/prisma'; // Import the global Prisma instance
class MapRepository {
async getFirst(): Promise<Map | null> {
try {
return await prisma.map.findFirst();
} catch (error: any) {
// Handle error
throw new Error(`Failed to get first map: ${error.message}`);
}
}
}
export default MapRepository;

View File

@ -0,0 +1,33 @@
import prisma from '../utilities/prisma'; // Import the global Prisma instance
import { User } from '@prisma/client';
class UserRepository {
async getByUsername(username: string): Promise<User | null> {
try {
return await prisma.user.findUnique({
where: {
username,
},
});
} catch (error: any) {
// Handle error
throw new Error(`Failed to get user by username: ${error.message}`);
}
}
async create(username: string, password: string): Promise<User> {
try {
return await prisma.user.create({
data: {
username,
password,
},
});
} catch (error: any) {
// Handle error
throw new Error(`Failed to create user: ${error.message}`);
}
}
}
export default new UserRepository;

81
src/app/server.ts Normal file
View File

@ -0,0 +1,81 @@
import fs from "fs";
import path from "path";
import express from 'express';
import http from 'http';
import cors from 'cors';
import {Server as HttpServer, Socket} from 'socket.io';
import config from './utilities/config';
import prisma from './utilities/prisma';
import api from "./utilities/api";
export class Server
{
private readonly app: express.Application;
private readonly server: any;
private readonly io: HttpServer;
/**
* Creates an instance of GameServer.
*/
constructor() {
this.app = express();
this.app.use(cors());
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: true }));
this.server = http.createServer(this.app)
this.io = new HttpServer(this.server);
}
/**
* Start the server
*/
public async start() {
// Print logo
const art = fs.readFileSync(path.join(__dirname, 'logo.txt'), 'utf8');
console.log('\x1b[31m%s\x1b[0m', art + '\n');
// Check prisma connection
try {
await prisma.$connect();
console.log('[✅] Database connected');
} catch (error: any) {
throw new Error(`[❌] Database connection failed: ${error.message}`);
}
// Start the server
try {
await this.server.listen(config.PORT);
console.log('[✅] Socket.IO running on port', config.PORT);
} catch (error: any) {
throw new Error(`[❌] Socket.IO failed to start: ${error.message}`);
}
// Add API routes
await api.addAuthRoutes(this.app);
// Add socket events
this.io.on('connection', this.handleConnection.bind(this));
}
/**
* Handle socket connection
* @param socket
* @private
*/
private async handleConnection(socket: Socket) {
const eventsPath = path.join(__dirname, 'events');
try {
const files = await fs.promises.readdir(eventsPath);
for (const file of files) {
if (!file.endsWith('.ts')) {
continue;
}
const module = await import(path.join(eventsPath, file));
module.default(socket, this.io);
}
} catch (error: any) {
throw new Error('[❌] Failed to load event handlers: ' + error.message);
}
}
}

30
src/app/services/user.ts Normal file
View File

@ -0,0 +1,30 @@
import bcrypt from "bcryptjs";
import UserRepository from "../repositories/user";
class UserService {
async login(username: string, password: string): Promise<boolean | any> {
const user = await UserRepository.getByUsername(username);
if (!user) {
return false;
}
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return false;
}
return user;
}
async register(username: string, password: string): Promise<boolean | any> {
const user = await UserRepository.getByUsername(username);
if (user) {
return false;
}
const hashedPassword = await bcrypt.hash(password, 10);
return await UserRepository.create(username, hashedPassword);
}
}
export default UserService;

32
src/app/utilities/api.ts Normal file
View File

@ -0,0 +1,32 @@
import { Request, Response } from 'express';
import UserService from '../services/user';
async function addAuthRoutes(app: any) {
app.post('/login', async (req: Request, res: Response) => {
const { username, password } = req.body;
const userService = new UserService();
const user = await userService.login(username, password);
if (user) {
return res.status(200).json(user);
}
return res.status(401).json({ message: 'Invalid credentials' });
});
app.post('/register', async (req: Request, res: Response) => {
const { username, password } = req.body;
const userService = new UserService();
const user = await userService.register(username, password);
if (user) {
return res.status(201).json(user);
}
return res.status(400).json({ message: 'Failed to register user' });
});
console.log('[🌎] Auth routes added');
}
export default { addAuthRoutes };

View File

@ -0,0 +1,10 @@
import dotenv from "dotenv";
dotenv.config();
class config {
static ENV: string = process.env.ENV || "prod";
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 5000;
}
export default config;

View File

@ -0,0 +1,5 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;