common.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. /*!
  3. * Module dependencies.
  4. */
  5. const Binary = require('../driver').get().Binary;
  6. const Decimal128 = require('../types/decimal128');
  7. const ObjectId = require('../types/objectid');
  8. const isMongooseObject = require('./isMongooseObject');
  9. exports.flatten = flatten;
  10. exports.modifiedPaths = modifiedPaths;
  11. /*!
  12. * ignore
  13. */
  14. function flatten(update, path, options, schema) {
  15. let keys;
  16. if (update && isMongooseObject(update) && !Buffer.isBuffer(update)) {
  17. keys = Object.keys(update.toObject({ transform: false, virtuals: false }));
  18. } else {
  19. keys = Object.keys(update || {});
  20. }
  21. const numKeys = keys.length;
  22. const result = {};
  23. path = path ? path + '.' : '';
  24. for (let i = 0; i < numKeys; ++i) {
  25. const key = keys[i];
  26. const val = update[key];
  27. result[path + key] = val;
  28. // Avoid going into mixed paths if schema is specified
  29. const keySchema = schema && schema.path && schema.path(path + key);
  30. const isNested = schema && schema.nested && schema.nested[path + key];
  31. if (keySchema && keySchema.instance === 'Mixed') continue;
  32. if (shouldFlatten(val)) {
  33. if (options && options.skipArrays && Array.isArray(val)) {
  34. continue;
  35. }
  36. const flat = flatten(val, path + key, options, schema);
  37. for (const k in flat) {
  38. result[k] = flat[k];
  39. }
  40. if (Array.isArray(val)) {
  41. result[path + key] = val;
  42. }
  43. }
  44. if (isNested) {
  45. const paths = Object.keys(schema.paths);
  46. for (const p of paths) {
  47. if (p.startsWith(path + key + '.') && !result.hasOwnProperty(p)) {
  48. result[p] = void 0;
  49. }
  50. }
  51. }
  52. }
  53. return result;
  54. }
  55. /*!
  56. * ignore
  57. */
  58. function modifiedPaths(update, path, result) {
  59. const keys = Object.keys(update || {});
  60. const numKeys = keys.length;
  61. result = result || {};
  62. path = path ? path + '.' : '';
  63. for (let i = 0; i < numKeys; ++i) {
  64. const key = keys[i];
  65. let val = update[key];
  66. result[path + key] = true;
  67. if (isMongooseObject(val) && !Buffer.isBuffer(val)) {
  68. val = val.toObject({ transform: false, virtuals: false });
  69. }
  70. if (shouldFlatten(val)) {
  71. modifiedPaths(val, path + key, result);
  72. }
  73. }
  74. return result;
  75. }
  76. /*!
  77. * ignore
  78. */
  79. function shouldFlatten(val) {
  80. return val &&
  81. typeof val === 'object' &&
  82. !(val instanceof Date) &&
  83. !(val instanceof ObjectId) &&
  84. (!Array.isArray(val) || val.length > 0) &&
  85. !(val instanceof Buffer) &&
  86. !(val instanceof Decimal128) &&
  87. !(val instanceof Binary);
  88. }