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.

207 lines
4.2 KiB

  1. /* eslint no-empty: 1 */
  2. /*!
  3. * Module dependencies.
  4. */
  5. var SchemaType = require('../schematype'),
  6. CastError = SchemaType.CastError,
  7. oid = require('../types/objectid'),
  8. utils = require('../utils'),
  9. Document;
  10. /**
  11. * ObjectId SchemaType constructor.
  12. *
  13. * @param {String} key
  14. * @param {Object} options
  15. * @inherits SchemaType
  16. * @api public
  17. */
  18. function ObjectId(key, options) {
  19. SchemaType.call(this, key, options, 'ObjectID');
  20. }
  21. /**
  22. * This schema type's name, to defend against minifiers that mangle
  23. * function names.
  24. *
  25. * @api public
  26. */
  27. ObjectId.schemaName = 'ObjectId';
  28. /*!
  29. * Inherits from SchemaType.
  30. */
  31. ObjectId.prototype = Object.create(SchemaType.prototype);
  32. ObjectId.prototype.constructor = ObjectId;
  33. /**
  34. * Adds an auto-generated ObjectId default if turnOn is true.
  35. * @param {Boolean} turnOn auto generated ObjectId defaults
  36. * @api public
  37. * @return {SchemaType} this
  38. */
  39. ObjectId.prototype.auto = function(turnOn) {
  40. if (turnOn) {
  41. this.default(defaultId);
  42. this.set(resetId);
  43. }
  44. return this;
  45. };
  46. /**
  47. * Check if the given value satisfies a required validator.
  48. *
  49. * @param {Any} value
  50. * @param {Document} doc
  51. * @return {Boolean}
  52. * @api public
  53. */
  54. ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
  55. if (SchemaType._isRef(this, value, doc, true)) {
  56. return !!value;
  57. }
  58. return value instanceof oid;
  59. };
  60. /**
  61. * Casts to ObjectId
  62. *
  63. * @param {Object} value
  64. * @param {Object} doc
  65. * @param {Boolean} init whether this is an initialization cast
  66. * @api private
  67. */
  68. ObjectId.prototype.cast = function(value, doc, init) {
  69. if (SchemaType._isRef(this, value, doc, init)) {
  70. // wait! we may need to cast this to a document
  71. if (value === null || value === undefined) {
  72. return value;
  73. }
  74. // lazy load
  75. Document || (Document = require('./../document'));
  76. if (value instanceof Document) {
  77. value.$__.wasPopulated = true;
  78. return value;
  79. }
  80. // setting a populated path
  81. if (value instanceof oid) {
  82. return value;
  83. } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
  84. throw new CastError('ObjectId', value, this.path);
  85. }
  86. // Handle the case where user directly sets a populated
  87. // path to a plain object; cast to the Model used in
  88. // the population query.
  89. var path = doc.$__fullPath(this.path);
  90. var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
  91. var pop = owner.populated(path, true);
  92. var ret = value;
  93. if (!doc.$__.populated ||
  94. !doc.$__.populated[path] ||
  95. !doc.$__.populated[path].options ||
  96. !doc.$__.populated[path].options.options ||
  97. !doc.$__.populated[path].options.options.lean) {
  98. ret = new pop.options.model(value);
  99. ret.$__.wasPopulated = true;
  100. }
  101. return ret;
  102. }
  103. if (value === null || value === undefined) {
  104. return value;
  105. }
  106. if (value instanceof oid) {
  107. return value;
  108. }
  109. if (value._id) {
  110. if (value._id instanceof oid) {
  111. return value._id;
  112. }
  113. if (value._id.toString instanceof Function) {
  114. try {
  115. return new oid(value._id.toString());
  116. } catch (e) {
  117. }
  118. }
  119. }
  120. if (value.toString instanceof Function) {
  121. try {
  122. return new oid(value.toString());
  123. } catch (err) {
  124. throw new CastError('ObjectId', value, this.path);
  125. }
  126. }
  127. throw new CastError('ObjectId', value, this.path);
  128. };
  129. /*!
  130. * ignore
  131. */
  132. function handleSingle(val) {
  133. return this.cast(val);
  134. }
  135. ObjectId.prototype.$conditionalHandlers =
  136. utils.options(SchemaType.prototype.$conditionalHandlers, {
  137. $gt: handleSingle,
  138. $gte: handleSingle,
  139. $lt: handleSingle,
  140. $lte: handleSingle
  141. });
  142. /**
  143. * Casts contents for queries.
  144. *
  145. * @param {String} $conditional
  146. * @param {any} [val]
  147. * @api private
  148. */
  149. ObjectId.prototype.castForQuery = function($conditional, val) {
  150. var handler;
  151. if (arguments.length === 2) {
  152. handler = this.$conditionalHandlers[$conditional];
  153. if (!handler) {
  154. throw new Error('Can\'t use ' + $conditional + ' with ObjectId.');
  155. }
  156. return handler.call(this, val);
  157. }
  158. return this.cast($conditional);
  159. };
  160. /*!
  161. * ignore
  162. */
  163. function defaultId() {
  164. return new oid();
  165. }
  166. function resetId(v) {
  167. this.$__._id = null;
  168. return v;
  169. }
  170. /*!
  171. * Module exports.
  172. */
  173. module.exports = ObjectId;