123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /**
- * Copyright (c) 2015-present, Parse, LLC.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @flow
- */
- import encode from './encode';
- import ParseFile from './ParseFile';
- import ParseObject from './ParseObject';
- import ParseRelation from './ParseRelation';
- import TaskQueue from './TaskQueue';
- import { RelationOp } from './ParseOp';
- /*:: import type { Op } from './ParseOp';*/
- /*:: export type AttributeMap = { [attr: string]: any };*/
- /*:: export type OpsMap = { [attr: string]: Op };*/
- /*:: export type ObjectCache = { [attr: string]: string };*/
- /*:: export type State = {
- serverData: AttributeMap;
- pendingOps: Array<OpsMap>;
- objectCache: ObjectCache;
- tasks: TaskQueue;
- existed: boolean
- };*/
- export function defaultState()
- /*: State*/
- {
- return {
- serverData: {},
- pendingOps: [{}],
- objectCache: {},
- tasks: new TaskQueue(),
- existed: false
- };
- }
- export function setServerData(serverData
- /*: AttributeMap*/
- , attributes
- /*: AttributeMap*/
- ) {
- for (const attr in attributes) {
- if (typeof attributes[attr] !== 'undefined') {
- serverData[attr] = attributes[attr];
- } else {
- delete serverData[attr];
- }
- }
- }
- export function setPendingOp(pendingOps
- /*: Array<OpsMap>*/
- , attr
- /*: string*/
- , op
- /*: ?Op*/
- ) {
- const last = pendingOps.length - 1;
- if (op) {
- pendingOps[last][attr] = op;
- } else {
- delete pendingOps[last][attr];
- }
- }
- export function pushPendingState(pendingOps
- /*: Array<OpsMap>*/
- ) {
- pendingOps.push({});
- }
- export function popPendingState(pendingOps
- /*: Array<OpsMap>*/
- )
- /*: OpsMap*/
- {
- const first = pendingOps.shift();
- if (!pendingOps.length) {
- pendingOps[0] = {};
- }
- return first;
- }
- export function mergeFirstPendingState(pendingOps
- /*: Array<OpsMap>*/
- ) {
- const first = popPendingState(pendingOps);
- const next = pendingOps[0];
- for (const attr in first) {
- if (next[attr] && first[attr]) {
- const merged = next[attr].mergeWith(first[attr]);
- if (merged) {
- next[attr] = merged;
- }
- } else {
- next[attr] = first[attr];
- }
- }
- }
- export function estimateAttribute(serverData
- /*: AttributeMap*/
- , pendingOps
- /*: Array<OpsMap>*/
- , className
- /*: string*/
- , id
- /*: ?string*/
- , attr
- /*: string*/
- )
- /*: mixed*/
- {
- let value = serverData[attr];
- for (let i = 0; i < pendingOps.length; i++) {
- if (pendingOps[i][attr]) {
- if (pendingOps[i][attr] instanceof RelationOp) {
- if (id) {
- value = pendingOps[i][attr].applyTo(value, {
- className: className,
- id: id
- }, attr);
- }
- } else {
- value = pendingOps[i][attr].applyTo(value);
- }
- }
- }
- return value;
- }
- export function estimateAttributes(serverData
- /*: AttributeMap*/
- , pendingOps
- /*: Array<OpsMap>*/
- , className
- /*: string*/
- , id
- /*: ?string*/
- )
- /*: AttributeMap*/
- {
- const data = {};
- for (var attr in serverData) {
- data[attr] = serverData[attr];
- }
- for (let i = 0; i < pendingOps.length; i++) {
- for (attr in pendingOps[i]) {
- if (pendingOps[i][attr] instanceof RelationOp) {
- if (id) {
- data[attr] = pendingOps[i][attr].applyTo(data[attr], {
- className: className,
- id: id
- }, attr);
- }
- } else {
- if (attr.includes('.')) {
- // convert a.b.c into { a: { b: { c: value } } }
- const fields = attr.split('.');
- const last = fields[fields.length - 1];
- let object = Object.assign({}, data);
- for (let i = 0; i < fields.length - 1; i++) {
- object = object[fields[i]];
- }
- object[last] = pendingOps[i][attr].applyTo(object[last]);
- } else {
- data[attr] = pendingOps[i][attr].applyTo(data[attr]);
- }
- }
- }
- }
- return data;
- }
- export function commitServerChanges(serverData
- /*: AttributeMap*/
- , objectCache
- /*: ObjectCache*/
- , changes
- /*: AttributeMap*/
- ) {
- for (const attr in changes) {
- const val = changes[attr];
- serverData[attr] = val;
- if (val && typeof val === 'object' && !(val instanceof ParseObject) && !(val instanceof ParseFile) && !(val instanceof ParseRelation)) {
- const json = encode(val, false, true);
- objectCache[attr] = JSON.stringify(json);
- }
- }
- }
|