aboutsummaryrefslogtreecommitdiff
path: root/node_modules/loglevelnext/lib/MethodFactory.js
blob: cdf7038d0aaaf2d9d137d086055f258d977bda2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'use strict';

const noop = () => {};
const levels = Symbol('valid log levels');
const instance = Symbol('a log instance');

module.exports = class MethodFactory {
  constructor(logger) {
    this[instance] = logger;
    this[levels] = {
      TRACE: 0,
      DEBUG: 1,
      INFO: 2,
      WARN: 3,
      ERROR: 4,
      SILENT: 5
    };
  }

  get levels() {
    return this[levels];
  }

  get logger() {
    return this[instance];
  }

  set logger(logger) {
    this[instance] = logger;
  }

  get methods() {
    return Object.keys(this.levels)
      .map(key => key.toLowerCase())
      .filter(key => key !== 'silent');
  }

  // eslint-disable-next-line class-methods-use-this
  bindMethod(obj, methodName) {
    const method = obj[methodName];
    if (typeof method.bind === 'function') {
      return method.bind(obj);
    }

    try {
      return Function.prototype.bind.call(method, obj);
    } catch (e) {
      // Missing bind shim or IE8 + Modernizr, fallback to wrapping
      return function result() {
        // eslint-disable-next-line prefer-rest-params
        return Function.prototype.apply.apply(method, [obj, arguments]);
      };
    }
  }

  distillLevel(level) {
    let result = level;

    if (typeof result === 'string' && typeof this.levels[result.toUpperCase()] !== 'undefined') {
      result = this.levels[result.toUpperCase()];
    }

    if (this.levelValid(result)) {
      return result;
    }
  }

  levelValid(level) {
    if (typeof level === 'number' && level >= 0 && level <= this.levels.SILENT) {
      return true;
    }

    return false;
  }

  /**
   * Build the best logging method possible for this env
   * Wherever possible we want to bind, not wrap, to preserve stack traces.
   * Since we're targeting modern browsers, there's no need to wait for the
   * console to become available.
   */
  // eslint-disable-next-line class-methods-use-this
  make(methodName) {
    if (methodName === 'debug') {
      methodName = 'log';
    }

    /* eslint-disable no-console */
    if (typeof console[methodName] !== 'undefined') {
      return this.bindMethod(console, methodName);
    } else if (typeof console.log !== 'undefined') {
      return this.bindMethod(console, 'log');
    }

    /* eslint-enable no-console */
    return noop;
  }

  replaceMethods(logLevel) {
    const level = this.distillLevel(logLevel);

    if (level == null) {
      throw new Error(`loglevelnext: replaceMethods() called with invalid level: ${logLevel}`);
    }

    if (!this.logger || this.logger.type !== 'LogLevel') {
      throw new TypeError('loglevelnext: Logger is undefined or invalid. Please specify a valid Logger instance.');
    }

    this.methods.forEach((methodName) => {
      const { [methodName.toUpperCase()]: methodLevel } = this.levels;

      this.logger[methodName] = (methodLevel < level) ? noop : this.make(methodName);
    });

    // Define log.log as an alias for log.debug
    this.logger.log = this.logger.debug;
  }
};