export { default as createStore } from "./createStore"
export { default as bindActionCreators } from "./bindActionCreators"
export { default as combineReducers } from "./combineReducers"
export { default as applyMiddleware } from "./applyMiddleware"
export { default as compose } from "./compose"
function getRandomString(length) {
return Math.random().toString(36).substr(2, length).split("").join(".")
}
export default {
INIT() {
return `@@redux/INIT${getRandomString(6)}`
},
UNKNOWN() {
return `@@redux/PROBE_UNKNOWN_ACTION${getRandomString(6)}`
}
}
export default function isPlainObject(obj) {
if (typeof obj !== "object") {
return false;
}
return Object.getPrototypeOf(obj) === Object.prototype;
}
import ActionTypes from "./utils/ActionTypes"
import isPlainObject from "./utils/isPlainObject"
export default function createStore(reducer, defaultState, enhanced) {
if (typeof defaultState === "function") {
enhanced = defaultState;
defaultState = undefined;
}
if (typeof enhanced === "function") {
return enhanced(createStore)(reducer, defaultState);
}
let currentReducer = reducer,
currentState = defaultState;
const listeners = [];
function dispatch(action) {
if (!isPlainObject(action)) {
throw new TypeError("action must be a plain object");
}
if (action.type === undefined) {
throw new TypeError("action must has a property of type");
}
currentState = currentReducer(currentState, action)
for (const listener of listeners) {
listener();
}
}
function getState() {
return currentState;
}
function subscribe(listener) {
listeners.push(listener);
let isRemove = false;
return function () {
if (isRemove) {
return;
}
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
isRemove = true;
}
}
dispatch({
type: ActionTypes.INIT()
})
return {
dispatch,
getState,
subscribe
}
}
import isPlainObject from "./utils/isPlainObject"
import ActionTypes from "./utils/ActionTypes"
function validateReducers(reducers) {
if (typeof reducers !== "object") {
throw new TypeError("reducers must be an object");
}
if (!isPlainObject(reducers)) {
throw new TypeError("reducers must be a plain object");
}
for (const key in reducers) {
if (reducers.hasOwnProperty(key)) {
const reducer = reducers[key];
let state = reducer(undefined, {
type: ActionTypes.INIT()
})
if (state === undefined) {
throw new TypeError("reducers must not return undefined");
}
state = reducer(undefined, {
type: ActionTypes.UNKNOWN()
})
if (state === undefined) {
throw new TypeError("reducers must not return undefined");
}
}
}
}
export default function (reducers) {
validateReducers(reducers);
return function (state = {}, action) {
const newState = {};
for (const key in reducers) {
if (reducers.hasOwnProperty(key)) {
const reducer = reducers[key];
newState[key] = reducer(state[key], action);
}
}
return newState;
}
}
export default function (actionCreators, dispatch) {
if (typeof actionCreators === "function") {
return getAutoDispatchActionCreator(actionCreators, dispatch);
}
else if (typeof actionCreators === "object") {
const result = {};
for (const key in actionCreators) {
if (actionCreators.hasOwnProperty(key)) {
const actionCreator = actionCreators[key];
if (typeof actionCreator === "function") {
result[key] = getAutoDispatchActionCreator(actionCreator, dispatch);
}
}
}
return result;
}
else {
throw new TypeError("actionCreators must be an object or function which means action creator")
}
}
function getAutoDispatchActionCreator(actionCreator, dispatch) {
return function (...args) {
const action = actionCreator(...args)
dispatch(action);
}
}
export default function compose(...funcs) {
if (funcs.length === 0) {
return args => args;
}
else if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
import compose from "./compose"
export default function (...middlewares) {
return function (createStore) {
return function (reducer, defaultState) {
const store = createStore(reducer, defaultState);
let dispatch = () => { throw new Error("目前还不能使用dispatch") };
const simpleStore = {
getState: store.getState,
dispatch: store.dispatch
}
const dispatchProducers = middlewares.map(mid => mid(simpleStore));
dispatch = compose(...dispatchProducers)(store.dispatch);
return {
...store,
dispatch
}
}
}
}