@sloanfinger/socker-js

1.0.5 • Public • Published

Socker.js

An easy-to-use websocket library based on Promises with built-in support for heartbeats and storing user data. Built using ws and uuid.

Table of Contents

Installation

npm i @sloanfinger/socker-js

Examples

Getting Started:

Start by requiring the Socker class:

const { Socker } = require('@sloanfinger/socker-js');

Next, you can create a new Socker, using these options.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

Then, you can listen for when users connect.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

});

The user class is passed to the .onConnect() callback/Promise, allowing you to listen for user events, store data, and send messages to the user.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

	user.send('Hello! What is your name?');
	user.onReceive((name, stopListener) => {
		stopListener();

		user.set('name', name);
		user.send(`Hi, ${name}! Nice to meet you!`);

	});

});

Using Async/Await

If you want to create long chains/conversations between the server and the user, it's much easier to use Async/Await instead of callbacks.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect(async (user) => { // Now we're working asynchronously!

	await user.send('Hello! What is your name?');

	let name = await user.onReceive();d
	await user.send(`Hi, ${name}! How old are you?`);

	let age = await user.onReceive();
	await user.send(`Do you have a job? If so, what do you do?`);

	let job = await user.onReceive();
	await user.send(`That's cool! Do you enjoy it?`);

	// To be continued...

});

Storing Data

Data can be attached to users in the form of key-value pairs.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

	user.send('Hi! What is your name?');

	user.onReceive((name, stopListener) => {

		stopListener();

		user.set('name', name);
		user.send(`Hello, ${ user.get('name') }!`);

	});

});

Selecting Users

You can use the .getUsers() method on the Socker class to select users based on data they have stored or their ID.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

	user.send('Hi! How old are you?');

	user.onReceive((age, stopListener) => {

		stopListener();

		user.set('age', age);
		user.send(`There are ${ socker.getUsers('age >= 18').length } users who are age 18 or older.`);

	});

});

The .getUsers() method returns an array of user IDs. However, all of the events and methods that you would find attached to a regular user are available on said array.

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

	user.send('Hi! How old are you?'); // Asks user for age

	user.onReceive((age, stopListener) => { // Listens for response

		stopListener(); // Stops listening after event fires

		user.set('age', age); // Sets age to user input
		if (age >= 18) {

			user.send('Joined 18+ chat. Enter a message:');
			user.onReceive((message) => {

				// Send all 18+ users the message
				socker.getUsers('age >= 18').send('> ' + message);

			});

		}

	});

});

To get a single user based on their id, you can use .getUser().

const { Socker } = require('@sloanfinger/socker-js');

const socker = new Socker({port: 8080});

socker.onConnect((user) => {

	// These are functionally the same
	user.send('Hi!');
	socker.getUser(user.getId()).send('Hi!');


});

The .getUsers() method allows for any JavaScript comparison operators to be used. This is currently acheived by using eval(), meaning you should never use user input in the .getUsers() method.

API Docs

Class: Socker

This class is used to create/interact with the WebSocket user.

new Socker(options)

  • options {Object}
  • host {String} The path to bind the server to
  • port {Number} The port to bind the server to
  • server {http.Server|https.Server} A Node.js HTTP(S) Server
  • noServer {Boolean} Enable no server mode
  • path {String} Only accept connections from matching path
  • maxPayload {Number} The maximum size of a message in bytes
  • heartbeat {Number} How often to check for unresponsive connections

Creates a new websocket server. You must specify either port, server, or noServer, otherwise and error will be thrown. Specifying port will automatically create a new HTTP server. Specifying either server or noServer allows you to use an external HTTP(S) server. For more info, see here.

The heartbeat option changes the interval at which the server will check for unresponsive connections. After each interval, the server will ping each user. If the user does not respond (which should happen automatically) before the next interval is reached, then the connection will be stopped.

Socker is based on the ws npm package. For a comprehensive list/explanation on the above parameters (and a few more) for new Socker(), you can view the parameters for new Websocket.Server() on ws's API Docs.

Event: .onHeaders([callback])

