/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * strict-local * @format */ 'use strict'; var _objectSpread2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/objectSpread")); /** * @internal * * Wrapper API that is an amalgam of the `RelayModernRecord` API and * `MutableRecordSource` interface, implementing copy-on-write semantics for * records in a record source. If a `backup` is supplied, the mutator will * ensure that the backup contains sufficient information to revert all * modifications by publishing the backup. * * Modifications are applied to fresh copies of records with optional backups * created: * - Records in `base` are never modified. * - Modifications cause a fresh version of a record to be created in `sink`. * These sink records contain only modified fields. * - If a `backup` is supplied, any modifications to a record will cause the * sink version of the record to be added to the backup. * - Creation of a record causes a sentinel object to be added to the backup * so that the new record can be removed from the store by publishing the * backup. */ var RelayRecordSourceMutator = /*#__PURE__*/ function () { function RelayRecordSourceMutator(base, sink, backup) { this._backup = backup; this._base = base; this._sink = sink; this.__sources = [sink, base]; } var _proto = RelayRecordSourceMutator.prototype; _proto._createBackupRecord = function _createBackupRecord(dataID) { var backup = this._backup; if (backup && !backup.has(dataID)) { var baseRecord = this._base.get(dataID); if (baseRecord != null) { backup.set(dataID, baseRecord); } else if (baseRecord === null) { backup["delete"](dataID); } } }; _proto._setSentinelFieldsInBackupRecord = function _setSentinelFieldsInBackupRecord(dataID, record) { var backup = this._backup; if (backup) { var backupRecord = backup.get(dataID); if (backupRecord && backupRecord !== require("./RelayStoreUtils").UNPUBLISH_RECORD_SENTINEL) { var copy = null; for (var key in record) { if (record.hasOwnProperty(key)) { if (!(key in backupRecord)) { copy = copy || (0, _objectSpread2["default"])({}, backupRecord); copy[key] = require("./RelayStoreUtils").UNPUBLISH_FIELD_SENTINEL; } } } backup.set(dataID, copy || backupRecord); } } }; _proto._setSentinelFieldInBackupRecord = function _setSentinelFieldInBackupRecord(dataID, storageKey) { var backup = this._backup; if (backup) { var backupRecord = backup.get(dataID); if (backupRecord && backupRecord !== require("./RelayStoreUtils").UNPUBLISH_RECORD_SENTINEL && !(storageKey in backupRecord)) { var copy = (0, _objectSpread2["default"])({}, backupRecord); require("./RelayModernRecord").setValue(copy, storageKey, require("./RelayStoreUtils").UNPUBLISH_FIELD_SENTINEL); backup.set(dataID, copy); } } }; _proto._getSinkRecord = function _getSinkRecord(dataID) { var sinkRecord = this._sink.get(dataID); if (!sinkRecord) { var baseRecord = this._base.get(dataID); !baseRecord ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayRecordSourceMutator: Cannot modify non-existent record `%s`.', dataID) : require("fbjs/lib/invariant")(false) : void 0; sinkRecord = require("./RelayModernRecord").create(dataID, require("./RelayModernRecord").getType(baseRecord)); this._sink.set(dataID, sinkRecord); } return sinkRecord; }; _proto.copyFields = function copyFields(sourceID, sinkID) { var sinkSource = this._sink.get(sourceID); var baseSource = this._base.get(sourceID); !(sinkSource || baseSource) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayRecordSourceMutator#copyFields(): Cannot copy fields from ' + 'non-existent record `%s`.', sourceID) : require("fbjs/lib/invariant")(false) : void 0; this._createBackupRecord(sinkID); var sink = this._getSinkRecord(sinkID); if (baseSource) { require("./RelayModernRecord").copyFields(baseSource, sink); } if (sinkSource) { require("./RelayModernRecord").copyFields(sinkSource, sink); } this._setSentinelFieldsInBackupRecord(sinkID, sink); }; _proto.copyFieldsFromRecord = function copyFieldsFromRecord(record, sinkID) { this.copyFields(require("./RelayModernRecord").getDataID(record), sinkID); var sink = this._getSinkRecord(sinkID); require("./RelayModernRecord").copyFields(record, sink); this._setSentinelFieldsInBackupRecord(sinkID, sink); }; _proto.create = function create(dataID, typeName) { !(this._base.getStatus(dataID) !== require("./RelayRecordState").EXISTENT && this._sink.getStatus(dataID) !== require("./RelayRecordState").EXISTENT) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayRecordSourceMutator#create(): Cannot create a record with id ' + '`%s`, this record already exists.', dataID) : require("fbjs/lib/invariant")(false) : void 0; if (this._backup) { this._backup.set(dataID, require("./RelayStoreUtils").UNPUBLISH_RECORD_SENTINEL); } var record = require("./RelayModernRecord").create(dataID, typeName); this._sink.set(dataID, record); }; _proto["delete"] = function _delete(dataID) { this._createBackupRecord(dataID); this._sink["delete"](dataID); }; _proto.getStatus = function getStatus(dataID) { return this._sink.has(dataID) ? this._sink.getStatus(dataID) : this._base.getStatus(dataID); }; _proto.getType = function getType(dataID) { for (var ii = 0; ii < this.__sources.length; ii++) { var record = this.__sources[ii].get(dataID); if (record) { return require("./RelayModernRecord").getType(record); } else if (record === null) { return null; } } }; _proto.getValue = function getValue(dataID, storageKey) { for (var ii = 0; ii < this.__sources.length; ii++) { var record = this.__sources[ii].get(dataID); if (record) { var value = require("./RelayModernRecord").getValue(record, storageKey); if (value !== undefined) { return value; } } else if (record === null) { return null; } } }; _proto.setValue = function setValue(dataID, storageKey, value) { this._createBackupRecord(dataID); var sinkRecord = this._getSinkRecord(dataID); require("./RelayModernRecord").setValue(sinkRecord, storageKey, value); this._setSentinelFieldInBackupRecord(dataID, storageKey); }; _proto.getLinkedRecordID = function getLinkedRecordID(dataID, storageKey) { for (var ii = 0; ii < this.__sources.length; ii++) { var record = this.__sources[ii].get(dataID); if (record) { var linkedID = require("./RelayModernRecord").getLinkedRecordID(record, storageKey); if (linkedID !== undefined) { return linkedID; } } else if (record === null) { return null; } } }; _proto.setLinkedRecordID = function setLinkedRecordID(dataID, storageKey, linkedID) { this._createBackupRecord(dataID); var sinkRecord = this._getSinkRecord(dataID); require("./RelayModernRecord").setLinkedRecordID(sinkRecord, storageKey, linkedID); this._setSentinelFieldInBackupRecord(dataID, storageKey); }; _proto.getLinkedRecordIDs = function getLinkedRecordIDs(dataID, storageKey) { for (var ii = 0; ii < this.__sources.length; ii++) { var record = this.__sources[ii].get(dataID); if (record) { var linkedIDs = require("./RelayModernRecord").getLinkedRecordIDs(record, storageKey); if (linkedIDs !== undefined) { return linkedIDs; } } else if (record === null) { return null; } } }; _proto.setLinkedRecordIDs = function setLinkedRecordIDs(dataID, storageKey, linkedIDs) { this._createBackupRecord(dataID); var sinkRecord = this._getSinkRecord(dataID); require("./RelayModernRecord").setLinkedRecordIDs(sinkRecord, storageKey, linkedIDs); this._setSentinelFieldInBackupRecord(dataID, storageKey); }; return RelayRecordSourceMutator; }(); module.exports = RelayRecordSourceMutator;