@novice1/socket - v0.4.9
    Preparing search index...

    @novice1/socket - v0.4.9

    @novice1/socket

    Simplifies building server-side Socket.IO applications. It provides:

    • Namespace builders to group events under a namespace.
    • Event handlers with middleware support, so you can chain logic per event.
    • Application lifecycle hooks such as connection and disconnect handling.
    • Utilities for building robust real-time communication.

    Install the package together with socket.io, which is a peer dependency and must be installed in your project:

    npm install @novice1/socket "socket.io@^4.8.4"
    

    If you already have socket.io 4.8.4 or later in your project, you only need:

    npm install @novice1/socket
    
    import { NspBuilder, createServerApp } from '@novice1/socket';
    import { createServer } from 'http';

    const http = createServer();

    // create namespace and add events to it
    const defaultNamespace = new NspBuilder()
    .add('chat message', function (req, res, next) {
    const msg = req.data[0];
    console.log('message: ' + msg);
    res.of().emit('chat message', msg);
    })
    .add('disconnecting', function (req, res, next) {
    console.log('user disconnecting');
    });

    // create application
    const socketApp = createServerApp()
    .onConnection((socket, nsp) => {
    // socket.use(fn)
    // socket.join(room[, callback])
    // socket.disconnect(close)

    // Inherited from EventEmitter (along with other methods not mentioned here).
    // See Node.js documentation for the events module.
    // socket.once(eventName, listener)
    // socket.removeListener(eventName, listener)
    // socket.removeAllListeners([eventName])
    // socket.eventNames()

    console.log('a user connected');
    })
    .onDisconnect((reason, socket, nsp) => {
    console.log('user disconnected');
    })
    .link(defaultNamespace); // link namespace to the application

    // build the application
    socketApp.build(http);

    // start server
    http.listen(3000, function () {
    console.log('listening on *:3000');
    });

    Bun is supported through the @socket.io/bun-engine package. See the Socket.IO Bun engine announcement for background.

    bun add @socket.io/bun-engine
    
    import { createServerApp } from '@novice1/socket';
    import { Server as Engine } from '@socket.io/bun-engine';

    const socketApp = createServerApp()
    .onConnection((socket, nsp) => {
    // ...
    })
    .onDisconnect((reason, socket, nsp) => {
    // ...
    })
    .build();

    // Bun engine instance. CORS configuration is optional.
    const engine = new Engine({
    path: '/socket.io/',
    cors: {
    origin: '*',
    methods: ['GET', 'POST'],
    },
    });

    socketApp.getServer()?.bind(engine);

    export default {
    port: 3000,
    ...engine.handler(),
    };

    When setting a namespace you can define the name otherwise it will be '/' by default

    import { NspBuilder } from '@novice1/socket';

    const defaultNamespace = new NspBuilder(); // same as new NspBuilder('/')

    const appNamespace = new NspBuilder('/app');

    You can add an event listener to a namespace with the method 'add'. It uses the method chaining pattern. The first argument is the event's name. The other arguments must be the functions to execute. Multiple functions can be executed. Each function receives three parameters:

    import { NspBuilder } from '@novice1/socket';

    const appNamespace = new NspBuilder('/app').add(
    'my event',
    function one(req, res, next) {
    // do something
    next(); // defer execution to the next function ('two')
    },
    function two(req, res) {
    // do something
    }
    );

    // also
    appNamespace.add(
    {
    name: 'event name',
    description: 'short description',
    tags: ['Example'],
    },
    function (req, res) {
    // do something
    }
    );

    It is an object with the following properties:

    • data : Array of data sent through the event
    • event : the event's details (name, description, tags)
    • nsp : Namespace
    • socket : Socket
    • handshake : Socket.handshake

    Can be used to emit an event from a socket, a room or a namespace

    Example

    import { NspBuilder } from '@novice1/socket';

    new NspBuilder('/app')
    .add('respond from socket', function one(req, res, next) {
    const msg = req.data[0];

    // examples from socket and room
    res.emit('chat message', msg);
    res.volatile.emit('chat message', msg);
    res.broadcast.emit('chat message', msg);
    res.compressed.emit('chat message', msg);
    res.notCompressed.emit('chat message', msg);
    res.in('room1').emit('chat message', msg);
    res.to('room1').emit('chat message', msg);
    })
    .add('respond from namespace', function (req, res) {
    const msg = req.data[0];

    // examples from namespaces and room
    res.of().emit('chat message', msg); // from current namespace
    res.of('/chat').emit('chat message', msg); // from '/chat' namespace
    res.of().volatile.emit('chat message', msg);
    res.of().local.emit('chat message', msg);
    res.of().in('room1').emit('chat message', msg);
    res.of().to('room1').emit('chat message', msg);
    });

    The advantage with ListenerBuilder is that you can define the callback (ErrorController) to be called when you execute the "next" callback with an argument that evaluates to true.

    Example

    import { NspBuilder, ListenerBuilder } from '@novice1/socket';

    const listenerBuilder = new ListenerBuilder(
    'eventName',
    (req, res, next) => {
    if (req.data[0]) {
    // not ok, call ErrorController
    next(new Error('missing message'));
    } else {
    // ok, defer
    next();
    }
    },
    (req, res) => {
    // done
    }
    ).setErrorController((err, req, res) => {
    // not ok, do something
    });

    new NspBuilder('/app').add(listenerBuilder);

    Example

    import { NspBuilder } from '@novice1/socket';

    new NspBuilder().use((socket, next) => {
    if (socket.request.headers.cookie) {
    return next();
    }
    next(new Error('Authentication error'));
    });

    See namespace.use(fn)

    Register a middleware to all sockets of a namespace.

    Example

    import { NspBuilder } from '@novice1/socket';

    new NspBuilder().add((socket, packet, next) => {
    if (packet.doge === true) return next();
    next(new Error('Not a doge error'));
    });

    See socket.use(fn)

    A namespace can be linked to another namespace. That way the name of the one being linked will be the concatenation of the namespace linking it and its own. The first argument can also be another string to use in the concatenation.

    Example

    import { NspBuilder, createServerApp } from '@novice1/socket';
    import { createServer } from 'http';

    const http = createServer();

    const main = new NspBuilder('/main');

    const app = new NspBuilder('/app');

    main.link('/v1', app);

    createServerApp()
    .link(main) // same as link('/', main)
    .build(http);
    // the namespaces created will be '/main' and '/main/v1/app'

    http.listen(3000, function () {
    console.log('listening on *:3000');
    });

    When setting the application, you link the namespaces that will be used to build the socket.io server. You can also limit the namespaces used to build the server.

    Example

    import { NspBuilder, createServerApp } from '@novice1/socket';

    const appNsp = new NspBuilder('/app');
    const otherNsp = new NspBuilder();

    createServerApp().link(appNsp).link('/other', otherNsp);
    // the namespaces created will be '/app' and '/other'

    createServerApp(['/main']) // limit to '/main'
    .link(appNsp)
    .link('/other', otherNsp); // useless
    // the namespaces created will be '/main'

    It will build the socket.io server from a http server. The settings (namespaces, etc ...) need to be set before the build.

    import { NspBuilder, createServerApp } from '@novice1/socket';
    import { createServer } from 'http';

    const http = createServer();

    const appNsp = new NspBuilder('/app');

    createServerApp().link(appNsp).build(http); // build socket.io server

    http.listen(3000, function () {
    console.log('listening on *:3000');
    });

    Get a description of events listened by namespaces with the property events.

    import { createServerApp } from '@novice1/socket';

    const app = createServerApp();

    // do something

    console.log(app.events['/']);
    // displays an array of events listened in the namespace '/'

    Get an array of the active namespaces (= created on the server) with the property activeNamespaces. You can also get one namespace with the method getNamespace.

    import { createServerApp } from '@novice1/socket';
    import { createServer } from 'http';

    const http = createServer();

    const app = createServerApp();

    // do something

    app.build(http);

    console.log(app.activeNamespaces);
    // displays an array of strings

    const nsp = app.getNamespace('/');
    // get namespace '/' from socket.io server

    You can disconnect all clients and stop handling future connections by executing the method destroy. To rebuild the application you can call the method build with no arguments.

    import { createServerApp } from '@novice1/socket';
    import { createServer } from 'http';

    const http = createServer();

    const app = createServerApp();

    // do something

    app.build(http);

    http.listen(3000, function () {
    console.log('listening on *:3000');

    app.destroy();
    // all connections closed and no future connections

    app.build();
    // connection possible again
    });

    Closes the Socket.IO server and the underlying HTTP server.

    • add(...fn) : this
    • add(string, ...fn) : this
    • add(object, ...fn) : this
    • add(...NspBuilder) : this (alias for "link"method)
    • add(string, ...NspBuilder) : this (alias for "link"method)
    • getPaths() : string[]
    • getEvents() : object
    • link(...NspBuilder) : this
    • link(string, ...NspBuilder) : this
    • use(...fn) : this
    • adapter
    • add(...fn) : this
    • add(string, ...fn) : this
    • add(object, ...fn) : this
    • add(...NspBuilder) : this (alias for "link" method)
    • add(string, ...NspBuilder) : this (alias for "link"method)
    • build([http.Server|options]) : this
    • build(port|http.Server[, options]) : this
    • close
    • destroy() : this
    • getNamespace(string) : Namespace
    • link(...NspBuilder) : this
    • link(string, ...NspBuilder) : this
    • use(...fn) : this
    • onConnection(..fn) : this
    • onDisconnect(..fn) : this
    import { NspBuilder, utils } from '@novice1/socket';

    const { explodeData } = utils;

    const defaultNamespace = new NspBuilder().add(
    'chat message',
    explodeData(function (msg) {
    // - this.req
    // - this.res
    // - this.next
    console.log('message: ' + msg);
    this.res.of().emit('chat message', msg);
    })
    );
    import { NspBuilder, utils } from '@novice1/socket';

    const { errorHandler } = utils;

    const defaultNamespace = new NspBuilder().add(
    'chat message',
    errorHandler(function (req, res) {
    // do something that could throw an error
    }, 'chat error')
    );
    // a message will be emitted on 'chat error' if an Error is thrown

    Other examples

    import { NspBuilder, utils } from '@novice1/socket';

    const { errorHandler, explodeData } = utils;

    const defaultNamespace = new NspBuilder().add(
    'chat message',
    errorHandler(
    explodeData(function (msg) {
    // do something
    }),
    'chat error'
    )
    );