moveImmutableProperties.js 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. 'use strict';
  2. const get = require('../get');
  3. /**
  4. * Given an update, move all $set on immutable properties to $setOnInsert.
  5. * This should only be called for upserts, because $setOnInsert bypasses the
  6. * strictness check for immutable properties.
  7. */
  8. module.exports = function moveImmutableProperties(schema, update, ctx) {
  9. if (update == null) {
  10. return;
  11. }
  12. const keys = Object.keys(update);
  13. for (const key of keys) {
  14. const isDollarKey = key.startsWith('$');
  15. if (key === '$set') {
  16. const updatedPaths = Object.keys(update[key]);
  17. for (const path of updatedPaths) {
  18. _walkUpdatePath(schema, update[key], path, update, ctx);
  19. }
  20. } else if (!isDollarKey) {
  21. _walkUpdatePath(schema, update, key, update, ctx);
  22. }
  23. }
  24. };
  25. function _walkUpdatePath(schema, op, path, update, ctx) {
  26. const schematype = schema.path(path);
  27. if (schematype == null) {
  28. return;
  29. }
  30. let immutable = get(schematype, 'options.immutable', null);
  31. if (immutable == null) {
  32. return;
  33. }
  34. if (typeof immutable === 'function') {
  35. immutable = immutable.call(ctx, ctx);
  36. }
  37. if (!immutable) {
  38. return;
  39. }
  40. update.$setOnInsert = update.$setOnInsert || {};
  41. update.$setOnInsert[path] = op[path];
  42. delete op[path];
  43. }