1.0.3 • Published 6 years ago

socket-mansion v1.0.3

Weekly downloads
4
License
MIT
Repository
github
Last release
6 years ago

Socket-Mansion

Build Status Code Coverage Build Status Maintainability

Socket-Mansion helps you connect your sockets to rooms, while also keeping check on where your users are.

This lets you focus on the actual function of the room instead of worrying about connections.

You should see your socket-mansion as a container for all rooms, while the modules you inject are rooms, you decide the states of the rooms.

npm install socket-mansion --save

How to use (in 4 steps)

Step 1. Create room

Constructor: Your room modules need to have, io and id as parameters.

function room(io, id) {
    this.io = io
    this.id = id
}

User joins: When a user joins the room, room.setup(socket, userObj) will be called. An example how your setup function can look like.

room.prototype.setup = function (socket, userObj) {
    const user = {name: userObj.user.name, id: socket.id}
    socket.emit("hello mansion", "Hey all! I joined a room.");
}

User leaves: When a user leaves the room, room.off(socket) will be called. This is a good time to maybe update your rooms state, or remove events for the socket. Example:

room.prototype.off = function (socket) {
    socket.off(`my event`)
}

Step 2. Add your room module to the mansion before server.listen()

var http               = require('http')
var app                = require('../app')
const {socketMansion}  = require('socket-mansion')
const chat             = require('../src/chat').chat
const game             = require('../src/game').game

const modules = [
    {
        module: chat,
        name: "chat"
    },
    {
        module: game,
        name: "game"
    },
]
var server = http.createServer(app)
socketMansion(server, modules)

Step 3. Client side

The mansion has some events already created for you, so you can easily connect to your room-events. Before I show you, make sure you setup your user before using any emits.

Setup user:

socket.emit(`setup user`, userObj)  // Client emits
{id: socket.id, user: userObj}      // Server saves

Events: Here are the events, as you can see on the create room we have a third argument which is the modules name you want to use.

    socket.on('get users', (users) => {
        //receive users from mansion
    })

    socket.on('get rooms', (rooms) => {
        //receive rooms, which contains the users and the id of room
    })

    socket.emit('get users') // Triggers above
    socket.emit('get rooms') // Triggers above

    socket.emit('create room', 'name', 'chat')
    socket.emit('join room', 'name')
    socket.emit('leave room', 'name')
    socket.emit('remove room', 'name') // does not trigger .off, you should leave aswell

Step 4. Wait.. won't my room events be the same if I create a new room with the same module?

Yes you are correct, to fix this we can use the id that we get in our room constructor. Then we can do something like this

// "room chat" function on server-side
chat.prototype.message = function (socket) {
    socket.on(`message ${this.id}`, (text) => {
        // All clients in room gets this message
        this.io.sockets.in(this.id).emit(`new ${this.id}`, text)
    })
}
// client
socket.on(`new ${roomId}`, (text) => {
    console.log(text)
})
socket.emit(`new ${roomId}`, "hello!")
// hello!

Example with React

Instead of me posting lots of code, then please checkout

Chat (server)

Choose room (client)

Chat room (client)

Test your room modules easily with mocha

A test with mocha and sockets can look like this,

it('Should create room1 with chat module and have player1 and player2', (done) => {
    var client1 = io(socketURL, options);
    client1.on('connect', () => {

        var client2  = io(socketURL, options);
        client2.on('connect', () => {

            client1.emit('setup user', {name: "player1"});
            client2.emit('setup user', {name: "player2"});

            client1.emit(`create room`, `room1`, module);

            client1.emit('join room', `room1`);
            client2.emit('join room', `room1`);

            client2.on('message room1', (messages) => {
                assert.equal(messages[0].text, 'Room room1 has been created');
                assert.equal(messages[1].text, 'player1 has joined the server, welcome!');
                assert.equal(messages[2].text, 'player2 has joined the server, welcome!');

                client1.disconnect();
                client2.disconnect();
                done();
            });
        });
    });
});

Wouldn't it be great if you could remove the following,

// var client1 = io(socketURL, options);
// client1.on('connect', () => {
//
//    var client2  = io(socketURL, options);
//    client2.on('connect', () => {
//
//        client1.emit('setup user', {name: "player1"});
//        client2.emit('setup user', {name: "player2"});
//
//        client1.emit(`create room`, `room1`, module);
//
//        client1.emit('join room', `room1`);
//        client2.emit('join room', `room1`);

        client2.on('message room1', (messages) => {
            assert.equal(messages[0].text, 'Room room1 has been created');
            assert.equal(messages[1].text, 'player1 has joined the server, welcome!');
            assert.equal(messages[2].text, 'player2 has joined the server, welcome!');

            client1.disconnect();
            client2.disconnect();
            done();
        });
//    });
// });

You can use the setupRoomTest() to achieve something like this,

it('Should create room1 with chat module and have player1 and player2', (done) => {
    const testFunc = (client1, client2) => (done) => {
        client2.on('message room1', (messages) => {
            assert.equal(messages[0].text, 'Room room1 has been created');
            assert.equal(messages[1].text, 'player1 has joined the server, welcome!');
            assert.equal(messages[2].text, 'player2 has joined the server, welcome!');

            client1.disconnect();
            client2.disconnect();
            done();
        });
    };

    setupRoomTest({
        socketURL: socketURL,
        options: options,
        func: testFunc,
        done: done,
        room: 'room1',
        module: 'chat'
    });
});