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

dinamic-socket

v1.1.0

Published

Buscador dinâmico para socket.io, inspirado no dinamicfetch, com ele você pode deixar mais fluido seu trabalho de salvar dados em loja, configurar ouvinte e emissão de eventos

Downloads

42

Readme

Instalação

    npm install --save dinamic-socket

O que é o dinamic-socket ?

Muitas vezes fazemos nossas chamadas websocket na mão. Tendo em vista isso, é meio cansativo configurar como os dados devem ser manipulados.

É aí que entra o dinamic-socket, buscador dinâmico para socket.io, inspirado no dinamicfetch, com ele você pode deixar mais fluido seu trabalho de salvar dados em loja, configurar ouvinte e emissão de eventos. Utilizando ganchos personalizados e outras formas.

Que metodologia ele trás?

Para você entender a metodologia dele, sugiro ler esse mesmo tópico no pacote dinamicfetch

Como usar?

Tendo em vista a metodologia, partiremos para o uso.

Método create

    // socket.config.js
    import dinamicsocket, {io, create, on, emit} from 'dinamic-socket';

    let socket = create({
        host:'https://host:port', //obrigatório
        store:Store,//opcional
        namespace:'/seu_namespace', //opcional, ficará assim https://host:port/seu_namespace
        options:{}, //opcional, opções do io.connect(<host>, <options>)
        io:require('socket.io-client'), //opcional, caso eu queira passar uma outra versão do socket.io externamente, pois nesse pacote estou utilizando a v3.1.1
        removeListener:true, // Padrão true, se verdadeiro, o dinamic-socket removerá ouvintes repetidos automaticamente, é útil se você não quer duplicar eventos
        onStart(data){

            /*
                data retorna:

                para data.type do tipo 'on':
                {
                    <host> -> host usado.
                    <namespace> -> namespace usado.
                    <options> -> opções usadas no socket.io no método connect
                    <isHook> -> define se o ouvinte é um gancho ou não
                    <type> -> retorna o tipo de onSuccess, se ele veio de um ouvinte "on" ou se uma emissão "emit".
                    <socket> -> instância do socket.
                    <name> -> endpoint usado por essa solicitação
                    <model> -> model usado na solicitação
                    <key> -> key usada por essa solicitação
                    <remove>
                }
                para data.type do tipo 'emit':
                {
                    <host> ->
                    <namespace> ->
                    <options> ->
                    <type> ->
                    <socket> ->
                    <name> ->
                    <model> ->
                    <key> ->
                    <remove> ->
                    <overwrite> ->
                    <body>
                }
            */
            
        },
        onSuccess(data){
            /*
                data retorna:

                {
                    <type> -> retorna o tipo de onSuccess, se ele veio de um ouvinte "on" ou se uma emissão "emit".
                    <data> -> dados retornados do servidor.
                    <host> -> host usado.
                    <namespace> -> namespace usado.
                    <options> -> opções usadas no socket.io no método connect
                    <shaper> -> dados modelados.
                    <name> -> endpoint usado por essa solicitação
                    <key> -> key usada por essa solicitação
                    <model> -> model usado na solicitação
                    <remove>
                }
            */
        },
        onError(err){
            /*
                usado apenas para emit
                retorna um erro personalisado se houver
            */
        }
    });

    /*
        socket retorna:

        {
            <create>, // o método create.
            <on>, //ouvinte de evento personalisado do dinamic-socket.
            <$on>, //gancho de evento personalisado do dinamic-socket.
            <emit> // emissor de evento personalisado do dinamic-socket.
            <socket> //instância do socket.
        }
    */

usos do método on

    import socket, {on} from 'socket.config.js';

    let listen = on('<name>', '<model>', '<key>', '<remove>', '<callback>');

    /*
        name -> simplesmente é o endpoint da chamada.
        model -> é o model a ser utilizado da store para tratamento de dados. Obs: ver os casos de uso de dinamicfetch pra entender melhor.
        key -> se passado indico que quero alterar o determinado model da store com base nos dados que estou enviando do servidor.
        remove -> se passado em conjunto com a key, indica que quero remover um determinado item da store com base na key. Ele é um booleano, pode ser como true/false ou um array caso eu use múltiplos model [true/false, false/true]
        callback -> retorna todos os dados visto em create->onSuccess
    */

    /*
        liten retorna:

        {
            removeListener -> uma função responsável por remover o ouvinte, se removeListener estiver como false no método create, utilizar esse retorno quando for desmontar um componente

            socket -> a instância do socket atual
        }
    */

    //outra forma de usar

    on({
        name:/*endpoint*/,
        model:/*model*/,
        key:/*key*/,
        remove:/*remove*/,
        callback:/*callback*/
    });

    /*
        você também pode controlar o key, remove e overwrite através do servidor também. Por exemplo:

        -------------------------------------------------------------------
        //server.js

        io.on('connection', socket=>{
            io.emit('users', {id:1, name:'Rodrigo'}, {key:'id', remove:true});

            //ou

            io.emit('users', {id:1, name:'Rodrigo'}, {overwrite:true});
        })

        -------------------------------------------------------------------

        o primeiro parâmetro é o endpoint, o segundo é os dados que vou enviar a esse endpoint, o terceiro é o controle do meu dinamic-socket.
        É importante manter esse padrão.
    */

