Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@workpop/optimistic-middleware

Package Overview
Dependencies
Maintainers
6
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@workpop/optimistic-middleware - npm Package Compare versions

Comparing version 0.3.0 to 1.0.0

CHANGELOG.md

65

dist/middleware.js

@@ -15,58 +15,59 @@ 'use strict';

var OPTIMISTIC = {
START: 'OPTIMISTIC_UPDATE_START',
ERROR: 'OPTIMISTIC_UPDATE_FAILURE',
SUCCESS: 'OPTIMISTIC_UPDATE_SUCCESS'
};
function optimisticMiddleware(store) {
return function (next) {
return function (action) {
var storeState = store.getState();
var simulate = action.simulate;
var onSuccess = action.onSuccess;
var onError = action.onError;
var errorType = action.errorType;
var mutation = action.mutation;
var async = action.async;
var stateKey = action.stateKey;
var type = action.type;
var data = action.data;
var type = action.type;
var optimistic = action.optimistic;
var rest = _objectWithoutProperties(action, ['onSuccess', 'onError', 'errorType', 'mutation', 'stateKey', 'data', 'type']);
// get the previous state before we start
var rest = _objectWithoutProperties(action, ['simulate', 'onSuccess', 'onError', 'async', 'stateKey', 'type', 'data', 'optimistic']);
// if we don't have a mutation, proceed like normal
var previousState = storeState && storeState[stateKey] && storeState[stateKey].data;
// if we don't have a mutation, proceed like normal
if (!mutation) {
if (!optimistic) {
return next(action);
}
// get state of the world before mutation
var storeState = store.getState();
// get the previous state before we start
var previousState = storeState && storeState[stateKey] && storeState[stateKey].data;
// apply the optimistic update first. This is described in our reducer for this actionType
next(_extends({
type: type,
data: data,
optimisticState: OPTIMISTIC.START
}, rest));
// if there is a simulation function, run the simulation with dispatch and data from the action bound to it.
if (isFunction(simulate)) {
simulate(next, data);
} else {
// otherwise dispatch the type with the data passed to the action creator
next(_extends({
type: type,
data: data
}, rest));
}
// next we're going to call our mutation, because we're in a Meteor context, we are expecting a callback with e,r
return mutation(function (error, result) {
return async(function (error, result) {
// if there is an error we need to revert our state back to the initial state before middleware ran
if (error) {
// if the user supplies an onError callback as a function, call their function with
// dispatch, the previousState, and the error we received
if (isFunction(onError)) {
onError(error);
return onError(next, previousState, error);
}
// if not, automatically pass the original type action the previousState as data
return next({
error: error.reason,
data: previousState,
optimisticState: OPTIMISTIC.ERROR,
type: errorType || type
type: type
});
}
// apply our update again but this time, change the OPTIMISTIC state
if (isFunction(onSuccess)) {
onSuccess(result);
// if the user supplies a onSuccess callback as a function, call their function with
// dispatch and the result of our async cal
if (!isFunction(onSuccess)) {
return false;
}
return next({
type: type,
optimisticState: OPTIMISTIC.SUCCESS,
data: data
});
return onSuccess(next, result);
});

@@ -73,0 +74,0 @@ };

{
"name": "@workpop/optimistic-middleware",
"version": "0.3.0",
"version": "1.0.0",
"description": "Optimistic Methods Middleware for Redux",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -42,2 +42,3 @@ # Optimistic Middleware

#### Generic Optimistic Action Creator
```js

@@ -47,11 +48,97 @@ function optimisticAddTodo(text) {

type: 'ADD_TODO',
data: text,
stateKey: 'todos',
mutation(cb) {
async(cb) {
return Meteor.call('addTodo', text, cb);
},
data: text
}
}
}
```
#### Functional Simulation
the simulate function will allow you to customize your simulations.
```js
function optimisticAddTodo(text) {
return {
type: 'ADD_TODO',
data: text,
simulate(dispatch, data) {
dispatch({
type: 'ADD_TODO_ID',
data: _.get(data, '_id');
});
return dispatch({
type: 'ALL_TODOS',
data
});
}
stateKey: 'todos',
async(cb) {
return Meteor.call('addTodo', text, cb);
}
}
}
```
#### Custom Errors
```js
function optimisticAddTodo(text) {
return {
type: 'ADD_TODO',
data: text,
onError(dispatch, prevState, error) {
if (error.reason === 'you suck') {
dispatch({
type: 'TODO_ERROR',
data: error.reason
});
}
return dispatch({
type: 'ADD_TODO',
data: prevState
});
}
stateKey: 'todos',
async(cb) {
return Meteor.call('addTodo', text, cb);
}
}
}
```
#### Custom onSuccess
```js
function someThunk(result) {
return (dispatch) => {
someOtherAsync(result,(e, result) => {
if (e) {
console.error('ERROR');
}
dispatch({
type: 'TOGGLE_TODO_LIST',
data: result
});
});
}
}
function optimisticAddTodo(text) {
return {
type: 'ADD_TODO',
data: text,
onSuccess(dispatch, result) {
dispatch(someThunk(result));
}
stateKey: 'todos',
async(cb) {
return Meteor.call('addTodo', text, cb);
}
}
}
```
Let's break down our action shape:

@@ -63,3 +150,3 @@

stateKey: string,
mutation: Function,
async: Function,
data: any

@@ -73,5 +160,9 @@ }

2. `[stateKey] - key of reducer related to action`
3. `[mutation] - asynchronous function intended to mutate some data on the server`
3. `[async] - asynchronous function intended to make mutation/remote call to the server`
4. `[data] - data needed to change the state in the reducer`
5. `[onSuccess] - function to be called when async function returns *optional`
6. `[simulate] - function be called to simulate the optimistic update *optional`
7. `[onError] - function to be called when the async function returns an error *optional`
## How this works:

@@ -81,20 +172,15 @@

We start the dispatch process immediately executing the data change in the action to the reducer. The state is appended with `OPTIMISTIC_UPDATE_START`, to signal the start of our dispatch.
We start the dispatch process immediately executing the data change in the action to the reducer.
From there, we call our asynchronous method.
If the method returns an error, we append several pieces of meta data with the error reason and `OPTIMISTIC_UPDATE_FAILURE` (helpful for development).
If the method returns an error, we append several pieces of meta data with the error reason.
```js
type OptimisticErrorType = {
error: string,
data: any
optimisticState: string,
type: string
}
```
If successful, we append `OPTIMISTIC_UPDATE_SUCCESS` and finish the dispatch process.
## Caveats
Because we are reverting our state when errors occur based on the reducer state, this middleware is confined to the reducer `stateKey` passed into the action. Optimistic Middleware does not currently support updates that affect multiple stateKeys.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc