index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. 'use strict';
  2. var util = require('util');
  3. var isArrayish = require('is-arrayish');
  4. var errorEx = function errorEx(name, properties) {
  5. if (!name || name.constructor !== String) {
  6. properties = name || {};
  7. name = Error.name;
  8. }
  9. var errorExError = function ErrorEXError(message) {
  10. if (!this) {
  11. return new ErrorEXError(message);
  12. }
  13. message = message instanceof Error
  14. ? message.message
  15. : (message || this.message);
  16. Error.call(this, message);
  17. Error.captureStackTrace(this, errorExError);
  18. this.name = name;
  19. Object.defineProperty(this, 'message', {
  20. configurable: true,
  21. enumerable: false,
  22. get: function () {
  23. var newMessage = message.split(/\r?\n/g);
  24. for (var key in properties) {
  25. if (!properties.hasOwnProperty(key)) {
  26. continue;
  27. }
  28. var modifier = properties[key];
  29. if ('message' in modifier) {
  30. newMessage = modifier.message(this[key], newMessage) || newMessage;
  31. if (!isArrayish(newMessage)) {
  32. newMessage = [newMessage];
  33. }
  34. }
  35. }
  36. return newMessage.join('\n');
  37. },
  38. set: function (v) {
  39. message = v;
  40. }
  41. });
  42. var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack');
  43. var stackGetter = stackDescriptor.get;
  44. var stackValue = stackDescriptor.value;
  45. delete stackDescriptor.value;
  46. delete stackDescriptor.writable;
  47. stackDescriptor.get = function () {
  48. var stack = (stackGetter)
  49. ? stackGetter.call(this).split(/\r?\n+/g)
  50. : stackValue.split(/\r?\n+/g);
  51. // starting in Node 7, the stack builder caches the message.
  52. // just replace it.
  53. stack[0] = this.name + ': ' + this.message;
  54. var lineCount = 1;
  55. for (var key in properties) {
  56. if (!properties.hasOwnProperty(key)) {
  57. continue;
  58. }
  59. var modifier = properties[key];
  60. if ('line' in modifier) {
  61. var line = modifier.line(this[key]);
  62. if (line) {
  63. stack.splice(lineCount++, 0, ' ' + line);
  64. }
  65. }
  66. if ('stack' in modifier) {
  67. modifier.stack(this[key], stack);
  68. }
  69. }
  70. return stack.join('\n');
  71. };
  72. Object.defineProperty(this, 'stack', stackDescriptor);
  73. };
  74. if (Object.setPrototypeOf) {
  75. Object.setPrototypeOf(errorExError.prototype, Error.prototype);
  76. Object.setPrototypeOf(errorExError, Error);
  77. } else {
  78. util.inherits(errorExError, Error);
  79. }
  80. return errorExError;
  81. };
  82. errorEx.append = function (str, def) {
  83. return {
  84. message: function (v, message) {
  85. v = v || def;
  86. if (v) {
  87. message[0] += ' ' + str.replace('%s', v.toString());
  88. }
  89. return message;
  90. }
  91. };
  92. };
  93. errorEx.line = function (str, def) {
  94. return {
  95. line: function (v) {
  96. v = v || def;
  97. if (v) {
  98. return str.replace('%s', v.toString());
  99. }
  100. return null;
  101. }
  102. };
  103. };
  104. module.exports = errorEx;