npm package: @loserboy/socket
Description: A small, fast & clean WebSocket library for Node.js and browser
Author: l0s3rboy
Latest version: 1.0.0

[![npm](http://img.shields.io/npm/v/@loserboy/socket.svg)](https://www.npmjs.com/package/@los3rboy/socket)
[![release](https://img.shields.io/github/release/los3rboy/socket.svg)](https://github.com/los3rboy/socket)
[![license](http://img.shields.io/npm/l/@loserboy/socket.svg)](https://github.com/los3rboy/socket/blob/main/LICENSE)

> © 2023-2024, Elcidio Atianor ([@los3rboy](https://github.com/los3rboy)). MIT License.

# Socket

**Socket** is a **small**, **fast**, **simple** WebSocket library for Node.js and the browser. 

### Core Features

- **Fast**, **small** and easily integrable
- Simple and clean API (inspired on Socket.io & express)
- Uses pure **WebSocket** transport (no polling or XMLHttpRequest)
- Gives developer full controll over request **authentication** or **upgrade** logic
- Supports **reconnection** and message **broadcasting**
- Thoroughly **tested**
- Written in pure Vanilla JavaScript (no unnecessary code added by language frameworks)

## Installation

With **npm**:
```js
npm i @loserboy/socket --save
```  

## Guide

```js
//Node.js
const {Sever, Router} = require('@loserboy/socket');

// or:
import {Sever, Router} from '@loserboy/socket';

//Client
import {Socket} from '@loserboy/socket/dist/socket.esm.min.js';

// or:
<script src='/node_modules/@loserboy/socket/dist/socket.umd.min.js></script>
```

### Basic Example

Create a server and a router to listen fo connections on [/socket](ws://localhost:3000/socket).

```js
//Server
const http = require('node:http');
const {Server, Router} = require('@loserboy/socket');

const httpServer = http.createServer((req, res) => {
    //some smart code
})

//create a simple authentication/upgrade function (your own)
function authRequest(req, netSocket, done) {
    //do some authentication tasks here and get some data useful for your application 
    let cookies = cookie.parse(req.headers['cookie'])
    let jwtToken = cookies['jwt'];
    
    if (!jwtToken) return done(new Error('Failed to get authentication token from cookie'))
    jwt.verify(jwtToken, process.env.JWT_SECRET, jwtOptions, (err, payload) => {
        //pass an error abort request upgrade
        if (err) return done(err);
            User.findOne({ username: payload.username })
                .then(user => {
                    let {firstName, lastName} = user;
                    //any data useful for your application (pass as second argument)
                    done(null, {firstName, lastName});
                })
                .catch(done)
        });
}

//create a Socket server
const server = new Socket(httpServer, {
    //pass your auth/upgrade function here 
    onSocketUpgrade: authRequest
})

//create a simple router
const router = new Router();

//listen to some events
router.on('connection', (socket) => {
    //listen to custom events
    socket.on('answer', (answer) => {
        console.log('Client said: ' + answer);
    })
    socket.on('another event', (...args) => {
        //another action
    })
    
    //or internal events...
    socket.on('error', (err) => {
        //take actions
    })
    
    //sending events to the client
    socket.emit('greeting', 'Hello socket!'); //to socket
    socket.cast.emit('anouncement', 'Hey buddies, I greet you all!'); //to another sockets
    socket.to('someSocketId').emit('private message', 'Hi buddy!'); //to a specific socket
    socket.to(['someSocketId', 'someOtherId']).emit('private message', 'Hi buddy!'); //to a specific socket
})

//let router listen to socket connections
//e.g. ws://localhost:3000/socket
server.use('/socket', router);
server.use('/socket', anotherRouter); //multiple routers on same path
server.use('/another_path', [router, anotherRouter], someOtherRouter); //Arrays, commas also work

//start your server
httpServer.listen(3000)
```

### Client example

Assuming you've already loaded the client-side socket:

```js
const socket = new Socket('wss://localhost:3000/socket'); //or simply /socket
// ...
socket.on('connect', () => {
    //start emiting events
})

socket.on('greeting', (greeting) => {
    console.log(greeting);
    socket.emit('answer', 'Hello server!');
})

socket.emit('another event', ...args)
socket.close()
```

### Routers

Create routers to listen to connections on specific path by the router constructor
- Routers can emit & broadcast events to sockets or another routes
**NOTE:** Routers can not listen to custom events (emitted by client sockets)

```js
// router send & broadcast events
router.emit('greeting', 'Hello all sockets!'); //to all socket in this route
router.to('someSocketId').emit('private message', 'Hi buddy!'); //to a specific socket
router.to('/routeOrPath').emit('anouncement', 'Hu ho!'); //to a specific route or path
```

## Documentation

The full **API reference** with lots of details, features and examples is coming soon.

## Changelogs

See [CHANGELOG][changelog] for complete list of changes.

## Contributing

Clone project's github repository:

```sh
git clone https://github.com/los3rboy/socket.git
```

Install dependencies:

```sh
npm install terser rollup -g
```

Add tests to relevant file under [test](test/) directory and run:  

```sh
npm run build && npm run test
```

## License

[**MIT**][license]

[changelog]:https://github.com/los3rboy/socket/blob/main/CHANGELOG.md
[license]:https://github.com/los3rboy/socket/blob/main/LICENSE