JWJS
Purpose
To allow a django-like system for building apps. Also includes libraries for building sockets and managing api calls.
Bonus:
There's also a function to allow fake api calls, triggered using TEST_API
and
creating mock_views.js
in your app.
Usage
You build apps breadth-wise across your system. Create a folder for each app you wish to use. i.e.
users
chats
etc...
The apps
// @param dataOpts: a dict containing two vars, {TEST_API, initialState}
export default {
config: (dataOpts) => ({
reducers: {...app reducers},
sagas: [...app sagas],
initialState: {... data that aligns with the reducers},
init: [...list of functions to execute post store-building]
})
}
General Settings
Where reducers, sagas, etc are imported from the app. And then somewhere on the main page, include:
export const {settings, storeOpts, API} = jwjs.configure({
APPS: {users, chats, ...},
'STORE_DATA': {initial data (if any) matching the apps' reducers},
'API_OPTS': {
'ROOT_URL': 'Where your api will connect to',
'HEADERS': { A dict of headers passed to each request (csrf, app_key, etc) }
},
'SOCKET_OPTS': {
'ROOT_URL': 'ws[s]://your-socket-domain-here'
}
})
The above will provide info for every api call and socket connection.
The Store
The store is managed by jwjs. You pass the store opts created by configure
and any third party reducers, sagas, middlewares. It gets built like so:
import {buildStore} from 'jwjs';
import {storeOpts} from './settings'; // settings built from settings
export default buildStore({
storeOpts,
// third party additions go here.
// i.e. redux-form, redux-form-saga, react-router-redux
reducers: {
'form': formReducer,
'routing': routerReducer
},
sagas: [
formActionSaga,
],
middlewares: [
routerMiddleware(browserHistory)
]
})
Api
Using the settings passed into configure, you can make api calls using sagas. The engine currently used is Axios. (This may be extended/modified in future) A typical api call will look like:
import {API} from '../path/to/settings';
// this will be called by a saga-fork
function* apiCall(){
try {
let resp = yield call(API.post, '/api/endpoint/', data)
} catch(errors) {
// Handle errors on request
}
}
Sockets
Comes with a built in socket relay system. This is handled by redux-saga:eventChannel. Currently only uses the native websocket, accompanied by ReconnectingSocket. The different saga calls are outlined below.
SOCKET.INIT
Usage:
yield put({type: 'SOCKET.INIT', payload: {socket_access}})
Will connect to the endpoint provided in settings.SOCKET_OPTS.ROOT_URL
at
<root_url>/<socket_access>
. See jwjs-io
for how to handle the endpoint.
SOCKET.PUBLISH
Usage:
yield put({type: 'SOCKET.PUBLISH, payload: {
sender: {id},
payload: {...body of the request to process/relay},
recipients: [list of ids to relay to],
triggers: 'Reducer action',
notToSender: true|FALSE - false by default
}})
Using the above payload, you can send whatever you like to the listed recipients (assuming they have an active connection). The trigger is the saga/reducer action that is triggered on receipt of the payload. This will be consistent between the sender and recipients.
SOCKET.DISCONNECT
Usage:
yield put({type: 'SOCKET.DISCONNECT'})
Will send a message to the socket server to disconnect the currently running connection.
Events
These are pretty self explanatory
- SOCKET.DISCONNECTED
- SOCKET.CONNECTED
- SOCKET.CONNECTION_ERROR