# FSE Chat The Chat Application is a real-time messaging platform that allows users to engage in text-based conversations. It is built using Node.js, Express, Socket.io, and Passport.js. The application provides a simple and intuitive interface for users to register, log in, and participate in chat conversations. ## Table of Contents - [Features](#Features) - [Technical Stack](#Technical-Stack) - [File Structure](#File-Structure) - [Reference](#Reference) - [Frontend](#Frontend) - [Backend](#Backend) - [Database](#Database) ## Features - Real-time Messaging: Users can send and receive messages in real-time, providing a seamless chatting experience. - User Authentication: The application includes user authentication functionality, allowing users to securely log in and log out. - User Registration: New users can create an account by registering with a unique username and password. - Persistent Data Storage: Messages are stored in a database, ensuring that the chat history is preserved even after users leave and return to the application. ## Technical Stack The application is built using the following technologies and libraries: - Express.js: A popular web application framework for Node.js. - Socket.io: A library for enabling real-time bidirectional communication between the server and clients. - Pug.js: A template engine used for rendering dynamic HTML views. - Passport.js: A user authentication middleware for Node.js. - Prisma: An ORM (Object-Relational Mapping) tool for simplifying database interactions. ## File Structure ``` - server - route.js - index.js - utils.js - chatSocket.js - views - layout.pug - index.pug - login.pug - register.pug - public - script.js - style.css - prisma - schema.prisma - index.js - package.json ``` ## Frontend The frontend of the FSE Chat Room project is built using Pug.js and follows the BEM (Block-Element-Modifier) methodology for styling. ### Pug.js Templates The project utilizes Pug.js as the templating engine to generate HTML. The main templates used in the frontend are as follows: ```pug extends layout.pug block content header.header-container h1.page-heading FSE Chat Room form.logout-form(action='/logout', method='post') input.button.button--orange(type='submit', value='Logout') ul#messages.msg-list form#form.msg-form(action="") textarea#input.msg-form__input div.msg-form__btn-container button.button.button--orange Post script. const currentUser = !{JSON.stringify(username)}; script(src="/socket.io/socket.io.js") script(src="/script.js") ``` ### BEM (Block-Element-Modifier) CSS The frontend styling follows the BEM methodology, providing a structured and modular approach to CSS. Here's an example of the CSS classes used: ```css .logout-form { margin: 0; } .msg-form { position: fixed; margin: 0; bottom: 0; left: 0; right: 0; display: flex; flex-direction: column; justify-content: space-between; height: 8rem; box-sizing: border-box; background-color: #fff; } .msg-form__input { flex-grow: 1; padding: 0.25rem; margin: 0.25rem; resize: none; border: 1px solid #333; } ``` ## Backend The backend of the FSE Chat Room project is built using Express.js and Socket.IO for real-time communication. It also utilizes Passport.js for authentication and Prisma as the ORM (Object-Relational Mapping) tool for database operations. ### Server Setup The server is set up using the following code in the ChatAppServer class: ```javascript class ChatAppServer { constructor() { this.init() this.useMiddleWares() this.addRoutes() this.listenServer() } // ... code continues } ``` The ChatAppServer class handles the initialization of the server, middleware configuration, route setup, and server listening. ### Routes The backend routes are organized into separate router classes, including IndexRouter, AuthRouter, and ChatRouter. Here's an example of how the routes are defined: ```javascript class BaseRouter { constructor() { this.router = express.Router(); } getRouter() { return this.router; } } class IndexRouter extends BaseRouter { constructor() { super(); this.router.get('/', isAuthenticated, this.getHome.bind(this)); } // ... code continues } class AuthRouter extends BaseRouter { constructor() { super(); // ... route definitions } // ... route handler functions } class ChatRouter extends BaseRouter { constructor() { super(); // ... route definitions } // ... route handler functions } module.exports = { IndexRouter, AuthRouter, ChatRouter }; ``` The routes are organized into separate classes to keep the code modular and maintainable. Each router class extends the BaseRouter class, which provides the underlying express.Router() instance. ### WebSocket Communication WebSocket communication is handled by the ChatSocket class, which utilizes the Socket.IO library. Here's an example of how it's implemented: ```javascript class ChatSocket { constructor(io, sessionMiddleware) { this.io = io; this.sessionMiddleware = sessionMiddleware; } initialize() { // ... middleware this.io.on('connection', (socket) => { socket.on('chat message', this.handleChatMessage.bind(this, socket)); }); } // ... event handler functions } module.exports = ChatSocket; ``` The ChatSocket class initializes Socket.IO and handles WebSocket events, such as the 'connection' event and the 'chat message' event. ## Database The FSE Chat Room project utilizes a SQLite database for storing user information and chat messages. The database schema is defined using Prisma, an ORM (Object-Relational Mapping) tool. Here's an example of the schema: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) username String @unique password String messages Message[] } model Message { id Int @id @default(autoincrement()) content String user User @relation(fields: [username], references: [username]) username String createdAt DateTime @default(now()) } ``` The User model represents a user in the system and has the following fields: * `id`: An auto-incrementing integer that serves as the primary key. * `username`: A unique string that represents the user's username. * `password`: A string that stores the hashed password of the user. * `messages`: A one-to-many relationship with the Message model, representing the messages posted by the user. The Message model represents a chat message and has the following fields: * `id`: An auto-incrementing integer that serves as the primary key. * `content`: A string that stores the content of the message. * `user`: A many-to-one relationship with the User model, representing the user who posted the message. * `username`: A string that references the username field of the User model. * `createdAt`: A datetime field that stores the timestamp when the message was created. The Prisma schema enables easy interaction with the database using the Prisma Client. The Prisma Client generates a JavaScript client that provides a type-safe API for querying and manipulating data in the database. ## Reference - [Socket.IO chat-example](https://socket.io/get-started/chat) - [Passport tutorial](https://www.passportjs.org/tutorials/password/) - [Prisma Quickstart](https://www.prisma.io/docs/getting-started/quickstart) - [Express App using classes](https://youtu.be/kbPXLlnYuBg) - [BEM,CSS 設計模式](https://chupai.github.io/posts/2104/bem/#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99)