UNPKG

3.97 kBJavaScriptView Raw
1import { formatTime } from './helpers';
2import diffLogger from './diff';
3
4/**
5 * Get log level string based on supplied params
6 *
7 * @param {string | function | object} level - console[level]
8 * @param {object} action - selected action
9 * @param {array} payload - selected payload
10 * @param {string} type - log entry type
11 *
12 * @returns {string} level
13 */
14function getLogLevel(level, action, payload, type) {
15 switch (typeof level) {
16 case `object`:
17 return typeof level[type] === `function` ? level[type](...payload) : level[type];
18 case `function`:
19 return level(action);
20 default:
21 return level;
22 }
23}
24
25function defaultTitleFormatter(options) {
26 const {
27 timestamp,
28 duration,
29 } = options;
30
31 return (action, time, took) => {
32 const parts = [`action`];
33
34 parts.push(`%c${String(action.type)}`);
35 if (timestamp) parts.push(`%c@ ${time}`);
36 if (duration) parts.push(`%c(in ${took.toFixed(2)} ms)`);
37
38 return parts.join(` `);
39 };
40}
41
42export function printBuffer(buffer, options) {
43 const {
44 logger,
45 actionTransformer,
46 titleFormatter = defaultTitleFormatter(options),
47 collapsed,
48 colors,
49 level,
50 diff,
51 } = options;
52
53 buffer.forEach((logEntry, key) => {
54 const { started, startedTime, action, prevState, error } = logEntry;
55 let { took, nextState } = logEntry;
56 const nextEntry = buffer[key + 1];
57
58 if (nextEntry) {
59 nextState = nextEntry.prevState;
60 took = nextEntry.started - started;
61 }
62
63 // Message
64 const formattedAction = actionTransformer(action);
65 const isCollapsed = (typeof collapsed === `function`) ? collapsed(() => nextState, action, logEntry) : collapsed;
66
67 const formattedTime = formatTime(startedTime);
68 const titleCSS = colors.title ? `color: ${colors.title(formattedAction)};` : ``;
69 const headerCSS = [`color: gray; font-weight: lighter;`];
70 headerCSS.push(titleCSS);
71 if (options.timestamp) headerCSS.push(`color: gray; font-weight: lighter;`);
72 if (options.duration) headerCSS.push(`color: gray; font-weight: lighter;`);
73 const title = titleFormatter(formattedAction, formattedTime, took);
74
75 // Render
76 try {
77 if (isCollapsed) {
78 if (colors.title) logger.groupCollapsed(`%c ${title}`, ...headerCSS);
79 else logger.groupCollapsed(title);
80 } else {
81 if (colors.title) logger.group(`%c ${title}`, ...headerCSS);
82 else logger.group(title);
83 }
84 } catch (e) {
85 logger.log(title);
86 }
87
88 const prevStateLevel = getLogLevel(level, formattedAction, [prevState], `prevState`);
89 const actionLevel = getLogLevel(level, formattedAction, [formattedAction], `action`);
90 const errorLevel = getLogLevel(level, formattedAction, [error, prevState], `error`);
91 const nextStateLevel = getLogLevel(level, formattedAction, [nextState], `nextState`);
92
93 if (prevStateLevel) {
94 if (colors.prevState) logger[prevStateLevel](`%c prev state`, `color: ${colors.prevState(prevState)}; font-weight: bold`, prevState);
95 else logger[prevStateLevel](`prev state`, prevState);
96 }
97
98 if (actionLevel) {
99 if (colors.action) logger[actionLevel](`%c action `, `color: ${colors.action(formattedAction)}; font-weight: bold`, formattedAction);
100 else logger[actionLevel](`action `, formattedAction);
101 }
102
103 if (error && errorLevel) {
104 if (colors.error) logger[errorLevel](`%c error `, `color: ${colors.error(error, prevState)}; font-weight: bold;`, error);
105 else logger[errorLevel](`error `, error);
106 }
107
108 if (nextStateLevel) {
109 if (colors.nextState) logger[nextStateLevel](`%c next state`, `color: ${colors.nextState(nextState)}; font-weight: bold`, nextState);
110 else logger[nextStateLevel](`next state`, nextState);
111 }
112
113 if (diff) {
114 diffLogger(prevState, nextState, logger, isCollapsed);
115 }
116
117 try {
118 logger.groupEnd();
119 } catch (e) {
120 logger.log(`—— log end ——`);
121 }
122 });
123}