relay-runtime 18.1.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/experimental.js +1 -1
- package/experimental.js.flow +22 -9
- package/handlers/connection/ConnectionHandler.js.flow +6 -1
- package/index.js +1 -1
- package/index.js.flow +4 -0
- package/lib/experimental.js +5 -2
- package/lib/handlers/connection/ConnectionHandler.js +1 -1
- package/lib/index.js +3 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +1 -1
- package/lib/mutations/RelayRecordProxy.js +14 -3
- package/lib/mutations/RelayRecordSourceMutator.js +17 -0
- package/lib/mutations/RelayRecordSourceProxy.js +2 -1
- package/lib/mutations/createUpdatableProxy.js +1 -1
- package/lib/mutations/validateMutation.js +2 -2
- package/lib/network/RelayObservable.js +1 -3
- package/lib/network/wrapNetworkWithLogObserver.js +2 -2
- package/lib/query/fetchQuery.js +1 -1
- package/lib/store/DataChecker.js +4 -5
- package/lib/store/OperationExecutor.js +11 -0
- package/lib/store/RelayModernEnvironment.js +13 -4
- package/lib/store/RelayModernFragmentSpecResolver.js +4 -4
- package/lib/store/RelayModernStore.js +43 -21
- package/lib/store/RelayPublishQueue.js +11 -15
- package/lib/store/RelayReader.js +244 -183
- package/lib/store/RelayReferenceMarker.js +3 -4
- package/lib/store/RelayResponseNormalizer.js +48 -26
- package/lib/store/RelayStoreSubscriptions.js +2 -2
- package/lib/store/RelayStoreUtils.js +8 -0
- package/lib/store/ResolverCache.js +1 -165
- package/lib/store/ResolverFragments.js +2 -2
- package/lib/store/createRelayLoggingContext.js +17 -0
- package/lib/store/generateTypenamePrefixedDataID.js +9 -0
- package/lib/store/live-resolvers/LiveResolverCache.js +5 -10
- package/lib/store/live-resolvers/resolverDataInjector.js +4 -4
- package/lib/store/observeFragmentExperimental.js +60 -13
- package/lib/store/observeQueryExperimental.js +21 -0
- package/lib/util/RelayFeatureFlags.js +7 -2
- package/lib/util/handlePotentialSnapshotErrors.js +12 -9
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +1 -0
- package/mutations/RelayRecordProxy.js.flow +30 -3
- package/mutations/RelayRecordSourceMutator.js.flow +27 -0
- package/mutations/RelayRecordSourceProxy.js.flow +4 -0
- package/mutations/createUpdatableProxy.js.flow +1 -1
- package/mutations/validateMutation.js.flow +3 -3
- package/network/RelayNetworkTypes.js.flow +3 -0
- package/network/RelayObservable.js.flow +1 -5
- package/network/wrapNetworkWithLogObserver.js.flow +19 -1
- package/package.json +1 -1
- package/query/fetchQuery.js.flow +1 -1
- package/store/DataChecker.js.flow +5 -2
- package/store/OperationExecutor.js.flow +12 -1
- package/store/RelayExperimentalGraphResponseTransform.js.flow +4 -4
- package/store/RelayModernEnvironment.js.flow +22 -6
- package/store/RelayModernFragmentSpecResolver.js.flow +6 -6
- package/store/RelayModernRecord.js.flow +1 -1
- package/store/RelayModernSelector.js.flow +2 -0
- package/store/RelayModernStore.js.flow +74 -27
- package/store/RelayOptimisticRecordSource.js.flow +2 -0
- package/store/RelayPublishQueue.js.flow +32 -21
- package/store/RelayReader.js.flow +400 -145
- package/store/RelayRecordState.js.flow +1 -1
- package/store/RelayReferenceMarker.js.flow +3 -4
- package/store/RelayResponseNormalizer.js.flow +94 -62
- package/store/RelayStoreSubscriptions.js.flow +2 -2
- package/store/RelayStoreTypes.js.flow +45 -15
- package/store/RelayStoreUtils.js.flow +30 -1
- package/store/ResolverCache.js.flow +2 -271
- package/store/ResolverFragments.js.flow +5 -3
- package/store/StoreInspector.js.flow +5 -0
- package/store/createRelayContext.js.flow +3 -2
- package/store/createRelayLoggingContext.js.flow +46 -0
- package/store/generateTypenamePrefixedDataID.js.flow +25 -0
- package/store/live-resolvers/LiveResolverCache.js.flow +5 -10
- package/store/live-resolvers/resolverDataInjector.js.flow +10 -6
- package/store/observeFragmentExperimental.js.flow +82 -28
- package/store/observeQueryExperimental.js.flow +61 -0
- package/store/waitForFragmentExperimental.js.flow +4 -3
- package/util/NormalizationNode.js.flow +10 -1
- package/util/ReaderNode.js.flow +9 -3
- package/util/RelayConcreteNode.js.flow +3 -1
- package/util/RelayError.js.flow +1 -0
- package/util/RelayFeatureFlags.js.flow +31 -7
- package/util/RelayRuntimeTypes.js.flow +17 -3
- package/util/getPaginationVariables.js.flow +2 -0
- package/util/handlePotentialSnapshotErrors.js.flow +24 -12
- package/util/registerEnvironmentWithDevTools.js.flow +4 -2
- package/util/withProvidedVariables.js.flow +1 -0
- package/util/withStartAndDuration.js.flow +3 -0
- package/relay-runtime-experimental.js +0 -4
- package/relay-runtime-experimental.min.js +0 -9
- package/relay-runtime.js +0 -4
- package/relay-runtime.min.js +0 -9
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
|
|
3
4
|
var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator").default;
|
|
5
|
+
var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
|
|
4
6
|
var Observable = require('../network/RelayObservable');
|
|
5
|
-
var _require = require('../query/
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
var _require = require('../query/fetchQueryInternal'),
|
|
8
|
+
getObservableForActiveRequest = _require.getObservableForActiveRequest;
|
|
9
|
+
var _require2 = require('../query/GraphQLTag'),
|
|
10
|
+
getFragment = _require2.getFragment;
|
|
11
|
+
var _require3 = require('../util/handlePotentialSnapshotErrors'),
|
|
12
|
+
handlePotentialSnapshotErrors = _require3.handlePotentialSnapshotErrors;
|
|
13
|
+
var _require4 = require('./RelayModernSelector'),
|
|
14
|
+
getSelector = _require4.getSelector;
|
|
12
15
|
var invariant = require('invariant');
|
|
13
16
|
function waitForFragmentData(_x, _x2, _x3) {
|
|
14
17
|
return _waitForFragmentData.apply(this, arguments);
|
|
@@ -47,15 +50,15 @@ function observeFragment(environment, fragment, fragmentRef) {
|
|
|
47
50
|
!(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected a selector, got null.') : invariant(false) : void 0;
|
|
48
51
|
switch (fragmentSelector.kind) {
|
|
49
52
|
case 'SingularReaderSelector':
|
|
50
|
-
return
|
|
53
|
+
return observeSingularSelector(environment, fragment, fragmentSelector);
|
|
51
54
|
case 'PluralReaderSelector':
|
|
52
55
|
{
|
|
53
|
-
|
|
56
|
+
return observePluralSelector(environment, fragment, fragmentSelector);
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
!false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unsupported fragment selector kind') : invariant(false) : void 0;
|
|
57
60
|
}
|
|
58
|
-
function
|
|
61
|
+
function observeSingularSelector(environment, fragmentNode, fragmentSelector) {
|
|
59
62
|
var snapshot = environment.lookup(fragmentSelector);
|
|
60
63
|
return Observable.create(function (sink) {
|
|
61
64
|
sink.next(snapshotToFragmentState(environment, fragmentNode, fragmentSelector.owner, snapshot));
|
|
@@ -67,6 +70,28 @@ function observeSelector(environment, fragmentNode, fragmentSelector) {
|
|
|
67
70
|
};
|
|
68
71
|
});
|
|
69
72
|
}
|
|
73
|
+
function observePluralSelector(environment, fragmentNode, fragmentSelector) {
|
|
74
|
+
var snapshots = fragmentSelector.selectors.map(function (selector) {
|
|
75
|
+
return environment.lookup(selector);
|
|
76
|
+
});
|
|
77
|
+
return Observable.create(function (sink) {
|
|
78
|
+
var states = snapshots.map(function (snapshot, index) {
|
|
79
|
+
return snapshotToFragmentState(environment, fragmentNode, fragmentSelector.selectors[index].owner, snapshot);
|
|
80
|
+
});
|
|
81
|
+
sink.next(mergeFragmentStates(states));
|
|
82
|
+
var subscriptions = snapshots.map(function (snapshot, index) {
|
|
83
|
+
return environment.subscribe(snapshot, function (latestSnapshot) {
|
|
84
|
+
states[index] = snapshotToFragmentState(environment, fragmentNode, fragmentSelector.selectors[index].owner, latestSnapshot);
|
|
85
|
+
sink.next(mergeFragmentStates(states));
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
return function () {
|
|
89
|
+
return subscriptions.forEach(function (subscription) {
|
|
90
|
+
return subscription.dispose();
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
70
95
|
function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
|
|
71
96
|
var missingLiveResolverFields = snapshot.missingLiveResolverFields != null && snapshot.missingLiveResolverFields.length > 0;
|
|
72
97
|
var missingClientEdges = snapshot.missingClientEdges != null && snapshot.missingClientEdges.length > 0;
|
|
@@ -76,15 +101,14 @@ function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
|
|
|
76
101
|
};
|
|
77
102
|
}
|
|
78
103
|
if (snapshot.isMissingData) {
|
|
79
|
-
|
|
80
|
-
if (pendingOperations != null) {
|
|
104
|
+
if (getObservableForActiveRequest(environment, owner) != null || environment.getOperationTracker().getPendingOperationsAffectingOwner(owner) != null) {
|
|
81
105
|
return {
|
|
82
106
|
state: 'loading'
|
|
83
107
|
};
|
|
84
108
|
}
|
|
85
109
|
}
|
|
86
110
|
try {
|
|
87
|
-
handlePotentialSnapshotErrors(environment, snapshot.
|
|
111
|
+
handlePotentialSnapshotErrors(environment, snapshot.fieldErrors);
|
|
88
112
|
} catch (error) {
|
|
89
113
|
return {
|
|
90
114
|
error: error,
|
|
@@ -97,6 +121,29 @@ function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
|
|
|
97
121
|
value: snapshot.data
|
|
98
122
|
};
|
|
99
123
|
}
|
|
124
|
+
function mergeFragmentStates(states) {
|
|
125
|
+
var value = [];
|
|
126
|
+
var _iterator = (0, _createForOfIteratorHelper2["default"])(states),
|
|
127
|
+
_step;
|
|
128
|
+
try {
|
|
129
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
130
|
+
var state = _step.value;
|
|
131
|
+
if (state.state === 'ok') {
|
|
132
|
+
value.push(state.value);
|
|
133
|
+
} else {
|
|
134
|
+
return state;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (err) {
|
|
138
|
+
_iterator.e(err);
|
|
139
|
+
} finally {
|
|
140
|
+
_iterator.f();
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
state: 'ok',
|
|
144
|
+
value: value
|
|
145
|
+
};
|
|
146
|
+
}
|
|
100
147
|
module.exports = {
|
|
101
148
|
observeFragment: observeFragment,
|
|
102
149
|
waitForFragmentData: waitForFragmentData
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
|
|
4
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
5
|
+
var _require = require('./observeFragmentExperimental'),
|
|
6
|
+
observeFragment = _require.observeFragment;
|
|
7
|
+
var _require2 = require('./RelayModernOperationDescriptor'),
|
|
8
|
+
createOperationDescriptor = _require2.createOperationDescriptor;
|
|
9
|
+
function observeQuery(environment, gqlQuery, variables) {
|
|
10
|
+
var operation = createOperationDescriptor(gqlQuery, variables);
|
|
11
|
+
var rootFragmentRef = {
|
|
12
|
+
__id: operation.fragment.dataID,
|
|
13
|
+
__fragments: (0, _defineProperty2["default"])({}, operation.fragment.node.name, operation.request.variables),
|
|
14
|
+
__fragmentOwner: operation.request
|
|
15
|
+
};
|
|
16
|
+
var fragmentNode = operation.request.node.fragment;
|
|
17
|
+
return observeFragment(environment, fragmentNode, rootFragmentRef);
|
|
18
|
+
}
|
|
19
|
+
module.exports = {
|
|
20
|
+
observeQuery: observeQuery
|
|
21
|
+
};
|
|
@@ -5,7 +5,6 @@ var RelayFeatureFlags = {
|
|
|
5
5
|
ENABLE_RELAY_RESOLVERS: false,
|
|
6
6
|
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: false,
|
|
7
7
|
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: false,
|
|
8
|
-
ENABLE_LOAD_QUERY_REQUEST_DEDUPING: true,
|
|
9
8
|
ENABLE_DO_NOT_WRAP_LIVE_QUERY: false,
|
|
10
9
|
ENABLE_NOTIFY_SUBSCRIPTION: false,
|
|
11
10
|
BATCH_ASYNC_MODULE_UPDATES_FN: null,
|
|
@@ -13,6 +12,8 @@ var RelayFeatureFlags = {
|
|
|
13
12
|
MAX_DATA_ID_LENGTH: null,
|
|
14
13
|
STRING_INTERN_LEVEL: 0,
|
|
15
14
|
LOG_MISSING_RECORDS_IN_PROD: false,
|
|
15
|
+
ENABLE_STORE_ID_COLLISION_LOGGING: false,
|
|
16
|
+
ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS: false,
|
|
16
17
|
ENABLE_LOOSE_SUBSCRIPTION_ATTRIBUTION: false,
|
|
17
18
|
ENABLE_OPERATION_TRACKER_OPTIMISTIC_UPDATES: false,
|
|
18
19
|
ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE: false,
|
|
@@ -20,6 +21,10 @@ var RelayFeatureFlags = {
|
|
|
20
21
|
MARK_RESOLVER_VALUES_AS_CLEAN_AFTER_FRAGMENT_REREAD: false,
|
|
21
22
|
ENABLE_CYLE_DETECTION_IN_VARIABLES: false,
|
|
22
23
|
ENABLE_ACTIVITY_COMPATIBILITY: false,
|
|
23
|
-
|
|
24
|
+
ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX: true,
|
|
25
|
+
ENABLE_USE_PAGINATION_IS_LOADING_FIX: false,
|
|
26
|
+
DISALLOW_NESTED_UPDATES: false,
|
|
27
|
+
ENABLE_TYPENAME_PREFIXED_DATA_ID: false,
|
|
28
|
+
ENABLE_UI_CONTEXT_ON_RELAY_LOGGER: false
|
|
24
29
|
};
|
|
25
30
|
module.exports = RelayFeatureFlags;
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
|
|
4
|
+
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
4
5
|
var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
|
|
5
6
|
var invariant = require('invariant');
|
|
6
|
-
function handleFieldErrors(environment,
|
|
7
|
-
var _iterator = (0, _createForOfIteratorHelper2["default"])(
|
|
7
|
+
function handleFieldErrors(environment, fieldErrors, loggingContext) {
|
|
8
|
+
var _iterator = (0, _createForOfIteratorHelper2["default"])(fieldErrors),
|
|
8
9
|
_step;
|
|
9
10
|
try {
|
|
10
11
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
11
12
|
var fieldError = _step.value;
|
|
12
|
-
environment.relayFieldLogger(fieldError)
|
|
13
|
+
environment.relayFieldLogger((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, fieldError), {}, {
|
|
14
|
+
uiContext: loggingContext
|
|
15
|
+
}));
|
|
13
16
|
}
|
|
14
17
|
} catch (err) {
|
|
15
18
|
_iterator.e(err);
|
|
16
19
|
} finally {
|
|
17
20
|
_iterator.f();
|
|
18
21
|
}
|
|
19
|
-
var _iterator2 = (0, _createForOfIteratorHelper2["default"])(
|
|
22
|
+
var _iterator2 = (0, _createForOfIteratorHelper2["default"])(fieldErrors),
|
|
20
23
|
_step2;
|
|
21
24
|
try {
|
|
22
25
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
@@ -24,9 +27,9 @@ function handleFieldErrors(environment, errorResponseFields) {
|
|
|
24
27
|
if (eventShouldThrow(_fieldError)) {
|
|
25
28
|
switch (_fieldError.kind) {
|
|
26
29
|
case 'relay_resolver.error':
|
|
27
|
-
throw new Error("Relay: Resolver error at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'."));
|
|
30
|
+
throw new Error("Relay: Resolver error at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'. Message: ").concat(_fieldError.error.message));
|
|
28
31
|
case 'relay_field_payload.error':
|
|
29
|
-
throw new Error("Relay: Unexpected response payload -
|
|
32
|
+
throw new Error("Relay: Unexpected response payload - check server logs for details.");
|
|
30
33
|
case 'missing_expected_data.throw':
|
|
31
34
|
throw new Error("Relay: Missing expected data at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'."));
|
|
32
35
|
case 'missing_required_field.throw':
|
|
@@ -62,9 +65,9 @@ function eventShouldThrow(event) {
|
|
|
62
65
|
throw new Error('Relay: Unexpected event kind');
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
|
-
function handlePotentialSnapshotErrors(environment,
|
|
66
|
-
if (
|
|
67
|
-
handleFieldErrors(environment,
|
|
68
|
+
function handlePotentialSnapshotErrors(environment, fieldErrors, loggingContext) {
|
|
69
|
+
if (fieldErrors != null) {
|
|
70
|
+
handleFieldErrors(environment, fieldErrors, loggingContext);
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
module.exports = {
|
|
@@ -87,6 +87,7 @@ class ActorSpecificEnvironment implements IActorEnvironment {
|
|
|
87
87
|
config.handlerProvider,
|
|
88
88
|
defaultGetDataID,
|
|
89
89
|
config.missingFieldHandlers,
|
|
90
|
+
this.__log,
|
|
90
91
|
);
|
|
91
92
|
this._defaultRenderPolicy = config.defaultRenderPolicy;
|
|
92
93
|
// TODO:T92305692 Remove `options` in favor of directly using `actorIdentifier` on the environment
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {TRelayFieldError} from '../store/RelayErrorTrie';
|
|
14
15
|
import type {RecordProxy} from '../store/RelayStoreTypes';
|
|
15
16
|
import type {Arguments} from '../store/RelayStoreUtils';
|
|
16
17
|
import type {DataID} from '../util/RelayRuntimeTypes';
|
|
@@ -65,22 +66,48 @@ class RelayRecordProxy implements RecordProxy {
|
|
|
65
66
|
return this._mutator.getValue(this._dataID, storageKey);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
setValue(
|
|
69
|
+
setValue(
|
|
70
|
+
value: mixed,
|
|
71
|
+
name: string,
|
|
72
|
+
args?: ?Arguments,
|
|
73
|
+
errors?: ?$ReadOnlyArray<TRelayFieldError>,
|
|
74
|
+
): RecordProxy {
|
|
69
75
|
invariant(
|
|
70
76
|
isValidLeafValue(value),
|
|
71
77
|
'RelayRecordProxy#setValue(): Expected a scalar or array of scalars, ' +
|
|
72
78
|
'got `%s`.',
|
|
73
79
|
JSON.stringify(value),
|
|
74
80
|
);
|
|
75
|
-
|
|
81
|
+
|
|
82
|
+
return this.setValue__UNSAFE(value, name, args, errors);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getErrors(
|
|
86
|
+
name: string,
|
|
87
|
+
args?: ?Arguments,
|
|
88
|
+
): ?$ReadOnlyArray<TRelayFieldError> {
|
|
89
|
+
const storageKey = getStableStorageKey(name, args);
|
|
90
|
+
return this._mutator.getErrors(this._dataID, storageKey);
|
|
76
91
|
}
|
|
77
92
|
|
|
78
93
|
// This is used in the typesafe updaters.
|
|
79
94
|
// We already validated that the value has the correct type
|
|
80
95
|
// so it should be safe to store complex structures as scalar values (custom scalars)
|
|
81
|
-
setValue__UNSAFE(
|
|
96
|
+
setValue__UNSAFE(
|
|
97
|
+
value: mixed,
|
|
98
|
+
name: string,
|
|
99
|
+
args?: ?Arguments,
|
|
100
|
+
errors?: ?$ReadOnlyArray<TRelayFieldError>,
|
|
101
|
+
): RecordProxy {
|
|
82
102
|
const storageKey = getStableStorageKey(name, args);
|
|
83
103
|
this._mutator.setValue(this._dataID, storageKey, value);
|
|
104
|
+
if (errors != null) {
|
|
105
|
+
if (errors.length === 0) {
|
|
106
|
+
this._mutator.setErrors(this._dataID, storageKey);
|
|
107
|
+
} else {
|
|
108
|
+
this._mutator.setErrors(this._dataID, storageKey, errors);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
84
111
|
return this;
|
|
85
112
|
}
|
|
86
113
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {TRelayFieldError} from '../store/RelayErrorTrie';
|
|
14
15
|
import type {RecordState} from '../store/RelayRecordState';
|
|
15
16
|
import type {
|
|
16
17
|
MutableRecordSource,
|
|
@@ -179,6 +180,32 @@ class RelayRecordSourceMutator {
|
|
|
179
180
|
RelayModernRecord.setValue(sinkRecord, storageKey, value);
|
|
180
181
|
}
|
|
181
182
|
|
|
183
|
+
getErrors(
|
|
184
|
+
dataID: DataID,
|
|
185
|
+
storageKey: string,
|
|
186
|
+
): ?$ReadOnlyArray<TRelayFieldError> {
|
|
187
|
+
for (let ii = 0; ii < this.__sources.length; ii++) {
|
|
188
|
+
const record = this.__sources[ii].get(dataID);
|
|
189
|
+
if (record) {
|
|
190
|
+
const value = RelayModernRecord.getErrors(record, storageKey);
|
|
191
|
+
if (value !== undefined) {
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
194
|
+
} else if (record === null) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setErrors(
|
|
201
|
+
dataID: DataID,
|
|
202
|
+
storageKey: string,
|
|
203
|
+
errors?: $ReadOnlyArray<TRelayFieldError>,
|
|
204
|
+
): void {
|
|
205
|
+
const sinkRecord = this._getSinkRecord(dataID);
|
|
206
|
+
RelayModernRecord.setErrors(sinkRecord, storageKey, errors);
|
|
207
|
+
}
|
|
208
|
+
|
|
182
209
|
getLinkedRecordID(dataID: DataID, storageKey: string): ?DataID {
|
|
183
210
|
for (let ii = 0; ii < this.__sources.length; ii++) {
|
|
184
211
|
const record = this.__sources[ii].get(dataID);
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
FragmentType,
|
|
19
19
|
HandleFieldPayload,
|
|
20
20
|
HasUpdatableSpread,
|
|
21
|
+
LogFunction,
|
|
21
22
|
MissingFieldHandler,
|
|
22
23
|
RecordProxy,
|
|
23
24
|
RecordSource,
|
|
@@ -53,12 +54,14 @@ class RelayRecordSourceProxy implements RecordSourceProxy {
|
|
|
53
54
|
_invalidatedStore: boolean;
|
|
54
55
|
_idsMarkedForInvalidation: DataIDSet;
|
|
55
56
|
_missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>;
|
|
57
|
+
_log: LogFunction;
|
|
56
58
|
|
|
57
59
|
constructor(
|
|
58
60
|
mutator: RelayRecordSourceMutator,
|
|
59
61
|
getDataID: GetDataID,
|
|
60
62
|
handlerProvider?: ?HandlerProvider,
|
|
61
63
|
missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>,
|
|
64
|
+
log: ?LogFunction,
|
|
62
65
|
) {
|
|
63
66
|
this.__mutator = mutator;
|
|
64
67
|
this._handlerProvider = handlerProvider || null;
|
|
@@ -67,6 +70,7 @@ class RelayRecordSourceProxy implements RecordSourceProxy {
|
|
|
67
70
|
this._invalidatedStore = false;
|
|
68
71
|
this._idsMarkedForInvalidation = new Set();
|
|
69
72
|
this._missingFieldHandlers = missingFieldHandlers;
|
|
73
|
+
this._log = log ?? (LogEvent => {});
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
publishSource(
|
|
@@ -181,11 +181,11 @@ function updateProxyFromSelections<TData>(
|
|
|
181
181
|
case 'ClientEdgeToServerObject':
|
|
182
182
|
case 'Defer':
|
|
183
183
|
case 'ModuleImport':
|
|
184
|
-
case 'RelayLiveResolver':
|
|
185
184
|
case 'RequiredField':
|
|
186
185
|
case 'CatchField':
|
|
187
186
|
case 'Stream':
|
|
188
187
|
case 'RelayResolver':
|
|
188
|
+
case 'RelayLiveResolver':
|
|
189
189
|
// These types of reader nodes are not currently handled.
|
|
190
190
|
throw new Error(
|
|
191
191
|
'Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.',
|
|
@@ -145,13 +145,13 @@ if (__DEV__) {
|
|
|
145
145
|
return validateModuleImport(context);
|
|
146
146
|
case 'TypeDiscriminator':
|
|
147
147
|
return validateAbstractKey(context, selection.abstractKey);
|
|
148
|
-
case 'RelayResolver':
|
|
149
|
-
case 'RelayLiveResolver':
|
|
150
148
|
case 'ClientEdgeToClientObject':
|
|
151
149
|
case 'LinkedHandle':
|
|
152
150
|
case 'ScalarHandle':
|
|
153
151
|
case 'Defer':
|
|
154
|
-
case 'Stream':
|
|
152
|
+
case 'Stream':
|
|
153
|
+
case 'RelayResolver':
|
|
154
|
+
case 'RelayLiveResolver': {
|
|
155
155
|
// TODO(T35864292) - Add missing validations for these types
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {OperationAvailability} from '../store/RelayStoreTypes';
|
|
14
15
|
import type {RequestParameters} from '../util/RelayConcreteNode';
|
|
15
16
|
import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
|
|
16
17
|
import type RelayObservable, {ObservableFromValue} from './RelayObservable';
|
|
@@ -104,6 +105,8 @@ export type ExecuteFunction = (
|
|
|
104
105
|
logRequestInfo?: ?LogRequestInfoFunction,
|
|
105
106
|
encryptedVariables?: ?string,
|
|
106
107
|
preprocessResponse?: ?preprocessResponseFunction,
|
|
108
|
+
// Run datachecker on the current operation and returns the OperationAvailability
|
|
109
|
+
checkOperation?: () => OperationAvailability,
|
|
107
110
|
) => RelayObservable<GraphQLResponse>;
|
|
108
111
|
|
|
109
112
|
/**
|
|
@@ -614,11 +614,7 @@ if (__DEV__) {
|
|
|
614
614
|
// Default implementation of HostReportErrors() in development builds.
|
|
615
615
|
// Can be replaced by the host application environment.
|
|
616
616
|
RelayObservable.onUnhandledError((error, isUncaughtThrownError) => {
|
|
617
|
-
|
|
618
|
-
if (typeof fail === 'function') {
|
|
619
|
-
// In test environments (Jest), fail() immediately fails the current test.
|
|
620
|
-
fail(String(error));
|
|
621
|
-
} else if (isUncaughtThrownError) {
|
|
617
|
+
if (isUncaughtThrownError) {
|
|
622
618
|
// Rethrow uncaught thrown errors on the next frame to avoid breaking
|
|
623
619
|
// current logic.
|
|
624
620
|
setTimeout(() => {
|
|
@@ -12,12 +12,17 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
import type ActorSpecificEnvironment from '../multi-actor-environment/ActorSpecificEnvironment';
|
|
14
14
|
import type RelayModernEnvironment from '../store/RelayModernEnvironment';
|
|
15
|
+
import type {
|
|
16
|
+
LogRequestInfoFunction,
|
|
17
|
+
OperationAvailability,
|
|
18
|
+
} from '../store/RelayStoreTypes';
|
|
15
19
|
import type {RequestParameters} from '../util/RelayConcreteNode';
|
|
16
20
|
import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
|
|
17
21
|
import type {
|
|
18
22
|
GraphQLResponse,
|
|
19
23
|
INetwork,
|
|
20
24
|
UploadableMap,
|
|
25
|
+
preprocessResponseFunction,
|
|
21
26
|
} from './RelayNetworkTypes';
|
|
22
27
|
import type RelayObservable from './RelayObservable';
|
|
23
28
|
import type {Subscription} from './RelayObservable';
|
|
@@ -42,6 +47,10 @@ function wrapNetworkWithLogObserver(
|
|
|
42
47
|
variables: Variables,
|
|
43
48
|
cacheConfig: CacheConfig,
|
|
44
49
|
uploadables?: ?UploadableMap,
|
|
50
|
+
_?: ?LogRequestInfoFunction,
|
|
51
|
+
encryptedVariables?: ?string,
|
|
52
|
+
preprocessResponse?: ?preprocessResponseFunction,
|
|
53
|
+
checkOperation?: () => OperationAvailability,
|
|
45
54
|
): RelayObservable<GraphQLResponse> {
|
|
46
55
|
const networkRequestId = generateID();
|
|
47
56
|
const logObserver = {
|
|
@@ -89,7 +98,16 @@ function wrapNetworkWithLogObserver(
|
|
|
89
98
|
});
|
|
90
99
|
};
|
|
91
100
|
return network
|
|
92
|
-
.execute(
|
|
101
|
+
.execute(
|
|
102
|
+
params,
|
|
103
|
+
variables,
|
|
104
|
+
cacheConfig,
|
|
105
|
+
uploadables,
|
|
106
|
+
logRequestInfo,
|
|
107
|
+
encryptedVariables,
|
|
108
|
+
preprocessResponse,
|
|
109
|
+
checkOperation,
|
|
110
|
+
)
|
|
93
111
|
.do(logObserver);
|
|
94
112
|
},
|
|
95
113
|
};
|
package/package.json
CHANGED
package/query/fetchQuery.js.flow
CHANGED
|
@@ -138,7 +138,7 @@ function fetchQuery<TVariables: Variables, TData, TRawResponse>(
|
|
|
138
138
|
const fetchPolicy = options?.fetchPolicy ?? 'network-only';
|
|
139
139
|
|
|
140
140
|
function readData(snapshot: Snapshot): TData {
|
|
141
|
-
handlePotentialSnapshotErrors(environment, snapshot.
|
|
141
|
+
handlePotentialSnapshotErrors(environment, snapshot.fieldErrors);
|
|
142
142
|
/* $FlowFixMe[incompatible-return] we assume readData returns the right
|
|
143
143
|
* data just having written it from network or checked availability. */
|
|
144
144
|
return snapshot.data;
|
|
@@ -90,6 +90,7 @@ function check(
|
|
|
90
90
|
operationLoader,
|
|
91
91
|
getDataID,
|
|
92
92
|
shouldProcessClientComponents,
|
|
93
|
+
log,
|
|
93
94
|
);
|
|
94
95
|
const result = checker.check(node, dataID);
|
|
95
96
|
if (log != null) {
|
|
@@ -123,6 +124,7 @@ class DataChecker {
|
|
|
123
124
|
ActorIdentifier,
|
|
124
125
|
[RelayRecordSourceMutator, RelayRecordSourceProxy],
|
|
125
126
|
>;
|
|
127
|
+
_log: ?LogFunction;
|
|
126
128
|
|
|
127
129
|
constructor(
|
|
128
130
|
getSourceForActor: (actorIdentifier: ActorIdentifier) => RecordSource,
|
|
@@ -135,6 +137,7 @@ class DataChecker {
|
|
|
135
137
|
operationLoader: ?OperationLoader,
|
|
136
138
|
getDataID: GetDataID,
|
|
137
139
|
shouldProcessClientComponents: ?boolean,
|
|
140
|
+
log: ?LogFunction,
|
|
138
141
|
) {
|
|
139
142
|
this._getSourceForActor = getSourceForActor;
|
|
140
143
|
this._getTargetForActor = getTargetForActor;
|
|
@@ -152,6 +155,7 @@ class DataChecker {
|
|
|
152
155
|
this._recordWasMissing = false;
|
|
153
156
|
this._variables = variables;
|
|
154
157
|
this._shouldProcessClientComponents = shouldProcessClientComponents;
|
|
158
|
+
this._log = log;
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
_getMutatorAndRecordProxyForActor(
|
|
@@ -170,6 +174,7 @@ class DataChecker {
|
|
|
170
174
|
this._getDataID,
|
|
171
175
|
undefined,
|
|
172
176
|
this._handlers,
|
|
177
|
+
this._log,
|
|
173
178
|
);
|
|
174
179
|
tuple = [mutator, recordSourceProxy];
|
|
175
180
|
this._mutatorRecordSourceProxyCache.set(actorIdentifier, tuple);
|
|
@@ -449,8 +454,6 @@ class DataChecker {
|
|
|
449
454
|
this._traverseSelections(selection.fragment.selections, dataID);
|
|
450
455
|
break;
|
|
451
456
|
case 'RelayResolver':
|
|
452
|
-
this._checkResolver(selection, dataID);
|
|
453
|
-
break;
|
|
454
457
|
case 'RelayLiveResolver':
|
|
455
458
|
this._checkResolver(selection, dataID);
|
|
456
459
|
break;
|
|
@@ -245,6 +245,12 @@ class Executor<TMutation: MutationParameters> {
|
|
|
245
245
|
cacheConfig: this._operation.request.cacheConfig ?? {},
|
|
246
246
|
});
|
|
247
247
|
},
|
|
248
|
+
unsubscribe: () => {
|
|
249
|
+
this._log({
|
|
250
|
+
name: 'execute.unsubscribe',
|
|
251
|
+
executeId: this._executeId,
|
|
252
|
+
});
|
|
253
|
+
},
|
|
248
254
|
});
|
|
249
255
|
|
|
250
256
|
if (
|
|
@@ -293,7 +299,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
293
299
|
}
|
|
294
300
|
|
|
295
301
|
_updateActiveState(): void {
|
|
296
|
-
let activeState;
|
|
302
|
+
let activeState: ActiveState;
|
|
297
303
|
switch (this._state) {
|
|
298
304
|
case 'started': {
|
|
299
305
|
activeState = 'active';
|
|
@@ -606,6 +612,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
606
612
|
{
|
|
607
613
|
actorIdentifier: this._actorIdentifier,
|
|
608
614
|
getDataID: this._getDataID,
|
|
615
|
+
log: this._log,
|
|
609
616
|
path: [],
|
|
610
617
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
611
618
|
treatMissingFieldsAsNull,
|
|
@@ -715,6 +722,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
715
722
|
{
|
|
716
723
|
actorIdentifier: this._actorIdentifier,
|
|
717
724
|
getDataID: this._getDataID,
|
|
725
|
+
log: this._log,
|
|
718
726
|
path: followupPayload.path,
|
|
719
727
|
treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
|
|
720
728
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
@@ -797,6 +805,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
797
805
|
{
|
|
798
806
|
actorIdentifier: this._actorIdentifier,
|
|
799
807
|
getDataID: this._getDataID,
|
|
808
|
+
log: this._log,
|
|
800
809
|
path: [],
|
|
801
810
|
treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
|
|
802
811
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
@@ -1253,6 +1262,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
1253
1262
|
{
|
|
1254
1263
|
actorIdentifier: this._actorIdentifier,
|
|
1255
1264
|
getDataID: this._getDataID,
|
|
1265
|
+
log: this._log,
|
|
1256
1266
|
path: placeholder.path,
|
|
1257
1267
|
treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
|
|
1258
1268
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
@@ -1480,6 +1490,7 @@ class Executor<TMutation: MutationParameters> {
|
|
|
1480
1490
|
const relayPayload = this._normalizeResponse(response, selector, typeName, {
|
|
1481
1491
|
actorIdentifier: this._actorIdentifier,
|
|
1482
1492
|
getDataID: this._getDataID,
|
|
1493
|
+
log: this._log,
|
|
1483
1494
|
path: [...normalizationPath, responseKey, String(itemIndex)],
|
|
1484
1495
|
treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
|
|
1485
1496
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
@@ -222,10 +222,10 @@ export class GraphModeNormalizer {
|
|
|
222
222
|
$streamID,
|
|
223
223
|
__id: dataID,
|
|
224
224
|
__typename: ROOT_TYPE,
|
|
225
|
-
};
|
|
225
|
+
} as RecordChunk;
|
|
226
226
|
yield {
|
|
227
227
|
$kind: 'Complete',
|
|
228
|
-
};
|
|
228
|
+
} as CompleteChunk;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
*_flushFields(
|
|
@@ -247,9 +247,9 @@ export class GraphModeNormalizer {
|
|
|
247
247
|
__typename: typename,
|
|
248
248
|
__id: cacheKey,
|
|
249
249
|
$streamID,
|
|
250
|
-
};
|
|
250
|
+
} as RecordChunk;
|
|
251
251
|
} else if (Object.keys(fields).length > 0) {
|
|
252
|
-
yield {...fields, $kind: 'Extend', $streamID};
|
|
252
|
+
yield {...fields, $kind: 'Extend', $streamID} as ExtendChunk;
|
|
253
253
|
}
|
|
254
254
|
return $streamID;
|
|
255
255
|
}
|