applyDefaults.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. 'use strict';
  2. const isNestedProjection = require('../projection/isNestedProjection');
  3. module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip, options) {
  4. const paths = Object.keys(doc.$__schema.paths);
  5. const plen = paths.length;
  6. const skipParentChangeTracking = options?.skipParentChangeTracking;
  7. for (let i = 0; i < plen; ++i) {
  8. let def;
  9. let curPath = '';
  10. const p = paths[i];
  11. if (p === '_id' && doc.$__.skipId) {
  12. continue;
  13. }
  14. const type = doc.$__schema.paths[p];
  15. const path = type.splitPath();
  16. const len = path.length;
  17. if (path[len - 1] === '$*') {
  18. continue;
  19. }
  20. let included = false;
  21. let doc_ = doc._doc;
  22. for (let j = 0; j < len; ++j) {
  23. if (doc_ == null) {
  24. break;
  25. }
  26. const piece = path[j];
  27. curPath += (!curPath.length ? '' : '.') + piece;
  28. if (exclude === true) {
  29. if (curPath in fields) {
  30. break;
  31. }
  32. } else if (exclude === false && fields && !included) {
  33. const hasSubpaths = type.$isSingleNested || type.$isMongooseDocumentArray;
  34. if ((curPath in fields && !isNestedProjection(fields[curPath])) || (j === len - 1 && hasSubpaths && hasIncludedChildren != null && hasIncludedChildren[curPath])) {
  35. included = true;
  36. } else if (hasIncludedChildren != null && !hasIncludedChildren[curPath]) {
  37. break;
  38. }
  39. }
  40. if (j === len - 1) {
  41. if (doc_[piece] !== void 0) {
  42. break;
  43. }
  44. if (isBeforeSetters != null) {
  45. if (typeof type.defaultValue === 'function') {
  46. if (!type.defaultValue.$runBeforeSetters && isBeforeSetters) {
  47. break;
  48. }
  49. if (type.defaultValue.$runBeforeSetters && !isBeforeSetters) {
  50. break;
  51. }
  52. } else if (!isBeforeSetters) {
  53. // Non-function defaults should always run **before** setters
  54. continue;
  55. }
  56. }
  57. if (pathsToSkip && pathsToSkip[curPath]) {
  58. break;
  59. }
  60. if (fields && exclude !== null) {
  61. if (exclude === true) {
  62. // apply defaults to all non-excluded fields
  63. if (p in fields) {
  64. continue;
  65. }
  66. try {
  67. def = type.getDefault(doc, false);
  68. } catch (err) {
  69. doc.invalidate(p, err);
  70. break;
  71. }
  72. if (typeof def !== 'undefined') {
  73. doc_[piece] = def;
  74. applyChangeTracking(doc, p, skipParentChangeTracking);
  75. }
  76. } else if (included) {
  77. // selected field
  78. try {
  79. def = type.getDefault(doc, false);
  80. } catch (err) {
  81. doc.invalidate(p, err);
  82. break;
  83. }
  84. if (typeof def !== 'undefined') {
  85. doc_[piece] = def;
  86. applyChangeTracking(doc, p, skipParentChangeTracking);
  87. }
  88. }
  89. } else {
  90. try {
  91. def = type.getDefault(doc, false);
  92. } catch (err) {
  93. doc.invalidate(p, err);
  94. break;
  95. }
  96. if (typeof def !== 'undefined') {
  97. doc_[piece] = def;
  98. applyChangeTracking(doc, p, skipParentChangeTracking);
  99. }
  100. }
  101. } else {
  102. doc_ = doc_[piece];
  103. }
  104. }
  105. }
  106. };
  107. /*!
  108. * ignore
  109. */
  110. function applyChangeTracking(doc, fullPath, skipParentChangeTracking) {
  111. doc.$__.activePaths.default(fullPath);
  112. if (!skipParentChangeTracking && doc.$isSubdocument && doc.$isSingleNested && doc.$parent() != null) {
  113. doc.$parent().$__.activePaths.default(doc.$__pathRelativeToParent(fullPath));
  114. }
  115. }