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