relay-runtime 11.0.1 → 13.0.0-rc.1
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/handlers/RelayDefaultHandlerProvider.js.flow +2 -2
- package/handlers/connection/ConnectionHandler.js.flow +8 -17
- package/handlers/connection/MutationHandlers.js.flow +7 -11
- package/index.js +1 -1
- package/index.js.flow +60 -36
- package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
- package/lib/handlers/connection/ConnectionHandler.js +13 -19
- package/lib/handlers/connection/MutationHandlers.js +4 -7
- package/lib/index.js +58 -43
- package/lib/multi-actor-environment/ActorIdentifier.js +33 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +152 -0
- package/lib/multi-actor-environment/ActorUtils.js +27 -0
- package/lib/multi-actor-environment/MultiActorEnvironment.js +419 -0
- package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
- package/lib/multi-actor-environment/index.js +21 -0
- package/lib/mutations/RelayDeclarativeMutationConfig.js +4 -1
- package/lib/mutations/RelayRecordProxy.js +3 -2
- package/lib/mutations/RelayRecordSourceMutator.js +3 -2
- package/lib/mutations/RelayRecordSourceProxy.js +12 -4
- package/lib/mutations/RelayRecordSourceSelectorProxy.js +18 -5
- package/lib/mutations/applyOptimisticMutation.js +6 -6
- package/lib/mutations/commitMutation.js +14 -10
- package/lib/mutations/readUpdatableQuery_EXPERIMENTAL.js +238 -0
- package/lib/mutations/validateMutation.js +10 -5
- package/lib/network/ConvertToExecuteFunction.js +2 -1
- package/lib/network/RelayNetwork.js +3 -2
- package/lib/network/RelayQueryResponseCache.js +21 -5
- package/lib/network/wrapNetworkWithLogObserver.js +79 -0
- package/lib/query/GraphQLTag.js +3 -2
- package/lib/query/fetchQuery.js +6 -5
- package/lib/query/fetchQueryInternal.js +1 -1
- package/lib/query/fetchQuery_DEPRECATED.js +2 -1
- package/lib/store/ClientID.js +7 -1
- package/lib/store/DataChecker.js +123 -54
- package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +518 -200
- package/lib/store/RelayConcreteVariables.js +26 -8
- package/lib/store/RelayExperimentalGraphResponseHandler.js +153 -0
- package/lib/store/RelayExperimentalGraphResponseTransform.js +391 -0
- package/lib/store/RelayModernEnvironment.js +175 -240
- package/lib/store/RelayModernFragmentSpecResolver.js +52 -26
- package/lib/store/RelayModernOperationDescriptor.js +2 -1
- package/lib/store/RelayModernRecord.js +47 -12
- package/lib/store/RelayModernSelector.js +14 -8
- package/lib/store/RelayModernStore.js +56 -28
- package/lib/store/RelayOperationTracker.js +34 -24
- package/lib/store/RelayPublishQueue.js +41 -13
- package/lib/store/RelayReader.js +288 -48
- package/lib/store/RelayRecordSource.js +87 -3
- package/lib/store/RelayReferenceMarker.js +34 -22
- package/lib/store/RelayResponseNormalizer.js +211 -110
- package/lib/store/RelayStoreReactFlightUtils.js +4 -10
- package/lib/store/RelayStoreSubscriptions.js +14 -9
- package/lib/store/RelayStoreUtils.js +12 -7
- package/lib/store/ResolverCache.js +213 -0
- package/lib/store/ResolverFragments.js +61 -0
- package/lib/store/cloneRelayHandleSourceField.js +5 -4
- package/lib/store/cloneRelayScalarHandleSourceField.js +5 -4
- package/lib/store/createRelayContext.js +4 -2
- package/lib/store/readInlineData.js +6 -2
- package/lib/subscription/requestSubscription.js +34 -25
- package/lib/util/RelayConcreteNode.js +3 -0
- package/lib/util/RelayFeatureFlags.js +10 -4
- package/lib/util/RelayProfiler.js +17 -187
- package/lib/util/RelayReplaySubject.js +22 -7
- package/lib/util/RelayRuntimeTypes.js +0 -6
- package/lib/util/StringInterner.js +71 -0
- package/lib/util/getFragmentIdentifier.js +15 -7
- package/lib/util/getOperation.js +2 -1
- package/lib/util/getPaginationMetadata.js +41 -0
- package/lib/util/getPaginationVariables.js +66 -0
- package/lib/util/getPendingOperationsForFragment.js +55 -0
- package/lib/util/getRefetchMetadata.js +36 -0
- package/lib/util/getRelayHandleKey.js +2 -2
- package/lib/util/getRequestIdentifier.js +2 -2
- package/lib/util/getValueAtPath.js +51 -0
- package/lib/util/isEmptyObject.js +1 -1
- package/lib/util/registerEnvironmentWithDevTools.js +26 -0
- package/lib/util/withDuration.js +31 -0
- package/multi-actor-environment/ActorIdentifier.js.flow +43 -0
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +225 -0
- package/multi-actor-environment/ActorUtils.js.flow +33 -0
- package/multi-actor-environment/MultiActorEnvironment.js.flow +506 -0
- package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +261 -0
- package/multi-actor-environment/index.js.flow +26 -0
- package/mutations/RelayDeclarativeMutationConfig.js.flow +32 -26
- package/mutations/RelayRecordProxy.js.flow +4 -5
- package/mutations/RelayRecordSourceMutator.js.flow +4 -6
- package/mutations/RelayRecordSourceProxy.js.flow +19 -10
- package/mutations/RelayRecordSourceSelectorProxy.js.flow +22 -7
- package/mutations/applyOptimisticMutation.js.flow +13 -14
- package/mutations/commitLocalUpdate.js.flow +1 -1
- package/mutations/commitMutation.js.flow +35 -46
- package/mutations/readUpdatableQuery_EXPERIMENTAL.js.flow +309 -0
- package/mutations/validateMutation.js.flow +26 -16
- package/network/ConvertToExecuteFunction.js.flow +2 -2
- package/network/RelayNetwork.js.flow +4 -5
- package/network/RelayNetworkTypes.js.flow +5 -4
- package/network/RelayObservable.js.flow +1 -1
- package/network/RelayQueryResponseCache.js.flow +34 -21
- package/network/wrapNetworkWithLogObserver.js.flow +100 -0
- package/package.json +3 -2
- package/query/GraphQLTag.js.flow +9 -9
- package/query/PreloadableQueryRegistry.js.flow +2 -1
- package/query/fetchQuery.js.flow +11 -13
- package/query/fetchQueryInternal.js.flow +6 -9
- package/query/fetchQuery_DEPRECATED.js.flow +6 -6
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/ClientID.js.flow +14 -3
- package/store/DataChecker.js.flow +141 -59
- package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +605 -303
- package/store/RelayConcreteVariables.js.flow +27 -8
- package/store/RelayExperimentalGraphResponseHandler.js.flow +124 -0
- package/store/RelayExperimentalGraphResponseTransform.js.flow +475 -0
- package/store/RelayModernEnvironment.js.flow +173 -240
- package/store/RelayModernFragmentSpecResolver.js.flow +55 -31
- package/store/RelayModernOperationDescriptor.js.flow +12 -7
- package/store/RelayModernRecord.js.flow +67 -11
- package/store/RelayModernSelector.js.flow +24 -14
- package/store/RelayModernStore.js.flow +66 -36
- package/store/RelayOperationTracker.js.flow +59 -43
- package/store/RelayOptimisticRecordSource.js.flow +2 -2
- package/store/RelayPublishQueue.js.flow +79 -34
- package/store/RelayReader.js.flow +351 -73
- package/store/RelayRecordSource.js.flow +72 -6
- package/store/RelayReferenceMarker.js.flow +40 -26
- package/store/RelayResponseNormalizer.js.flow +258 -99
- package/store/RelayStoreReactFlightUtils.js.flow +4 -11
- package/store/RelayStoreSubscriptions.js.flow +19 -11
- package/store/RelayStoreTypes.js.flow +209 -43
- package/store/RelayStoreUtils.js.flow +24 -11
- package/store/ResolverCache.js.flow +249 -0
- package/store/ResolverFragments.js.flow +121 -0
- package/store/StoreInspector.js.flow +2 -2
- package/store/TypeID.js.flow +1 -1
- package/store/ViewerPattern.js.flow +2 -2
- package/store/cloneRelayHandleSourceField.js.flow +5 -6
- package/store/cloneRelayScalarHandleSourceField.js.flow +5 -6
- package/store/createFragmentSpecResolver.js.flow +3 -4
- package/store/createRelayContext.js.flow +3 -3
- package/store/normalizeRelayPayload.js.flow +6 -7
- package/store/readInlineData.js.flow +7 -8
- package/subscription/requestSubscription.js.flow +53 -41
- package/util/NormalizationNode.js.flow +10 -3
- package/util/ReaderNode.js.flow +38 -2
- package/util/RelayConcreteNode.js.flow +5 -0
- package/util/RelayFeatureFlags.js.flow +24 -10
- package/util/RelayProfiler.js.flow +22 -194
- package/util/RelayReplaySubject.js.flow +9 -9
- package/util/RelayRuntimeTypes.js.flow +72 -3
- package/util/StringInterner.js.flow +69 -0
- package/util/createPayloadFor3DField.js.flow +3 -3
- package/util/getFragmentIdentifier.js.flow +27 -15
- package/util/getOperation.js.flow +2 -2
- package/util/getPaginationMetadata.js.flow +72 -0
- package/util/getPaginationVariables.js.flow +108 -0
- package/util/getPendingOperationsForFragment.js.flow +62 -0
- package/util/getRefetchMetadata.js.flow +79 -0
- package/util/getRelayHandleKey.js.flow +1 -2
- package/util/getRequestIdentifier.js.flow +3 -3
- package/util/getValueAtPath.js.flow +46 -0
- package/util/isEmptyObject.js.flow +1 -0
- package/util/registerEnvironmentWithDevTools.js.flow +33 -0
- package/util/resolveImmediate.js.flow +1 -1
- package/util/withDuration.js.flow +32 -0
- package/lib/store/RelayRecordSourceMapImpl.js +0 -107
- package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +0 -318
- package/store/RelayRecordSourceMapImpl.js.flow +0 -91
- package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +0 -283
|
@@ -12,18 +12,41 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
import type {ActorIdentifier} from '../multi-actor-environment/ActorIdentifier';
|
|
16
|
+
import type {PayloadData} from '../network/RelayNetworkTypes';
|
|
17
|
+
import type {
|
|
18
|
+
NormalizationActorChange,
|
|
19
|
+
NormalizationDefer,
|
|
20
|
+
NormalizationFlightField,
|
|
21
|
+
NormalizationLinkedField,
|
|
22
|
+
NormalizationModuleImport,
|
|
23
|
+
NormalizationNode,
|
|
24
|
+
NormalizationScalarField,
|
|
25
|
+
NormalizationStream,
|
|
26
|
+
} from '../util/NormalizationNode';
|
|
27
|
+
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
28
|
+
import type {
|
|
29
|
+
FollowupPayload,
|
|
30
|
+
HandleFieldPayload,
|
|
31
|
+
IncrementalDataPlaceholder,
|
|
32
|
+
MutableRecordSource,
|
|
33
|
+
NormalizationSelector,
|
|
34
|
+
ReactFlightPayloadDeserializer,
|
|
35
|
+
ReactFlightReachableExecutableDefinitions,
|
|
36
|
+
ReactFlightServerErrorHandler,
|
|
37
|
+
Record,
|
|
38
|
+
RelayResponsePayload,
|
|
39
|
+
} from './RelayStoreTypes';
|
|
22
40
|
|
|
23
41
|
const {
|
|
24
|
-
|
|
42
|
+
ACTOR_IDENTIFIER_FIELD_NAME,
|
|
43
|
+
getActorIdentifierFromPayload,
|
|
44
|
+
} = require('../multi-actor-environment/ActorUtils');
|
|
45
|
+
const {
|
|
46
|
+
ACTOR_CHANGE,
|
|
25
47
|
CLIENT_COMPONENT,
|
|
26
48
|
CLIENT_EXTENSION,
|
|
49
|
+
CONDITION,
|
|
27
50
|
DEFER,
|
|
28
51
|
FLIGHT_FIELD,
|
|
29
52
|
FRAGMENT_SPREAD,
|
|
@@ -36,49 +59,31 @@ const {
|
|
|
36
59
|
STREAM,
|
|
37
60
|
TYPE_DISCRIMINATOR,
|
|
38
61
|
} = require('../util/RelayConcreteNode');
|
|
62
|
+
const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
39
63
|
const {generateClientID, isClientID} = require('./ClientID');
|
|
64
|
+
const {getLocalVariables} = require('./RelayConcreteVariables');
|
|
65
|
+
const RelayModernRecord = require('./RelayModernRecord');
|
|
40
66
|
const {createNormalizationSelector} = require('./RelayModernSelector');
|
|
41
67
|
const {
|
|
42
|
-
refineToReactFlightPayloadData,
|
|
43
68
|
REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
|
|
44
69
|
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
45
70
|
REACT_FLIGHT_TYPE_NAME,
|
|
71
|
+
refineToReactFlightPayloadData,
|
|
46
72
|
} = require('./RelayStoreReactFlightUtils');
|
|
47
73
|
const {
|
|
74
|
+
ROOT_ID,
|
|
75
|
+
ROOT_TYPE,
|
|
76
|
+
TYPENAME_KEY,
|
|
48
77
|
getArgumentValues,
|
|
49
78
|
getHandleStorageKey,
|
|
50
79
|
getModuleComponentKey,
|
|
51
80
|
getModuleOperationKey,
|
|
52
81
|
getStorageKey,
|
|
53
|
-
TYPENAME_KEY,
|
|
54
|
-
ROOT_ID,
|
|
55
|
-
ROOT_TYPE,
|
|
56
82
|
} = require('./RelayStoreUtils');
|
|
57
|
-
const {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
NormalizationDefer,
|
|
62
|
-
NormalizationFlightField,
|
|
63
|
-
NormalizationLinkedField,
|
|
64
|
-
NormalizationModuleImport,
|
|
65
|
-
NormalizationNode,
|
|
66
|
-
NormalizationScalarField,
|
|
67
|
-
NormalizationStream,
|
|
68
|
-
} from '../util/NormalizationNode';
|
|
69
|
-
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
70
|
-
import type {
|
|
71
|
-
HandleFieldPayload,
|
|
72
|
-
IncrementalDataPlaceholder,
|
|
73
|
-
ModuleImportPayload,
|
|
74
|
-
MutableRecordSource,
|
|
75
|
-
NormalizationSelector,
|
|
76
|
-
ReactFlightReachableExecutableDefinitions,
|
|
77
|
-
ReactFlightPayloadDeserializer,
|
|
78
|
-
ReactFlightServerErrorHandler,
|
|
79
|
-
Record,
|
|
80
|
-
RelayResponsePayload,
|
|
81
|
-
} from './RelayStoreTypes';
|
|
83
|
+
const {TYPE_SCHEMA_TYPE, generateTypeID} = require('./TypeID');
|
|
84
|
+
const areEqual = require('areEqual');
|
|
85
|
+
const invariant = require('invariant');
|
|
86
|
+
const warning = require('warning');
|
|
82
87
|
|
|
83
88
|
export type GetDataID = (
|
|
84
89
|
fieldValue: interface {[string]: mixed},
|
|
@@ -92,6 +97,7 @@ export type NormalizationOptions = {|
|
|
|
92
97
|
+reactFlightPayloadDeserializer?: ?ReactFlightPayloadDeserializer,
|
|
93
98
|
+reactFlightServerErrorHandler?: ?ReactFlightServerErrorHandler,
|
|
94
99
|
+shouldProcessClientComponents?: ?boolean,
|
|
100
|
+
+actorIdentifier?: ?ActorIdentifier,
|
|
95
101
|
|};
|
|
96
102
|
|
|
97
103
|
/**
|
|
@@ -119,13 +125,14 @@ function normalize(
|
|
|
119
125
|
* Helper for handling payloads.
|
|
120
126
|
*/
|
|
121
127
|
class RelayResponseNormalizer {
|
|
128
|
+
_actorIdentifier: ?ActorIdentifier;
|
|
122
129
|
_getDataId: GetDataID;
|
|
123
130
|
_handleFieldPayloads: Array<HandleFieldPayload>;
|
|
124
131
|
_treatMissingFieldsAsNull: boolean;
|
|
125
132
|
_incrementalPlaceholders: Array<IncrementalDataPlaceholder>;
|
|
126
133
|
_isClientExtension: boolean;
|
|
127
134
|
_isUnmatchedAbstractType: boolean;
|
|
128
|
-
|
|
135
|
+
_followupPayloads: Array<FollowupPayload>;
|
|
129
136
|
_path: Array<string>;
|
|
130
137
|
_recordSource: MutableRecordSource;
|
|
131
138
|
_variables: Variables;
|
|
@@ -138,13 +145,14 @@ class RelayResponseNormalizer {
|
|
|
138
145
|
variables: Variables,
|
|
139
146
|
options: NormalizationOptions,
|
|
140
147
|
) {
|
|
148
|
+
this._actorIdentifier = options.actorIdentifier;
|
|
141
149
|
this._getDataId = options.getDataID;
|
|
142
150
|
this._handleFieldPayloads = [];
|
|
143
151
|
this._treatMissingFieldsAsNull = options.treatMissingFieldsAsNull;
|
|
144
152
|
this._incrementalPlaceholders = [];
|
|
145
153
|
this._isClientExtension = false;
|
|
146
154
|
this._isUnmatchedAbstractType = false;
|
|
147
|
-
this.
|
|
155
|
+
this._followupPayloads = [];
|
|
148
156
|
this._path = options.path ? [...options.path] : [];
|
|
149
157
|
this._recordSource = recordSource;
|
|
150
158
|
this._variables = variables;
|
|
@@ -170,7 +178,7 @@ class RelayResponseNormalizer {
|
|
|
170
178
|
errors: null,
|
|
171
179
|
fieldPayloads: this._handleFieldPayloads,
|
|
172
180
|
incrementalPlaceholders: this._incrementalPlaceholders,
|
|
173
|
-
|
|
181
|
+
followupPayloads: this._followupPayloads,
|
|
174
182
|
source: this._recordSource,
|
|
175
183
|
isFinal: false,
|
|
176
184
|
};
|
|
@@ -182,7 +190,6 @@ class RelayResponseNormalizer {
|
|
|
182
190
|
'RelayResponseNormalizer(): Undefined variable `%s`.',
|
|
183
191
|
name,
|
|
184
192
|
);
|
|
185
|
-
// $FlowFixMe[cannot-write]
|
|
186
193
|
return this._variables[name];
|
|
187
194
|
}
|
|
188
195
|
|
|
@@ -209,13 +216,22 @@ class RelayResponseNormalizer {
|
|
|
209
216
|
this._normalizeField(node, selection, record, data);
|
|
210
217
|
break;
|
|
211
218
|
case CONDITION:
|
|
212
|
-
const conditionValue =
|
|
219
|
+
const conditionValue = Boolean(
|
|
220
|
+
this._getVariableValue(selection.condition),
|
|
221
|
+
);
|
|
213
222
|
if (conditionValue === selection.passingValue) {
|
|
214
223
|
this._traverseSelections(selection, record, data);
|
|
215
224
|
}
|
|
216
225
|
break;
|
|
217
226
|
case FRAGMENT_SPREAD: {
|
|
227
|
+
const prevVariables = this._variables;
|
|
228
|
+
this._variables = getLocalVariables(
|
|
229
|
+
this._variables,
|
|
230
|
+
selection.fragment.argumentDefinitions,
|
|
231
|
+
selection.args,
|
|
232
|
+
);
|
|
218
233
|
this._traverseSelections(selection.fragment, record, data);
|
|
234
|
+
this._variables = prevVariables;
|
|
219
235
|
break;
|
|
220
236
|
}
|
|
221
237
|
case INLINE_FRAGMENT: {
|
|
@@ -225,7 +241,7 @@ class RelayResponseNormalizer {
|
|
|
225
241
|
if (typeName === selection.type) {
|
|
226
242
|
this._traverseSelections(selection, record, data);
|
|
227
243
|
}
|
|
228
|
-
} else
|
|
244
|
+
} else {
|
|
229
245
|
const implementsInterface = data.hasOwnProperty(abstractKey);
|
|
230
246
|
const typeName = RelayModernRecord.getType(record);
|
|
231
247
|
const typeID = generateTypeID(typeName);
|
|
@@ -242,36 +258,24 @@ class RelayResponseNormalizer {
|
|
|
242
258
|
if (implementsInterface) {
|
|
243
259
|
this._traverseSelections(selection, record, data);
|
|
244
260
|
}
|
|
245
|
-
} else {
|
|
246
|
-
// legacy behavior for abstract refinements: always normalize even
|
|
247
|
-
// if the type doesn't conform, but track if the type matches or not
|
|
248
|
-
// for determining whether response fields are expected to be present
|
|
249
|
-
const implementsInterface = data.hasOwnProperty(abstractKey);
|
|
250
|
-
const parentIsUnmatchedAbstractType = this._isUnmatchedAbstractType;
|
|
251
|
-
this._isUnmatchedAbstractType =
|
|
252
|
-
this._isUnmatchedAbstractType || !implementsInterface;
|
|
253
|
-
this._traverseSelections(selection, record, data);
|
|
254
|
-
this._isUnmatchedAbstractType = parentIsUnmatchedAbstractType;
|
|
255
261
|
}
|
|
256
262
|
break;
|
|
257
263
|
}
|
|
258
264
|
case TYPE_DISCRIMINATOR: {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this._recordSource.set(typeID, typeRecord);
|
|
268
|
-
}
|
|
269
|
-
RelayModernRecord.setValue(
|
|
270
|
-
typeRecord,
|
|
271
|
-
abstractKey,
|
|
272
|
-
implementsInterface,
|
|
273
|
-
);
|
|
265
|
+
const {abstractKey} = selection;
|
|
266
|
+
const implementsInterface = data.hasOwnProperty(abstractKey);
|
|
267
|
+
const typeName = RelayModernRecord.getType(record);
|
|
268
|
+
const typeID = generateTypeID(typeName);
|
|
269
|
+
let typeRecord = this._recordSource.get(typeID);
|
|
270
|
+
if (typeRecord == null) {
|
|
271
|
+
typeRecord = RelayModernRecord.create(typeID, TYPE_SCHEMA_TYPE);
|
|
272
|
+
this._recordSource.set(typeID, typeRecord);
|
|
274
273
|
}
|
|
274
|
+
RelayModernRecord.setValue(
|
|
275
|
+
typeRecord,
|
|
276
|
+
abstractKey,
|
|
277
|
+
implementsInterface,
|
|
278
|
+
);
|
|
275
279
|
break;
|
|
276
280
|
}
|
|
277
281
|
case LINKED_HANDLE:
|
|
@@ -282,13 +286,17 @@ class RelayResponseNormalizer {
|
|
|
282
286
|
const fieldKey = getStorageKey(selection, this._variables);
|
|
283
287
|
const handleKey = getHandleStorageKey(selection, this._variables);
|
|
284
288
|
this._handleFieldPayloads.push({
|
|
289
|
+
/* $FlowFixMe[class-object-subtyping] added when improving typing
|
|
290
|
+
* for this parameters */
|
|
285
291
|
args,
|
|
286
292
|
dataID: RelayModernRecord.getDataID(record),
|
|
287
293
|
fieldKey,
|
|
288
294
|
handle: selection.handle,
|
|
289
295
|
handleKey,
|
|
290
296
|
handleArgs: selection.handleArgs
|
|
291
|
-
?
|
|
297
|
+
? /* $FlowFixMe[class-object-subtyping] added when improving typing
|
|
298
|
+
* for this parameters */
|
|
299
|
+
getArgumentValues(selection.handleArgs, this._variables)
|
|
292
300
|
: {},
|
|
293
301
|
});
|
|
294
302
|
break;
|
|
@@ -320,6 +328,9 @@ class RelayResponseNormalizer {
|
|
|
320
328
|
throw new Error('Flight fields are not yet supported.');
|
|
321
329
|
}
|
|
322
330
|
break;
|
|
331
|
+
case ACTOR_CHANGE:
|
|
332
|
+
this._normalizeActorChange(node, selection, record, data);
|
|
333
|
+
break;
|
|
323
334
|
default:
|
|
324
335
|
(selection: empty);
|
|
325
336
|
invariant(
|
|
@@ -363,6 +374,7 @@ class RelayResponseNormalizer {
|
|
|
363
374
|
this._variables,
|
|
364
375
|
),
|
|
365
376
|
typeName: RelayModernRecord.getType(record),
|
|
377
|
+
actorIdentifier: this._actorIdentifier,
|
|
366
378
|
});
|
|
367
379
|
}
|
|
368
380
|
}
|
|
@@ -395,6 +407,7 @@ class RelayResponseNormalizer {
|
|
|
395
407
|
parentID: RelayModernRecord.getDataID(record),
|
|
396
408
|
node: stream,
|
|
397
409
|
variables: this._variables,
|
|
410
|
+
actorIdentifier: this._actorIdentifier,
|
|
398
411
|
});
|
|
399
412
|
}
|
|
400
413
|
}
|
|
@@ -425,13 +438,16 @@ class RelayResponseNormalizer {
|
|
|
425
438
|
operationReference ?? null,
|
|
426
439
|
);
|
|
427
440
|
if (operationReference != null) {
|
|
428
|
-
this.
|
|
441
|
+
this._followupPayloads.push({
|
|
442
|
+
kind: 'ModuleImportPayload',
|
|
443
|
+
args: moduleImport.args,
|
|
429
444
|
data,
|
|
430
445
|
dataID: RelayModernRecord.getDataID(record),
|
|
431
446
|
operationReference,
|
|
432
447
|
path: [...this._path],
|
|
433
448
|
typeName,
|
|
434
449
|
variables: this._variables,
|
|
450
|
+
actorIdentifier: this._actorIdentifier,
|
|
435
451
|
});
|
|
436
452
|
}
|
|
437
453
|
}
|
|
@@ -489,7 +505,11 @@ class RelayResponseNormalizer {
|
|
|
489
505
|
this._validateConflictingFieldsWithIdenticalId(
|
|
490
506
|
record,
|
|
491
507
|
storageKey,
|
|
492
|
-
|
|
508
|
+
// When using `treatMissingFieldsAsNull` the conflicting validation raises a false positive
|
|
509
|
+
// because the value is set using `null` but validated using `fieldValue` which at this point
|
|
510
|
+
// will be `undefined`.
|
|
511
|
+
// Setting this to `null` matches the value that we actually set to the `fieldValue`.
|
|
512
|
+
null,
|
|
493
513
|
);
|
|
494
514
|
}
|
|
495
515
|
}
|
|
@@ -524,6 +544,99 @@ class RelayResponseNormalizer {
|
|
|
524
544
|
}
|
|
525
545
|
}
|
|
526
546
|
|
|
547
|
+
_normalizeActorChange(
|
|
548
|
+
parent: NormalizationNode,
|
|
549
|
+
selection: NormalizationActorChange,
|
|
550
|
+
record: Record,
|
|
551
|
+
data: PayloadData,
|
|
552
|
+
) {
|
|
553
|
+
const field = selection.linkedField;
|
|
554
|
+
invariant(
|
|
555
|
+
typeof data === 'object' && data,
|
|
556
|
+
'_normalizeActorChange(): Expected data for field `%s` to be an object.',
|
|
557
|
+
field.name,
|
|
558
|
+
);
|
|
559
|
+
const responseKey = field.alias || field.name;
|
|
560
|
+
const storageKey = getStorageKey(field, this._variables);
|
|
561
|
+
const fieldValue = data[responseKey];
|
|
562
|
+
|
|
563
|
+
if (fieldValue == null) {
|
|
564
|
+
if (fieldValue === undefined) {
|
|
565
|
+
const isOptionalField =
|
|
566
|
+
this._isClientExtension || this._isUnmatchedAbstractType;
|
|
567
|
+
|
|
568
|
+
if (isOptionalField) {
|
|
569
|
+
return;
|
|
570
|
+
} else if (!this._treatMissingFieldsAsNull) {
|
|
571
|
+
if (__DEV__) {
|
|
572
|
+
warning(
|
|
573
|
+
false,
|
|
574
|
+
'RelayResponseNormalizer: Payload did not contain a value ' +
|
|
575
|
+
'for field `%s: %s`. Check that you are parsing with the same ' +
|
|
576
|
+
'query that was used to fetch the payload.',
|
|
577
|
+
responseKey,
|
|
578
|
+
storageKey,
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
RelayModernRecord.setValue(record, storageKey, null);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const actorIdentifier = getActorIdentifierFromPayload(fieldValue);
|
|
589
|
+
if (actorIdentifier == null) {
|
|
590
|
+
if (__DEV__) {
|
|
591
|
+
warning(
|
|
592
|
+
false,
|
|
593
|
+
'RelayResponseNormalizer: Payload did not contain a value ' +
|
|
594
|
+
'for field `%s`. Check that you are parsing with the same ' +
|
|
595
|
+
'query that was used to fetch the payload. Payload is `%s`.',
|
|
596
|
+
ACTOR_IDENTIFIER_FIELD_NAME,
|
|
597
|
+
JSON.stringify(fieldValue, null, 2),
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
RelayModernRecord.setValue(record, storageKey, null);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// $FlowFixMe[incompatible-call]
|
|
605
|
+
const typeName = field.concreteType ?? this._getRecordType(fieldValue);
|
|
606
|
+
const nextID =
|
|
607
|
+
this._getDataId(
|
|
608
|
+
// $FlowFixMe[incompatible-call]
|
|
609
|
+
fieldValue,
|
|
610
|
+
typeName,
|
|
611
|
+
) ||
|
|
612
|
+
RelayModernRecord.getLinkedRecordID(record, storageKey) ||
|
|
613
|
+
generateClientID(RelayModernRecord.getDataID(record), storageKey);
|
|
614
|
+
|
|
615
|
+
invariant(
|
|
616
|
+
typeof nextID === 'string',
|
|
617
|
+
'RelayResponseNormalizer: Expected id on field `%s` to be a string.',
|
|
618
|
+
storageKey,
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
RelayModernRecord.setActorLinkedRecordID(
|
|
622
|
+
record,
|
|
623
|
+
storageKey,
|
|
624
|
+
actorIdentifier,
|
|
625
|
+
nextID,
|
|
626
|
+
);
|
|
627
|
+
|
|
628
|
+
this._followupPayloads.push({
|
|
629
|
+
kind: 'ActorPayload',
|
|
630
|
+
data: (fieldValue: $FlowFixMe),
|
|
631
|
+
dataID: nextID,
|
|
632
|
+
path: [...this._path, responseKey],
|
|
633
|
+
typeName,
|
|
634
|
+
variables: this._variables,
|
|
635
|
+
node: field,
|
|
636
|
+
actorIdentifier,
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
527
640
|
_normalizeFlightField(
|
|
528
641
|
parent: NormalizationNode,
|
|
529
642
|
selection: NormalizationFlightField,
|
|
@@ -535,11 +648,37 @@ class RelayResponseNormalizer {
|
|
|
535
648
|
const fieldValue = data[responseKey];
|
|
536
649
|
|
|
537
650
|
if (fieldValue == null) {
|
|
651
|
+
if (fieldValue === undefined) {
|
|
652
|
+
// Flight field may be missing in the response if:
|
|
653
|
+
// - It is inside an abstract type refinement where the concrete type does
|
|
654
|
+
// not conform to the interface/union.
|
|
655
|
+
// However an otherwise-required field may also be missing if the server
|
|
656
|
+
// is configured to skip fields with `null` values, in which case the
|
|
657
|
+
// client is assumed to be correctly configured with
|
|
658
|
+
// treatMissingFieldsAsNull=true.
|
|
659
|
+
if (this._isUnmatchedAbstractType) {
|
|
660
|
+
// Field not expected to exist regardless of whether the server is pruning null
|
|
661
|
+
// fields or not.
|
|
662
|
+
return;
|
|
663
|
+
} else {
|
|
664
|
+
// Not optional and the server is not pruning null fields: field is expected
|
|
665
|
+
// to be present
|
|
666
|
+
invariant(
|
|
667
|
+
this._treatMissingFieldsAsNull,
|
|
668
|
+
'RelayResponseNormalizer: Payload did not contain a value for ' +
|
|
669
|
+
'field `%s: %s`. Check that you are parsing with the same ' +
|
|
670
|
+
'query that was used to fetch the payload.',
|
|
671
|
+
responseKey,
|
|
672
|
+
storageKey,
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
538
676
|
RelayModernRecord.setValue(record, storageKey, null);
|
|
539
677
|
return;
|
|
540
678
|
}
|
|
541
679
|
|
|
542
680
|
const reactFlightPayload = refineToReactFlightPayloadData(fieldValue);
|
|
681
|
+
const reactFlightPayloadDeserializer = this._reactFlightPayloadDeserializer;
|
|
543
682
|
|
|
544
683
|
invariant(
|
|
545
684
|
reactFlightPayload != null,
|
|
@@ -549,10 +688,10 @@ class RelayResponseNormalizer {
|
|
|
549
688
|
fieldValue,
|
|
550
689
|
);
|
|
551
690
|
invariant(
|
|
552
|
-
typeof
|
|
691
|
+
typeof reactFlightPayloadDeserializer === 'function',
|
|
553
692
|
'RelayResponseNormalizer: Expected reactFlightPayloadDeserializer to ' +
|
|
554
693
|
'be a function, got `%s`.',
|
|
555
|
-
|
|
694
|
+
reactFlightPayloadDeserializer,
|
|
556
695
|
);
|
|
557
696
|
|
|
558
697
|
if (reactFlightPayload.errors.length > 0) {
|
|
@@ -573,54 +712,74 @@ class RelayResponseNormalizer {
|
|
|
573
712
|
}
|
|
574
713
|
}
|
|
575
714
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
715
|
+
const reactFlightID = generateClientID(
|
|
716
|
+
RelayModernRecord.getDataID(record),
|
|
717
|
+
getStorageKey(selection, this._variables),
|
|
718
|
+
);
|
|
719
|
+
let reactFlightClientResponseRecord = this._recordSource.get(reactFlightID);
|
|
720
|
+
if (reactFlightClientResponseRecord == null) {
|
|
721
|
+
reactFlightClientResponseRecord = RelayModernRecord.create(
|
|
722
|
+
reactFlightID,
|
|
723
|
+
REACT_FLIGHT_TYPE_NAME,
|
|
724
|
+
);
|
|
725
|
+
this._recordSource.set(reactFlightID, reactFlightClientResponseRecord);
|
|
726
|
+
}
|
|
727
|
+
|
|
581
728
|
if (reactFlightPayload.tree == null) {
|
|
729
|
+
// This typically indicates that a fatal server error prevented rows from
|
|
730
|
+
// being written. When this occurs, we should not continue normalization of
|
|
731
|
+
// the Flight field because the row response is malformed.
|
|
732
|
+
//
|
|
733
|
+
// Receiving empty rows is OK because it can indicate the start of a stream.
|
|
582
734
|
warning(
|
|
583
735
|
false,
|
|
584
736
|
'RelayResponseNormalizer: Expected `tree` not to be null. This ' +
|
|
585
737
|
'typically indicates that a fatal server error prevented any Server ' +
|
|
586
738
|
'Component rows from being written.',
|
|
587
739
|
);
|
|
740
|
+
// We create the flight record with a null value for the tree
|
|
741
|
+
// and empty reachable definitions
|
|
742
|
+
RelayModernRecord.setValue(
|
|
743
|
+
reactFlightClientResponseRecord,
|
|
744
|
+
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
745
|
+
null,
|
|
746
|
+
);
|
|
747
|
+
RelayModernRecord.setValue(
|
|
748
|
+
reactFlightClientResponseRecord,
|
|
749
|
+
REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
|
|
750
|
+
[],
|
|
751
|
+
);
|
|
752
|
+
RelayModernRecord.setLinkedRecordID(record, storageKey, reactFlightID);
|
|
588
753
|
return;
|
|
589
754
|
}
|
|
590
755
|
|
|
591
756
|
// We store the deserialized reactFlightClientResponse in a separate
|
|
592
757
|
// record and link it to the parent record. This is so we can GC the Flight
|
|
593
758
|
// tree later even if the parent record is still reachable.
|
|
594
|
-
const reactFlightClientResponse =
|
|
759
|
+
const reactFlightClientResponse = reactFlightPayloadDeserializer(
|
|
595
760
|
reactFlightPayload.tree,
|
|
596
761
|
);
|
|
597
|
-
|
|
598
|
-
RelayModernRecord.getDataID(record),
|
|
599
|
-
getStorageKey(selection, this._variables),
|
|
600
|
-
);
|
|
601
|
-
let reactFlightClientResponseRecord = this._recordSource.get(reactFlightID);
|
|
602
|
-
if (reactFlightClientResponseRecord == null) {
|
|
603
|
-
reactFlightClientResponseRecord = RelayModernRecord.create(
|
|
604
|
-
reactFlightID,
|
|
605
|
-
REACT_FLIGHT_TYPE_NAME,
|
|
606
|
-
);
|
|
607
|
-
this._recordSource.set(reactFlightID, reactFlightClientResponseRecord);
|
|
608
|
-
}
|
|
762
|
+
|
|
609
763
|
RelayModernRecord.setValue(
|
|
610
764
|
reactFlightClientResponseRecord,
|
|
611
765
|
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
612
766
|
reactFlightClientResponse,
|
|
613
767
|
);
|
|
614
|
-
|
|
768
|
+
|
|
769
|
+
const reachableExecutableDefinitions: Array<ReactFlightReachableExecutableDefinitions> =
|
|
770
|
+
[];
|
|
615
771
|
for (const query of reactFlightPayload.queries) {
|
|
616
772
|
if (query.response.data != null) {
|
|
617
|
-
this.
|
|
773
|
+
this._followupPayloads.push({
|
|
774
|
+
kind: 'ModuleImportPayload',
|
|
775
|
+
args: null,
|
|
618
776
|
data: query.response.data,
|
|
619
777
|
dataID: ROOT_ID,
|
|
620
778
|
operationReference: query.module,
|
|
621
779
|
path: [],
|
|
622
780
|
typeName: ROOT_TYPE,
|
|
623
781
|
variables: query.variables,
|
|
782
|
+
actorIdentifier: this._actorIdentifier,
|
|
624
783
|
});
|
|
625
784
|
}
|
|
626
785
|
reachableExecutableDefinitions.push({
|
|
@@ -630,13 +789,16 @@ class RelayResponseNormalizer {
|
|
|
630
789
|
}
|
|
631
790
|
for (const fragment of reactFlightPayload.fragments) {
|
|
632
791
|
if (fragment.response.data != null) {
|
|
633
|
-
this.
|
|
792
|
+
this._followupPayloads.push({
|
|
793
|
+
kind: 'ModuleImportPayload',
|
|
794
|
+
args: null,
|
|
634
795
|
data: fragment.response.data,
|
|
635
796
|
dataID: fragment.__id,
|
|
636
797
|
operationReference: fragment.module,
|
|
637
798
|
path: [],
|
|
638
799
|
typeName: fragment.__typename,
|
|
639
800
|
variables: fragment.variables,
|
|
801
|
+
actorIdentifier: this._actorIdentifier,
|
|
640
802
|
});
|
|
641
803
|
}
|
|
642
804
|
reachableExecutableDefinitions.push({
|
|
@@ -853,9 +1015,6 @@ class RelayResponseNormalizer {
|
|
|
853
1015
|
}
|
|
854
1016
|
}
|
|
855
1017
|
|
|
856
|
-
|
|
857
|
-
'RelayResponseNormalizer.normalize',
|
|
1018
|
+
module.exports = {
|
|
858
1019
|
normalize,
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
module.exports = {normalize: instrumentedNormalize};
|
|
1020
|
+
};
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const invariant = require('invariant');
|
|
16
|
-
|
|
17
|
-
const {getType} = require('./RelayModernRecord');
|
|
18
|
-
|
|
19
15
|
import type {ReactFlightPayloadData} from '../network/RelayNetworkTypes';
|
|
20
16
|
import type {ReactFlightClientResponse, Record} from './RelayStoreTypes';
|
|
21
17
|
|
|
18
|
+
const {getType} = require('./RelayModernRecord');
|
|
19
|
+
const invariant = require('invariant');
|
|
20
|
+
|
|
22
21
|
// Reachable (client) executable definitions encountered while server component
|
|
23
22
|
// rendering
|
|
24
23
|
const REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY = 'executableDefinitions';
|
|
@@ -51,13 +50,7 @@ function getReactFlightClientResponse(
|
|
|
51
50
|
'got %s.',
|
|
52
51
|
record,
|
|
53
52
|
);
|
|
54
|
-
|
|
55
|
-
REACT_FLIGHT_TREE_STORAGE_KEY
|
|
56
|
-
]: $FlowFixMe);
|
|
57
|
-
if (response != null) {
|
|
58
|
-
return response;
|
|
59
|
-
}
|
|
60
|
-
return null;
|
|
53
|
+
return (record[REACT_FLIGHT_TREE_STORAGE_KEY]: $FlowFixMe);
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
module.exports = {
|