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.

compile.js 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. 'use strict';
  2. const documentSchemaSymbol = require('../../helpers/symbols').documentSchemaSymbol;
  3. const get = require('../../helpers/get');
  4. const getSymbol = require('../../helpers/symbols').getSymbol;
  5. const utils = require('../../utils');
  6. let Document;
  7. /*!
  8. * exports
  9. */
  10. exports.compile = compile;
  11. exports.defineKey = defineKey;
  12. /*!
  13. * Compiles schemas.
  14. */
  15. function compile(tree, proto, prefix, options) {
  16. Document = Document || require('../../document');
  17. const keys = Object.keys(tree);
  18. const len = keys.length;
  19. let limb;
  20. let key;
  21. for (let i = 0; i < len; ++i) {
  22. key = keys[i];
  23. limb = tree[key];
  24. const hasSubprops = utils.isPOJO(limb) && Object.keys(limb).length &&
  25. (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type));
  26. const subprops = hasSubprops ? limb : null;
  27. defineKey(key, subprops, proto, prefix, keys, options);
  28. }
  29. }
  30. /*!
  31. * Defines the accessor named prop on the incoming prototype.
  32. */
  33. function defineKey(prop, subprops, prototype, prefix, keys, options) {
  34. Document = Document || require('../../document');
  35. const path = (prefix ? prefix + '.' : '') + prop;
  36. prefix = prefix || '';
  37. if (subprops) {
  38. Object.defineProperty(prototype, prop, {
  39. enumerable: true,
  40. configurable: true,
  41. get: function() {
  42. const _this = this;
  43. if (!this.$__.getters) {
  44. this.$__.getters = {};
  45. }
  46. if (!this.$__.getters[path]) {
  47. const nested = Object.create(Document.prototype, getOwnPropertyDescriptors(this));
  48. // save scope for nested getters/setters
  49. if (!prefix) {
  50. nested.$__.scope = this;
  51. }
  52. nested.$__.nestedPath = path;
  53. Object.defineProperty(nested, 'schema', {
  54. enumerable: false,
  55. configurable: true,
  56. writable: false,
  57. value: prototype.schema
  58. });
  59. Object.defineProperty(nested, documentSchemaSymbol, {
  60. enumerable: false,
  61. configurable: true,
  62. writable: false,
  63. value: prototype.schema
  64. });
  65. Object.defineProperty(nested, 'toObject', {
  66. enumerable: false,
  67. configurable: true,
  68. writable: false,
  69. value: function() {
  70. return utils.clone(_this.get(path, null, {
  71. virtuals: get(this, 'schema.options.toObject.virtuals', null)
  72. }));
  73. }
  74. });
  75. Object.defineProperty(nested, 'toJSON', {
  76. enumerable: false,
  77. configurable: true,
  78. writable: false,
  79. value: function() {
  80. return _this.get(path, null, {
  81. virtuals: get(_this, 'schema.options.toJSON.virtuals', null)
  82. });
  83. }
  84. });
  85. Object.defineProperty(nested, '$__isNested', {
  86. enumerable: false,
  87. configurable: true,
  88. writable: false,
  89. value: true
  90. });
  91. const _isEmptyOptions = Object.freeze({
  92. minimize: true,
  93. virtuals: false,
  94. getters: false,
  95. transform: false
  96. });
  97. Object.defineProperty(nested, '$isEmpty', {
  98. enumerable: false,
  99. configurable: true,
  100. writable: false,
  101. value: function() {
  102. return Object.keys(this.get(path, null, _isEmptyOptions) || {}).length === 0;
  103. }
  104. });
  105. compile(subprops, nested, path, options);
  106. this.$__.getters[path] = nested;
  107. }
  108. return this.$__.getters[path];
  109. },
  110. set: function(v) {
  111. if (v instanceof Document) {
  112. v = v.toObject({ transform: false });
  113. }
  114. const doc = this.$__.scope || this;
  115. return doc.$set(path, v);
  116. }
  117. });
  118. } else {
  119. Object.defineProperty(prototype, prop, {
  120. enumerable: true,
  121. configurable: true,
  122. get: function() {
  123. return this[getSymbol].call(this.$__.scope || this, path);
  124. },
  125. set: function(v) {
  126. return this.$set.call(this.$__.scope || this, path, v);
  127. }
  128. });
  129. }
  130. }
  131. // gets descriptors for all properties of `object`
  132. // makes all properties non-enumerable to match previous behavior to #2211
  133. function getOwnPropertyDescriptors(object) {
  134. const result = {};
  135. Object.getOwnPropertyNames(object).forEach(function(key) {
  136. result[key] = Object.getOwnPropertyDescriptor(object, key);
  137. // Assume these are schema paths, ignore them re: #5470
  138. if (result[key].get) {
  139. delete result[key];
  140. return;
  141. }
  142. result[key].enumerable = ['isNew', '$__', 'errors', '_doc', '$locals'].indexOf(key) === -1;
  143. });
  144. return result;
  145. }