npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@haivinh/chat-messenger

v2.0.5

Published

NestJS npm package using repository typeorm and socket io

Downloads

8

Readme

Description :

These days nestjs and ws are also gradually developing, I have written a way to help you have the most basic chat-message, including related to messages such as send message, recall, send media, count message, ... and the basics of socket client.

=> Also you can find instructions about it on the page : https://socket.io/docs/v4/ and https://docs.nestjs.com/

Required

  • Swagger UI
  • Typeorm
  • Database sql ( mysql, postgresql )

Installation

install package :

  npm i @haivinh/chat-messenger

import package :

  import * as haivinh from '@haivinh/chat-messenger/dist';

SETUP BACKEND

In file "app.module.ts" import socket io to module :

  • step import :
    • AliasIdInJWTToken : alias id user in jwt token
    • AliasIdUser : alias column id user
    • EntityUser : entities user in project
    • AliasNameUser: 'email';
Example:
    haivinh.SocketIoModule.CustomerOptionModule({
            AliasIdInJWTToken: 'id',
            AliasIdUser: 'user_id',
            EntityUser: User,
            AliasNameUser: 'email';
        }),

In DataSourceOptions config ( data-source in project ):

  • add entity Messenger and GropChat after path entiy
Example:
  export const dataSource: DataSourceOptions = {
    type: 'postgres',
    host: process.env.TYPEORM_HOST || 'localhost',
    port: +process.env.TYPEORM_PORT || 3306,
    username: process.env.TYPEORM_USERNAME || 'root',
    password: process.env.TYPEORM_PASSWORD || '123456',
    database: process.env.TYPEORM_DATABASE || 'databasename',
    entities: ['./**/*.entity.js', Messenger, GroupChat,SocketClient],
    migrations: ['../../dist/database/migrations/*.{ts,js}'],
    synchronize: process.env.TYPEORM_SYNCHRONIZE === 'true',
    logging: process.env.TYPEORM_LOGGING === 'true',
};

migration:generate ( create new migration compatible table in project )

    "typeorm-generate": "node --require ts-node/register ./node_modules/typeorm/cli.js -d ./typeorm-datasource.ts migration:generate src/database/migrations/newmigration",

run migration: migration:run example :

    "typeorm-run": "node --require ts-node/register ./node_modules/typeorm/cli.js -d ./typeorm-datasource.ts migration:run",

Setup Front-end

REQUIRED socket io Front-End :

add to option socketio front-end

  • transports : ['websocket'];
  • URL : domain backend;
  • auth : token user login
Eample :
const URL = "http://localhost:4000";
  transports: ["websocket", "polling"],
  transports: ["websocket"],
  autoConnect: false,
  path:'/message/',
  auth: { token: `Bearer ${localStorage.getItem("token")}` }
});

in App.js you can connect socket io and listen event socket

  • recMessage : user send messenger to room
  • resultMessengerFailder : user send messenger falider
  • #socket.id drag the user into a room
Example :
/**
 * TODO : innit Socket and listing Event socket io
 * @param {*} setMessenger : func set Messenger
 * @param {*} addMessenger : func Add Messenger
 */
export const initSocket = async (setMessenger, addMessenger) => {
  await socket.connect();
  socket.on("recMessage", (messenger) => {
    console.log("recMessage ==================>", messenger);
    setMessenger(null);
    addMessenger(messenger);
  });

  socket.on("connect", () => {
    socket.on(socket.id, (idGroup) => {
      console.log(`${socket.id}=====================>`, idGroup);
      socket.emit("onConversationJoin", idGroup);
    });

    socket.on(`msg.leaveRoom-${socket.id}`, (idGroup) => {
      console.log(
        `${socket.id}========onConversationLeave=============>`,
        idGroup
      );
      socket.emit("onConversationLeave", idGroup);
    });
  });

  socket.on("resultMessenger", (data) => {
    if (!data.content) notification("fail to messenger");
  });
};

Follow socket :

  1. Start call api listGroup
API : api/group-user?page=1&size=20 || Method : GET
  1. After getting the group id, we will pull the user into that grop using the client's socket.id
socket.on(socket.id, (idGroup) => {
  console.log(`${socket.id}=====================>`, idGroup);
  socket.emit("onConversationJoin", idGroup);
});
  1. After dragging the client into the room, the client will receive the messenger by event recMessage,you need to check condition in recMessenger messenger for best display
