diff --git a/README.md b/README.md index ccb850e..cf09687 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,10 @@ Name | Description `hostname` | *String* used to specify host for [`remotedev-server`](https://github.com/zalmoxisus/remotedev-server). If `port` is specified, default value is `localhost`. `port` | *Number* used to specify host's port for [`remotedev-server`](https://github.com/zalmoxisus/remotedev-server). `secure` | *Boolean* specifies whether to use `https` protocol for [`remotedev-server`](https://github.com/zalmoxisus/remotedev-server). -`filters` | *Map of arrays* named `whitelist` or `blacklist` to filter action types. `maxAge` | *Number* of maximum allowed actions to be stored on the history tree, the oldest actions are removed once maxAge is reached. Default is `30`. +`filters` | *Map of arrays* named `whitelist` or `blacklist` to filter action types. See the example bellow. +`actionsFilter` | *Function* which takes action object and id number as arguments, and should return action object back. See the example bellow. +`statesFilter` | *Function* which takes state object and index as arguments, and should return state object back. See the example bellow. `startOn` | *String* or *Array of strings* indicating an action or a list of actions, which should start remote monitoring (when `realtime` is `false`). `stopOn` | *String* or *Array of strings* indicating an action or a list of actions, which should stop remote monitoring. `sendOn` | *String* or *Array of strings* indicating an action or a list of actions, which should trigger sending the history to the monitor (without starting it). *Note*: when using it, add a `fetch` polyfill if needed. @@ -104,7 +106,12 @@ export default function configureStore(initialState) { devTools({ name: 'Android app', realtime: true, hostname: 'localhost', port: 8000, - maxAge: 30, filters: { blacklist: ['EFFECT_RESOLVED'] } + maxAge: 30, filters: { blacklist: ['EFFECT_RESOLVED'] }, + actionsFilter: (action) => ( + action.type === 'FILE_DOWNLOAD_SUCCESS' && action.data ? + { ...action, data: '<>' } : action + ), + statesFilter: (state) => state.data ? { ...state, data: '<>' } : state }) ); // If you have other enhancers & middlewares diff --git a/package.json b/package.json index a2f0d68..783cd2b 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "jsan": "^3.1.3", "querystring": "^0.2.0", "redux-devtools-instrument": "^1.1.0", - "remotedev-utils": "0.0.2", + "remotedev-utils": "0.0.4", "socketcluster-client": "5.0.6" } } diff --git a/src/devTools.js b/src/devTools.js index 64375f0..645b6f0 100644 --- a/src/devTools.js +++ b/src/devTools.js @@ -4,6 +4,7 @@ import configureStore from './configureStore'; import { defaultSocketOptions } from './constants'; import { getHostForRN } from './utils/reactNative'; import { evalAction, getActionsArray } from 'remotedev-utils'; +import { isFiltered, filterStagedActions, filterState } from 'remotedev-utils/lib/filters'; const ERROR = '@@remotedev/ERROR'; @@ -29,36 +30,11 @@ let sendOnError; let sendTo; let lastErrorMsg; let actionCreators; - -function isFiltered(action) { - if (!action || !action.action || !action.action.type) return false; - return ( - filters.whitelist && !action.action.type.match(filters.whitelist.join('|')) || - filters.blacklist && action.action.type.match(filters.blacklist.join('|')) - ); -} - -function filterStagedActions(state) { - if (!filters) return state; - - const filteredStagedActionIds = []; - const filteredComputedStates = []; - - state.stagedActionIds.forEach((id, idx) => { - if (!isFiltered(state.actionsById[id])) { - filteredStagedActionIds.push(id); - filteredComputedStates.push(state.computedStates[idx]); - } - }); - - return { ...state, - stagedActionIds: filteredStagedActionIds, - computedStates: filteredComputedStates - }; -} +let statesFilter; +let actionsFilter; function getLiftedState() { - return filterStagedActions(store.liftedStore.getState()); + return filterStagedActions(store.liftedStore.getState(), filters); } function send() { @@ -84,15 +60,20 @@ function send() { } function relay(type, state, action, nextActionId) { - if (filters && isFiltered(action)) return; + if (isFiltered(action, filters)) return; const message = { type, id: socket.id, name: instanceName }; - if (state) message.payload = type === 'ERROR' ? state : stringify(state); + if (state) { + message.payload = type === 'ERROR' ? state : + stringify(filterState(state, type, filters, statesFilter, actionsFilter, nextActionId)); + } if (type === 'ACTION') { - message.action = stringify(action); + message.action = stringify( + !actionsFilter ? action : actionsFilter(action.action, nextActionId - 1) + ); message.isExcess = isExcess; message.nextActionId = nextActionId; } else if (action) { @@ -209,6 +190,8 @@ function init(options) { if (sendOnError === 1) catchErrors(); if (options.actionCreators) actionCreators = () => getActionsArray(options.actionCreators); + statesFilter = options.statesFilter; + actionsFilter = options.actionsFilter; } function start() { @@ -243,7 +226,7 @@ function stop() { function checkForReducerErrors(liftedState = store.liftedStore.getState()) { if (liftedState.computedStates[liftedState.currentStateIndex].error) { - if (started) relay('STATE', filterStagedActions(liftedState)); + if (started) relay('STATE', filterStagedActions(liftedState, filters)); else send(); return true; } @@ -275,7 +258,7 @@ function handleChange(state, liftedState, maxAge) { relay('ACTION', state, liftedAction, nextActionId); if (!isExcess && maxAge) isExcess = liftedState.stagedActionIds.length >= maxAge; } else { - relay('STATE', filterStagedActions(liftedState)); + relay('STATE', filterStagedActions(liftedState, filters)); } }