arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/mongoose/lib/schema/string.js
node_modules/mongoose/lib/schema/string.jsRaw
  1
  2/*!
  3 * Module dependencies.
  4 */
  5
  6var SchemaType = require('../schematype')
  7  , CastError = SchemaType.CastError
  8  , utils = require('../utils')
  9  , Document
 10
 11/**
 12 * String SchemaType constructor.
 13 *
 14 * @param {String} key
 15 * @param {Object} options
 16 * @inherits SchemaType
 17 * @api private
 18 */
 19
 20function SchemaString (key, options) {
 21  this.enumValues = [];
 22  this.regExp = null;
 23  SchemaType.call(this, key, options, 'String');
 24};
 25
 26/*!
 27 * Inherits from SchemaType.
 28 */
 29
 30SchemaString.prototype.__proto__ = SchemaType.prototype;
 31
 32/**
 33 * Adds enumeration values and a coinciding validator.
 34 *
 35 * ####Example:
 36 *
 37 *     var states = 'opening open closing closed'.split(' ')
 38 *     var s = new Schema({ state: { type: String, enum: states })
 39 *     var M = db.model('M', s)
 40 *     var m = new M({ state: 'invalid' })
 41 *     m.save(function (err) {
 42 *       console.error(err) // validator error
 43 *       m.state = 'open'
 44 *       m.save() // success
 45 *     })
 46 *
 47 * @param {String} [args...] enumeration values
 48 * @return {SchemaType} this
 49 * @api public
 50 */
 51
 52SchemaString.prototype.enum = function () {
 53  var len = arguments.length;
 54
 55  if (!len || undefined === arguments[0] || false === arguments[0]) {
 56    if (this.enumValidator){
 57      this.enumValidator = false;
 58      this.validators = this.validators.filter(function(v){
 59        return v[1] != 'enum';
 60      });
 61    }
 62    return this;
 63  }
 64
 65  for (var i = 0; i < len; i++) {
 66    if (undefined !== arguments[i]) {
 67      this.enumValues.push(this.cast(arguments[i]));
 68    }
 69  }
 70
 71  if (!this.enumValidator) {
 72    var values = this.enumValues;
 73    this.enumValidator = function(v){
 74      return undefined === v || ~values.indexOf(v);
 75    };
 76    this.validators.push([this.enumValidator, 'enum']);
 77  }
 78
 79  return this;
 80};
 81
 82/**
 83 * Adds a lowercase setter.
 84 *
 85 * ####Example:
 86 *
 87 *     var s = new Schema({ email: { type: String, lowercase: true }})
 88 *     var M = db.model('M', s);
 89 *     var m = new M({ email: 'SomeEmail@example.COM' });
 90 *     console.log(m.email) // someemail@example.com
 91 *
 92 * @api public
 93 * @return {SchemaType} this
 94 */
 95
 96SchemaString.prototype.lowercase = function () {
 97  return this.set(function (v, self) {
 98    if ('string' != typeof v) v = self.cast(v)
 99    if (v) return v.toLowerCase();
100    return v;
101  });
102};
103
104/**
105 * Adds an uppercase setter.
106 *
107 * ####Example:
108 *
109 *     var s = new Schema({ caps: { type: String, uppercase: true }})
110 *     var M = db.model('M', s);
111 *     var m = new M({ caps: 'an example' });
112 *     console.log(m.caps) // AN EXAMPLE
113 *
114 * @api public
115 * @return {SchemaType} this
116 */
117
118SchemaString.prototype.uppercase = function () {
119  return this.set(function (v, self) {
120    if ('string' != typeof v) v = self.cast(v)
121    if (v) return v.toUpperCase();
122    return v;
123  });
124};
125
126/**
127 * Adds a trim setter.
128 *
129 * The string value will be trimmed when set.
130 *
131 * ####Example:
132 *
133 *     var s = new Schema({ name: { type: String, trim: true }})
134 *     var M = db.model('M', s)
135 *     var string = ' some name '
136 *     console.log(string.length) // 11
137 *     var m = new M({ name: string })
138 *     console.log(m.name.length) // 9
139 *
140 * @api public
141 * @return {SchemaType} this
142 */
143
144SchemaString.prototype.trim = function () {
145  return this.set(function (v, self) {
146    if ('string' != typeof v) v = self.cast(v)
147    if (v) return v.trim();
148    return v;
149  });
150};
151
152/**
153 * Sets a regexp validator.
154 *
155 * Any value that does not pass `regExp`.test(val) will fail validation.
156 *
157 * ####Example:
158 *
159 *     var s = new Schema({ name: { type: String, match: /^a/ }})
160 *     var M = db.model('M', s)
161 *     var m = new M({ name: 'invalid' })
162 *     m.validate(function (err) {
163 *       console.error(err) // validation error
164 *       m.name = 'apples'
165 *       m.validate(function (err) {
166 *         assert.ok(err) // success
167 *       })
168 *     })
169 *
170 * @param {RegExp} regExp regular expression to test against
171 * @return {SchemaType} this
172 * @api public
173 */
174
175SchemaString.prototype.match = function match (regExp) {
176  this.validators.push([function(v){
177    return null != v && '' !== v
178      ? regExp.test(v)
179      : true
180  }, 'regexp']);
181
182  return this;
183};
184
185/**
186 * Check required
187 *
188 * @param {String|null|undefined} value
189 * @api private
190 */
191
192SchemaString.prototype.checkRequired = function checkRequired (value, doc) {
193  if (SchemaType._isRef(this, value, doc, true)) {
194    return null != value;
195  } else {
196    return (value instanceof String || typeof value == 'string') && value.length;
197  }
198};
199
200/**
201 * Casts to String
202 *
203 * @api private
204 */
205
206SchemaString.prototype.cast = function (value, doc, init) {
207  if (SchemaType._isRef(this, value, doc, init)) {
208    // wait! we may need to cast this to a document
209
210    if (null == value) {
211      return value;
212    }
213
214    // lazy load
215    Document || (Document = require('./../document'));
216
217    if (value instanceof Document) {
218      value.$__.wasPopulated = true;
219      return value;
220    }
221
222    // setting a populated path
223    if ('string' == typeof value) {
224      return value;
225    } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
226      throw new CastError('string', value, this.path);
227    }
228
229    // Handle the case where user directly sets a populated
230    // path to a plain object; cast to the Model used in
231    // the population query.
232    var path = doc.$__fullPath(this.path);
233    var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
234    var pop = owner.populated(path, true);
235    var ret = new pop.options.model(value);
236    ret.$__.wasPopulated = true;
237    return ret;
238  }
239
240  if (value === null) {
241    return value;
242  }
243
244  if ('undefined' !== typeof value) {
245    // handle documents being passed
246    if (value._id && 'string' == typeof value._id) {
247      return value._id;
248    }
249    if (value.toString) {
250      return value.toString();
251    }
252  }
253
254
255  throw new CastError('string', value, this.path);
256};
257
258/*!
259 * ignore
260 */
261
262function handleSingle (val) {
263  return this.castForQuery(val);
264}
265
266function handleArray (val) {
267  var self = this;
268  return val.map(function (m) {
269    return self.castForQuery(m);
270  });
271}
272
273SchemaString.prototype.$conditionalHandlers = {
274    '$ne' : handleSingle
275  , '$in' : handleArray
276  , '$nin': handleArray
277  , '$gt' : handleSingle
278  , '$lt' : handleSingle
279  , '$gte': handleSingle
280  , '$lte': handleSingle
281  , '$all': handleArray
282  , '$regex': handleSingle
283  , '$options': handleSingle
284};
285
286/**
287 * Casts contents for queries.
288 *
289 * @param {String} $conditional
290 * @param {any} [val]
291 * @api private
292 */
293
294SchemaString.prototype.castForQuery = function ($conditional, val) {
295  var handler;
296  if (arguments.length === 2) {
297    handler = this.$conditionalHandlers[$conditional];
298    if (!handler)
299      throw new Error("Can't use " + $conditional + " with String.");
300    return handler.call(this, val);
301  } else {
302    val = $conditional;
303    if (val instanceof RegExp) return val;
304    return this.cast(val);
305  }
306};
307
308/*!
309 * Module exports.
310 */
311
312module.exports = SchemaString;