socket.on("recMessage", (messenger) => {
  console.log("recMessage ==================>", messenger);
  setMessenger(null);
  addMessenger(messenger);
});
  1. Send a message to the group, you will call

note :

Since you will need upload management I won't interfere to best protect your privacy, I will just save urlMedia on messenger and not add anything else, retrieving sent media count is also based on go to urlMedia sent on message

API : api/messenger || Method : POST
     var param = {"content": messenger, "group_id": idGroup};
      if (replyTo != null) param['replyTo'] = replyTo;
      if (urlMedia != null) param['urlMedia'] = urlMedia;
  1. Create and join group, you wil call
API : api/group-user || Method : POST
param = {"listIdUser": \[idUser\]}
  1. If you want to mute a group, you'll need to call. Since it only hides notifications, notification display will need to be set up in the frontend
API : api/group-user/$idGroup || Method : PUT
  1. If you want to delete all messages in the group, you will call. It will delete all old messages in the group for you
API : api/group-user/$idGroup || Method : DELETE
  1. If you want to revoke or delete user messages, please call. It will change the status of messenger ( 0 : active, 1 : unactive, 2: hide by user )
API : api/messenger/$idMessenger || Method : DELETE
  1. Get list media send to group ( option filter )
API : media-in-group/$idGroup || Method : GET

Set up Adapter and middleware

middleware socket io

create file authen-socket.ts in server

import {
    UnauthorizedException,
} from '@nestjs/common';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { Socket } from 'socket.io';
import { User } from 'src/database/entities/user.entity';
import { JwtService } from '@nestjs/jwt';

export interface AuthenticatedSocket extends Socket {
    user?: User;
}

export class AuthAdapter extends IoAdapter {
    createIOServer(port: number, options?: any): any {
        const server = super.createIOServer(port, { ...options, cors: true });
        //	Adds the middleware function to the websocket server.
        console.log('run to middleware ========================>');

        server.use((socket: AuthenticatedSocket, next) => {
            if (socket.handshake.auth && socket.handshake.auth.token) {
                const jwtService: JwtService = new JwtService();
                const jwt = socket.handshake.auth.token.replace('Bearer ', '');
                var data = jwtService.decode(jwt, { json: true });
                console.log(
                    'run to check authenrication ======================>',
                    socket.handshake.auth.token,
                );
                if (data) {
                    console.log('authenrication ======================>', data);
                    next();
                } else {
                    console.log(
                        'failder authenrication ======================>',
                        data,
                    );
                    next(
                        new UnauthorizedException(
                            `Authentication error ${socket.handshake.auth.token}`,
                        ),
                    );
                }
            } else {
                next(
                    new UnauthorizedException(
                        `Authentication error ${socket.handshake.auth.token}`,
                    ),
                );
            }
        });
        return server;
    }
}

add option in client

export const socket = io(BASEDOMAIN_SOCKETIO, {
  transports: ["websocket", "polling"],
  // upgrade:true,
  withCredentials: true,
  autoConnect: false,
  auth: { token: `Bearer ${token}` }
});

RedisIoAdapter

create file redis-adapter-config.ts in server


import { IoAdapter } from '@nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';

export class RedisIoAdapter extends IoAdapter {
  private adapterConstructor: ReturnType<typeof createAdapter>;

  async connectToRedis(): Promise<void> {
    const pubClient = createClient({
      url: `redis://${process.env.TYPEORM_REDIS_HOST}:${process.env.TYPEORM_REDIS_PORT}`,
      password:process.env.TYPEORM_REDIS_PASSWORD.toString() || '123456'
    });

    const subClient = pubClient.duplicate();
    await Promise.all([pubClient.connect(), subClient.connect()])

    this.adapterConstructor = createAdapter(pubClient, subClient);
  }

  createIOServer(port: number, options?: ServerOptions): any {
    const server = super.createIOServer(port, options);
    server.adapter(this.adapterConstructor);
    console.log('server IO  ===========================>',server);
    return server;
  }
}

main.ts server

add line to main.ts

    app.useWebSocketAdapter(new AuthAdapter(app)); // middleware socket adapter
    const redisIoAdapter = new RedisIoAdapter(app); // redis socket adapter
    await redisIoAdapter.connectToRedis();
    app.useWebSocketAdapter(redisIoAdapter);

Create

Change Log

See Changelog for more information.

Support

I'm in the process of developing, looking forward to your support and contributions(https://github.com/Haivinh0704/chat-messenger-socketio/issues) Thank you

License

Licensed under the MIT License - see the LICENSE file for details.