GithubHelp home page GithubHelp logo

ruby184 / adonis-socket.io Goto Github PK

View Code? Open in Web Editor NEW
11.0 4.0 2.0 1.63 MB

AdonisJs 5 websocket provider using socket.io under the hood

License: MIT License

Shell 0.23% TypeScript 99.77%
adonisjs socket-io websocket

adonis-socket.io's Introduction

@ruby184/adonis-socket.io

AdonisJs 5 websocket provider using socket.io under the hood

github-actions-image npm-image license-image typescript-image

This package is trying to implement main ideas from this Adonis RFC. Package is not production ready until v1.0. Use it at your own risk.

Currently implemented features:

  • define socket.io namespaces including dynamic ones with adonis-like routes syntax
  • add adonis-like class middlewares similar to route ones to namespaces
  • handle events on namespaces with controllers and allow to ack events with value returned from event handler
  • centralized exception handling similar to http
  • working with adonis auth middleware
  • more to come...

Installation

Install it from npm

npm i @ruby184/adonis-socket.io

and then configure it using adonis

node ace configure @ruby184/adonis-socket.io

TODO

  • allow .where regex definition for namespace dynamic parameters
  • allow to define controller namespace for socket.io namespace
  • define static namespaces directly as socket.io namespaces and use matching only for dynamic ones (perf)
  • test everything
  • we should not create and use response, but return Proxy to intercept and throw error when user tries to use response in websocket context
  • extract errors handling to dedicated exception handler to report and handle
  • look at how to make easy integration of socket.io multi server support with adonis
  • look how we can make use of socket middleware which is a function that gets executed for every incoming Packet
  • handle transformaton of adonis cors config to socket.io as they are not 100% compatible

Usage

Examples

Here is an example of tracking users online status using this package inspired by default examples from socket.io

  1. Currently package supports authentication by api tokens. Update middleware created by @adonisjs/auth in app/Middleware/Auth.ts and add wsHandle method to support websockets
import type { WsContextContract } from '@ioc:Ruby184/Socket.IO/WsContext'
  /**
   * Handle ws namespace connection
   */
  public async wsHandle(
    { auth }: WsContextContract,
    next: () => Promise<void>,
    customGuards: (keyof GuardsList)[]
  ) {
    /**
     * Uses the user defined guards or the default guard mentioned in
     * the config file
     */
    const guards = customGuards.length ? customGuards : [auth.name]
    await this.authenticate(auth, guards)
    await next()
  }
  1. Update start/wsKernel.ts to add authentication middleware updated in previous step. We will add global middleware but you can also use named one and just add it to required nameespace in next step.
Ws.middleware.register([() => import('App/Middleware/Auth')])
  1. Add events listeners in start/socket.ts
Ws.namespace('/')
  .connected('ActivityController.onConnected')
  .disconnected('ActivityController.onDisconnected')
  1. Create a websocket controller in app/Controllers/Ws/ActivityController.ts
import type { WsContextContract } from '@ioc:Ruby184/Socket.IO/WsContext'
import User from 'App/Models/User'

export default class ActivityController {
  private getUserRoom(user: User): string {
    return `user:${user.id}`
  }

  public async onConnected({ socket, auth, logger }: WsContextContract) {
    // all connections for the same authenticated user will be in the room
    const room = this.getUserRoom(auth.user!)
    const userSockets = await socket.in(room).allSockets()

    // this is first connection for given user
    if (userSockets.size === 0) {
      socket.broadcast.emit('user:online', auth.user)
    }

    // add this socket to user room
    socket.join(room)
    // add userId to data shared between Socket.IO servers
    // https://socket.io/docs/v4/server-api/#namespacefetchsockets
    socket.data.userId = auth.user!.id

    const allSockets = await socket.nsp.except(room).fetchSockets()
    const onlineIds = new Set<number>()

    for (const remoteSocket of allSockets) {
      onlineIds.add(remoteSocket.data.userId)
    }

    const onlineUsers = await User.findMany([...onlineIds])

    socket.emit('user:list', onlineUsers)

    logger.info('user connected: %d', auth.user!.id)
  }

  // see https://socket.io/get-started/private-messaging-part-2/#disconnection-handler
  public async onDisconnected({ socket, auth, logger }: WsContextContract, reason: string) {
    const room = this.getUserRoom(auth.user!)
    const userSockets = await socket.in(room).allSockets()

    // user is disconnected
    if (userSockets.size === 0) {
      // notify other users
      socket.broadcast.emit('user:offline', auth.user)
    }

    logger.info('user disconnected (%s): %d', reason, auth.user!.id)
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.