2acb9e907caa4b52dacc1e75b10704663d73dd5c1b0d8322adc8a6ac0466a90e42a6beee796b2846df16222cf1829c78387465e3b7dc8e4bc4f1369af102cf 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. 'use strict';
  2. /* eslint-disable
  3. arrow-parens,
  4. multiline-ternary,
  5. consistent-return,
  6. no-param-reassign,
  7. prefer-destructuring
  8. */
  9. const noop = () => {};
  10. const levels = Symbol('levels');
  11. const instance = Symbol('instance');
  12. class MethodFactory {
  13. constructor(logger) {
  14. this[levels] = {
  15. TRACE: 0,
  16. DEBUG: 1,
  17. INFO: 2,
  18. WARN: 3,
  19. ERROR: 4,
  20. SILENT: 5
  21. };
  22. this[instance] = logger;
  23. }
  24. set logger(logger) {
  25. this[instance] = logger;
  26. }
  27. get logger() {
  28. return this[instance];
  29. }
  30. get levels() {
  31. return this[levels];
  32. }
  33. get methods() {
  34. return Object.keys(this.levels)
  35. .map((key) => key.toLowerCase())
  36. .filter((key) => key !== 'silent');
  37. }
  38. distillLevel(level) {
  39. let result = level;
  40. if (
  41. typeof result === 'string' &&
  42. typeof this.levels[result.toUpperCase()] !== 'undefined'
  43. ) {
  44. result = this.levels[result.toUpperCase()];
  45. }
  46. if (this.levelValid(result)) {
  47. return result;
  48. }
  49. }
  50. levelValid(level) {
  51. if (
  52. typeof level === 'number' && level >= 0 &&
  53. level <= this.levels.SILENT
  54. ) {
  55. return true;
  56. }
  57. return false;
  58. }
  59. /**
  60. * Build the best logging method possible for this env
  61. * Wherever possible we want to bind, not wrap, to preserve stack traces.
  62. * Since we're targeting modern browsers, there's no need to wait for the
  63. * console to become available.
  64. */
  65. // eslint-disable-next-line class-methods-use-this
  66. make(method) {
  67. if (method === 'debug') {
  68. method = 'log';
  69. }
  70. /* eslint-disable no-console */
  71. if (typeof console[method] !== 'undefined') {
  72. return this.bindMethod(console, method);
  73. } else if (typeof console.log !== 'undefined') {
  74. return this.bindMethod(console, 'log');
  75. }
  76. /* eslint-enable no-console */
  77. return noop;
  78. }
  79. // eslint-disable-next-line class-methods-use-this
  80. bindMethod(obj, name) {
  81. const method = obj[name];
  82. if (typeof method.bind === 'function') {
  83. return method.bind(obj);
  84. }
  85. try {
  86. return Function.prototype.bind.call(method, obj);
  87. } catch (err) {
  88. // Missing bind shim or IE8 + Modernizr, fallback to wrapping
  89. return function result() {
  90. // eslint-disable-next-line prefer-rest-params
  91. return Function.prototype.apply.apply(method, [obj, arguments]);
  92. };
  93. }
  94. }
  95. replaceMethods(logLevel) {
  96. const level = this.distillLevel(logLevel);
  97. if (level == null) {
  98. throw new Error(
  99. `loglevel: replaceMethods() called with invalid level: ${logLevel}`
  100. );
  101. }
  102. if (!this.logger || this.logger.type !== 'LogLevel') {
  103. throw new TypeError(
  104. 'loglevel: Logger is undefined or invalid. Please specify a valid Logger instance.'
  105. );
  106. }
  107. this.methods.forEach((method) => {
  108. this.logger[method] = (this.levels[method.toUpperCase()] < level)
  109. ? noop
  110. : this.make(method);
  111. });
  112. // Define log.log as an alias for log.debug
  113. this.logger.log = this.logger.debug;
  114. }
  115. }
  116. module.exports = MethodFactory;