Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

number.js 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. 'use strict';
  2. /*!
  3. * Module requirements.
  4. */
  5. const MongooseError = require('../error');
  6. const SchemaType = require('../schematype');
  7. const castNumber = require('../cast/number');
  8. const handleBitwiseOperator = require('./operators/bitwise');
  9. const utils = require('../utils');
  10. const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
  11. const CastError = SchemaType.CastError;
  12. let Document;
  13. /**
  14. * Number SchemaType constructor.
  15. *
  16. * @param {String} key
  17. * @param {Object} options
  18. * @inherits SchemaType
  19. * @api public
  20. */
  21. function SchemaNumber(key, options) {
  22. SchemaType.call(this, key, options, 'Number');
  23. }
  24. /**
  25. * Attaches a getter for all Number instances.
  26. *
  27. * ####Example:
  28. *
  29. * // Make all numbers round down
  30. * mongoose.Number.get(function(v) { return Math.floor(v); });
  31. *
  32. * const Model = mongoose.model('Test', new Schema({ test: Number }));
  33. * new Model({ test: 3.14 }).test; // 3
  34. *
  35. * @param {Function} getter
  36. * @return {this}
  37. * @function get
  38. * @static
  39. * @api public
  40. */
  41. SchemaNumber.get = SchemaType.get;
  42. /*!
  43. * ignore
  44. */
  45. SchemaNumber._cast = castNumber;
  46. /**
  47. * Get/set the function used to cast arbitrary values to numbers.
  48. *
  49. * ####Example:
  50. *
  51. * // Make Mongoose cast empty strings '' to 0 for paths declared as numbers
  52. * const original = mongoose.Number.cast();
  53. * mongoose.Number.cast(v => {
  54. * if (v === '') { return 0; }
  55. * return original(v);
  56. * });
  57. *
  58. * // Or disable casting entirely
  59. * mongoose.Number.cast(false);
  60. *
  61. * @param {Function} caster
  62. * @return {Function}
  63. * @function get
  64. * @static
  65. * @api public
  66. */
  67. SchemaNumber.cast = function cast(caster) {
  68. if (arguments.length === 0) {
  69. return this._cast;
  70. }
  71. if (caster === false) {
  72. caster = v => {
  73. if (typeof v !== 'number') {
  74. throw new Error();
  75. }
  76. return v;
  77. };
  78. }
  79. this._cast = caster;
  80. return this._cast;
  81. };
  82. /**
  83. * This schema type's name, to defend against minifiers that mangle
  84. * function names.
  85. *
  86. * @api public
  87. */
  88. SchemaNumber.schemaName = 'Number';
  89. /*!
  90. * Inherits from SchemaType.
  91. */
  92. SchemaNumber.prototype = Object.create(SchemaType.prototype);
  93. SchemaNumber.prototype.constructor = SchemaNumber;
  94. /*!
  95. * ignore
  96. */
  97. SchemaNumber._checkRequired = v => typeof v === 'number' || v instanceof Number;
  98. /**
  99. * Override the function the required validator uses to check whether a string
  100. * passes the `required` check.
  101. *
  102. * @param {Function} fn
  103. * @return {Function}
  104. * @function checkRequired
  105. * @static
  106. * @api public
  107. */
  108. SchemaNumber.checkRequired = SchemaType.checkRequired;
  109. /**
  110. * Check if the given value satisfies a required validator.
  111. *
  112. * @param {Any} value
  113. * @param {Document} doc
  114. * @return {Boolean}
  115. * @api public
  116. */
  117. SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
  118. if (SchemaType._isRef(this, value, doc, true)) {
  119. return !!value;
  120. }
  121. // `require('util').inherits()` does **not** copy static properties, and
  122. // plugins like mongoose-float use `inherits()` for pre-ES6.
  123. const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
  124. this.constructor.checkRequired() :
  125. SchemaNumber.checkRequired();
  126. return _checkRequired(value);
  127. };
  128. /**
  129. * Sets a minimum number validator.
  130. *
  131. * ####Example:
  132. *
  133. * var s = new Schema({ n: { type: Number, min: 10 })
  134. * var M = db.model('M', s)
  135. * var m = new M({ n: 9 })
  136. * m.save(function (err) {
  137. * console.error(err) // validator error
  138. * m.n = 10;
  139. * m.save() // success
  140. * })
  141. *
  142. * // custom error messages
  143. * // We can also use the special {MIN} token which will be replaced with the invalid value
  144. * var min = [10, 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
  145. * var schema = new Schema({ n: { type: Number, min: min })
  146. * var M = mongoose.model('Measurement', schema);
  147. * var s= new M({ n: 4 });
  148. * s.validate(function (err) {
  149. * console.log(String(err)) // ValidationError: The value of path `n` (4) is beneath the limit (10).
  150. * })
  151. *
  152. * @param {Number} value minimum number
  153. * @param {String} [message] optional custom error message
  154. * @return {SchemaType} this
  155. * @see Customized Error Messages #error_messages_MongooseError-messages
  156. * @api public
  157. */
  158. SchemaNumber.prototype.min = function(value, message) {
  159. if (this.minValidator) {
  160. this.validators = this.validators.filter(function(v) {
  161. return v.validator !== this.minValidator;
  162. }, this);
  163. }
  164. if (value !== null && value !== undefined) {
  165. let msg = message || MongooseError.messages.Number.min;
  166. msg = msg.replace(/{MIN}/, value);
  167. this.validators.push({
  168. validator: this.minValidator = function(v) {
  169. return v == null || v >= value;
  170. },
  171. message: msg,
  172. type: 'min',
  173. min: value
  174. });
  175. }
  176. return this;
  177. };
  178. /**
  179. * Sets a maximum number validator.
  180. *
  181. * ####Example:
  182. *
  183. * var s = new Schema({ n: { type: Number, max: 10 })
  184. * var M = db.model('M', s)
  185. * var m = new M({ n: 11 })
  186. * m.save(function (err) {
  187. * console.error(err) // validator error
  188. * m.n = 10;
  189. * m.save() // success
  190. * })
  191. *
  192. * // custom error messages
  193. * // We can also use the special {MAX} token which will be replaced with the invalid value
  194. * var max = [10, 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
  195. * var schema = new Schema({ n: { type: Number, max: max })
  196. * var M = mongoose.model('Measurement', schema);
  197. * var s= new M({ n: 4 });
  198. * s.validate(function (err) {
  199. * console.log(String(err)) // ValidationError: The value of path `n` (4) exceeds the limit (10).
  200. * })
  201. *
  202. * @param {Number} maximum number
  203. * @param {String} [message] optional custom error message
  204. * @return {SchemaType} this
  205. * @see Customized Error Messages #error_messages_MongooseError-messages
  206. * @api public
  207. */
  208. SchemaNumber.prototype.max = function(value, message) {
  209. if (this.maxValidator) {
  210. this.validators = this.validators.filter(function(v) {
  211. return v.validator !== this.maxValidator;
  212. }, this);
  213. }
  214. if (value !== null && value !== undefined) {
  215. let msg = message || MongooseError.messages.Number.max;
  216. msg = msg.replace(/{MAX}/, value);
  217. this.validators.push({
  218. validator: this.maxValidator = function(v) {
  219. return v == null || v <= value;
  220. },
  221. message: msg,
  222. type: 'max',
  223. max: value
  224. });
  225. }
  226. return this;
  227. };
  228. /**
  229. * Casts to number
  230. *
  231. * @param {Object} value value to cast
  232. * @param {Document} doc document that triggers the casting
  233. * @param {Boolean} init
  234. * @api private
  235. */
  236. SchemaNumber.prototype.cast = function(value, doc, init) {
  237. if (SchemaType._isRef(this, value, doc, init)) {
  238. // wait! we may need to cast this to a document
  239. if (value === null || value === undefined) {
  240. return value;
  241. }
  242. // lazy load
  243. Document || (Document = require('./../document'));
  244. if (value instanceof Document) {
  245. value.$__.wasPopulated = true;
  246. return value;
  247. }
  248. // setting a populated path
  249. if (typeof value === 'number') {
  250. return value;
  251. } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
  252. throw new CastError('number', value, this.path);
  253. }
  254. // Handle the case where user directly sets a populated
  255. // path to a plain object; cast to the Model used in
  256. // the population query.
  257. const path = doc.$__fullPath(this.path);
  258. const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
  259. const pop = owner.populated(path, true);
  260. const ret = new pop.options[populateModelSymbol](value);
  261. ret.$__.wasPopulated = true;
  262. return ret;
  263. }
  264. const val = value && typeof value._id !== 'undefined' ?
  265. value._id : // documents
  266. value;
  267. const castNumber = typeof this.constructor.cast === 'function' ?
  268. this.constructor.cast() :
  269. SchemaNumber.cast();
  270. try {
  271. return castNumber(val);
  272. } catch (err) {
  273. throw new CastError('number', val, this.path);
  274. }
  275. };
  276. /*!
  277. * ignore
  278. */
  279. function handleSingle(val) {
  280. return this.cast(val);
  281. }
  282. function handleArray(val) {
  283. const _this = this;
  284. if (!Array.isArray(val)) {
  285. return [this.cast(val)];
  286. }
  287. return val.map(function(m) {
  288. return _this.cast(m);
  289. });
  290. }
  291. SchemaNumber.prototype.$conditionalHandlers =
  292. utils.options(SchemaType.prototype.$conditionalHandlers, {
  293. $bitsAllClear: handleBitwiseOperator,
  294. $bitsAnyClear: handleBitwiseOperator,
  295. $bitsAllSet: handleBitwiseOperator,
  296. $bitsAnySet: handleBitwiseOperator,
  297. $gt: handleSingle,
  298. $gte: handleSingle,
  299. $lt: handleSingle,
  300. $lte: handleSingle,
  301. $mod: handleArray
  302. });
  303. /**
  304. * Casts contents for queries.
  305. *
  306. * @param {String} $conditional
  307. * @param {any} [value]
  308. * @api private
  309. */
  310. SchemaNumber.prototype.castForQuery = function($conditional, val) {
  311. let handler;
  312. if (arguments.length === 2) {
  313. handler = this.$conditionalHandlers[$conditional];
  314. if (!handler) {
  315. throw new CastError('Can\'t use ' + $conditional + ' with Number.');
  316. }
  317. return handler.call(this, val);
  318. }
  319. val = this._castForQuery($conditional);
  320. return val;
  321. };
  322. /*!
  323. * Module exports.
  324. */
  325. module.exports = SchemaNumber;