applyProjection.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. 'use strict';
  2. const hasIncludedChildren = require('./hasIncludedChildren');
  3. const isExclusive = require('./isExclusive');
  4. const isInclusive = require('./isInclusive');
  5. const isPOJO = require('../../utils').isPOJO;
  6. module.exports = function applyProjection(doc, projection, _hasIncludedChildren) {
  7. if (projection == null) {
  8. return doc;
  9. }
  10. if (doc == null) {
  11. return doc;
  12. }
  13. let exclude = null;
  14. if (isInclusive(projection)) {
  15. exclude = false;
  16. } else if (isExclusive(projection)) {
  17. exclude = true;
  18. }
  19. if (exclude == null) {
  20. return doc;
  21. } else if (exclude) {
  22. _hasIncludedChildren = _hasIncludedChildren || hasIncludedChildren(projection);
  23. return applyExclusiveProjection(doc, projection, _hasIncludedChildren);
  24. } else {
  25. _hasIncludedChildren = _hasIncludedChildren || hasIncludedChildren(projection);
  26. return applyInclusiveProjection(doc, projection, _hasIncludedChildren);
  27. }
  28. };
  29. function applyExclusiveProjection(doc, projection, hasIncludedChildren, projectionLimb, prefix) {
  30. if (doc == null || typeof doc !== 'object') {
  31. return doc;
  32. }
  33. if (Array.isArray(doc)) {
  34. return doc.map(el => applyExclusiveProjection(el, projection, hasIncludedChildren, projectionLimb, prefix));
  35. }
  36. const ret = { ...doc };
  37. projectionLimb = prefix ? (projectionLimb || {}) : projection;
  38. for (const key of Object.keys(ret)) {
  39. const fullPath = prefix ? prefix + '.' + key : key;
  40. if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
  41. if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
  42. ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  43. } else {
  44. delete ret[key];
  45. }
  46. } else if (hasIncludedChildren[fullPath]) {
  47. ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  48. }
  49. }
  50. return ret;
  51. }
  52. function applyInclusiveProjection(doc, projection, hasIncludedChildren, projectionLimb, prefix) {
  53. if (doc == null || typeof doc !== 'object') {
  54. return doc;
  55. }
  56. if (Array.isArray(doc)) {
  57. return doc.map(el => applyInclusiveProjection(el, projection, hasIncludedChildren, projectionLimb, prefix));
  58. }
  59. const ret = { ...doc };
  60. projectionLimb = prefix ? (projectionLimb || {}) : projection;
  61. for (const key of Object.keys(ret)) {
  62. const fullPath = prefix ? prefix + '.' + key : key;
  63. if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) {
  64. if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
  65. ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  66. }
  67. continue;
  68. } else if (hasIncludedChildren[fullPath]) {
  69. ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  70. } else {
  71. delete ret[key];
  72. }
  73. }
  74. return ret;
  75. }