diagnostics.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /**
  2. * Contains all configured adapters for the given environment.
  3. *
  4. * @type {Array}
  5. * @public
  6. */
  7. var adapters = [];
  8. /**
  9. * Contains all modifier functions.
  10. *
  11. * @typs {Array}
  12. * @public
  13. */
  14. var modifiers = [];
  15. /**
  16. * Our default logger.
  17. *
  18. * @public
  19. */
  20. var logger = function devnull() {};
  21. /**
  22. * Register a new adapter that will used to find environments.
  23. *
  24. * @param {Function} adapter A function that will return the possible env.
  25. * @returns {Boolean} Indication of a successful add.
  26. * @public
  27. */
  28. function use(adapter) {
  29. if (~adapters.indexOf(adapter)) return false;
  30. adapters.push(adapter);
  31. return true;
  32. }
  33. /**
  34. * Assign a new log method.
  35. *
  36. * @param {Function} custom The log method.
  37. * @public
  38. */
  39. function set(custom) {
  40. logger = custom;
  41. }
  42. /**
  43. * Check if the namespace is allowed by any of our adapters.
  44. *
  45. * @param {String} namespace The namespace that needs to be enabled
  46. * @returns {Boolean|Promise} Indication if the namespace is enabled by our adapters.
  47. * @public
  48. */
  49. function enabled(namespace) {
  50. var async = [];
  51. for (var i = 0; i < adapters.length; i++) {
  52. if (adapters[i].async) {
  53. async.push(adapters[i]);
  54. continue;
  55. }
  56. if (adapters[i](namespace)) return true;
  57. }
  58. if (!async.length) return false;
  59. //
  60. // Now that we know that we Async functions, we know we run in an ES6
  61. // environment and can use all the API's that they offer, in this case
  62. // we want to return a Promise so that we can `await` in React-Native
  63. // for an async adapter.
  64. //
  65. return new Promise(function pinky(resolve) {
  66. Promise.all(
  67. async.map(function prebind(fn) {
  68. return fn(namespace);
  69. })
  70. ).then(function resolved(values) {
  71. resolve(values.some(Boolean));
  72. });
  73. });
  74. }
  75. /**
  76. * Add a new message modifier to the debugger.
  77. *
  78. * @param {Function} fn Modification function.
  79. * @returns {Boolean} Indication of a successful add.
  80. * @public
  81. */
  82. function modify(fn) {
  83. if (~modifiers.indexOf(fn)) return false;
  84. modifiers.push(fn);
  85. return true;
  86. }
  87. /**
  88. * Write data to the supplied logger.
  89. *
  90. * @param {Object} meta Meta information about the log.
  91. * @param {Array} args Arguments for console.log.
  92. * @public
  93. */
  94. function write() {
  95. logger.apply(logger, arguments);
  96. }
  97. /**
  98. * Process the message with the modifiers.
  99. *
  100. * @param {Mixed} message The message to be transformed by modifers.
  101. * @returns {String} Transformed message.
  102. * @public
  103. */
  104. function process(message) {
  105. for (var i = 0; i < modifiers.length; i++) {
  106. message = modifiers[i].apply(modifiers[i], arguments);
  107. }
  108. return message;
  109. }
  110. /**
  111. * Introduce options to the logger function.
  112. *
  113. * @param {Function} fn Calback function.
  114. * @param {Object} options Properties to introduce on fn.
  115. * @returns {Function} The passed function
  116. * @public
  117. */
  118. function introduce(fn, options) {
  119. var has = Object.prototype.hasOwnProperty;
  120. for (var key in options) {
  121. if (has.call(options, key)) {
  122. fn[key] = options[key];
  123. }
  124. }
  125. return fn;
  126. }
  127. /**
  128. * Nope, we're not allowed to write messages.
  129. *
  130. * @returns {Boolean} false
  131. * @public
  132. */
  133. function nope(options) {
  134. options.enabled = false;
  135. options.modify = modify;
  136. options.set = set;
  137. options.use = use;
  138. return introduce(function diagnopes() {
  139. return false;
  140. }, options);
  141. }
  142. /**
  143. * Yep, we're allowed to write debug messages.
  144. *
  145. * @param {Object} options The options for the process.
  146. * @returns {Function} The function that does the logging.
  147. * @public
  148. */
  149. function yep(options) {
  150. /**
  151. * The function that receives the actual debug information.
  152. *
  153. * @returns {Boolean} indication that we're logging.
  154. * @public
  155. */
  156. function diagnostics() {
  157. var args = Array.prototype.slice.call(arguments, 0);
  158. write.call(write, options, process(args, options));
  159. return true;
  160. }
  161. options.enabled = true;
  162. options.modify = modify;
  163. options.set = set;
  164. options.use = use;
  165. return introduce(diagnostics, options);
  166. }
  167. /**
  168. * Simple helper function to introduce various of helper methods to our given
  169. * diagnostics function.
  170. *
  171. * @param {Function} diagnostics The diagnostics function.
  172. * @returns {Function} diagnostics
  173. * @public
  174. */
  175. module.exports = function create(diagnostics) {
  176. diagnostics.introduce = introduce;
  177. diagnostics.enabled = enabled;
  178. diagnostics.process = process;
  179. diagnostics.modify = modify;
  180. diagnostics.write = write;
  181. diagnostics.nope = nope;
  182. diagnostics.yep = yep;
  183. diagnostics.set = set;
  184. diagnostics.use = use;
  185. return diagnostics;
  186. }