cast.js 3.4 KB

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