UNPKG

3.2 kBJavaScriptView Raw
1import { printBuffer } from './core';
2import { timer } from './helpers';
3import defaults from './defaults';
4
5/**
6 * Creates logger with following options
7 *
8 * @namespace
9 * @param {object} options - options for logger
10 * @param {string | function | object} options.level - console[level]
11 * @param {boolean} options.duration - print duration of each action?
12 * @param {boolean} options.timestamp - print timestamp with each action?
13 * @param {object} options.colors - custom colors
14 * @param {object} options.logger - implementation of the `console` API
15 * @param {boolean} options.logErrors - should errors in action execution be caught, logged, and re-thrown?
16 * @param {boolean} options.collapsed - is group collapsed?
17 * @param {boolean} options.predicate - condition which resolves logger behavior
18 * @param {function} options.stateTransformer - transform state before print
19 * @param {function} options.actionTransformer - transform action before print
20 * @param {function} options.errorTransformer - transform error before print
21 *
22 * @returns {function} logger middleware
23 */
24function createLogger(options = {}) {
25 const loggerOptions = {
26 ...defaults,
27 ...options,
28 };
29
30 const {
31 logger,
32 transformer,
33 stateTransformer,
34 errorTransformer,
35 predicate,
36 logErrors,
37 diffPredicate,
38 } = loggerOptions;
39
40 // Return if 'console' object is not defined
41 if (typeof logger === `undefined`) {
42 return () => next => action => next(action);
43 }
44
45 if (transformer) {
46 console.error(`Option 'transformer' is deprecated, use 'stateTransformer' instead!`); // eslint-disable-line no-console
47 }
48
49 // Detect if 'createLogger' was passed directly to 'applyMiddleware'.
50 if (options.getState && options.dispatch) {
51 // eslint-disable-next-line no-console
52 console.error(`redux-logger not installed. Make sure to pass logger instance as middleware:
53
54import createLogger from 'redux-logger';
55
56const logger = createLogger();
57const store = createStore(
58 reducer,
59 applyMiddleware(logger)
60);`);
61
62 return () => next => action => next(action);
63 }
64
65 const logBuffer = [];
66
67 return ({ getState }) => (next) => (action) => {
68 // Exit early if predicate function returns 'false'
69 if (typeof predicate === `function` && !predicate(getState, action)) {
70 return next(action);
71 }
72
73 const logEntry = {};
74 logBuffer.push(logEntry);
75
76 logEntry.started = timer.now();
77 logEntry.startedTime = new Date();
78 logEntry.prevState = stateTransformer(getState());
79 logEntry.action = action;
80
81 let returnedValue;
82 if (logErrors) {
83 try {
84 returnedValue = next(action);
85 } catch (e) {
86 logEntry.error = errorTransformer(e);
87 }
88 } else {
89 returnedValue = next(action);
90 }
91
92 logEntry.took = timer.now() - logEntry.started;
93 logEntry.nextState = stateTransformer(getState());
94
95 const diff = loggerOptions.diff && typeof diffPredicate === `function` ? diffPredicate(getState, action) : loggerOptions.diff;
96
97 printBuffer(logBuffer, { ...loggerOptions, diff });
98 logBuffer.length = 0;
99
100 if (logEntry.error) throw logEntry.error;
101 return returnedValue;
102 };
103}
104
105export default createLogger;