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
'use strict';
 
const get = require('../get');
 
/**
 * Given an update, move all $set on immutable properties to $setOnInsert.
 * This should only be called for upserts, because $setOnInsert bypasses the
 * strictness check for immutable properties.
 */
 
module.exports = function moveImmutableProperties(schema, update, ctx) {
  if (update == null) {
    return;
  }
 
  const keys = Object.keys(update);
  for (const key of keys) {
    const isDollarKey = key.startsWith('$');
 
    if (key === '$set') {
      const updatedPaths = Object.keys(update[key]);
      for (const path of updatedPaths) {
        _walkUpdatePath(schema, update[key], path, update, ctx);
      }
    } else if (!isDollarKey) {
      _walkUpdatePath(schema, update, key, update, ctx);
    }
 
  }
};
 
function _walkUpdatePath(schema, op, path, update, ctx) {
  const schematype = schema.path(path);
  if (schematype == null) {
    return;
  }
 
  let immutable = get(schematype, 'options.immutable', null);
  if (immutable == null) {
    return;
  }
  if (typeof immutable === 'function') {
    immutable = immutable.call(ctx, ctx);
  }
 
  if (!immutable) {
    return;
  }
 
  update.$setOnInsert = update.$setOnInsert || {};
  update.$setOnInsert[path] = op[path];
  delete op[path];
}