ObjectStateMutations.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.commitServerChanges = commitServerChanges;
  6. exports.defaultState = defaultState;
  7. exports.estimateAttribute = estimateAttribute;
  8. exports.estimateAttributes = estimateAttributes;
  9. exports.mergeFirstPendingState = mergeFirstPendingState;
  10. exports.popPendingState = popPendingState;
  11. exports.pushPendingState = pushPendingState;
  12. exports.setPendingOp = setPendingOp;
  13. exports.setServerData = setServerData;
  14. var _encode = _interopRequireDefault(require("./encode"));
  15. var _ParseFile = _interopRequireDefault(require("./ParseFile"));
  16. var _ParseObject = _interopRequireDefault(require("./ParseObject"));
  17. var _ParseRelation = _interopRequireDefault(require("./ParseRelation"));
  18. var _TaskQueue = _interopRequireDefault(require("./TaskQueue"));
  19. var _ParseOp = require("./ParseOp");
  20. function _interopRequireDefault(obj) {
  21. return obj && obj.__esModule ? obj : {
  22. default: obj
  23. };
  24. }
  25. /**
  26. * @flow
  27. */
  28. /*:: import type { Op } from './ParseOp';*/
  29. /*:: export type AttributeMap = { [attr: string]: any };*/
  30. /*:: export type OpsMap = { [attr: string]: Op };*/
  31. /*:: export type ObjectCache = { [attr: string]: string };*/
  32. /*:: export type State = {
  33. serverData: AttributeMap,
  34. pendingOps: Array<OpsMap>,
  35. objectCache: ObjectCache,
  36. tasks: TaskQueue,
  37. existed: boolean,
  38. };*/
  39. function defaultState() /*: State*/{
  40. return {
  41. serverData: {},
  42. pendingOps: [{}],
  43. objectCache: {},
  44. tasks: new _TaskQueue.default(),
  45. existed: false
  46. };
  47. }
  48. function setServerData(serverData /*: AttributeMap*/, attributes /*: AttributeMap*/) {
  49. for (const attr in attributes) {
  50. if (typeof attributes[attr] !== 'undefined') {
  51. serverData[attr] = attributes[attr];
  52. } else {
  53. delete serverData[attr];
  54. }
  55. }
  56. }
  57. function setPendingOp(pendingOps /*: Array<OpsMap>*/, attr /*: string*/, op /*: ?Op*/) {
  58. const last = pendingOps.length - 1;
  59. if (op) {
  60. pendingOps[last][attr] = op;
  61. } else {
  62. delete pendingOps[last][attr];
  63. }
  64. }
  65. function pushPendingState(pendingOps /*: Array<OpsMap>*/) {
  66. pendingOps.push({});
  67. }
  68. function popPendingState(pendingOps /*: Array<OpsMap>*/) /*: OpsMap*/{
  69. const first = pendingOps.shift();
  70. if (!pendingOps.length) {
  71. pendingOps[0] = {};
  72. }
  73. return first;
  74. }
  75. function mergeFirstPendingState(pendingOps /*: Array<OpsMap>*/) {
  76. const first = popPendingState(pendingOps);
  77. const next = pendingOps[0];
  78. for (const attr in first) {
  79. if (next[attr] && first[attr]) {
  80. const merged = next[attr].mergeWith(first[attr]);
  81. if (merged) {
  82. next[attr] = merged;
  83. }
  84. } else {
  85. next[attr] = first[attr];
  86. }
  87. }
  88. }
  89. function estimateAttribute(serverData /*: AttributeMap*/, pendingOps /*: Array<OpsMap>*/, className /*: string*/, id /*: ?string*/, attr /*: string*/) /*: mixed*/{
  90. let value = serverData[attr];
  91. for (let i = 0; i < pendingOps.length; i++) {
  92. if (pendingOps[i][attr]) {
  93. if (pendingOps[i][attr] instanceof _ParseOp.RelationOp) {
  94. if (id) {
  95. value = pendingOps[i][attr].applyTo(value, {
  96. className: className,
  97. id: id
  98. }, attr);
  99. }
  100. } else {
  101. value = pendingOps[i][attr].applyTo(value);
  102. }
  103. }
  104. }
  105. return value;
  106. }
  107. function estimateAttributes(serverData /*: AttributeMap*/, pendingOps /*: Array<OpsMap>*/, className /*: string*/, id /*: ?string*/) /*: AttributeMap*/{
  108. const data = {};
  109. for (var attr in serverData) {
  110. data[attr] = serverData[attr];
  111. }
  112. for (let i = 0; i < pendingOps.length; i++) {
  113. for (attr in pendingOps[i]) {
  114. if (pendingOps[i][attr] instanceof _ParseOp.RelationOp) {
  115. if (id) {
  116. data[attr] = pendingOps[i][attr].applyTo(data[attr], {
  117. className: className,
  118. id: id
  119. }, attr);
  120. }
  121. } else {
  122. if (attr.includes('.')) {
  123. // convert a.b.c into { a: { b: { c: value } } }
  124. const fields = attr.split('.');
  125. const first = fields[0];
  126. const last = fields[fields.length - 1];
  127. data[first] = {
  128. ...serverData[first]
  129. };
  130. let object = {
  131. ...data
  132. };
  133. for (let i = 0; i < fields.length - 1; i++) {
  134. const key = fields[i];
  135. if (!(key in object)) {
  136. object[key] = {};
  137. }
  138. object = object[key];
  139. }
  140. object[last] = pendingOps[i][attr].applyTo(object[last]);
  141. } else {
  142. data[attr] = pendingOps[i][attr].applyTo(data[attr]);
  143. }
  144. }
  145. }
  146. }
  147. return data;
  148. }
  149. function nestedSet(obj, key, value) {
  150. const path = key.split('.');
  151. for (let i = 0; i < path.length - 1; i++) {
  152. if (!(path[i] in obj)) obj[path[i]] = {};
  153. obj = obj[path[i]];
  154. }
  155. if (typeof value === 'undefined') {
  156. delete obj[path[path.length - 1]];
  157. } else {
  158. obj[path[path.length - 1]] = value;
  159. }
  160. }
  161. function commitServerChanges(serverData /*: AttributeMap*/, objectCache /*: ObjectCache*/, changes /*: AttributeMap*/) {
  162. for (const attr in changes) {
  163. const val = changes[attr];
  164. nestedSet(serverData, attr, val);
  165. if (val && typeof val === 'object' && !(val instanceof _ParseObject.default) && !(val instanceof _ParseFile.default) && !(val instanceof _ParseRelation.default)) {
  166. const json = (0, _encode.default)(val, false, true);
  167. objectCache[attr] = JSON.stringify(json);
  168. }
  169. }
  170. }