usos do método emit

    import socket, {emit} from 'socket.config.js';

    socket.emit('<name>', '<body>', '<model>', '<key>', '<remove>', '<overwrite>', '<configs>'); //retorna uma promisse

    /*
        name -> simplesmente é o endpoint da chamada.
        body -> equivalente ao body de requisições http
        model -> é o model a ser utilizado da store para tratamento de dados. Obs: ver os casos de uso de dinamicfetch pra entender melhor.
        key -> se passado indico que quero alterar o determinado model da store com base nos dados que estou enviando do servidor.
        remove -> se passado em conjunto com a key, indica que quero remover um determinado item da store com base na key.
        overwrite -> indica se quero que os dados vindo do servidor sobrescreva meu model
    */

    //outra forma de usar

    socket.emit({
        name:/*endpoint*/,
        body:/*body*/,
        model:/*model*/,
        key:/*key*/,
        remove:/*remove*/,
        overwrite:/*overwrite*/
    });

usos como hook

    import socket, {$on} from 'socket.config.js';

    let data = $on('<name>', '<model>', '<key>', '<remove>', '<callback>');

    /* 
        data retorna todos os dados vistos em create->onSuccess + removeListener e socket
    */

Estruturando o lado do servidor

O que vou mostrar abaixo não é obrigatório para você usar o dinamic-socket (exceto um detalhe que há lá em baixo) mas sim uma sugestão de como você pode arquitetar seu socket.io no lado do servidor.

Estruturas de pastas e arquivos.

  • socket
    • controller
      • private
        • todos os endpoints privatos
      • public
        • todos os endpoints públicos
      • global
        • todos os endpoints global
    • index.js

Dentro de cada pasta private, public, global posso criar os arquivos que eu quiser.

Agora vamos trabalhar o index.js

    let glob = require('glob');
    let path = require('path');

    module.exports = (io) => {
        
        // ------------------------------------------socket privado-----------------------------------------------------------------------
        io.of('/private').use((socket, next) => {
            
            let query = socket.handshake.query;
            let {token} = query;
            
            if(query && token){
                try{
                    /* 
                        Aqui você faz sua verificação de login para sockets privados, pode usar o jwt se quiser, eu costumo usar ele para token.
                        Se as validações ocorrerem corretamente você chama o next().
                        Se não, você emite um evento de erro para o endpoint destino.
                     */
                }catch(err){
                    
                }
            }
        }).on('connection', (socket)=>{

            //uso o glob para lstar todos os arquivos do diretório passado e em seguida importa-los.
            glob.sync(path.join(__dirname, "controller", 'private', '*.js')).forEach(e=>{
                require(e)(io, socket);
            });
        });

        // ------------------------------------------socket público-----------------------------------------------------------------------
        io.of('/public').on('connection', (socket) => {

            glob.sync(path.join(__dirname, "controller", 'public', '*.js')).forEach(e=>{
                require(e)(io, socket);
            });
        });

        // ------------------------------------------socket global-----------------------------------------------------------------------
        io.of('/').on('connection', (socket) => {

            glob.sync(path.join(__dirname, "controller", 'global', '*.js')).forEach(e=>{
                require(e)(io, socket);
            });
        });
    }

No seu app.js, arquivo raiz da aplicação em muitos casos, você chama require('./socket')(io);

Fazemos assim dentro dos diretórios por exemplo. Essa é só uma ilustração, você pode separar as camadas em controller, services e repository

    // controller/private/teste.js
    module.exports = (io, socket)=>{
        socket.on('endpoint-test', async (data, callback)=>{
            /* 
                Quando for usar callback passe assim callback(<data>, <error>);
                O primeiro parâmetro é os dados que você quer emitir e o segundo é erro se ouver.
                Se não tiver erro, passe o segundo parâmetro como nulo e vice-versa.

                Essa regra é obrigatório para o callback do socket.emit do client funcionar bem.
             */
        })
    }

Casos de uso

Mais uma vez atento olhar a doc do dinamicfetch para entender o metodologia por trás do dinamic-socket. Os retorno de dados do servidor para client funciona de maneira semelhante ao pacote mencionado, a diferença é que eu incluo um control em certos casos. Por exemplo:

    io.emit('users', {id:1, name:'Rodrigo'}, {key:'id', remove:true});

    //ou

    io.emit('users', {id:1, name:'Rodrigo'}, {overwrite:true});

O terceiro parâmetro de envio também controla sobre como os dados irão se comportar. Fora isso, os padrões de envio de solicitação é o mesmo do dinamic-fetch, no caso aqui, serve tanto para io.emit como para callback.