Comparing version 2.14.1 to 3.0.0-beta2
@@ -1,5 +0,2 @@ | ||
import ActionContext from './ActionContext'; | ||
import ActionFunction from './ActionFunction'; | ||
import Middleware from './Middleware'; | ||
import Middleware from './interfaces/Middleware'; | ||
export default function applyMiddleware(...middleware: Middleware[]): void; | ||
export declare function dispatchWithMiddleware(action: ActionFunction, actionType: string, args: IArguments, actionContext: ActionContext): void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var dispatcher_1 = require("./dispatcher"); | ||
var globalContext_1 = require("./globalContext"); | ||
@@ -8,23 +10,11 @@ function applyMiddleware() { | ||
} | ||
var next = finalDispatch; | ||
var next = dispatcher_1.finalDispatch; | ||
for (var i = middleware.length - 1; i >= 0; i--) { | ||
next = applyMiddlewareInternal(middleware[i], next); | ||
next = applyNextMiddleware(middleware[i], next); | ||
} | ||
globalContext_1.getGlobalContext().dispatchWithMiddleware = next; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = applyMiddleware; | ||
function applyMiddlewareInternal(middleware, next) { | ||
return function (action, actionType, args, actionContext) { return middleware(next, action, actionType, args, actionContext); }; | ||
function applyNextMiddleware(middleware, next) { | ||
return function (actionMessage) { return middleware(next, actionMessage); }; | ||
} | ||
function dispatchWithMiddleware(action, actionType, args, actionContext) { | ||
if (!globalContext_1.getGlobalContext().dispatchWithMiddleware) { | ||
globalContext_1.getGlobalContext().dispatchWithMiddleware = finalDispatch; | ||
} | ||
globalContext_1.getGlobalContext().dispatchWithMiddleware(action, actionType, args, actionContext); | ||
} | ||
exports.dispatchWithMiddleware = dispatchWithMiddleware; | ||
function finalDispatch(action, actionType, args, actionContext) { | ||
return action(); | ||
} | ||
//# sourceMappingURL=applyMiddleware.js.map |
@@ -1,1 +0,1 @@ | ||
export default function createStore<T>(key: string, initialState: T): T; | ||
export default function createStore<T>(key: string, initialState: T): () => T; |
"use strict"; | ||
var rootStore_1 = require("./rootStore"); | ||
var action_1 = require("./action"); | ||
var internalCreateStore = function internalCreateStore(key, initialState) { | ||
rootStore_1.default.set(key, initialState); | ||
}; | ||
internalCreateStore = action_1.default("createStore")(internalCreateStore); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var mobx_1 = require("mobx"); | ||
var getRootStore_1 = require("./getRootStore"); | ||
var createStoreAction = mobx_1.action('createStore', function createStoreAction(key, initialState) { | ||
getRootStore_1.default().set(key, initialState); | ||
}); | ||
function createStore(key, initialState) { | ||
internalCreateStore(key, initialState); | ||
return rootStore_1.default.get(key); | ||
createStoreAction(key, initialState); | ||
return function () { return getRootStore_1.default().get(key); }; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = createStore; | ||
; | ||
//# sourceMappingURL=createStore.js.map |
import { ObservableMap } from 'mobx'; | ||
import ActionContext from './ActionContext'; | ||
import ActionFunction from './ActionFunction'; | ||
import ActionMessage from './interfaces/ActionMessage'; | ||
import DispatchFunction from './interfaces/DispatchFunction'; | ||
import Subscriber from './interfaces/Subscriber'; | ||
import ActionContext from './legacy/ActionContext'; | ||
import ActionFunction from './legacy/ActionFunction'; | ||
export interface GlobalContext { | ||
schemaVersion: number; | ||
inDispatch: number; | ||
rootStore: ObservableMap<any>; | ||
dispatchWithMiddleware: (action: ActionFunction, actionType: string, args: IArguments, actionContext: ActionContext) => Promise<any> | void; | ||
testMode: boolean; | ||
strictMode: boolean; | ||
nextActionId: number; | ||
subscriptions: { | ||
[key: string]: Subscriber<ActionMessage>[]; | ||
}; | ||
dispatchWithMiddleware: DispatchFunction; | ||
legacyInDispatch: number; | ||
legacyDispatchWithMiddleware: (action: ActionFunction, actionType: string, args: IArguments, actionContext: ActionContext) => Promise<any> | void; | ||
legacyTestMode: boolean; | ||
} | ||
@@ -12,0 +19,0 @@ export declare function __resetGlobalContext(): void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var mobx_1 = require("mobx"); | ||
var schemaVersion = 2; | ||
// A reset global context function to be used INTERNALLY by SatchelJS tests and for initialization ONLY | ||
var schemaVersion = 3; | ||
function __resetGlobalContext() { | ||
global.__satchelGlobalContext = { | ||
schemaVersion: schemaVersion, | ||
inDispatch: 0, | ||
rootStore: mobx_1.map({}), | ||
nextActionId: 0, | ||
subscriptions: {}, | ||
dispatchWithMiddleware: null, | ||
testMode: false, | ||
strictMode: true | ||
legacyInDispatch: 0, | ||
legacyDispatchWithMiddleware: null, | ||
legacyTestMode: false, | ||
}; | ||
@@ -18,3 +20,3 @@ } | ||
if (schemaVersion != global.__satchelGlobalContext.schemaVersion) { | ||
throw new Error("Detected incompatible SatchelJS versions loaded."); | ||
throw new Error('Detected incompatible SatchelJS versions loaded.'); | ||
} | ||
@@ -27,4 +29,2 @@ } | ||
exports.getGlobalContext = getGlobalContext; | ||
; | ||
// Side Effects: actually initialize the global context if it is undefined | ||
if (!global.__satchelGlobalContext) { | ||
@@ -36,2 +36,1 @@ __resetGlobalContext(); | ||
} | ||
//# sourceMappingURL=globalContext.js.map |
@@ -1,14 +0,16 @@ | ||
export { default as rootStore } from './rootStore'; | ||
export { default as initializeState } from './initializeState'; | ||
import { useStrict } from 'mobx'; | ||
export { default as ActionCreator } from './interfaces/ActionCreator'; | ||
export { default as ActionMessage } from './interfaces/ActionMessage'; | ||
export { default as DispatchFunction } from './interfaces/DispatchFunction'; | ||
export { default as Middleware } from './interfaces/Middleware'; | ||
export { default as Subscriber } from './interfaces/Subscriber'; | ||
export { actionCreator, boundActionCreator } from './actionCreator'; | ||
export { default as applyMiddleware } from './applyMiddleware'; | ||
export { default as Middleware } from './Middleware'; | ||
export { default as ActionFunction } from './ActionFunction'; | ||
export { default as ActionContext } from './ActionContext'; | ||
export { default as DispatchFunction } from './DispatchFunction'; | ||
export { default as createStore } from './createStore'; | ||
export { default as action } from './action'; | ||
export { default as select, SelectorFunction } from './select'; | ||
export { default as createUndo, UndoResult, CreateUndoReturnValue } from './createUndo'; | ||
export { getActionType } from './functionInternals'; | ||
export { initializeTestMode, resetTestMode } from './testMode'; | ||
export { useStrict } from './useStrict'; | ||
export { dispatch } from './dispatcher'; | ||
export { default as initializeState } from './initializeState'; | ||
export { default as mutator } from './mutator'; | ||
export { default as orchestrator } from './orchestrator'; | ||
export { default as getRootStore } from './getRootStore'; | ||
export { simpleMutator, simpleOrchestrator } from './simpleSubscribers'; | ||
export { useStrict }; |
"use strict"; | ||
var rootStore_1 = require("./rootStore"); | ||
exports.rootStore = rootStore_1.default; | ||
var initializeState_1 = require("./initializeState"); | ||
exports.initializeState = initializeState_1.default; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var mobx_1 = require("mobx"); | ||
exports.useStrict = mobx_1.useStrict; | ||
var actionCreator_1 = require("./actionCreator"); | ||
exports.actionCreator = actionCreator_1.actionCreator; | ||
exports.boundActionCreator = actionCreator_1.boundActionCreator; | ||
var applyMiddleware_1 = require("./applyMiddleware"); | ||
@@ -10,15 +12,15 @@ exports.applyMiddleware = applyMiddleware_1.default; | ||
exports.createStore = createStore_1.default; | ||
var action_1 = require("./action"); | ||
exports.action = action_1.default; | ||
var select_1 = require("./select"); | ||
exports.select = select_1.default; | ||
var createUndo_1 = require("./createUndo"); | ||
exports.createUndo = createUndo_1.default; | ||
var functionInternals_1 = require("./functionInternals"); | ||
exports.getActionType = functionInternals_1.getActionType; | ||
var testMode_1 = require("./testMode"); | ||
exports.initializeTestMode = testMode_1.initializeTestMode; | ||
exports.resetTestMode = testMode_1.resetTestMode; | ||
var useStrict_1 = require("./useStrict"); | ||
exports.useStrict = useStrict_1.useStrict; | ||
//# sourceMappingURL=index.js.map | ||
var dispatcher_1 = require("./dispatcher"); | ||
exports.dispatch = dispatcher_1.dispatch; | ||
var initializeState_1 = require("./initializeState"); | ||
exports.initializeState = initializeState_1.default; | ||
var mutator_1 = require("./mutator"); | ||
exports.mutator = mutator_1.default; | ||
var orchestrator_1 = require("./orchestrator"); | ||
exports.orchestrator = orchestrator_1.default; | ||
var getRootStore_1 = require("./getRootStore"); | ||
exports.getRootStore = getRootStore_1.default; | ||
var simpleSubscribers_1 = require("./simpleSubscribers"); | ||
exports.simpleMutator = simpleSubscribers_1.simpleMutator; | ||
exports.simpleOrchestrator = simpleSubscribers_1.simpleOrchestrator; | ||
mobx_1.useStrict(true); |
@@ -1,2 +0,4 @@ | ||
declare let initializeState: (initialState: any) => void; | ||
export default initializeState; | ||
declare const _default: (initialState: { | ||
[key: string]: any; | ||
}) => void; | ||
export default _default; |
"use strict"; | ||
var rootStore_1 = require("./rootStore"); | ||
var action_1 = require("./action"); | ||
// initializeState can be used to completely replace the existing state object, e.g. to restore | ||
// the stores from a serialized value or to provide a clean starting state for test cases. | ||
var initializeState = function initializeState(initialState) { | ||
rootStore_1.default.clear(); | ||
rootStore_1.default.merge(initialState); | ||
}; | ||
initializeState = action_1.default("initializeState")(initializeState); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = initializeState; | ||
//# sourceMappingURL=initializeState.js.map | ||
var mobx_1 = require("mobx"); | ||
var getRootStore_1 = require("./getRootStore"); | ||
exports.default = mobx_1.action('initializeState', function initializeState(initialState) { | ||
var rootStore = getRootStore_1.default(); | ||
rootStore.clear(); | ||
rootStore.merge(initialState); | ||
}); |
{ | ||
"name": "satcheljs", | ||
"version": "2.14.1", | ||
"version": "3.0.0-beta2", | ||
"description": "Store implementation for functional reactive flux.", | ||
"main": "./lib/index.js", | ||
"lint-staged": { | ||
"*.{ts,tsx}": [ | ||
"prettier --tab-width 4 --print-width 100 --write --trailing-comma es5 --jsx-bracket-same-line --single-quote", | ||
"git add" | ||
] | ||
}, | ||
"scripts": { | ||
"copy-project-files": "node ../../tools/copy-project-files.js", | ||
"build": "npm run copy-project-files && node ../../node_modules/typescript/lib/tsc.js", | ||
"start": "npm run copy-project-files && node ../../node_modules/typescript/lib/tsc.js -w", | ||
"test": "node ../../node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=jasmine.json --verbose" | ||
"precommit": "lint-staged", | ||
"clean": "rimraf build lib", | ||
"lint": "tslint -t stylish --project tsconfig.json", | ||
"build:source": "tsc -p tsconfig.release.json", | ||
"watch": "tsc -w -p tsconfig.release.json", | ||
"test:unit": "jest", | ||
"build": "run-s clean build:source", | ||
"start": "run-s clean watch", | ||
"test": "run-s lint test:unit", | ||
"test:start": "jest --watch" | ||
}, | ||
"author": "Scott Mikula <smikula@microsoft.com>", | ||
"license": "MIT", | ||
"dependencies": { | ||
"mobx": "~2.6.5" | ||
}, | ||
"devDependencies": { | ||
"jasmine": "~2.4.1", | ||
"typescript": "~1.8.9" | ||
"@types/enzyme": "2.8.1", | ||
"@types/jasmine": "~2.5.53", | ||
"@types/jsdom": "^11.0.1", | ||
"@types/node": "~6.0.78", | ||
"@types/react": "15.0.37", | ||
"@types/react-addons-perf": "~0.14.18", | ||
"@types/react-addons-test-utils": "~0.14.19", | ||
"@types/react-dom": "~15.5.1", | ||
"enzyme": "^2.9.1", | ||
"husky": "~0.14.3", | ||
"jasmine": "^2.6.0", | ||
"jest": "20.0.4", | ||
"lint-staged": "~4.0.1", | ||
"npm-run-all": "^4.0.2", | ||
"prettier": "~1.5.2", | ||
"react-test-renderer": "^15.6.1", | ||
"rimraf": "^2.5.4", | ||
"tslint": "~5.5.0", | ||
"tslint-eslint-rules": "~4.1.1", | ||
"tslint-microsoft-contrib": "~5.0.1", | ||
"typescript": "~2.3.4" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/microsoft/satcheljs" | ||
"dependencies": { | ||
"mobx": "~2.6.5", | ||
"mobx-react": "~4.0.3", | ||
"mobx-react-devtools": "~4.2.10", | ||
"react": "^15.6.1", | ||
"react-addons-perf": "^15.4.2", | ||
"react-dom": "^15.6.1" | ||
}, | ||
"typings": "./lib/index.d.ts", | ||
"main": "lib/index.js", | ||
"typings": "lib/index.d.ts", | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org/" | ||
"registry": "https://registry.npmjs.org" | ||
} | ||
} | ||
} |
158
README.md
@@ -1,7 +0,6 @@ | ||
[![Build Status](https://travis-ci.org/Microsoft/satcheljs.svg?branch=master)](https://travis-ci.org/Microsoft/satcheljs) | ||
# Satchel | ||
Satchel is a data store based on the [Flux architecture](http://facebook.github.io/react/blog/2014/05/06/flux.html). It is characterized by exposing an observable state that makes view updates painless and efficient. | ||
Satchel is a dataflow framework based on the [Flux architecture](http://facebook.github.io/react/blog/2014/05/06/flux.html). It is characterized by exposing an observable state that makes view updates painless and efficient. | ||
[![Build Status](https://travis-ci.org/Microsoft/satcheljs.svg?branch=master)](https://travis-ci.org/Microsoft/satcheljs) | ||
@@ -11,10 +10,10 @@ ## Influences | ||
Satchel is an attempt to synthesize the best of several dataflow patterns typically used to drive a React-based UI. In particular: | ||
* [Flux](http://facebook.github.io/react/blog/2014/05/06/flux.html) is not a library itself, but is a dataflow pattern conceived for use with React. In Flux, dataflow is unidirectional, and the only way to modify state is by dispatching actions through a central dispatcher. | ||
* [Redux](http://redux.js.org/index.html) is an implementation of Flux that consolidates stores into a single state tree and attempts to simplify state changes by making all mutations via pure functions called reducers. Ultimately, however, we found that reducers and immutable state were difficult to reason about, particularly in a large, interconnected app. | ||
* [Redux](http://redux.js.org/index.html) is an implementation of Flux that consolidates stores into a single state tree and attempts to simplify state changes by making all mutations via pure functions called reducers. Ultimately, however, we found reducers and immutable state cumbersome to deal with, particularly in a large, interconnected app. | ||
* [MobX](http://mobxjs.github.io/mobx/index.html) provides a seamless way to make state observable, and allows React to listen to state changes and rerender in a very performant way. Satchel uses MobX under the covers to allow React components to observe the data they depend on. | ||
## Advantages | ||
There are a number of advantages to using Satchel to maintain your application state. (Each of the frameworks above has some, but not all, of these qualities.) | ||
There are a number of advantages to using Satchel to maintain your application state: | ||
@@ -24,6 +23,6 @@ * Satchel enables a very **performant UI**, only rerendering the minimal amount necessary. MobX makes UI updates very efficient by automatically detecting specifically what components need to rerender for a given state change. | ||
* Satchel supports **middleware** that can act on each action that is dispatched. (For example, for tracing or performance instrumentation.) | ||
* Satchel requires **minimal boilerplate** code. | ||
* Satchel is **type-safe** out of the box, without any extra effort on the consumer's part. | ||
## Installation | ||
## Installation | ||
Install via NPM: | ||
@@ -39,18 +38,15 @@ | ||
## Usage | ||
## Usage | ||
The following examples assume you're developing in Typescript. | ||
### Create a store with some initial state | ||
```typescript | ||
interface MyStoreSchema { | ||
foo: number; | ||
bar: string; | ||
} | ||
import { createStore } from 'satcheljs'; | ||
var myStore = createStore<MyStoreSchema>( | ||
"mystore", | ||
var store = createStore( | ||
'scoreboardStore', | ||
{ | ||
foo: 1, | ||
bar: "baz" | ||
score: 0 | ||
}); | ||
@@ -60,66 +56,118 @@ ``` | ||
### Create a component that consumes your state | ||
Notice the @observer decorator on the component---this is what tells MobX to rerender the component if any of the data it relies on changes. | ||
```typescript | ||
Notice the `@observer` decorator on the component—this is what tells MobX to rerender the component whenever the data it relies on changes. | ||
```javascript | ||
@observer | ||
class ApplicationComponent extends React.Component<any, any> { | ||
render() { | ||
return (<div>foo is {myStore.foo}</div>); | ||
} | ||
render() { | ||
return (<div>Score = {store.score}</div>); | ||
} | ||
} | ||
``` | ||
### Implement an action to update the store | ||
### Implement an action creator | ||
```typescript | ||
let updateFoo = | ||
function updateFoo(newFoo: number) { | ||
myStore.foo = newFoo; | ||
}; | ||
import { actionCreator } from 'satcheljs'; | ||
updateFoo = action("updateFoo")(updateFoo); | ||
let addPoints = actionCreator('ADD_POINTS', | ||
(points: number) => ({ | ||
points: points | ||
})); | ||
``` | ||
Note that the above is just syntactic sugar for applying an @action decorator. Typescript doesn't support decorators on function expressions yet, but it will in 2.0. At that point the syntax for creating an action will be simply: | ||
### Implement a mutator | ||
You specify what action a mutator subscribes to by providing the corresponding action creator. | ||
If you're using TypeScript, the type of `actionMessage` is automatically inferred. | ||
```typescript | ||
let updateFoo = | ||
@action("updateFoo") | ||
function updateFoo(newFoo: number) { | ||
myStore.foo = newFoo; | ||
}; | ||
import { mutator } from 'satcheljs'; | ||
mutator(addPoints, (actionMessage) => { | ||
store.score += actionMessage.points; | ||
}; | ||
``` | ||
### Call the action | ||
### Create and dispatch an action | ||
It's just a function: | ||
```typescript | ||
import { dispatch } from 'satcheljs'; | ||
dispatch(addPoints(2)); | ||
``` | ||
### Bound action creators | ||
Bound action creators create and dispatch the action in one call. | ||
Also notice that if the action doesn't need any arguments then you don't need to supply an action creator function. | ||
```typescript | ||
updateFoo(2); | ||
import { boundActionCreator } from 'satcheljs'; | ||
let resetScore = boundActionCreator('RESET_SCORE'); | ||
// This dispatches a RESET_SCORE action. Of course, you'd still need a mutator | ||
// to subscribe to it to update the store. | ||
resetScore(); | ||
``` | ||
### Asynchronous actions | ||
### Orchestrators | ||
Often actions will need to do some sort of asynchronous work (such as making a server request) and then update the state based on the result. | ||
Since the asynchronous callback happens outside of the context of the original action the callback itself must be an action too. | ||
(Again, this syntax will be simplified once Typescript 2.0 is available.) | ||
Orchestrators are like mutators—they subscribe to actions—but they serve a different purpose. | ||
While mutators modify the store, orchestrators are responsible for side effects. | ||
Side effects might include making a server call or even dispatching further actions. | ||
The following example shows how an orchestrator can persist a value to a server before updating the store. | ||
```typescript | ||
let updateFooAsync = | ||
function updateFooAsync(newFoo: number) { | ||
// You can modify the state in the original action | ||
myStore.loading = true; | ||
import { boundActionCreator, orchestrator } from 'satcheljs'; | ||
// doSomethingAsync returns a promise | ||
doSomethingAsync().then( | ||
action("doSomethingAsyncCallback")( | ||
() => { | ||
// Modify the state again in the callback | ||
myStore.loading = false; | ||
myStore.foo = newFoo; | ||
})); | ||
}; | ||
let requestAddPoints = boundActionCreator('REQUEST_ADD_POINTS', | ||
(points: number) => ({ | ||
})); | ||
updateFooAsync = action("updateFooAsync")(updateFooAsync); | ||
orchestrator(requestAddPoints, (actionMessage) => { | ||
updatePointsOnServer(store.score + actionMessage.points) | ||
.then((response) => { | ||
if (response.result == 200) { | ||
addPoints(actionMessage.points); | ||
} | ||
}); | ||
}; | ||
``` | ||
### Simple mutators and orchestrators | ||
In many cases a given action only needs to be handled by one mutator. | ||
Satchel provides the concept of a simple mutator which ecapsulates action creation, dispatch, and handling in one simple function call. | ||
The `addPoints` mutator above could be implemented as follows: | ||
```typescript | ||
let addPoints = simpleMutator( | ||
'addPoints', | ||
function addPoints(points: number) { | ||
store.score += points; | ||
}); | ||
``` | ||
Simple orchestrators can be created similarly: | ||
```typescript | ||
let requestAddPoints = simpleOrchestrator( | ||
'requestAddPoints', | ||
function requestAddPoints(points: number) { | ||
.then((response) => { | ||
if (response.result == 200) { | ||
addPoints(points); | ||
} | ||
}); | ||
}); | ||
``` | ||
These simple mutators and orchestrators are succinct and easy to write, but they come with a restriction: | ||
the action creator is not exposed, so no other mutators or orchestrators can subscribe to it. | ||
If an action needs multiple handlers then it must use the full pattern with action creators and handlers implemented separately. | ||
## License - MIT |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
51655
86
1030
170
6
21
2
2
1
1
+ Addedmobx-react@~4.0.3
+ Addedmobx-react-devtools@~4.2.10
+ Addedreact@^15.6.1
+ Addedreact-addons-perf@^15.4.2
+ Addedreact-dom@^15.6.1
+ Addedasap@2.0.6(transitive)
+ Addedcore-js@1.2.7(transitive)
+ Addedcreate-react-class@15.7.0(transitive)
+ Addedencoding@0.1.13(transitive)
+ Addedfbjs@0.8.18(transitive)
+ Addedhoist-non-react-statics@1.2.0(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addedisomorphic-fetch@2.2.1(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedmobx-react@4.0.4(transitive)
+ Addedmobx-react-devtools@4.2.15(transitive)
+ Addednode-fetch@1.7.3(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedpromise@7.3.1(transitive)
+ Addedprop-types@15.8.1(transitive)
+ Addedreact@15.7.0(transitive)
+ Addedreact-addons-perf@15.4.2(transitive)
+ Addedreact-dom@15.7.0(transitive)
+ Addedreact-is@16.13.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsetimmediate@1.0.5(transitive)
+ Addedua-parser-js@0.7.40(transitive)
+ Addedwhatwg-fetch@3.6.20(transitive)