relay-runtime 11.0.0 → 13.0.0-rc.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/handlers/RelayDefaultHandlerProvider.js.flow +2 -2
- package/handlers/connection/ConnectionHandler.js.flow +8 -10
- package/handlers/connection/MutationHandlers.js.flow +31 -7
- package/index.js +1 -1
- package/index.js.flow +60 -36
- package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
- package/lib/handlers/connection/ConnectionHandler.js +8 -8
- package/lib/handlers/connection/MutationHandlers.js +61 -5
- 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 +12 -5
- package/lib/network/ConvertToExecuteFunction.js +2 -1
- package/lib/network/RelayNetwork.js +3 -2
- package/lib/network/RelayQueryResponseCache.js +21 -4
- 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 +141 -60
- package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +532 -195
- package/lib/store/RelayConcreteVariables.js +24 -4
- package/lib/store/RelayModernEnvironment.js +175 -234
- 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 +58 -29
- package/lib/store/RelayOperationTracker.js +34 -24
- package/lib/store/RelayPublishQueue.js +41 -13
- package/lib/store/RelayReader.js +287 -46
- package/lib/store/RelayRecordSource.js +87 -3
- package/lib/store/RelayReferenceMarker.js +55 -31
- package/lib/store/RelayResponseNormalizer.js +250 -108
- package/lib/store/RelayStoreReactFlightUtils.js +8 -12
- package/lib/store/RelayStoreSubscriptions.js +14 -9
- package/lib/store/RelayStoreUtils.js +11 -5
- 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/defaultGetDataID.js +3 -1
- package/lib/store/readInlineData.js +6 -2
- package/lib/subscription/requestSubscription.js +35 -9
- package/lib/util/RelayConcreteNode.js +4 -0
- package/lib/util/RelayFeatureFlags.js +11 -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/deepFreeze.js +1 -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 +28 -16
- package/network/ConvertToExecuteFunction.js.flow +2 -2
- package/network/RelayNetwork.js.flow +4 -5
- package/network/RelayNetworkTypes.js.flow +17 -8
- package/network/RelayObservable.js.flow +1 -1
- package/network/RelayQueryResponseCache.js.flow +34 -20
- 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 +162 -67
- package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +616 -283
- package/store/RelayConcreteVariables.js.flow +27 -5
- package/store/RelayModernEnvironment.js.flow +176 -235
- 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 +72 -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 -72
- package/store/RelayRecordSource.js.flow +72 -6
- package/store/RelayReferenceMarker.js.flow +60 -33
- package/store/RelayResponseNormalizer.js.flow +288 -102
- package/store/RelayStoreReactFlightUtils.js.flow +9 -13
- package/store/RelayStoreSubscriptions.js.flow +19 -11
- package/store/RelayStoreTypes.js.flow +210 -44
- package/store/RelayStoreUtils.js.flow +25 -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/defaultGetDataID.js.flow +3 -1
- package/store/normalizeRelayPayload.js.flow +6 -7
- package/store/readInlineData.js.flow +7 -8
- package/subscription/requestSubscription.js.flow +54 -27
- package/util/NormalizationNode.js.flow +16 -3
- package/util/ReaderNode.js.flow +38 -2
- package/util/RelayConcreteNode.js.flow +4 -0
- package/util/RelayFeatureFlags.js.flow +24 -8
- package/util/RelayProfiler.js.flow +22 -194
- package/util/RelayReplaySubject.js.flow +9 -9
- package/util/RelayRuntimeTypes.js.flow +73 -4
- package/util/StringInterner.js.flow +69 -0
- package/util/createPayloadFor3DField.js.flow +3 -3
- package/util/deepFreeze.js.flow +2 -1
- 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 +2 -1
- 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,17 +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,
|
|
47
|
+
CLIENT_COMPONENT,
|
|
25
48
|
CLIENT_EXTENSION,
|
|
49
|
+
CONDITION,
|
|
26
50
|
DEFER,
|
|
27
51
|
FLIGHT_FIELD,
|
|
28
52
|
FRAGMENT_SPREAD,
|
|
@@ -35,52 +59,34 @@ const {
|
|
|
35
59
|
STREAM,
|
|
36
60
|
TYPE_DISCRIMINATOR,
|
|
37
61
|
} = require('../util/RelayConcreteNode');
|
|
62
|
+
const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
38
63
|
const {generateClientID, isClientID} = require('./ClientID');
|
|
64
|
+
const {getLocalVariables} = require('./RelayConcreteVariables');
|
|
65
|
+
const RelayModernRecord = require('./RelayModernRecord');
|
|
39
66
|
const {createNormalizationSelector} = require('./RelayModernSelector');
|
|
40
67
|
const {
|
|
41
|
-
|
|
42
|
-
REACT_FLIGHT_QUERIES_STORAGE_KEY,
|
|
68
|
+
REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
|
|
43
69
|
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
44
70
|
REACT_FLIGHT_TYPE_NAME,
|
|
71
|
+
refineToReactFlightPayloadData,
|
|
45
72
|
} = require('./RelayStoreReactFlightUtils');
|
|
46
73
|
const {
|
|
74
|
+
ROOT_ID,
|
|
75
|
+
ROOT_TYPE,
|
|
76
|
+
TYPENAME_KEY,
|
|
47
77
|
getArgumentValues,
|
|
48
78
|
getHandleStorageKey,
|
|
49
79
|
getModuleComponentKey,
|
|
50
80
|
getModuleOperationKey,
|
|
51
81
|
getStorageKey,
|
|
52
|
-
TYPENAME_KEY,
|
|
53
|
-
ROOT_ID,
|
|
54
|
-
ROOT_TYPE,
|
|
55
82
|
} = require('./RelayStoreUtils');
|
|
56
|
-
const {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
NormalizationDefer,
|
|
61
|
-
NormalizationFlightField,
|
|
62
|
-
NormalizationLinkedField,
|
|
63
|
-
NormalizationModuleImport,
|
|
64
|
-
NormalizationNode,
|
|
65
|
-
NormalizationScalarField,
|
|
66
|
-
NormalizationStream,
|
|
67
|
-
} from '../util/NormalizationNode';
|
|
68
|
-
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
69
|
-
import type {
|
|
70
|
-
HandleFieldPayload,
|
|
71
|
-
IncrementalDataPlaceholder,
|
|
72
|
-
ModuleImportPayload,
|
|
73
|
-
MutableRecordSource,
|
|
74
|
-
NormalizationSelector,
|
|
75
|
-
ReactFlightReachableQuery,
|
|
76
|
-
ReactFlightPayloadDeserializer,
|
|
77
|
-
ReactFlightServerErrorHandler,
|
|
78
|
-
Record,
|
|
79
|
-
RelayResponsePayload,
|
|
80
|
-
} 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');
|
|
81
87
|
|
|
82
88
|
export type GetDataID = (
|
|
83
|
-
fieldValue: {[string]: mixed
|
|
89
|
+
fieldValue: interface {[string]: mixed},
|
|
84
90
|
typeName: string,
|
|
85
91
|
) => mixed;
|
|
86
92
|
|
|
@@ -90,6 +96,8 @@ export type NormalizationOptions = {|
|
|
|
90
96
|
+path?: $ReadOnlyArray<string>,
|
|
91
97
|
+reactFlightPayloadDeserializer?: ?ReactFlightPayloadDeserializer,
|
|
92
98
|
+reactFlightServerErrorHandler?: ?ReactFlightServerErrorHandler,
|
|
99
|
+
+shouldProcessClientComponents?: ?boolean,
|
|
100
|
+
+actorIdentifier?: ?ActorIdentifier,
|
|
93
101
|
|};
|
|
94
102
|
|
|
95
103
|
/**
|
|
@@ -117,37 +125,41 @@ function normalize(
|
|
|
117
125
|
* Helper for handling payloads.
|
|
118
126
|
*/
|
|
119
127
|
class RelayResponseNormalizer {
|
|
128
|
+
_actorIdentifier: ?ActorIdentifier;
|
|
120
129
|
_getDataId: GetDataID;
|
|
121
130
|
_handleFieldPayloads: Array<HandleFieldPayload>;
|
|
122
131
|
_treatMissingFieldsAsNull: boolean;
|
|
123
132
|
_incrementalPlaceholders: Array<IncrementalDataPlaceholder>;
|
|
124
133
|
_isClientExtension: boolean;
|
|
125
134
|
_isUnmatchedAbstractType: boolean;
|
|
126
|
-
|
|
135
|
+
_followupPayloads: Array<FollowupPayload>;
|
|
127
136
|
_path: Array<string>;
|
|
128
137
|
_recordSource: MutableRecordSource;
|
|
129
138
|
_variables: Variables;
|
|
130
139
|
_reactFlightPayloadDeserializer: ?ReactFlightPayloadDeserializer;
|
|
131
140
|
_reactFlightServerErrorHandler: ?ReactFlightServerErrorHandler;
|
|
141
|
+
_shouldProcessClientComponents: ?boolean;
|
|
132
142
|
|
|
133
143
|
constructor(
|
|
134
144
|
recordSource: MutableRecordSource,
|
|
135
145
|
variables: Variables,
|
|
136
146
|
options: NormalizationOptions,
|
|
137
147
|
) {
|
|
148
|
+
this._actorIdentifier = options.actorIdentifier;
|
|
138
149
|
this._getDataId = options.getDataID;
|
|
139
150
|
this._handleFieldPayloads = [];
|
|
140
151
|
this._treatMissingFieldsAsNull = options.treatMissingFieldsAsNull;
|
|
141
152
|
this._incrementalPlaceholders = [];
|
|
142
153
|
this._isClientExtension = false;
|
|
143
154
|
this._isUnmatchedAbstractType = false;
|
|
144
|
-
this.
|
|
155
|
+
this._followupPayloads = [];
|
|
145
156
|
this._path = options.path ? [...options.path] : [];
|
|
146
157
|
this._recordSource = recordSource;
|
|
147
158
|
this._variables = variables;
|
|
148
159
|
this._reactFlightPayloadDeserializer =
|
|
149
160
|
options.reactFlightPayloadDeserializer;
|
|
150
161
|
this._reactFlightServerErrorHandler = options.reactFlightServerErrorHandler;
|
|
162
|
+
this._shouldProcessClientComponents = options.shouldProcessClientComponents;
|
|
151
163
|
}
|
|
152
164
|
|
|
153
165
|
normalizeResponse(
|
|
@@ -166,7 +178,7 @@ class RelayResponseNormalizer {
|
|
|
166
178
|
errors: null,
|
|
167
179
|
fieldPayloads: this._handleFieldPayloads,
|
|
168
180
|
incrementalPlaceholders: this._incrementalPlaceholders,
|
|
169
|
-
|
|
181
|
+
followupPayloads: this._followupPayloads,
|
|
170
182
|
source: this._recordSource,
|
|
171
183
|
isFinal: false,
|
|
172
184
|
};
|
|
@@ -204,13 +216,22 @@ class RelayResponseNormalizer {
|
|
|
204
216
|
this._normalizeField(node, selection, record, data);
|
|
205
217
|
break;
|
|
206
218
|
case CONDITION:
|
|
207
|
-
const conditionValue =
|
|
219
|
+
const conditionValue = Boolean(
|
|
220
|
+
this._getVariableValue(selection.condition),
|
|
221
|
+
);
|
|
208
222
|
if (conditionValue === selection.passingValue) {
|
|
209
223
|
this._traverseSelections(selection, record, data);
|
|
210
224
|
}
|
|
211
225
|
break;
|
|
212
226
|
case FRAGMENT_SPREAD: {
|
|
227
|
+
const prevVariables = this._variables;
|
|
228
|
+
this._variables = getLocalVariables(
|
|
229
|
+
this._variables,
|
|
230
|
+
selection.fragment.argumentDefinitions,
|
|
231
|
+
selection.args,
|
|
232
|
+
);
|
|
213
233
|
this._traverseSelections(selection.fragment, record, data);
|
|
234
|
+
this._variables = prevVariables;
|
|
214
235
|
break;
|
|
215
236
|
}
|
|
216
237
|
case INLINE_FRAGMENT: {
|
|
@@ -220,7 +241,7 @@ class RelayResponseNormalizer {
|
|
|
220
241
|
if (typeName === selection.type) {
|
|
221
242
|
this._traverseSelections(selection, record, data);
|
|
222
243
|
}
|
|
223
|
-
} else
|
|
244
|
+
} else {
|
|
224
245
|
const implementsInterface = data.hasOwnProperty(abstractKey);
|
|
225
246
|
const typeName = RelayModernRecord.getType(record);
|
|
226
247
|
const typeID = generateTypeID(typeName);
|
|
@@ -237,36 +258,24 @@ class RelayResponseNormalizer {
|
|
|
237
258
|
if (implementsInterface) {
|
|
238
259
|
this._traverseSelections(selection, record, data);
|
|
239
260
|
}
|
|
240
|
-
} else {
|
|
241
|
-
// legacy behavior for abstract refinements: always normalize even
|
|
242
|
-
// if the type doesn't conform, but track if the type matches or not
|
|
243
|
-
// for determining whether response fields are expected to be present
|
|
244
|
-
const implementsInterface = data.hasOwnProperty(abstractKey);
|
|
245
|
-
const parentIsUnmatchedAbstractType = this._isUnmatchedAbstractType;
|
|
246
|
-
this._isUnmatchedAbstractType =
|
|
247
|
-
this._isUnmatchedAbstractType || !implementsInterface;
|
|
248
|
-
this._traverseSelections(selection, record, data);
|
|
249
|
-
this._isUnmatchedAbstractType = parentIsUnmatchedAbstractType;
|
|
250
261
|
}
|
|
251
262
|
break;
|
|
252
263
|
}
|
|
253
264
|
case TYPE_DISCRIMINATOR: {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
this._recordSource.set(typeID, typeRecord);
|
|
263
|
-
}
|
|
264
|
-
RelayModernRecord.setValue(
|
|
265
|
-
typeRecord,
|
|
266
|
-
abstractKey,
|
|
267
|
-
implementsInterface,
|
|
268
|
-
);
|
|
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);
|
|
269
273
|
}
|
|
274
|
+
RelayModernRecord.setValue(
|
|
275
|
+
typeRecord,
|
|
276
|
+
abstractKey,
|
|
277
|
+
implementsInterface,
|
|
278
|
+
);
|
|
270
279
|
break;
|
|
271
280
|
}
|
|
272
281
|
case LINKED_HANDLE:
|
|
@@ -277,13 +286,17 @@ class RelayResponseNormalizer {
|
|
|
277
286
|
const fieldKey = getStorageKey(selection, this._variables);
|
|
278
287
|
const handleKey = getHandleStorageKey(selection, this._variables);
|
|
279
288
|
this._handleFieldPayloads.push({
|
|
289
|
+
/* $FlowFixMe[class-object-subtyping] added when improving typing
|
|
290
|
+
* for this parameters */
|
|
280
291
|
args,
|
|
281
292
|
dataID: RelayModernRecord.getDataID(record),
|
|
282
293
|
fieldKey,
|
|
283
294
|
handle: selection.handle,
|
|
284
295
|
handleKey,
|
|
285
296
|
handleArgs: selection.handleArgs
|
|
286
|
-
?
|
|
297
|
+
? /* $FlowFixMe[class-object-subtyping] added when improving typing
|
|
298
|
+
* for this parameters */
|
|
299
|
+
getArgumentValues(selection.handleArgs, this._variables)
|
|
287
300
|
: {},
|
|
288
301
|
});
|
|
289
302
|
break;
|
|
@@ -302,6 +315,12 @@ class RelayResponseNormalizer {
|
|
|
302
315
|
this._traverseSelections(selection, record, data);
|
|
303
316
|
this._isClientExtension = isClientExtension;
|
|
304
317
|
break;
|
|
318
|
+
case CLIENT_COMPONENT:
|
|
319
|
+
if (this._shouldProcessClientComponents === false) {
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
this._traverseSelections(selection.fragment, record, data);
|
|
323
|
+
break;
|
|
305
324
|
case FLIGHT_FIELD:
|
|
306
325
|
if (RelayFeatureFlags.ENABLE_REACT_FLIGHT_COMPONENT_FIELD) {
|
|
307
326
|
this._normalizeFlightField(node, selection, record, data);
|
|
@@ -309,6 +328,9 @@ class RelayResponseNormalizer {
|
|
|
309
328
|
throw new Error('Flight fields are not yet supported.');
|
|
310
329
|
}
|
|
311
330
|
break;
|
|
331
|
+
case ACTOR_CHANGE:
|
|
332
|
+
this._normalizeActorChange(node, selection, record, data);
|
|
333
|
+
break;
|
|
312
334
|
default:
|
|
313
335
|
(selection: empty);
|
|
314
336
|
invariant(
|
|
@@ -352,6 +374,7 @@ class RelayResponseNormalizer {
|
|
|
352
374
|
this._variables,
|
|
353
375
|
),
|
|
354
376
|
typeName: RelayModernRecord.getType(record),
|
|
377
|
+
actorIdentifier: this._actorIdentifier,
|
|
355
378
|
});
|
|
356
379
|
}
|
|
357
380
|
}
|
|
@@ -384,6 +407,7 @@ class RelayResponseNormalizer {
|
|
|
384
407
|
parentID: RelayModernRecord.getDataID(record),
|
|
385
408
|
node: stream,
|
|
386
409
|
variables: this._variables,
|
|
410
|
+
actorIdentifier: this._actorIdentifier,
|
|
387
411
|
});
|
|
388
412
|
}
|
|
389
413
|
}
|
|
@@ -414,13 +438,16 @@ class RelayResponseNormalizer {
|
|
|
414
438
|
operationReference ?? null,
|
|
415
439
|
);
|
|
416
440
|
if (operationReference != null) {
|
|
417
|
-
this.
|
|
441
|
+
this._followupPayloads.push({
|
|
442
|
+
kind: 'ModuleImportPayload',
|
|
443
|
+
args: moduleImport.args,
|
|
418
444
|
data,
|
|
419
445
|
dataID: RelayModernRecord.getDataID(record),
|
|
420
446
|
operationReference,
|
|
421
447
|
path: [...this._path],
|
|
422
448
|
typeName,
|
|
423
449
|
variables: this._variables,
|
|
450
|
+
actorIdentifier: this._actorIdentifier,
|
|
424
451
|
});
|
|
425
452
|
}
|
|
426
453
|
}
|
|
@@ -478,7 +505,11 @@ class RelayResponseNormalizer {
|
|
|
478
505
|
this._validateConflictingFieldsWithIdenticalId(
|
|
479
506
|
record,
|
|
480
507
|
storageKey,
|
|
481
|
-
|
|
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,
|
|
482
513
|
);
|
|
483
514
|
}
|
|
484
515
|
}
|
|
@@ -513,6 +544,99 @@ class RelayResponseNormalizer {
|
|
|
513
544
|
}
|
|
514
545
|
}
|
|
515
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
|
+
|
|
516
640
|
_normalizeFlightField(
|
|
517
641
|
parent: NormalizationNode,
|
|
518
642
|
selection: NormalizationFlightField,
|
|
@@ -524,11 +648,37 @@ class RelayResponseNormalizer {
|
|
|
524
648
|
const fieldValue = data[responseKey];
|
|
525
649
|
|
|
526
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
|
+
}
|
|
527
676
|
RelayModernRecord.setValue(record, storageKey, null);
|
|
528
677
|
return;
|
|
529
678
|
}
|
|
530
679
|
|
|
531
680
|
const reactFlightPayload = refineToReactFlightPayloadData(fieldValue);
|
|
681
|
+
const reactFlightPayloadDeserializer = this._reactFlightPayloadDeserializer;
|
|
532
682
|
|
|
533
683
|
invariant(
|
|
534
684
|
reactFlightPayload != null,
|
|
@@ -538,10 +688,10 @@ class RelayResponseNormalizer {
|
|
|
538
688
|
fieldValue,
|
|
539
689
|
);
|
|
540
690
|
invariant(
|
|
541
|
-
typeof
|
|
691
|
+
typeof reactFlightPayloadDeserializer === 'function',
|
|
542
692
|
'RelayResponseNormalizer: Expected reactFlightPayloadDeserializer to ' +
|
|
543
693
|
'be a function, got `%s`.',
|
|
544
|
-
|
|
694
|
+
reactFlightPayloadDeserializer,
|
|
545
695
|
);
|
|
546
696
|
|
|
547
697
|
if (reactFlightPayload.errors.length > 0) {
|
|
@@ -562,65 +712,104 @@ class RelayResponseNormalizer {
|
|
|
562
712
|
}
|
|
563
713
|
}
|
|
564
714
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
+
|
|
570
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.
|
|
571
734
|
warning(
|
|
572
735
|
false,
|
|
573
736
|
'RelayResponseNormalizer: Expected `tree` not to be null. This ' +
|
|
574
737
|
'typically indicates that a fatal server error prevented any Server ' +
|
|
575
738
|
'Component rows from being written.',
|
|
576
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);
|
|
577
753
|
return;
|
|
578
754
|
}
|
|
579
755
|
|
|
580
756
|
// We store the deserialized reactFlightClientResponse in a separate
|
|
581
757
|
// record and link it to the parent record. This is so we can GC the Flight
|
|
582
758
|
// tree later even if the parent record is still reachable.
|
|
583
|
-
const reactFlightClientResponse =
|
|
759
|
+
const reactFlightClientResponse = reactFlightPayloadDeserializer(
|
|
584
760
|
reactFlightPayload.tree,
|
|
585
761
|
);
|
|
586
|
-
|
|
587
|
-
RelayModernRecord.getDataID(record),
|
|
588
|
-
getStorageKey(selection, this._variables),
|
|
589
|
-
);
|
|
590
|
-
let reactFlightClientResponseRecord = this._recordSource.get(reactFlightID);
|
|
591
|
-
if (reactFlightClientResponseRecord == null) {
|
|
592
|
-
reactFlightClientResponseRecord = RelayModernRecord.create(
|
|
593
|
-
reactFlightID,
|
|
594
|
-
REACT_FLIGHT_TYPE_NAME,
|
|
595
|
-
);
|
|
596
|
-
this._recordSource.set(reactFlightID, reactFlightClientResponseRecord);
|
|
597
|
-
}
|
|
762
|
+
|
|
598
763
|
RelayModernRecord.setValue(
|
|
599
764
|
reactFlightClientResponseRecord,
|
|
600
765
|
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
601
766
|
reactFlightClientResponse,
|
|
602
767
|
);
|
|
603
|
-
|
|
768
|
+
|
|
769
|
+
const reachableExecutableDefinitions: Array<ReactFlightReachableExecutableDefinitions> =
|
|
770
|
+
[];
|
|
604
771
|
for (const query of reactFlightPayload.queries) {
|
|
605
772
|
if (query.response.data != null) {
|
|
606
|
-
this.
|
|
773
|
+
this._followupPayloads.push({
|
|
774
|
+
kind: 'ModuleImportPayload',
|
|
775
|
+
args: null,
|
|
607
776
|
data: query.response.data,
|
|
608
777
|
dataID: ROOT_ID,
|
|
609
778
|
operationReference: query.module,
|
|
610
779
|
path: [],
|
|
611
780
|
typeName: ROOT_TYPE,
|
|
612
781
|
variables: query.variables,
|
|
782
|
+
actorIdentifier: this._actorIdentifier,
|
|
613
783
|
});
|
|
614
784
|
}
|
|
615
|
-
|
|
785
|
+
reachableExecutableDefinitions.push({
|
|
616
786
|
module: query.module,
|
|
617
787
|
variables: query.variables,
|
|
618
788
|
});
|
|
619
789
|
}
|
|
790
|
+
for (const fragment of reactFlightPayload.fragments) {
|
|
791
|
+
if (fragment.response.data != null) {
|
|
792
|
+
this._followupPayloads.push({
|
|
793
|
+
kind: 'ModuleImportPayload',
|
|
794
|
+
args: null,
|
|
795
|
+
data: fragment.response.data,
|
|
796
|
+
dataID: fragment.__id,
|
|
797
|
+
operationReference: fragment.module,
|
|
798
|
+
path: [],
|
|
799
|
+
typeName: fragment.__typename,
|
|
800
|
+
variables: fragment.variables,
|
|
801
|
+
actorIdentifier: this._actorIdentifier,
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
reachableExecutableDefinitions.push({
|
|
805
|
+
module: fragment.module,
|
|
806
|
+
variables: fragment.variables,
|
|
807
|
+
});
|
|
808
|
+
}
|
|
620
809
|
RelayModernRecord.setValue(
|
|
621
810
|
reactFlightClientResponseRecord,
|
|
622
|
-
|
|
623
|
-
|
|
811
|
+
REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
|
|
812
|
+
reachableExecutableDefinitions,
|
|
624
813
|
);
|
|
625
814
|
RelayModernRecord.setLinkedRecordID(record, storageKey, reactFlightID);
|
|
626
815
|
}
|
|
@@ -826,9 +1015,6 @@ class RelayResponseNormalizer {
|
|
|
826
1015
|
}
|
|
827
1016
|
}
|
|
828
1017
|
|
|
829
|
-
|
|
830
|
-
'RelayResponseNormalizer.normalize',
|
|
1018
|
+
module.exports = {
|
|
831
1019
|
normalize,
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
module.exports = {normalize: instrumentedNormalize};
|
|
1020
|
+
};
|
|
@@ -12,14 +12,15 @@
|
|
|
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
|
|
|
22
|
-
const
|
|
18
|
+
const {getType} = require('./RelayModernRecord');
|
|
19
|
+
const invariant = require('invariant');
|
|
20
|
+
|
|
21
|
+
// Reachable (client) executable definitions encountered while server component
|
|
22
|
+
// rendering
|
|
23
|
+
const REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY = 'executableDefinitions';
|
|
23
24
|
const REACT_FLIGHT_TREE_STORAGE_KEY = 'tree';
|
|
24
25
|
const REACT_FLIGHT_TYPE_NAME = 'ReactFlightComponent';
|
|
25
26
|
|
|
@@ -32,6 +33,7 @@ function refineToReactFlightPayloadData(
|
|
|
32
33
|
typeof payload.status !== 'string' ||
|
|
33
34
|
(!Array.isArray(payload.tree) && payload.tree !== null) ||
|
|
34
35
|
!Array.isArray(payload.queries) ||
|
|
36
|
+
!Array.isArray(payload.fragments) ||
|
|
35
37
|
!Array.isArray(payload.errors)
|
|
36
38
|
) {
|
|
37
39
|
return null;
|
|
@@ -48,17 +50,11 @@ function getReactFlightClientResponse(
|
|
|
48
50
|
'got %s.',
|
|
49
51
|
record,
|
|
50
52
|
);
|
|
51
|
-
|
|
52
|
-
REACT_FLIGHT_TREE_STORAGE_KEY
|
|
53
|
-
]: $FlowFixMe);
|
|
54
|
-
if (response != null) {
|
|
55
|
-
return response;
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
53
|
+
return (record[REACT_FLIGHT_TREE_STORAGE_KEY]: $FlowFixMe);
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
module.exports = {
|
|
61
|
-
|
|
57
|
+
REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
|
|
62
58
|
REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
63
59
|
REACT_FLIGHT_TYPE_NAME,
|
|
64
60
|
getReactFlightClientResponse,
|