UNPKG

3.92 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 stateTransformer,
33 errorTransformer,
34 predicate,
35 logErrors,
36 diffPredicate,
37 } = loggerOptions;
38
39 // Return if 'console' object is not defined
40 if (typeof logger === `undefined`) {
41 return () => next => action => next(action);
42 }
43
44 // Detect if 'createLogger' was passed directly to 'applyMiddleware'.
45 if (options.getState && options.dispatch) {
46 // eslint-disable-next-line no-console
47 console.error(`[redux-logger] redux-logger not installed. Make sure to pass logger instance as middleware:
48// Logger with default options
49import { logger } from 'redux-logger'
50const store = createStore(
51 reducer,
52 applyMiddleware(logger)
53)
54// Or you can create your own logger with custom options http://bit.ly/redux-logger-options
55import createLogger from 'redux-logger'
56const logger = createLogger({
57 // ...options
58});
59const store = createStore(
60 reducer,
61 applyMiddleware(logger)
62)
63`);
64
65 return () => next => action => next(action);
66 }
67
68 const logBuffer = [];
69
70 return ({ getState }) => (next) => (action) => {
71 // Exit early if predicate function returns 'false'
72 if (typeof predicate === `function` && !predicate(getState, action)) {
73 return next(action);
74 }
75
76 const logEntry = {};
77
78 logBuffer.push(logEntry);
79
80 logEntry.started = timer.now();
81 logEntry.startedTime = new Date();
82 logEntry.prevState = stateTransformer(getState());
83 logEntry.action = action;
84
85 let returnedValue;
86 if (logErrors) {
87 try {
88 returnedValue = next(action);
89 } catch (e) {
90 logEntry.error = errorTransformer(e);
91 }
92 } else {
93 returnedValue = next(action);
94 }
95
96 logEntry.took = timer.now() - logEntry.started;
97 logEntry.nextState = stateTransformer(getState());
98
99 const diff = loggerOptions.diff && typeof diffPredicate === `function` ? diffPredicate(getState, action) : loggerOptions.diff;
100
101 printBuffer(logBuffer, { ...loggerOptions, diff });
102 logBuffer.length = 0;
103
104 if (logEntry.error) throw logEntry.error;
105 return returnedValue;
106 };
107}
108
109const defaultLogger = ({ dispatch, getState } = {}) => {
110 if (typeof dispatch === `function` || typeof getState === `function`) {
111 return createLogger()({ dispatch, getState });
112 } else {
113 // eslint-disable-next-line no-console
114 console.error(`
115[redux-logger v3] BREAKING CHANGE
116[redux-logger v3] Since 3.0.0 redux-logger exports by default logger with default settings.
117[redux-logger v3] Change
118[redux-logger v3] import createLogger from 'redux-logger'
119[redux-logger v3] to
120[redux-logger v3] import { createLogger } from 'redux-logger'
121`);
122 }
123};
124
125export {
126 defaults,
127 createLogger,
128 defaultLogger as logger,
129};
130
131export default defaultLogger;