parse
Version:
Parse JavaScript SDK
220 lines (218 loc) • 7.64 kB
JavaScript
;
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.commitServerChanges = commitServerChanges;
exports.defaultState = defaultState;
exports.estimateAttribute = estimateAttribute;
exports.estimateAttributes = estimateAttributes;
exports.mergeFirstPendingState = mergeFirstPendingState;
exports.popPendingState = popPendingState;
exports.pushPendingState = pushPendingState;
exports.setPendingOp = setPendingOp;
exports.setServerData = setServerData;
var _create = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/create"));
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array"));
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _encode = _interopRequireDefault(require("./encode"));
var _CoreManager = _interopRequireDefault(require("./CoreManager"));
var _ParseFile = _interopRequireDefault(require("./ParseFile"));
var _ParseRelation = _interopRequireDefault(require("./ParseRelation"));
var _TaskQueue = _interopRequireDefault(require("./TaskQueue"));
var _ParseOp = require("./ParseOp");
var _isDangerousKey = require("./isDangerousKey");
function defaultState() {
return {
serverData: (0, _create.default)(null),
pendingOps: [(0, _create.default)(null)],
objectCache: (0, _create.default)(null),
tasks: new _TaskQueue.default(),
existed: false
};
}
function setServerData(serverData, attributes) {
for (const attr in attributes) {
// Skip properties from prototype chain
if (!Object.prototype.hasOwnProperty.call(attributes, attr)) {
continue;
}
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
continue;
}
if (typeof attributes[attr] !== "undefined") {
serverData[attr] = attributes[attr];
} else {
delete serverData[attr];
}
}
}
function setPendingOp(pendingOps, attr, op) {
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
return;
}
const last = pendingOps.length - 1;
if (op) {
pendingOps[last][attr] = op;
} else {
delete pendingOps[last][attr];
}
}
function pushPendingState(pendingOps) {
pendingOps.push((0, _create.default)(null));
}
function popPendingState(pendingOps) {
const first = pendingOps.shift();
if (!pendingOps.length) {
pendingOps[0] = (0, _create.default)(null);
}
return first;
}
function mergeFirstPendingState(pendingOps) {
const first = popPendingState(pendingOps);
const next = pendingOps[0];
for (const attr in first) {
// Skip properties from prototype chain
if (!Object.prototype.hasOwnProperty.call(first, attr)) {
continue;
}
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
continue;
}
if (next[attr] && first[attr]) {
const merged = next[attr].mergeWith(first[attr]);
if (merged) {
next[attr] = merged;
}
} else {
next[attr] = first[attr];
}
}
}
function estimateAttribute(serverData, pendingOps, object, attr) {
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
return undefined;
}
let value = serverData[attr];
for (let i = 0; i < pendingOps.length; i++) {
if (pendingOps[i][attr]) {
if (pendingOps[i][attr] instanceof _ParseOp.RelationOp) {
if (object.id) {
value = pendingOps[i][attr].applyTo(value, object, attr);
}
} else {
value = pendingOps[i][attr].applyTo(value);
}
}
}
return value;
}
function estimateAttributes(serverData, pendingOps, object) {
const data = (0, _create.default)(null);
for (var attr in serverData) {
data[attr] = serverData[attr];
}
for (let i = 0; i < pendingOps.length; i++) {
for (attr in pendingOps[i]) {
// Skip properties from prototype chain
if (!Object.prototype.hasOwnProperty.call(pendingOps[i], attr)) {
continue;
}
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
continue;
}
if (pendingOps[i][attr] instanceof _ParseOp.RelationOp) {
if (object.id) {
data[attr] = pendingOps[i][attr].applyTo(data[attr], object, attr);
}
} else {
if ((0, _includes.default)(attr).call(attr, '.')) {
// similar to nestedSet function
const fields = attr.split('.');
const last = fields[fields.length - 1];
let object = data;
for (let i = 0; i < fields.length - 1; i++) {
const key = fields[i];
if (!(key in object)) {
const nextKey = fields[i + 1];
if (!isNaN(nextKey)) {
object[key] = [];
} else {
object[key] = (0, _create.default)(null);
}
} else {
if ((0, _isArray.default)(object[key])) {
object[key] = [...object[key]];
} else {
object[key] = {
...object[key]
};
}
}
object = object[key];
}
object[last] = pendingOps[i][attr].applyTo(object[last]);
} else {
data[attr] = pendingOps[i][attr].applyTo(data[attr]);
}
}
}
}
return data;
}
/**
* Allows setting properties/variables deep in an object.
* Converts a.b into { a: { b: value } } for dot notation on Objects
* Converts a.0.b into { a: [{ b: value }] } for dot notation on Arrays
*
* @param obj The object to assign the value to
* @param key The key to assign. If it's in a deeper path, then use dot notation (`prop1.prop2.prop3`)
* Note that intermediate object(s) in the nested path are automatically created if they don't exist.
* @param value The value to assign. If it's an `undefined` then the key is deleted.
*/
function nestedSet(obj, key, value) {
const paths = key.split('.');
for (let i = 0; i < paths.length - 1; i++) {
const path = paths[i];
if (!(path in obj)) {
const nextPath = paths[i + 1];
if (!isNaN(nextPath)) {
obj[path] = [];
} else {
obj[path] = (0, _create.default)(null);
}
}
obj = obj[path];
}
if (typeof value === 'undefined') {
delete obj[paths[paths.length - 1]];
} else {
obj[paths[paths.length - 1]] = value;
}
}
function commitServerChanges(serverData, objectCache, changes) {
const ParseObject = _CoreManager.default.getParseObject();
for (const attr in changes) {
// Skip properties from prototype chain
if (!Object.prototype.hasOwnProperty.call(changes, attr)) {
continue;
}
// Skip dangerous keys that could pollute prototypes
if ((0, _isDangerousKey.isDangerousKey)(attr)) {
continue;
}
const val = changes[attr];
nestedSet(serverData, attr, val);
if (val && typeof val === 'object' && !(val instanceof ParseObject) && !(val instanceof _ParseFile.default) && !(val instanceof _ParseRelation.default)) {
const json = (0, _encode.default)(val, false, true);
objectCache[attr] = (0, _stringify.default)(json);
}
}
}