cast.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. 'use strict';
  2. /*!
  3. * Module dependencies.
  4. */
  5. const MongooseError = require('./mongooseError');
  6. const util = require('util');
  7. /**
  8. * Casting Error constructor.
  9. *
  10. * @param {String} type
  11. * @param {String} value
  12. * @inherits MongooseError
  13. * @api private
  14. */
  15. class CastError extends MongooseError {
  16. constructor(type, value, path, reason, schemaType) {
  17. // If no args, assume we'll `init()` later.
  18. if (arguments.length > 0) {
  19. const stringValue = getStringValue(value);
  20. const valueType = getValueType(value);
  21. const messageFormat = getMessageFormat(schemaType);
  22. const msg = formatMessage(null, type, stringValue, path, messageFormat, valueType, reason);
  23. super(msg);
  24. this.init(type, value, path, reason, schemaType);
  25. } else {
  26. super(formatMessage());
  27. }
  28. }
  29. toJSON() {
  30. return {
  31. stringValue: this.stringValue,
  32. valueType: this.valueType,
  33. kind: this.kind,
  34. value: this.value,
  35. path: this.path,
  36. reason: this.reason,
  37. name: this.name,
  38. message: this.message
  39. };
  40. }
  41. /*!
  42. * ignore
  43. */
  44. init(type, value, path, reason, schemaType) {
  45. this.stringValue = getStringValue(value);
  46. this.messageFormat = getMessageFormat(schemaType);
  47. this.kind = type;
  48. this.value = value;
  49. this.path = path;
  50. this.reason = reason;
  51. this.valueType = getValueType(value);
  52. }
  53. /*!
  54. * ignore
  55. * @param {Readonly<CastError>} other
  56. */
  57. copy(other) {
  58. this.messageFormat = other.messageFormat;
  59. this.stringValue = other.stringValue;
  60. this.kind = other.kind;
  61. this.value = other.value;
  62. this.path = other.path;
  63. this.reason = other.reason;
  64. this.message = other.message;
  65. this.valueType = other.valueType;
  66. }
  67. /*!
  68. * ignore
  69. */
  70. setModel(model) {
  71. this.model = model;
  72. this.message = formatMessage(model, this.kind, this.stringValue, this.path,
  73. this.messageFormat, this.valueType);
  74. }
  75. }
  76. Object.defineProperty(CastError.prototype, 'name', {
  77. value: 'CastError'
  78. });
  79. function getStringValue(value) {
  80. let stringValue = util.inspect(value);
  81. stringValue = stringValue.replace(/^'|'$/g, '"');
  82. if (!stringValue.startsWith('"')) {
  83. stringValue = '"' + stringValue + '"';
  84. }
  85. return stringValue;
  86. }
  87. function getValueType(value) {
  88. if (value == null) {
  89. return '' + value;
  90. }
  91. const t = typeof value;
  92. if (t !== 'object') {
  93. return t;
  94. }
  95. if (typeof value.constructor !== 'function') {
  96. return t;
  97. }
  98. return value.constructor.name;
  99. }
  100. function getMessageFormat(schemaType) {
  101. const messageFormat = schemaType &&
  102. schemaType.options &&
  103. schemaType.options.cast || null;
  104. if (typeof messageFormat === 'string') {
  105. return messageFormat;
  106. }
  107. }
  108. /*!
  109. * ignore
  110. */
  111. function formatMessage(model, kind, stringValue, path, messageFormat, valueType, reason) {
  112. if (messageFormat != null) {
  113. let ret = messageFormat.
  114. replace('{KIND}', kind).
  115. replace('{VALUE}', stringValue).
  116. replace('{PATH}', path);
  117. if (model != null) {
  118. ret = ret.replace('{MODEL}', model.modelName);
  119. }
  120. return ret;
  121. } else {
  122. const valueTypeMsg = valueType ? ' (type ' + valueType + ')' : '';
  123. let ret = 'Cast to ' + kind + ' failed for value ' +
  124. stringValue + valueTypeMsg + ' at path "' + path + '"';
  125. if (model != null) {
  126. ret += ' for model "' + model.modelName + '"';
  127. }
  128. if (reason != null &&
  129. typeof reason.constructor === 'function' &&
  130. reason.constructor.name !== 'AssertionError' &&
  131. reason.constructor.name !== 'Error') {
  132. ret += ' because of "' + reason.constructor.name + '"';
  133. }
  134. return ret;
  135. }
  136. }
  137. /*!
  138. * exports
  139. */
  140. module.exports = CastError;