applyTimestampsToUpdate.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. 'use strict';
  2. /*!
  3. * ignore
  4. */
  5. const get = require('../get');
  6. module.exports = applyTimestampsToUpdate;
  7. /*!
  8. * ignore
  9. */
  10. function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, options) {
  11. const updates = currentUpdate;
  12. let _updates = updates;
  13. const overwrite = get(options, 'overwrite', false);
  14. const timestamps = get(options, 'timestamps', true);
  15. // Support skipping timestamps at the query level, see gh-6980
  16. if (!timestamps || updates == null) {
  17. return currentUpdate;
  18. }
  19. const skipCreatedAt = timestamps != null && timestamps.createdAt === false;
  20. const skipUpdatedAt = timestamps != null && timestamps.updatedAt === false;
  21. if (overwrite) {
  22. if (currentUpdate && currentUpdate.$set) {
  23. currentUpdate = currentUpdate.$set;
  24. updates.$set = {};
  25. _updates = updates.$set;
  26. }
  27. if (!skipUpdatedAt && updatedAt && !currentUpdate[updatedAt]) {
  28. _updates[updatedAt] = now;
  29. }
  30. if (!skipCreatedAt && createdAt && !currentUpdate[createdAt]) {
  31. _updates[createdAt] = now;
  32. }
  33. return updates;
  34. }
  35. currentUpdate = currentUpdate || {};
  36. if (Array.isArray(updates)) {
  37. // Update with aggregation pipeline
  38. updates.push({ $set: { [updatedAt]: now } });
  39. return updates;
  40. }
  41. updates.$set = updates.$set || {};
  42. if (!skipUpdatedAt && updatedAt &&
  43. (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt])) {
  44. let timestampSet = false;
  45. if (updatedAt.indexOf('.') !== -1) {
  46. const pieces = updatedAt.split('.');
  47. for (let i = 1; i < pieces.length; ++i) {
  48. const remnant = pieces.slice(-i).join('.');
  49. const start = pieces.slice(0, -i).join('.');
  50. if (currentUpdate[start] != null) {
  51. currentUpdate[start][remnant] = now;
  52. timestampSet = true;
  53. break;
  54. } else if (currentUpdate.$set && currentUpdate.$set[start]) {
  55. currentUpdate.$set[start][remnant] = now;
  56. timestampSet = true;
  57. break;
  58. }
  59. }
  60. }
  61. if (!timestampSet) {
  62. updates.$set[updatedAt] = now;
  63. }
  64. if (updates.hasOwnProperty(updatedAt)) {
  65. delete updates[updatedAt];
  66. }
  67. }
  68. if (!skipCreatedAt && createdAt) {
  69. if (currentUpdate[createdAt]) {
  70. delete currentUpdate[createdAt];
  71. }
  72. if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
  73. delete currentUpdate.$set[createdAt];
  74. }
  75. let timestampSet = false;
  76. if (createdAt.indexOf('.') !== -1) {
  77. const pieces = createdAt.split('.');
  78. for (let i = 1; i < pieces.length; ++i) {
  79. const remnant = pieces.slice(-i).join('.');
  80. const start = pieces.slice(0, -i).join('.');
  81. if (currentUpdate[start] != null) {
  82. currentUpdate[start][remnant] = now;
  83. timestampSet = true;
  84. break;
  85. } else if (currentUpdate.$set && currentUpdate.$set[start]) {
  86. currentUpdate.$set[start][remnant] = now;
  87. timestampSet = true;
  88. break;
  89. }
  90. }
  91. }
  92. if (!timestampSet) {
  93. updates.$setOnInsert = updates.$setOnInsert || {};
  94. updates.$setOnInsert[createdAt] = now;
  95. }
  96. }
  97. if (Object.keys(updates.$set).length === 0) {
  98. delete updates.$set;
  99. }
  100. return updates;
  101. }