0.0.6 • Published 5 years ago
supercharged v0.0.6
Supercharged is a set of abstractions for building robust client-server interfaces.
The library is split into three submodules:
client
- Client-side (React) abstractions for exchanging data with the serverserver
- Interfaces and utilities for the server (Express)shared
- Constants and other primitive data common to both the client and server
Architecture
The abstractions provided by this library make a few assumptions:
- Data is passed between the server and client as JSON over HTTP, or as strings over WebSocket
- The client-side code uses React and higher-order components
- The HTTP API exposed by the server is RESTful, exposing routes as resources with CRUD operations encapsulated in HTTP verbs
That said, this library provides:
- Client input payload validation with ajv
- Declarative interface for defining resources (routes) and their behaviors (HTTP verbs) on the server
- Abstractions for bidirectional communication over WebSockets
- Robust/fault-tolerant HTTP and WebSocket network call abstractions with HOCs on the client
- Standardized interface for communicating error states between the server and client
Installation
# Primary dependency
$ npm install --save supercharged
# Peer dependencies
$ npm install --save @babel/core @babel/plugin-proposal-decorators express react
supercharged
makes use of decorators in the server-side code. Add the following entry in .babelrc
:
"plugins": [
+ ["@babel/plugin-proposal-decorators", {"legacy": true}],
...
]
Usage
Server
Expose HTTP APIs and WebSocket tunnel endpoints on the server by defining routes with corresponding handlers:
import { HTTPHandler, WebSocketHandler, route, withSchema } from 'supercharged/server';
@route('/api/echo')
class EchoHTTPHandler extends HTTPHandler {
@withSchema({
properties: {
echo: {
type: 'string',
},
},
required: ['echo'],
})
post({ echo }) {
if (echo.length > 5) {
return this.success({
data: echo,
});
}
return this.error({
data: 'Echo text too short!',
});
}
}
@route('/ws/echo')
class EchoWebSocketHandler extends WebSocketHandler {
onMessage(message) {
this.sendMessage(message);
}
}
Initialize your Express application with the defined handlers:
import Express from 'express';
import { supercharge } from 'supercharged/server';
const app = Express();
supercharge(app, [EchoHTTPHandler, EchoWebSocketHandler]);
app.listen(3000);
Client
Create a higher-order component that calls the server-defined HTTP API:
import React, { Component } from 'react';
import { withResource } from 'supercharged/client';
class EchoComponent extends Component {
state = { text: '' };
render() {
const { echo: { invoke, data } } = this.props;
const { text } = this.state;
return (
<div>
<p>Most recent echo response: {data}</p>
<input
type="text"
value={text}
onChange={({ target: { value } }) => this.setState({ text: value })}
/>
<button onClick={() => invoke({ echo: text }))}>
Invoke echo endpoint
</button>
</div>
);
}
}
export default withResource({
key: 'echo',
method: 'POST',
endpoint: '/api/echo',
invokeOnMount: false,
})(EchoComponent);
For the WebSocket tunnel:
import React, { Component } from 'react';
import { withTunnel } from 'supercharged/client';
const EchoComponent = ({ echo: { sendMessage, messages } }) => (
<div>
<p>Messages sent from the server:</p>
{messages.map((message) => <p>{message}</p>)}
<button onClick={() => sendMessage('hello')}>Send message</button>
</div>
);
export default withTunnel({
key: 'echo',
endpoint: '/ws/echo',
})(EchoComponent);