PageRenderTime 30ms CodeModel.GetById 16ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/mongoose/lib/services/model/discriminator.js

https://bitbucket.org/coleman333/smartsite
JavaScript | 163 lines | 128 code | 27 blank | 8 comment | 26 complexity | 66ff6f84db1b75f46630430151fb60f5 MD5 | raw file
  1'use strict';
  2
  3var defineKey = require('../document/compile').defineKey;
  4var utils = require('../../utils');
  5
  6var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = {
  7  toJSON: true,
  8  toObject: true,
  9  _id: true,
 10  id: true
 11};
 12
 13/*!
 14 * ignore
 15 */
 16
 17module.exports = function discriminator(model, name, schema, tiedValue) {
 18  if (!(schema && schema.instanceOfSchema)) {
 19    throw new Error('You must pass a valid discriminator Schema');
 20  }
 21
 22  if (model.base && model.base.options.applyPluginsToDiscriminators) {
 23    model.base._applyPlugins(schema);
 24  }
 25
 26  if (model.schema.discriminatorMapping &&
 27      !model.schema.discriminatorMapping.isRoot) {
 28    throw new Error('Discriminator "' + name +
 29        '" can only be a discriminator of the root model');
 30  }
 31
 32  var key = model.schema.options.discriminatorKey;
 33
 34  var baseSchemaAddition = {};
 35  baseSchemaAddition[key] = {
 36    default: void 0,
 37    select: true,
 38    $skipDiscriminatorCheck: true
 39  };
 40  baseSchemaAddition[key][model.schema.options.typeKey] = String;
 41  model.schema.add(baseSchemaAddition);
 42  defineKey(key, null, model.prototype, null, [key], model.schema.options);
 43
 44  if (schema.path(key) && schema.path(key).options.$skipDiscriminatorCheck !== true) {
 45    throw new Error('Discriminator "' + name +
 46        '" cannot have field with name "' + key + '"');
 47  }
 48
 49  var value = name;
 50  if (typeof tiedValue == 'string' && tiedValue.length) {
 51    value = tiedValue;
 52  }
 53
 54  function merge(schema, baseSchema) {
 55    if (baseSchema.paths._id &&
 56        baseSchema.paths._id.options &&
 57        !baseSchema.paths._id.options.auto) {
 58      var originalSchema = schema;
 59      utils.merge(schema, originalSchema);
 60      delete schema.paths._id;
 61      delete schema.tree._id;
 62    }
 63
 64    // Find conflicting paths: if something is a path in the base schema
 65    // and a nested path in the child schema, overwrite the base schema path.
 66    // See gh-6076
 67    var baseSchemaPaths = Object.keys(baseSchema.paths);
 68    var conflictingPaths = [];
 69    for (i = 0; i < baseSchemaPaths.length; ++i) {
 70      if (schema.nested[baseSchemaPaths[i]]) {
 71        conflictingPaths.push(baseSchemaPaths[i]);
 72      }
 73    }
 74
 75    utils.merge(schema, baseSchema, {
 76      omit: { discriminators: true },
 77      omitNested: conflictingPaths.reduce((cur, path) => {
 78        cur['tree.' + path] = true;
 79        return cur;
 80      }, {})
 81    });
 82
 83    // Clean up conflicting paths _after_ merging re: gh-6076
 84    for (i = 0; i < conflictingPaths.length; ++i) {
 85      delete schema.paths[conflictingPaths[i]];
 86    }
 87
 88    var obj = {};
 89    obj[key] = {
 90      default: value,
 91      select: true,
 92      set: function(newName) {
 93        if (newName === value) {
 94          return value;
 95        }
 96        throw new Error('Can\'t set discriminator key "' + key + '"');
 97      },
 98      $skipDiscriminatorCheck: true
 99    };
100    obj[key][schema.options.typeKey] = String;
101    schema.add(obj);
102    schema.discriminatorMapping = {key: key, value: value, isRoot: false};
103
104    if (baseSchema.options.collection) {
105      schema.options.collection = baseSchema.options.collection;
106    }
107
108    var toJSON = schema.options.toJSON;
109    var toObject = schema.options.toObject;
110    var _id = schema.options._id;
111    var id = schema.options.id;
112
113    var keys = Object.keys(schema.options);
114    schema.options.discriminatorKey = baseSchema.options.discriminatorKey;
115
116    for (var i = 0; i < keys.length; ++i) {
117      var _key = keys[i];
118      if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) {
119        if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) {
120          throw new Error('Can\'t customize discriminator option ' + _key +
121              ' (can only modify ' +
122              Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') +
123              ')');
124        }
125      }
126    }
127
128    schema.options = utils.clone(baseSchema.options);
129    if (toJSON) schema.options.toJSON = toJSON;
130    if (toObject) schema.options.toObject = toObject;
131    if (typeof _id !== 'undefined') {
132      schema.options._id = _id;
133    }
134    schema.options.id = id;
135    schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks);
136
137    schema.plugins = Array.prototype.slice(baseSchema.plugins);
138    schema.callQueue = baseSchema.callQueue.concat(schema.callQueue);
139    delete schema._requiredpaths; // reset just in case Schema#requiredPaths() was called on either schema
140  }
141
142  // merges base schema into new discriminator schema and sets new type field.
143  merge(schema, model.schema);
144
145  if (!model.discriminators) {
146    model.discriminators = {};
147  }
148
149  if (!model.schema.discriminatorMapping) {
150    model.schema.discriminatorMapping = {key: key, value: null, isRoot: true};
151  }
152  if (!model.schema.discriminators) {
153    model.schema.discriminators = {};
154  }
155
156  model.schema.discriminators[name] = schema;
157
158  if (model.discriminators[name]) {
159    throw new Error('Discriminator with name "' + name + '" already exists');
160  }
161
162  return schema;
163};