relay-runtime
Version:
A core runtime for building GraphQL-driven applications.
948 lines (947 loc) • 45.3 kB
JavaScript
'use strict';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _excluded = ["message"];
var RelayFeatureFlags = require('../util/RelayFeatureFlags');
var _require = require('./live-resolvers/LiveResolverSuspenseSentinel'),
isSuspenseSentinel = _require.isSuspenseSentinel;
var RelayConcreteVariables = require('./RelayConcreteVariables');
var RelayModernRecord = require('./RelayModernRecord');
var _require2 = require('./RelayStoreUtils'),
CLIENT_EDGE_TRAVERSAL_PATH = _require2.CLIENT_EDGE_TRAVERSAL_PATH,
FRAGMENT_OWNER_KEY = _require2.FRAGMENT_OWNER_KEY,
FRAGMENT_PROP_NAME_KEY = _require2.FRAGMENT_PROP_NAME_KEY,
FRAGMENTS_KEY = _require2.FRAGMENTS_KEY,
ID_KEY = _require2.ID_KEY,
MODULE_COMPONENT_KEY = _require2.MODULE_COMPONENT_KEY,
ROOT_ID = _require2.ROOT_ID,
getArgumentValues = _require2.getArgumentValues,
getModuleComponentKey = _require2.getModuleComponentKey,
getStorageKey = _require2.getStorageKey;
var _require3 = require('./ResolverCache'),
NoopResolverCache = _require3.NoopResolverCache;
var _require4 = require('./ResolverFragments'),
RESOLVER_FRAGMENT_ERRORED_SENTINEL = _require4.RESOLVER_FRAGMENT_ERRORED_SENTINEL,
withResolverContext = _require4.withResolverContext;
var _require5 = require('./TypeID'),
generateTypeID = _require5.generateTypeID;
var invariant = require('invariant');
function read(recordSource, selector, resolverCache, resolverContext) {
var reader = new RelayReader(recordSource, selector, resolverCache !== null && resolverCache !== void 0 ? resolverCache : new NoopResolverCache(), resolverContext);
return reader.read();
}
var RelayReader = /*#__PURE__*/function () {
function RelayReader(recordSource, selector, resolverCache, resolverContext) {
var _selector$clientEdgeT, _ref, _this$_owner$node$ope, _this$_owner$node$ope2;
this._clientEdgeTraversalPath = (_selector$clientEdgeT = selector.clientEdgeTraversalPath) !== null && _selector$clientEdgeT !== void 0 && _selector$clientEdgeT.length ? (0, _toConsumableArray2["default"])(selector.clientEdgeTraversalPath) : [];
this._missingClientEdges = [];
this._missingLiveResolverFields = [];
this._isMissingData = false;
this._isWithinUnmatchedTypeRefinement = false;
this._fieldErrors = null;
this._owner = selector.owner;
this._useExecTimeResolvers = (_ref = (_this$_owner$node$ope = this._owner.node.operation.use_exec_time_resolvers) !== null && _this$_owner$node$ope !== void 0 ? _this$_owner$node$ope : ((_this$_owner$node$ope2 = this._owner.node.operation.exec_time_resolvers_enabled_provider) === null || _this$_owner$node$ope2 === void 0 ? void 0 : _this$_owner$node$ope2.get()) === true) !== null && _ref !== void 0 ? _ref : false;
this._recordSource = recordSource;
this._seenRecords = new Set();
this._selector = selector;
this._variables = selector.variables;
this._resolverCache = resolverCache;
this._fragmentName = selector.node.name;
this._updatedDataIDs = new Set();
this._resolverContext = resolverContext;
}
var _proto = RelayReader.prototype;
_proto.read = function read() {
var _this$_selector$node$;
var _this$_selector = this._selector,
node = _this$_selector.node,
dataID = _this$_selector.dataID,
isWithinUnmatchedTypeRefinement = _this$_selector.isWithinUnmatchedTypeRefinement;
var abstractKey = node.abstractKey;
var record = this._recordSource.get(dataID);
var isDataExpectedToBePresent = !isWithinUnmatchedTypeRefinement;
if (isDataExpectedToBePresent && abstractKey == null && record != null) {
if (!this._recordMatchesTypeCondition(record, node.type)) {
isDataExpectedToBePresent = false;
}
}
if (isDataExpectedToBePresent && abstractKey != null && record != null) {
var implementsInterface = this._implementsInterface(record, abstractKey);
if (implementsInterface === false) {
isDataExpectedToBePresent = false;
}
}
this._isWithinUnmatchedTypeRefinement = !isDataExpectedToBePresent;
var data = this._traverse(node, dataID, null);
var catchTo = (_this$_selector$node$ = this._selector.node.metadata) === null || _this$_selector$node$ === void 0 ? void 0 : _this$_selector$node$.catchTo;
if (catchTo != null) {
data = this._catchErrors(data, catchTo, null);
}
if (this._updatedDataIDs.size > 0) {
this._resolverCache.notifyUpdatedSubscribers(this._updatedDataIDs);
this._updatedDataIDs.clear();
}
return {
data: data,
isMissingData: this._isMissingData && isDataExpectedToBePresent,
missingClientEdges: this._missingClientEdges.length ? this._missingClientEdges : null,
missingLiveResolverFields: this._missingLiveResolverFields,
seenRecords: this._seenRecords,
selector: this._selector,
fieldErrors: this._fieldErrors
};
};
_proto._maybeAddFieldErrors = function _maybeAddFieldErrors(record, storageKey) {
var errors = RelayModernRecord.getErrors(record, storageKey);
if (errors == null) {
return;
}
var owner = this._fragmentName;
if (this._fieldErrors == null) {
this._fieldErrors = [];
}
for (var i = 0; i < errors.length; i++) {
var _error$path, _this$_selector$node$2, _this$_selector$node$3;
var error = errors[i];
this._fieldErrors.push({
kind: 'relay_field_payload.error',
owner: owner,
fieldPath: ((_error$path = error.path) !== null && _error$path !== void 0 ? _error$path : []).join('.'),
error: error,
shouldThrow: (_this$_selector$node$2 = (_this$_selector$node$3 = this._selector.node.metadata) === null || _this$_selector$node$3 === void 0 ? void 0 : _this$_selector$node$3.throwOnFieldError) !== null && _this$_selector$node$2 !== void 0 ? _this$_selector$node$2 : false,
handled: false,
uiContext: undefined
});
}
};
_proto._markDataAsMissing = function _markDataAsMissing(fieldName) {
var _this$_selector$node$4, _this$_selector$node$5;
if (this._isWithinUnmatchedTypeRefinement) {
return;
}
if (this._fieldErrors == null) {
this._fieldErrors = [];
}
var owner = this._fragmentName;
this._fieldErrors.push(((_this$_selector$node$4 = (_this$_selector$node$5 = this._selector.node.metadata) === null || _this$_selector$node$5 === void 0 ? void 0 : _this$_selector$node$5.throwOnFieldError) !== null && _this$_selector$node$4 !== void 0 ? _this$_selector$node$4 : false) ? {
kind: 'missing_expected_data.throw',
owner: owner,
fieldPath: fieldName,
handled: false,
uiContext: undefined
} : {
kind: 'missing_expected_data.log',
owner: owner,
fieldPath: fieldName,
uiContext: undefined
});
this._isMissingData = true;
if (this._clientEdgeTraversalPath.length) {
var top = this._clientEdgeTraversalPath[this._clientEdgeTraversalPath.length - 1];
if (top !== null) {
this._missingClientEdges.push({
request: top.readerClientEdge.operation,
clientEdgeDestinationID: top.clientEdgeDestinationID
});
}
}
};
_proto._traverse = function _traverse(node, dataID, prevData) {
var record = this._recordSource.get(dataID);
this._seenRecords.add(dataID);
if (record == null) {
if (record === undefined) {
this._markDataAsMissing('<record>');
}
return record;
}
var data = prevData || {};
var hadRequiredData = this._traverseSelections(node.selections, record, data);
return hadRequiredData ? data : null;
};
_proto._getVariableValue = function _getVariableValue(name) {
!this._variables.hasOwnProperty(name) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Undefined variable `%s`.', name) : invariant(false) : void 0;
return this._variables[name];
};
_proto._maybeReportUnexpectedNull = function _maybeReportUnexpectedNull(selection) {
if (selection.action === 'NONE') {
return;
}
var owner = this._fragmentName;
if (this._fieldErrors == null) {
this._fieldErrors = [];
}
var fieldName;
if (selection.field.linkedField != null) {
var _selection$field$link;
fieldName = (_selection$field$link = selection.field.linkedField.alias) !== null && _selection$field$link !== void 0 ? _selection$field$link : selection.field.linkedField.name;
} else {
var _selection$field$alia;
fieldName = (_selection$field$alia = selection.field.alias) !== null && _selection$field$alia !== void 0 ? _selection$field$alia : selection.field.name;
}
switch (selection.action) {
case 'THROW':
this._fieldErrors.push({
kind: 'missing_required_field.throw',
fieldPath: fieldName,
owner: owner,
handled: false,
uiContext: undefined
});
return;
case 'LOG':
this._fieldErrors.push({
kind: 'missing_required_field.log',
fieldPath: fieldName,
owner: owner,
uiContext: undefined
});
return;
default:
selection.action;
}
};
_proto._handleRequiredFieldValue = function _handleRequiredFieldValue(selection, value) {
if (value == null) {
this._maybeReportUnexpectedNull(selection);
return false;
}
return true;
};
_proto._catchErrors = function _catchErrors(_value, to, previousResponseFields) {
var value = _value;
switch (to) {
case 'RESULT':
value = this._asResult(_value);
break;
case 'NULL':
if (this._fieldErrors != null && this._fieldErrors.length > 0) {
value = null;
}
break;
default:
to;
}
var childrenFieldErrors = this._fieldErrors;
this._fieldErrors = previousResponseFields;
if (childrenFieldErrors != null) {
if (this._fieldErrors == null) {
this._fieldErrors = [];
}
for (var i = 0; i < childrenFieldErrors.length; i++) {
this._fieldErrors.push(markFieldErrorHasHandled(childrenFieldErrors[i]));
}
}
return value;
};
_proto._asResult = function _asResult(value) {
if (this._fieldErrors == null || this._fieldErrors.length === 0) {
return {
ok: true,
value: value
};
}
var errors = this._fieldErrors.map(function (error) {
switch (error.kind) {
case 'relay_field_payload.error':
var _error$error = error.error,
message = _error$error.message,
displayError = (0, _objectWithoutPropertiesLoose2["default"])(_error$error, _excluded);
return displayError;
case 'missing_expected_data.throw':
case 'missing_expected_data.log':
return {
path: error.fieldPath.split('.')
};
case 'relay_resolver.error':
return {
message: "Relay: Error in resolver for field at ".concat(error.fieldPath, " in ").concat(error.owner)
};
case 'missing_required_field.throw':
return {
message: "Relay: Missing @required value at path '".concat(error.fieldPath, "' in '").concat(error.owner, "'.")
};
case 'missing_required_field.log':
return null;
default:
error.kind;
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unexpected error fieldError kind: %s', error.kind) : invariant(false) : void 0;
}
}).filter(Boolean);
return {
ok: false,
errors: errors
};
};
_proto._traverseSelections = function _traverseSelections(selections, record, data) {
for (var i = 0; i < selections.length; i++) {
var selection = selections[i];
switch (selection.kind) {
case 'RequiredField':
var requiredFieldValue = this._readClientSideDirectiveField(selection, record, data);
if (!this._handleRequiredFieldValue(selection, requiredFieldValue)) {
return false;
}
break;
case 'CatchField':
{
var _selection$field$back, _selection$field, _field$alias;
var previousResponseFields = this._fieldErrors;
this._fieldErrors = null;
var catchFieldValue = this._readClientSideDirectiveField(selection, record, data);
var field = (_selection$field$back = (_selection$field = selection.field) === null || _selection$field === void 0 ? void 0 : _selection$field.backingField) !== null && _selection$field$back !== void 0 ? _selection$field$back : selection.field;
var fieldName = (_field$alias = field === null || field === void 0 ? void 0 : field.alias) !== null && _field$alias !== void 0 ? _field$alias : field === null || field === void 0 ? void 0 : field.name;
!(fieldName != null) ? process.env.NODE_ENV !== "production" ? invariant(false, "Couldn't determine field name for this field. It might be a ReaderClientExtension - which is not yet supported.") : invariant(false) : void 0;
data[fieldName] = this._catchErrors(catchFieldValue, selection.to, previousResponseFields);
break;
}
case 'ScalarField':
this._readScalar(selection, record, data);
break;
case 'LinkedField':
if (selection.plural) {
this._readPluralLink(selection, record, data);
} else {
this._readLink(selection, record, data);
}
break;
case 'Condition':
var conditionValue = Boolean(this._getVariableValue(selection.condition));
if (conditionValue === selection.passingValue) {
var hasExpectedData = this._traverseSelections(selection.selections, record, data);
if (!hasExpectedData) {
return false;
}
}
break;
case 'InlineFragment':
{
var _hasExpectedData = this._readInlineFragment(selection, record, data, false);
if (_hasExpectedData === false) {
return false;
}
break;
}
case 'RelayLiveResolver':
case 'RelayResolver':
{
if (this._useExecTimeResolvers) {
this._readScalar(selection, record, data);
} else {
this._readResolverField(selection, record, data);
}
break;
}
case 'FragmentSpread':
this._createFragmentPointer(selection, record, data);
break;
case 'AliasedInlineFragmentSpread':
{
this._readAliasedInlineFragment(selection, record, data);
break;
}
case 'ModuleImport':
this._readModuleImport(selection, record, data);
break;
case 'InlineDataFragmentSpread':
this._createInlineDataOrResolverFragmentPointer(selection, record, data);
break;
case 'Defer':
case 'ClientExtension':
{
var isMissingData = this._isMissingData;
var alreadyMissingClientEdges = this._missingClientEdges.length;
this._clientEdgeTraversalPath.push(null);
var _hasExpectedData2 = this._traverseSelections(selection.selections, record, data);
this._isMissingData = isMissingData || this._missingClientEdges.length > alreadyMissingClientEdges || this._missingLiveResolverFields.length > 0;
this._clientEdgeTraversalPath.pop();
if (!_hasExpectedData2) {
return false;
}
break;
}
case 'Stream':
{
var _hasExpectedData3 = this._traverseSelections(selection.selections, record, data);
if (!_hasExpectedData3) {
return false;
}
break;
}
case 'ActorChange':
this._readActorChange(selection, record, data);
break;
case 'ClientEdgeToClientObject':
case 'ClientEdgeToServerObject':
if (this._useExecTimeResolvers && (selection.backingField.kind === 'RelayResolver' || selection.backingField.kind === 'RelayLiveResolver')) {
var linkedField = selection.linkedField;
if (linkedField.plural) {
this._readPluralLink(linkedField, record, data);
} else {
this._readLink(linkedField, record, data);
}
} else {
this._readClientEdge(selection, record, data);
}
break;
default:
selection;
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Unexpected ast kind `%s`.', selection.kind) : invariant(false) : void 0;
}
}
return true;
};
_proto._readClientSideDirectiveField = function _readClientSideDirectiveField(selection, record, data) {
switch (selection.field.kind) {
case 'ScalarField':
return this._readScalar(selection.field, record, data);
case 'LinkedField':
if (selection.field.plural) {
return this._readPluralLink(selection.field, record, data);
} else {
return this._readLink(selection.field, record, data);
}
case 'RelayResolver':
case 'RelayLiveResolver':
{
if (this._useExecTimeResolvers) {
return this._readScalar(selection.field, record, data);
} else {
return this._readResolverField(selection.field, record, data);
}
}
case 'ClientEdgeToClientObject':
case 'ClientEdgeToServerObject':
if (this._useExecTimeResolvers && (selection.field.backingField.kind === 'RelayResolver' || selection.field.backingField.kind === 'RelayLiveResolver')) {
var field = selection.field;
if (field.linkedField.plural) {
return this._readPluralLink(field.linkedField, record, data);
} else {
return this._readLink(field.linkedField, record, data);
}
} else {
return this._readClientEdge(selection.field, record, data);
}
case 'AliasedInlineFragmentSpread':
return this._readAliasedInlineFragment(selection.field, record, data);
default:
selection.field.kind;
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Unexpected ast kind `%s`.', selection.field.kind) : invariant(false) : void 0;
}
};
_proto._readResolverField = function _readResolverField(field, record, data) {
var _field$alias2;
var parentRecordID = RelayModernRecord.getDataID(record);
var prevErrors = this._fieldErrors;
this._fieldErrors = null;
var result = this._readResolverFieldImpl(field, parentRecordID);
var fieldName = (_field$alias2 = field.alias) !== null && _field$alias2 !== void 0 ? _field$alias2 : field.name;
this._prependPreviousErrors(prevErrors, fieldName);
data[fieldName] = result;
return result;
};
_proto._readResolverFieldImpl = function _readResolverFieldImpl(field, parentRecordID) {
var _this = this;
var fragment = field.fragment;
var snapshot;
var getDataForResolverFragment = function getDataForResolverFragment(singularReaderSelector) {
if (snapshot != null) {
return {
data: snapshot.data,
isMissingData: snapshot.isMissingData,
fieldErrors: snapshot.fieldErrors
};
}
snapshot = read(_this._recordSource, singularReaderSelector, _this._resolverCache);
return {
data: snapshot.data,
isMissingData: snapshot.isMissingData,
fieldErrors: snapshot.fieldErrors
};
};
var evaluate = function evaluate() {
if (fragment != null) {
var key = {
__id: parentRecordID,
__fragmentOwner: _this._owner,
__fragments: (0, _defineProperty2["default"])({}, fragment.name, fragment.args ? getArgumentValues(fragment.args, _this._variables) : {})
};
if (_this._clientEdgeTraversalPath.length > 0 && _this._clientEdgeTraversalPath[_this._clientEdgeTraversalPath.length - 1] !== null) {
key[CLIENT_EDGE_TRAVERSAL_PATH] = (0, _toConsumableArray2["default"])(_this._clientEdgeTraversalPath);
}
var resolverContext = {
getDataForResolverFragment: getDataForResolverFragment
};
return withResolverContext(resolverContext, function () {
var _getResolverValue = getResolverValue(field, _this._variables, key, _this._resolverContext),
resolverResult = _getResolverValue[0],
resolverError = _getResolverValue[1];
return {
resolverResult: resolverResult,
snapshot: snapshot,
error: resolverError
};
});
} else {
var _getResolverValue2 = getResolverValue(field, _this._variables, null, _this._resolverContext),
resolverResult = _getResolverValue2[0],
_resolverError = _getResolverValue2[1];
return {
resolverResult: resolverResult,
snapshot: undefined,
error: _resolverError
};
}
};
var _this$_resolverCache$ = this._resolverCache.readFromCacheOrEvaluate(parentRecordID, field, this._variables, evaluate, getDataForResolverFragment),
result = _this$_resolverCache$[0],
seenRecord = _this$_resolverCache$[1],
resolverError = _this$_resolverCache$[2],
cachedSnapshot = _this$_resolverCache$[3],
suspenseID = _this$_resolverCache$[4],
updatedDataIDs = _this$_resolverCache$[5];
this._propagateResolverMetadata(field.path, cachedSnapshot, resolverError, seenRecord, suspenseID, updatedDataIDs);
return result;
};
_proto._propagateResolverMetadata = function _propagateResolverMetadata(fieldPath, cachedSnapshot, resolverError, seenRecord, suspenseID, updatedDataIDs) {
var _this2 = this;
if (cachedSnapshot != null) {
if (cachedSnapshot.missingClientEdges != null) {
for (var i = 0; i < cachedSnapshot.missingClientEdges.length; i++) {
var missing = cachedSnapshot.missingClientEdges[i];
this._missingClientEdges.push(missing);
}
}
if (cachedSnapshot.missingLiveResolverFields != null) {
this._isMissingData = this._isMissingData || cachedSnapshot.missingLiveResolverFields.length > 0;
for (var _i = 0; _i < cachedSnapshot.missingLiveResolverFields.length; _i++) {
var missingResolverField = cachedSnapshot.missingLiveResolverFields[_i];
this._missingLiveResolverFields.push(missingResolverField);
}
}
if (cachedSnapshot.fieldErrors != null) {
if (this._fieldErrors == null) {
this._fieldErrors = [];
}
for (var _i2 = 0; _i2 < cachedSnapshot.fieldErrors.length; _i2++) {
var _this$_selector$node$6;
var error = cachedSnapshot.fieldErrors[_i2];
if (((_this$_selector$node$6 = this._selector.node.metadata) === null || _this$_selector$node$6 === void 0 ? void 0 : _this$_selector$node$6.throwOnFieldError) === true) {
this._fieldErrors.push(error);
} else {
this._fieldErrors.push(markFieldErrorHasHandled(error));
}
}
}
this._isMissingData = this._isMissingData || cachedSnapshot.isMissingData;
}
if (resolverError) {
var _this$_selector$node$7, _this$_selector$node$8;
var errorEvent = {
kind: 'relay_resolver.error',
fieldPath: fieldPath,
owner: this._fragmentName,
error: resolverError,
shouldThrow: (_this$_selector$node$7 = (_this$_selector$node$8 = this._selector.node.metadata) === null || _this$_selector$node$8 === void 0 ? void 0 : _this$_selector$node$8.throwOnFieldError) !== null && _this$_selector$node$7 !== void 0 ? _this$_selector$node$7 : false,
handled: false,
uiContext: undefined
};
if (this._fieldErrors == null) {
this._fieldErrors = [errorEvent];
} else {
this._fieldErrors.push(errorEvent);
}
}
if (seenRecord != null) {
this._seenRecords.add(seenRecord);
}
if (suspenseID != null) {
this._isMissingData = true;
this._missingLiveResolverFields.push(suspenseID);
}
if (updatedDataIDs != null) {
updatedDataIDs.forEach(function (recordID) {
_this2._updatedDataIDs.add(recordID);
});
}
};
_proto._readClientEdge = function _readClientEdge(field, record, data) {
var _this3 = this;
var _backingField$alias;
var backingField = field.backingField;
!(backingField.kind !== 'ClientExtension') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Client extension client edges are not yet implemented.') : invariant(false) : void 0;
var fieldName = (_backingField$alias = backingField.alias) !== null && _backingField$alias !== void 0 ? _backingField$alias : backingField.name;
var backingFieldData = {};
this._traverseSelections([backingField], record, backingFieldData);
var clientEdgeResolverResponse = backingFieldData[fieldName];
if (clientEdgeResolverResponse == null || isSuspenseSentinel(clientEdgeResolverResponse)) {
data[fieldName] = clientEdgeResolverResponse;
return clientEdgeResolverResponse;
}
if (field.linkedField.plural) {
!Array.isArray(clientEdgeResolverResponse) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected plural Client Edge Relay Resolver at `%s` in `%s` to return an array containing IDs or objects with shape {id}.', backingField.path, this._owner.identifier) : invariant(false) : void 0;
var storeIDs;
!(field.kind === 'ClientEdgeToClientObject') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unexpected Client Edge to plural server type `%s`. This should be prevented by the compiler.', field.kind) : invariant(false) : void 0;
if (field.backingField.normalizationInfo == null) {
storeIDs = clientEdgeResolverResponse.map(function (itemResponse) {
var _field$concreteType;
var concreteType = (_field$concreteType = field.concreteType) !== null && _field$concreteType !== void 0 ? _field$concreteType : itemResponse.__typename;
!(typeof concreteType === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected resolver for field at `%s` in `%s` modeling an edge to an abstract type to return an object with a `__typename` property.', backingField.path, _this3._owner.identifier) : invariant(false) : void 0;
var localId = extractIdFromResponse(itemResponse, backingField.path, _this3._owner.identifier);
var id = _this3._resolverCache.ensureClientRecord(localId, concreteType);
var modelResolvers = field.modelResolvers;
if (modelResolvers != null) {
var modelResolver = modelResolvers[concreteType];
!(modelResolver !== undefined) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Invalid `__typename` returned by resolver at `%s` in `%s`. Expected one of %s but got `%s`.', backingField.path, _this3._owner.identifier, Object.keys(modelResolvers).join(', '), concreteType) : invariant(false) : void 0;
var model = _this3._readResolverFieldImpl(modelResolver, id);
return model != null ? id : null;
}
return id;
});
} else {
storeIDs = clientEdgeResolverResponse.map(function (obj) {
return extractIdFromResponse(obj, backingField.path, _this3._owner.identifier);
});
}
this._clientEdgeTraversalPath.push(null);
var edgeValues = this._readLinkedIds(field.linkedField, storeIDs, record, data);
this._clientEdgeTraversalPath.pop();
data[fieldName] = edgeValues;
return edgeValues;
} else {
var _field$concreteType2;
var id = extractIdFromResponse(clientEdgeResolverResponse, backingField.path, this._owner.identifier);
var storeID;
var concreteType = (_field$concreteType2 = field.concreteType) !== null && _field$concreteType2 !== void 0 ? _field$concreteType2 : clientEdgeResolverResponse.__typename;
var traversalPathSegment;
if (field.kind === 'ClientEdgeToClientObject') {
if (field.backingField.normalizationInfo == null) {
!(typeof concreteType === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected resolver for field at `%s` in `%s` modeling an edge to an abstract type to return an object with a `__typename` property.', backingField.path, this._owner.identifier) : invariant(false) : void 0;
storeID = this._resolverCache.ensureClientRecord(id, concreteType);
traversalPathSegment = null;
} else {
storeID = id;
traversalPathSegment = null;
}
} else {
storeID = id;
traversalPathSegment = {
readerClientEdge: field,
clientEdgeDestinationID: id
};
}
var modelResolvers = field.modelResolvers;
if (modelResolvers != null) {
!(typeof concreteType === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected resolver for field at `%s` in `%s` modeling an edge to an abstract type to return an object with a `__typename` property.', backingField.path, this._owner.identifier) : invariant(false) : void 0;
var modelResolver = modelResolvers[concreteType];
!(modelResolver !== undefined) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Invalid `__typename` returned by resolver at `%s` in `%s`. Expected one of %s but got `%s`.', backingField.path, this._owner.identifier, Object.keys(modelResolvers).join(', '), concreteType) : invariant(false) : void 0;
var model = this._readResolverFieldImpl(modelResolver, storeID);
if (model == null) {
data[fieldName] = null;
return null;
}
}
this._clientEdgeTraversalPath.push(traversalPathSegment);
var prevData = data[fieldName];
!(prevData == null || typeof prevData === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Expected data for field at `%s` in `%s` on record `%s` ' + 'to be an object, got `%s`.', backingField.path, this._owner.identifier, RelayModernRecord.getDataID(record), prevData) : invariant(false) : void 0;
var prevErrors = this._fieldErrors;
this._fieldErrors = null;
var edgeValue = this._traverse(field.linkedField, storeID, prevData);
this._prependPreviousErrors(prevErrors, fieldName);
this._clientEdgeTraversalPath.pop();
data[fieldName] = edgeValue;
return edgeValue;
}
};
_proto._readScalar = function _readScalar(field, record, data) {
var _field$alias3;
var fieldName = (_field$alias3 = field.alias) !== null && _field$alias3 !== void 0 ? _field$alias3 : field.name;
var storageKey = getStorageKey(field, this._variables);
var value = RelayModernRecord.getValue(record, storageKey);
if (value === null || RelayFeatureFlags.ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS && Array.isArray(value) && value.length === 0) {
this._maybeAddFieldErrors(record, storageKey);
} else if (value === undefined) {
this._markDataAsMissing(fieldName);
}
data[fieldName] = value;
return value;
};
_proto._readLink = function _readLink(field, record, data) {
var _field$alias4;
var fieldName = (_field$alias4 = field.alias) !== null && _field$alias4 !== void 0 ? _field$alias4 : field.name;
var storageKey = getStorageKey(field, this._variables);
var linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
if (linkedID == null) {
data[fieldName] = linkedID;
if (linkedID === null) {
this._maybeAddFieldErrors(record, storageKey);
} else if (linkedID === undefined) {
this._markDataAsMissing(fieldName);
}
return linkedID;
}
var prevData = data[fieldName];
!(prevData == null || typeof prevData === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Expected data for field `%s` at `%s` on record `%s` ' + 'to be an object, got `%s`.', fieldName, this._owner.identifier, RelayModernRecord.getDataID(record), prevData) : invariant(false) : void 0;
var prevErrors = this._fieldErrors;
this._fieldErrors = null;
var value = this._traverse(field, linkedID, prevData);
this._prependPreviousErrors(prevErrors, fieldName);
data[fieldName] = value;
return value;
};
_proto._prependPreviousErrors = function _prependPreviousErrors(prevErrors, fieldNameOrIndex) {
if (this._fieldErrors != null) {
for (var i = 0; i < this._fieldErrors.length; i++) {
var event = this._fieldErrors[i];
if (event.owner === this._fragmentName && (event.kind === 'missing_expected_data.throw' || event.kind === 'missing_expected_data.log' || event.kind === 'missing_required_field.throw' || event.kind === 'missing_required_field.log')) {
event.fieldPath = "".concat(fieldNameOrIndex, ".").concat(event.fieldPath);
}
}
if (prevErrors != null) {
for (var _i3 = this._fieldErrors.length - 1; _i3 >= 0; _i3--) {
prevErrors.push(this._fieldErrors[_i3]);
}
this._fieldErrors = prevErrors;
}
} else {
this._fieldErrors = prevErrors;
}
};
_proto._readActorChange = function _readActorChange(field, record, data) {
var _field$alias5;
var fieldName = (_field$alias5 = field.alias) !== null && _field$alias5 !== void 0 ? _field$alias5 : field.name;
var storageKey = getStorageKey(field, this._variables);
var externalRef = RelayModernRecord.getActorLinkedRecordID(record, storageKey);
if (externalRef == null) {
data[fieldName] = externalRef;
if (externalRef === undefined) {
this._markDataAsMissing(fieldName);
} else if (externalRef === null) {
this._maybeAddFieldErrors(record, storageKey);
}
return data[fieldName];
}
var actorIdentifier = externalRef[0],
dataID = externalRef[1];
var fragmentRef = {};
this._createFragmentPointer(field.fragmentSpread, RelayModernRecord.fromObject({
__id: dataID
}), fragmentRef);
data[fieldName] = {
__fragmentRef: fragmentRef,
__viewer: actorIdentifier
};
return data[fieldName];
};
_proto._readPluralLink = function _readPluralLink(field, record, data) {
var storageKey = getStorageKey(field, this._variables);
var linkedIDs = RelayModernRecord.getLinkedRecordIDs(record, storageKey);
if (linkedIDs === null || RelayFeatureFlags.ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS && Array.isArray(linkedIDs) && linkedIDs.length === 0) {
this._maybeAddFieldErrors(record, storageKey);
}
return this._readLinkedIds(field, linkedIDs, record, data);
};
_proto._readLinkedIds = function _readLinkedIds(field, linkedIDs, record, data) {
var _this4 = this;
var _field$alias6;
var fieldName = (_field$alias6 = field.alias) !== null && _field$alias6 !== void 0 ? _field$alias6 : field.name;
if (linkedIDs == null) {
data[fieldName] = linkedIDs;
if (linkedIDs === undefined) {
this._markDataAsMissing(fieldName);
}
return linkedIDs;
}
var prevData = data[fieldName];
!(prevData == null || Array.isArray(prevData)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Expected data for field `%s` on record `%s` ' + 'to be an array, got `%s`.', fieldName, RelayModernRecord.getDataID(record), prevData) : invariant(false) : void 0;
var prevErrors = this._fieldErrors;
this._fieldErrors = null;
var linkedArray = prevData || [];
linkedIDs.forEach(function (linkedID, nextIndex) {
if (linkedID == null) {
if (linkedID === undefined) {
_this4._markDataAsMissing(String(nextIndex));
}
linkedArray[nextIndex] = linkedID;
return;
}
var prevItem = linkedArray[nextIndex];
!(prevItem == null || typeof prevItem === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader(): Expected data for field `%s` on record `%s` ' + 'to be an object, got `%s`.', fieldName, RelayModernRecord.getDataID(record), prevItem) : invariant(false) : void 0;
var prevErrors = _this4._fieldErrors;
_this4._fieldErrors = null;
linkedArray[nextIndex] = _this4._traverse(field, linkedID, prevItem);
_this4._prependPreviousErrors(prevErrors, nextIndex);
});
this._prependPreviousErrors(prevErrors, fieldName);
data[fieldName] = linkedArray;
return linkedArray;
};
_proto._readModuleImport = function _readModuleImport(moduleImport, record, data) {
var componentKey = getModuleComponentKey(moduleImport.documentName);
var relayStoreComponent = RelayModernRecord.getValue(record, componentKey);
var component = relayStoreComponent !== undefined ? relayStoreComponent : moduleImport.componentModuleProvider;
if (component == null) {
if (component === undefined) {
this._markDataAsMissing('<module-import>');
}
return;
}
this._createFragmentPointer({
kind: 'FragmentSpread',
name: moduleImport.fragmentName,
args: moduleImport.args
}, record, data);
data[FRAGMENT_PROP_NAME_KEY] = moduleImport.fragmentPropName;
data[MODULE_COMPONENT_KEY] = component;
};
_proto._readAliasedInlineFragment = function _readAliasedInlineFragment(aliasedInlineFragment, record, data) {
var prevErrors = this._fieldErrors;
this._fieldErrors = null;
var fieldValue = this._readInlineFragment(aliasedInlineFragment.fragment, record, {}, true);
this._prependPreviousErrors(prevErrors, aliasedInlineFragment.name);
if (fieldValue === false) {
fieldValue = null;
}
data[aliasedInlineFragment.name] = fieldValue;
};
_proto._readInlineFragment = function _readInlineFragment(inlineFragment, record, data, skipUnmatchedAbstractTypes) {
if (inlineFragment.type == null) {
var hasExpectedData = this._traverseSelections(inlineFragment.selections, record, data);
if (hasExpectedData === false) {
return false;
}
return data;
}
var abstractKey = inlineFragment.abstractKey;
if (abstractKey == null) {
if (!this._recordMatchesTypeCondition(record, inlineFragment.type)) {
return null;
} else {
var hasExpectedData = this._traverseSelections(inlineFragment.selections, record, data);
if (!hasExpectedData) {
return false;
}
}
} else {
var implementsInterface = this._implementsInterface(record, abstractKey);
if (implementsInterface === false && skipUnmatchedAbstractTypes) {
return null;
}
var parentIsMissingData = this._isMissingData;
var parentIsWithinUnmatchedTypeRefinement = this._isWithinUnmatchedTypeRefinement;
this._isWithinUnmatchedTypeRefinement = parentIsWithinUnmatchedTypeRefinement || implementsInterface === false;
var hasMissingData = this._traverseSelections(inlineFragment.selections, record, data);
this._isWithinUnmatchedTypeRefinement = parentIsWithinUnmatchedTypeRefinement;
if (implementsInterface === false) {
this._isMissingData = parentIsMissingData;
return null;
} else if (implementsInterface == null) {
return undefined;
} else if (hasMissingData === false) {
return false;
}
}
return data;
};
_proto._recordMatchesTypeCondition = function _recordMatchesTypeCondition(record, type) {
var typeName = RelayModernRecord.getType(record);
return typeName != null && typeName === type || RelayModernRecord.getDataID(record) === ROOT_ID;
};
_proto._createFragmentPointer = function _createFragmentPointer(fragmentSpread, record, data) {
var fragmentPointers = data[FRAGMENTS_KEY];
if (fragmentPointers == null) {
fragmentPointers = data[FRAGMENTS_KEY] = {};
}
!(typeof fragmentPointers === 'object' && fragmentPointers != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader: Expected fragment spread data to be an object, got `%s`.', fragmentPointers) : invariant(false) : void 0;
if (data[ID_KEY] == null) {
data[ID_KEY] = RelayModernRecord.getDataID(record);
}
fragmentPointers[fragmentSpread.name] = getArgumentValues(fragmentSpread.args, this._variables, this._isWithinUnmatchedTypeRefinement);
data[FRAGMENT_OWNER_KEY] = this._owner;
if (this._clientEdgeTraversalPath.length > 0 && this._clientEdgeTraversalPath[this._clientEdgeTraversalPath.length - 1] !== null) {
data[CLIENT_EDGE_TRAVERSAL_PATH] = (0, _toConsumableArray2["default"])(this._clientEdgeTraversalPath);
}
};
_proto._createInlineDataOrResolverFragmentPointer = function _createInlineDataOrResolverFragmentPointer(fragmentSpreadOrFragment, record, data) {
var fragmentPointers = data[FRAGMENTS_KEY];
if (fragmentPointers == null) {
fragmentPointers = data[FRAGMENTS_KEY] = {};
}
!(typeof fragmentPointers === 'object' && fragmentPointers != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayReader: Expected fragment spread data to be an object, got `%s`.', fragmentPointers) : invariant(false) : void 0;
if (data[ID_KEY] == null) {
data[ID_KEY] = RelayModernRecord.getDataID(record);
}
var inlineData = {};
var parentFragmentName = this._fragmentName;
this._fragmentName = fragmentSpreadOrFragment.name;
var parentVariables = this._variables;
var argumentVariables = fragmentSpreadOrFragment.args ? getArgumentValues(fragmentSpreadOrFragment.args, this._variables) : {};
this._variables = RelayConcreteVariables.getFragmentVariables(fragmentSpreadOrFragment, this._owner.variables, argumentVariables);
this._traverseSelections(fragmentSpreadOrFragment.selections, record, inlineData);
this._variables = parentVariables;
this._fragmentName = parentFragmentName;
fragmentPointers[fragmentSpreadOrFragment.name] = inlineData;
};
_proto._implementsInterface = function _implementsInterface(record, abstractKey) {
var typeName = RelayModernRecord.getType(record);
var typeRecord = this._recordSource.get(generateTypeID(typeName));
var implementsInterface = typeRecord != null ? RelayModernRecord.getValue(typeRecord, abstractKey) : null;
if (implementsInterface == null) {
this._markDataAsMissing('<abstract-type-hint>');
}
return implementsInterface;
};
return RelayReader;
}();
function markFieldErrorHasHandled(event) {
switch (event.kind) {
case 'missing_expected_data.throw':
case 'missing_required_field.throw':
case 'relay_field_payload.error':
case 'relay_resolver.error':
return (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, event), {}, {
handled: true
});
case 'missing_expected_data.log':
case 'missing_required_field.log':
return event;
default:
event.kind;
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unexpected error response field kind: %s', event.kind) : invariant(false) : void 0;
}
}
function getResolverValue(field, variables, fragmentKey, resolverContext) {
var resolverFunction = typeof field.resolverModule === 'function' ? field.resolverModule : field.resolverModule["default"];
var resolverResult = null;
var resolverError = null;
try {
var resolverFunctionArgs = [];
if (field.fragment != null) {
resolverFunctionArgs.push(fragmentKey);
}
var args = field.args ? getArgumentValues(field.args, variables) : undefined;
resolverFunctionArgs.push(args);
resolverFunctionArgs.push(resolverContext);
resolverResult = resolverFunction.apply(null, resolverFunctionArgs);
} catch (e) {
resolverResult = null;
if (e !== RESOLVER_FRAGMENT_ERRORED_SENTINEL) {
resolverError = e;
}
}
return [resolverResult, resolverError];
}
function extractIdFromResponse(individualResponse, path, owner) {
if (typeof individualResponse === 'string') {
return individualResponse;
} else if (typeof individualResponse === 'object' && individualResponse != null && typeof individualResponse.id === 'string') {
return individualResponse.id;
}
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected object returned from edge resolver to be a string or an object with an `id` property at path %s in %s,', path, owner) : invariant(false) : void 0;
}
module.exports = {
read: read
};