API Reference Source

lib/errors/validation-error.js

  1. 'use strict';
  2.  
  3. const BaseError = require('./base-error');
  4.  
  5. /**
  6. * Validation Error. Thrown when the sequelize validation has failed. The error contains an `errors` property,
  7. * which is an array with 1 or more ValidationErrorItems, one for each validation that failed.
  8. *
  9. * @param {string} message Error message
  10. * @param {Array} [errors] Array of ValidationErrorItem objects describing the validation errors
  11. *
  12. * @property errors {ValidationErrorItems[]}
  13. */
  14. class ValidationError extends BaseError {
  15. constructor(message, errors) {
  16. super(message);
  17. this.name = 'SequelizeValidationError';
  18. this.message = 'Validation Error';
  19. /**
  20. *
  21. * @type {ValidationErrorItem[]}
  22. */
  23. this.errors = errors || [];
  24.  
  25. // Use provided error message if available...
  26. if (message) {
  27. this.message = message;
  28.  
  29. // ... otherwise create a concatenated message out of existing errors.
  30. } else if (this.errors.length > 0 && this.errors[0].message) {
  31. this.message = this.errors.map(err => `${err.type || err.origin}: ${err.message}`).join(',\n');
  32. }
  33. Error.captureStackTrace(this, this.constructor);
  34. }
  35.  
  36. /**
  37. * Gets all validation error items for the path / field specified.
  38. *
  39. * @param {string} path The path to be checked for error items
  40. *
  41. * @returns {Array<ValidationErrorItem>} Validation error items for the specified path
  42. */
  43. get(path) {
  44. return this.errors.reduce((reduced, error) => {
  45. if (error.path === path) {
  46. reduced.push(error);
  47. }
  48. return reduced;
  49. }, []);
  50. }
  51. }
  52.  
  53. /**
  54. * Validation Error Item
  55. * Instances of this class are included in the `ValidationError.errors` property.
  56. */
  57. class ValidationErrorItem {
  58. /**
  59. * Creates new validation error item
  60. *
  61. * @param {string} message An error message
  62. * @param {string} type The type/origin of the validation error
  63. * @param {string} path The field that triggered the validation error
  64. * @param {string} value The value that generated the error
  65. * @param {Object} [inst] the DAO instance that caused the validation error
  66. * @param {Object} [validatorKey] a validation "key", used for identification
  67. * @param {string} [fnName] property name of the BUILT-IN validator function that caused the validation error (e.g. "in" or "len"), if applicable
  68. * @param {string} [fnArgs] parameters used with the BUILT-IN validator function, if applicable
  69. */
  70. constructor(message, type, path, value, inst, validatorKey, fnName, fnArgs) {
  71. /**
  72. * An error message
  73. *
  74. * @type {string} message
  75. */
  76. this.message = message || '';
  77.  
  78. /**
  79. * The type/origin of the validation error
  80. *
  81. * @type {string}
  82. */
  83. this.type = null;
  84.  
  85. /**
  86. * The field that triggered the validation error
  87. *
  88. * @type {string}
  89. */
  90. this.path = path || null;
  91.  
  92. /**
  93. * The value that generated the error
  94. *
  95. * @type {string}
  96. */
  97. this.value = value !== undefined ? value : null;
  98.  
  99. this.origin = null;
  100.  
  101. /**
  102. * The DAO instance that caused the validation error
  103. *
  104. * @type {Model}
  105. */
  106. this.instance = inst || null;
  107.  
  108. /**
  109. * A validation "key", used for identification
  110. *
  111. * @type {string}
  112. */
  113. this.validatorKey = validatorKey || null;
  114.  
  115. /**
  116. * Property name of the BUILT-IN validator function that caused the validation error (e.g. "in" or "len"), if applicable
  117. *
  118. * @type {string}
  119. */
  120. this.validatorName = fnName || null;
  121.  
  122. /**
  123. * Parameters used with the BUILT-IN validator function, if applicable
  124. *
  125. * @type {string}
  126. */
  127. this.validatorArgs = fnArgs || [];
  128.  
  129. if (type) {
  130. if (ValidationErrorItem.Origins[ type ]) {
  131. this.origin = type;
  132. } else {
  133. const lowercaseType = `${type}`.toLowerCase().trim();
  134. const realType = ValidationErrorItem.TypeStringMap[ lowercaseType ];
  135.  
  136. if (realType && ValidationErrorItem.Origins[ realType ]) {
  137. this.origin = realType;
  138. this.type = type;
  139. }
  140. }
  141. }
  142.  
  143. // This doesn't need captureStackTrace because it's not a subclass of Error
  144. }
  145.  
  146. /**
  147. * return a lowercase, trimmed string "key" that identifies the validator.
  148. *
  149. * Note: the string will be empty if the instance has neither a valid `validatorKey` property nor a valid `validatorName` property
  150. *
  151. * @param {boolean} [useTypeAsNS=true] controls whether the returned value is "namespace",
  152. * this parameter is ignored if the validator's `type` is not one of ValidationErrorItem.Origins
  153. * @param {string} [NSSeparator='.'] a separator string for concatenating the namespace, must be not be empty,
  154. * defaults to "." (fullstop). only used and validated if useTypeAsNS is TRUE.
  155. * @throws {Error} thrown if NSSeparator is found to be invalid.
  156. * @returns {string}
  157. *
  158. * @private
  159. */
  160. getValidatorKey(useTypeAsNS, NSSeparator) {
  161. const useTANS = useTypeAsNS === undefined || !!useTypeAsNS;
  162. const NSSep = NSSeparator === undefined ? '.' : NSSeparator;
  163.  
  164. const type = this.origin;
  165. const key = this.validatorKey || this.validatorName;
  166. const useNS = useTANS && type && ValidationErrorItem.Origins[ type ];
  167.  
  168. if (useNS && (typeof NSSep !== 'string' || !NSSep.length)) {
  169. throw new Error('Invalid namespace separator given, must be a non-empty string');
  170. }
  171.  
  172. if (!(typeof key === 'string' && key.length)) {
  173. return '';
  174. }
  175.  
  176. return (useNS ? [type, key].join(NSSep) : key).toLowerCase().trim();
  177. }
  178. }
  179.  
  180. /**
  181. * An enum that defines valid ValidationErrorItem `origin` values
  182. *
  183. * @type {Object}
  184. * @property CORE {string} specifies errors that originate from the sequelize "core"
  185. * @property DB {string} specifies validation errors that originate from the storage engine
  186. * @property FUNCTION {string} specifies validation errors that originate from validator functions (both built-in and custom) defined for a given attribute
  187. */
  188. ValidationErrorItem.Origins = {
  189. CORE: 'CORE',
  190. DB: 'DB',
  191. FUNCTION: 'FUNCTION'
  192. };
  193.  
  194. /**
  195. * An object that is used internally by the `ValidationErrorItem` class
  196. * that maps current `type` strings (as given to ValidationErrorItem.constructor()) to
  197. * our new `origin` values.
  198. *
  199. * @type {Object}
  200. */
  201. ValidationErrorItem.TypeStringMap = {
  202. 'notnull violation': 'CORE',
  203. 'string violation': 'CORE',
  204. 'unique violation': 'DB',
  205. 'validation error': 'FUNCTION'
  206. };
  207.  
  208. module.exports = ValidationError;
  209. module.exports.ValidationErrorItem = ValidationErrorItem;