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.

discriminator.js 5.2KB

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