Redbone
Socket backend for your Redux application
Install
npm install --save redbone
Quick example
Server side
const Redbone = require('redbone');
const redbone = new Redbone(io);
redbone.watch('@@server/user/GET', async function(socket, action) {
if (!action.user) throw new Error('User not found');
const user = await Model.getUser(action.user);
if (!user) throw new Error('User not found');
socket.dispatch({ '@@user/current/SET', user });
});
redbone.watch('@@server/user/SET', async function(socket, action) {
if (!action.user) throw new Error('User is undefined');
const user = await Model.setUser(action.user);
socket.dispatch({ type: '@@system/SUCCESS_SAVE', user });
})
redbone.catch((socket, action, err) => {
if (action.type === '@@server/user/GET') {
if (err.message === 'User not found') {
return socket.dispatch({
type: '@@system/SHOW_ERROR_MODAL',
title: 'User not found'
});
}
}
socket.dispatch({
type: '@@system/SHOW_ERROR_MODAL',
title: 'Server Error',
err
});
});
Client side
After create your store, just add
io.on('dispatch', store.dispatch);
All socket.dispatch(action)
at redbone watcher will perform action to client
Optionaly, you can add special middleware to redux for client → server dispatching
import serverDispatchMiddleware from 'redbone/client/getServerDispatchMiddleware';
middlewares.unshift(serverDispatchMiddleware(io));
const createStoreWithMiddlewares = compose(applyMiddleware(...middlewares))(createStore);
const store = createStoreWithMiddlewares(reducer);
serverDispatchMiddleware
takes options as second parameter. If you want to pass server-side actions to store set next
property as true
.
If you want to filter actions, set array of types to exclude
or include
property:
middlewares.unshift(serverDispatchMiddleware(io, {
next: true,
exclude: [TYPES.EXCLUDED_TYPE, TYPES.EXCLUDED_TYPE_TOO],
include: [TYPES.INCLUDED_TYPE]
}));
If you set next
as false
, filters will not work!
Watchers
If you want process some of action.type
, you can use redbone.watch
:
redbone.watch(TYPE, fn);
TYPE
— is the action.type
fn
— function to process this TYPE
.
fn
receive 2 params:
socket
— syntetic Socket instanceaction
from client with { type: TYPE }
schema.
For quick load folder with watchers you can use readWatchers(dir)
or readWatchersSync(dir)
:
./watchers/user.js
const HttpError = require('redbone/Errors/HttpError');
const db = require('../db');
async load(socket, action) {
if (!action.id) throw new HttpError(400, 'User is is not defined');
const user = await db.User.findOne({ id: action.id });
socket.dispatch({ type: '@@client/user/SETUP', user });
}
module.exports = [
{ type: "@@server/user/LOAD", action: load }
];
./socket.js
redbone.readWatchersSync(path.join(__dirname, './watchers/'));
Maybe you want use your custom logic for setup several watchers? Ok, just use processWatchers(watchers)
method
Middlewares
Just use use
method of Redbone instance =).
redbone.use((socket, action) => {
if (!action.token) throw new HttpError(403, 'Invalid token');
});
If you want stop middleware, just return false
from it:
redbone.use((socket, action) => {
if (action.type === '@@server/CONSOLE_LOG') {
console.info(action.log);
return false;
}
});