This event is emitted before any of the response headers are written as a part of the handshake, allowing you inspect or modify the headers before they are sent. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onConnect([callback])

  • callback: {Function} Runs the given function when the event is emitted with the parameters user stopListener, and socker

This event is emitted when the handshake is complete. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onClose([callback])

  • callback: {Function} Runs the given function when the event is emitted with the parameters stopListener and socker

This event is emitted when the server closes. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onError([callback])

  • callback: {Function} Runs the given function when the event is emitted with the parameters error, stopListener, and socker

This event is emitted when the server encounters an error. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Method: .stop([callback])

  • callback: {Function} Runs the given function when the method is complete

This method will close the websocket server, if created internally, and force stop all users. Returns a promise that will resolve when the method is complete.

Method: .getUser(id)

  • id: {String} The id of the user to get

Returns the instance of the user with the given id.

Method: .getUsers(filter|ids)

Returns an instance of the User class which can be used to interact with all selected users.

The .getUsers() method allows for any JavaScript comparison operators to be used. This is currently acheived by using eval(), meaning you should never use user input in the .getUsers() method.

Class: User

This class is used to interact with the WebSocket server's user.

new User(socket, request)

  • socket: {ws.WebSocket} The socket automatically generated by ws
  • request: {http.IncomingMessage} The HTTP GET request sent by the user

Creates a new user. This is automatically passed to the callback or Promise.resolve() of the .onConnect() event of the Socker class.

Event: .onChange(key[, callback])

  • key: {String} The name of the data value stored with the user
  • callback: {Function} Runs the given function when the event is emitted with the parameters stopListener and user

This event is emitted when the any of the stored user data changes. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onReceive([callback])

  • callback: {Function} Runs the given function when the event is emitted with the parameters data, stopListener, and user

This event is emitted when the any of the stored user data changes. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onClose([callback])

This event is emitted when the user's connection closes. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Event: .onError([callback])

  • callback: {Function} Runs the given function when the event is emitted with the parameters error, stopListener, and user

This event is emitted when the user encounters an error. Returns a promise that will resolve the first time the event is emitted. Callbacks will be executed every time the event is emitted, unless stopListener() is called.

Method: .send(data[, options[, callback]])

  • data: {Any} The data to send
  • options: {Object} Options based on ws's websocket.send()
  • callback: {Function} Runs the given function when the method is complete

This method will send the specified data to the user. Returns a promise that will resolve when the method is complete.

Method: .ping([callback])

  • callback: {Function} Runs the given function when the method is complete

This method will ping the user. Returns a promise that will resolve when the method is complete.

Method: .isAlive()

Returns whether the user has responded to the most recent ping.

Method: .getId()

Returns the id of the user.

Method: .get(key)

  • key: {String} The key with which the user data is stored

Returns the data stored in the user with the given key. See: Method: .set(key, value[, readOnly])

Method: .set(key, value[, readOnly])

  • key: {String} The key with which the user data is stored
  • value: {Any} The value to store with the key in the user
  • readOnly: {Boolean} Specifies whether the data can be overriten

This method will store the value according to the key in the user. If the key already exists, the old value will be overwritten by the new value unless readOnly was set to true. The data is cached in a javascript object within the user, is not stored anywhere on the file system, and will be lost upon stopping either the user or the server.

Method: .stop([code[, reason]])

  • code: {Number} A numeric value indicating why the connection is being stopped
  • reason: {String} A human-readable string explaning why the connection is being stopped

This method will start a closing handshake.

Method: .forceStop()

This method will forcibly close the connection without a handshake.

stopListener()

This function is passed as an argument to the callback function of an event listener. When this function is called, the event listener will no longer fire.

Versions

Changelog

  • Add documentation

Future Plans

  • Client-side support for the Socker User class
  • Allow for user data storage to be easily integrated with popular Node.js Database solutions (Sqlite3, MongoDB, etc.)
  • Allow for websocket servers to be easily integrated with Express.js
  • Become dependency-free

License

MIT

Readme

Keywords

none

Package Sidebar

Install

npm i @sloanfinger/socker-js

Weekly Downloads

0

Version

1.0.5

License

ISC

Unpacked Size

32.7 kB

Total Files

5

Last publish

Collaborators

  • sloanfinger