UNPKG

11.9 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
6
7var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8
9exports.default = devToolsEnhancer;
10exports.preEnhancer = preEnhancer;
11exports.composeWithDevTools = composeWithDevTools;
12
13var _jsan = require('jsan');
14
15var _socketclusterClient = require('socketcluster-client');
16
17var _socketclusterClient2 = _interopRequireDefault(_socketclusterClient);
18
19var _configureStore = require('./configureStore');
20
21var _configureStore2 = _interopRequireDefault(_configureStore);
22
23var _constants = require('./constants');
24
25var _rnHostDetect = require('rn-host-detect');
26
27var _rnHostDetect2 = _interopRequireDefault(_rnHostDetect);
28
29var _remotedevUtils = require('remotedev-utils');
30
31var _catchErrors = require('remotedev-utils/lib/catchErrors');
32
33var _catchErrors2 = _interopRequireDefault(_catchErrors);
34
35var _filters = require('remotedev-utils/lib/filters');
36
37function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
38
39var instanceId = void 0;
40var instanceName = void 0;
41var suppressConnectErrors = void 0;
42var errorCounts = {};
43var socketOptions = void 0;
44var socket = void 0;
45var channel = void 0;
46var store = {};
47var lastAction = void 0;
48var filters = void 0;
49var isExcess = void 0;
50var isMonitored = void 0;
51var started = void 0;
52var startOn = void 0;
53var stopOn = void 0;
54var sendOn = void 0;
55var sendOnError = void 0;
56var sendTo = void 0;
57var lastErrorMsg = void 0;
58var locked = void 0;
59var paused = void 0;
60var actionCreators = void 0;
61var stateSanitizer = void 0;
62var actionSanitizer = void 0;
63
64function getLiftedState() {
65 return (0, _filters.filterStagedActions)(store.liftedStore.getState(), filters);
66}
67
68function send() {
69 if (!instanceId) instanceId = socket && socket.id || Math.random().toString(36).substr(2);
70 try {
71 fetch(sendTo, {
72 method: 'POST',
73 headers: {
74 'content-type': 'application/json'
75 },
76 body: JSON.stringify({
77 type: 'STATE',
78 id: instanceId,
79 name: instanceName,
80 payload: (0, _jsan.stringify)(getLiftedState())
81 })
82 }).catch(function (err) {
83 console.log(err);
84 });
85 } catch (err) {
86 console.log(err);
87 }
88}
89
90function relay(type, state, action, nextActionId) {
91 var message = {
92 type: type,
93 id: socket.id,
94 name: instanceName
95 };
96 if (state) {
97 message.payload = type === 'ERROR' ? state : (0, _jsan.stringify)((0, _filters.filterState)(state, type, filters, stateSanitizer, actionSanitizer, nextActionId));
98 }
99 if (type === 'ACTION') {
100 message.action = (0, _jsan.stringify)(!actionSanitizer ? action : actionSanitizer(action.action, nextActionId - 1));
101 message.isExcess = isExcess;
102 message.nextActionId = nextActionId;
103 } else if (action) {
104 message.action = action;
105 }
106 socket.emit(socket.id ? 'log' : 'log-noid', message);
107}
108
109function dispatchRemotely(action) {
110 try {
111 var result = (0, _remotedevUtils.evalAction)(action, actionCreators);
112 store.dispatch(result);
113 } catch (e) {
114 relay('ERROR', e.message);
115 }
116}
117
118function handleMessages(message) {
119 if (message.type === 'IMPORT' || message.type === 'SYNC' && socket.id && message.id !== socket.id) {
120 store.liftedStore.dispatch({
121 type: 'IMPORT_STATE', nextLiftedState: (0, _jsan.parse)(message.state)
122 });
123 } else if (message.type === 'UPDATE') {
124 relay('STATE', getLiftedState());
125 } else if (message.type === 'START') {
126 isMonitored = true;
127 if (typeof actionCreators === 'function') actionCreators = actionCreators();
128 relay('STATE', getLiftedState(), actionCreators);
129 } else if (message.type === 'STOP' || message.type === 'DISCONNECTED') {
130 isMonitored = false;
131 relay('STOP');
132 } else if (message.type === 'ACTION') {
133 dispatchRemotely(message.action);
134 } else if (message.type === 'DISPATCH') {
135 store.liftedStore.dispatch(message.action);
136 }
137}
138
139function async(fn) {
140 setTimeout(fn, 0);
141}
142
143function sendError(errorAction) {
144 // Prevent flooding
145 if (errorAction.message && errorAction.message === lastErrorMsg) return;
146 lastErrorMsg = errorAction.message;
147
148 async(function () {
149 store.dispatch(errorAction);
150 if (!started) send();
151 });
152}
153
154function str2array(str) {
155 return typeof str === 'string' ? [str] : str && str.length;
156}
157
158function init(options) {
159 instanceName = options.name;
160
161 var _ref = options.filters || {},
162 blacklist = _ref.blacklist,
163 whitelist = _ref.whitelist;
164
165 filters = (0, _filters.getLocalFilter)({
166 actionsBlacklist: blacklist || options.actionsBlacklist,
167 actionsWhitelist: whitelist || options.actionsWhitelist
168 });
169 if (options.port) {
170 socketOptions = {
171 port: options.port,
172 hostname: options.hostname || 'localhost',
173 secure: options.secure
174 };
175 } else socketOptions = _constants.defaultSocketOptions;
176
177 suppressConnectErrors = options.suppressConnectErrors !== undefined ? options.suppressConnectErrors : true;
178
179 startOn = str2array(options.startOn);
180 stopOn = str2array(options.stopOn);
181 sendOn = str2array(options.sendOn);
182 sendOnError = options.sendOnError;
183 if (sendOn || sendOnError) {
184 sendTo = options.sendTo || (socketOptions.secure ? 'https' : 'http') + '://' + socketOptions.hostname + ':' + socketOptions.port;
185 instanceId = options.id;
186 }
187 if (sendOnError === 1) (0, _catchErrors2.default)(sendError);
188
189 if (options.actionCreators) actionCreators = function actionCreators() {
190 return (0, _remotedevUtils.getActionsArray)(options.actionCreators);
191 };
192 stateSanitizer = options.stateSanitizer;
193 actionSanitizer = options.actionSanitizer;
194}
195
196function login() {
197 socket.emit('login', 'master', function (err, channelName) {
198 if (err) {
199 console.log(err);return;
200 }
201 channel = channelName;
202 socket.subscribe(channelName).watch(handleMessages);
203 socket.on(channelName, handleMessages);
204 });
205 started = true;
206 relay('START');
207}
208
209function stop(keepConnected) {
210 started = false;
211 isMonitored = false;
212 if (!socket) return;
213 socket.destroyChannel(channel);
214 if (keepConnected) {
215 socket.off(channel, handleMessages);
216 } else {
217 socket.off();
218 socket.disconnect();
219 }
220}
221
222function start() {
223 if (started || socket && socket.getState() === socket.CONNECTING) return;
224
225 socket = _socketclusterClient2.default.connect(socketOptions);
226
227 socket.on('error', function (err) {
228 // if we've already had this error before, increment it's counter, otherwise assign it '1' since we've had the error once.
229 errorCounts[err.name] = errorCounts.hasOwnProperty(err.name) ? errorCounts[err.name] + 1 : 1;
230
231 if (suppressConnectErrors) {
232 if (errorCounts[err.name] === 1) {
233 console.log('remote-redux-devtools: Socket connection errors are being suppressed. ' + '\n' + 'This can be disabled by setting suppressConnectErrors to \'false\'.');
234 console.log(err);
235 }
236 } else {
237 console.log(err);
238 }
239 });
240 socket.on('connect', function () {
241 console.log('connected to remotedev-server');
242 errorCounts = {}; // clear the errorCounts object, so that we'll log any new errors in the event of a disconnect
243 login();
244 });
245 socket.on('disconnect', function () {
246 stop(true);
247 });
248}
249
250function checkForReducerErrors() {
251 var liftedState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : store.liftedStore.getState();
252
253 if (liftedState.computedStates[liftedState.currentStateIndex].error) {
254 if (started) relay('STATE', (0, _filters.filterStagedActions)(liftedState, filters));else send();
255 return true;
256 }
257 return false;
258}
259
260function monitorReducer() {
261 var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
262 var action = arguments[1];
263
264 lastAction = action.type;
265 if (!started && sendOnError === 2 && store.liftedStore) async(checkForReducerErrors);else if (action.action) {
266 if (startOn && !started && startOn.indexOf(action.action.type) !== -1) async(start);else if (stopOn && started && stopOn.indexOf(action.action.type) !== -1) async(stop);else if (sendOn && !started && sendOn.indexOf(action.action.type) !== -1) async(send);
267 }
268 return state;
269}
270
271function handleChange(state, liftedState, maxAge) {
272 if (checkForReducerErrors(liftedState)) return;
273
274 if (lastAction === 'PERFORM_ACTION') {
275 var nextActionId = liftedState.nextActionId;
276 var liftedAction = liftedState.actionsById[nextActionId - 1];
277 if ((0, _filters.isFiltered)(liftedAction.action, filters)) return;
278 relay('ACTION', state, liftedAction, nextActionId);
279 if (!isExcess && maxAge) isExcess = liftedState.stagedActionIds.length >= maxAge;
280 } else {
281 if (lastAction === 'JUMP_TO_STATE') return;
282 if (lastAction === 'PAUSE_RECORDING') {
283 paused = liftedState.isPaused;
284 } else if (lastAction === 'LOCK_CHANGES') {
285 locked = liftedState.isLocked;
286 }
287 if (paused || locked) {
288 if (lastAction) lastAction = undefined;else return;
289 }
290 relay('STATE', (0, _filters.filterStagedActions)(liftedState, filters));
291 }
292}
293
294function devToolsEnhancer() {
295 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
296
297 init(_extends({}, options, {
298 hostname: (0, _rnHostDetect2.default)(options.hostname || 'localhost')
299 }));
300 var realtime = typeof options.realtime === 'undefined' ? process.env.NODE_ENV === 'development' : options.realtime;
301 if (!realtime && !(startOn || sendOn || sendOnError)) return function (f) {
302 return f;
303 };
304
305 var maxAge = options.maxAge || 30;
306 return function (next) {
307 return function (reducer, initialState) {
308 store = (0, _configureStore2.default)(next, monitorReducer, {
309 maxAge: maxAge,
310 shouldCatchErrors: !!sendOnError,
311 shouldHotReload: options.shouldHotReload,
312 shouldRecordChanges: options.shouldRecordChanges,
313 shouldStartLocked: options.shouldStartLocked,
314 pauseActionType: options.pauseActionType || '@@PAUSED'
315 })(reducer, initialState);
316
317 if (realtime) start();
318 store.subscribe(function () {
319 if (isMonitored) handleChange(store.getState(), store.liftedStore.getState(), maxAge);
320 });
321 return store;
322 };
323 };
324}
325
326function preEnhancer(createStore) {
327 return function (reducer, preloadedState, enhancer) {
328 store = createStore(reducer, preloadedState, enhancer);
329 return _extends({}, store, {
330 dispatch: function dispatch(action) {
331 return locked ? action : store.dispatch(action);
332 }
333 });
334 };
335}
336
337devToolsEnhancer.updateStore = function (newStore) {
338 console.warn('devTools.updateStore is deprecated use composeWithDevTools instead: ' + 'https://github.com/zalmoxisus/remote-redux-devtools#use-devtools-compose-helper');
339 store = newStore;
340};
341
342var compose = function compose(options) {
343 return function () {
344 for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
345 funcs[_key] = arguments[_key];
346 }
347
348 return function () {
349 return [preEnhancer].concat(funcs).reduceRight(function (composed, f) {
350 return f(composed);
351 }, devToolsEnhancer(options).apply(undefined, arguments));
352 };
353 };
354};
355
356function composeWithDevTools() {
357 if (arguments.length === 0) {
358 return devToolsEnhancer();
359 }
360 if (arguments.length === 1 && _typeof(arguments.length <= 0 ? undefined : arguments[0]) === 'object') {
361 return compose(arguments.length <= 0 ? undefined : arguments[0]);
362 }
363 return compose({}).apply(undefined, arguments);
364}
\No newline at end of file