relay-runtime 11.0.0-rc.0 → 12.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/handlers/connection/ConnectionHandler.js.flow +7 -0
- package/handlers/connection/MutationHandlers.js.flow +28 -0
- package/index.js +1 -1
- package/index.js.flow +20 -3
- package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
- package/lib/handlers/connection/ConnectionHandler.js +12 -6
- package/lib/handlers/connection/MutationHandlers.js +67 -8
- package/lib/index.js +15 -0
- package/lib/multi-actor-environment/ActorIdentifier.js +33 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +148 -0
- package/lib/multi-actor-environment/ActorUtils.js +27 -0
- package/lib/multi-actor-environment/MultiActorEnvironment.js +406 -0
- package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
- package/lib/multi-actor-environment/index.js +21 -0
- package/lib/mutations/RelayRecordProxy.js +1 -1
- package/lib/mutations/RelayRecordSourceMutator.js +1 -1
- package/lib/mutations/RelayRecordSourceProxy.js +1 -1
- package/lib/mutations/RelayRecordSourceSelectorProxy.js +7 -2
- package/lib/mutations/applyOptimisticMutation.js +1 -1
- package/lib/mutations/commitMutation.js +5 -2
- package/lib/mutations/validateMutation.js +39 -17
- package/lib/network/RelayNetwork.js +1 -1
- package/lib/network/RelayObservable.js +3 -1
- package/lib/network/RelayQueryResponseCache.js +20 -3
- package/lib/network/wrapNetworkWithLogObserver.js +78 -0
- package/lib/query/GraphQLTag.js +1 -1
- package/lib/query/fetchQuery.js +1 -1
- package/lib/query/fetchQueryInternal.js +1 -1
- package/lib/store/DataChecker.js +132 -50
- package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +524 -187
- package/lib/store/RelayConcreteVariables.js +29 -4
- package/lib/store/RelayModernEnvironment.js +137 -220
- package/lib/store/RelayModernFragmentSpecResolver.js +49 -23
- package/lib/store/RelayModernRecord.js +36 -2
- package/lib/store/RelayModernSelector.js +1 -1
- package/lib/store/RelayModernStore.js +53 -22
- package/lib/store/RelayOperationTracker.js +34 -24
- package/lib/store/RelayPublishQueue.js +30 -8
- package/lib/store/RelayReader.js +177 -29
- package/lib/store/RelayRecordSource.js +87 -3
- package/lib/store/RelayReferenceMarker.js +53 -28
- package/lib/store/RelayResponseNormalizer.js +247 -108
- package/lib/store/RelayStoreReactFlightUtils.js +7 -11
- package/lib/store/RelayStoreSubscriptions.js +8 -5
- package/lib/store/RelayStoreUtils.js +10 -4
- package/lib/store/ResolverCache.js +213 -0
- package/lib/store/ResolverFragments.js +57 -0
- package/lib/store/cloneRelayHandleSourceField.js +1 -1
- package/lib/store/cloneRelayScalarHandleSourceField.js +1 -1
- package/lib/store/createRelayContext.js +2 -2
- package/lib/store/defaultGetDataID.js +3 -1
- package/lib/store/readInlineData.js +1 -1
- package/lib/subscription/requestSubscription.js +32 -6
- package/lib/util/RelayConcreteNode.js +3 -0
- package/lib/util/RelayFeatureFlags.js +5 -4
- package/lib/util/RelayProfiler.js +17 -187
- package/lib/util/RelayReplaySubject.js +22 -7
- package/lib/util/deepFreeze.js +1 -0
- package/lib/util/getPaginationMetadata.js +41 -0
- package/lib/util/getPaginationVariables.js +67 -0
- package/lib/util/getPendingOperationsForFragment.js +55 -0
- package/lib/util/getRefetchMetadata.js +36 -0
- package/lib/util/getRelayHandleKey.js +1 -1
- package/lib/util/getRequestIdentifier.js +1 -1
- 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 +217 -0
- package/multi-actor-environment/ActorUtils.js.flow +33 -0
- package/multi-actor-environment/MultiActorEnvironment.js.flow +485 -0
- package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +245 -0
- package/multi-actor-environment/index.js.flow +27 -0
- package/mutations/RelayRecordSourceSelectorProxy.js.flow +7 -2
- package/mutations/commitMutation.js.flow +3 -1
- package/mutations/validateMutation.js.flow +42 -16
- package/network/RelayNetworkTypes.js.flow +17 -8
- package/network/RelayObservable.js.flow +2 -0
- package/network/RelayQueryResponseCache.js.flow +31 -17
- package/network/wrapNetworkWithLogObserver.js.flow +99 -0
- package/package.json +3 -2
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/ClientID.js.flow +5 -1
- package/store/DataChecker.js.flow +148 -44
- package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +578 -237
- package/store/RelayConcreteVariables.js.flow +31 -1
- package/store/RelayModernEnvironment.js.flow +132 -220
- package/store/RelayModernFragmentSpecResolver.js.flow +40 -14
- package/store/RelayModernOperationDescriptor.js.flow +9 -3
- package/store/RelayModernRecord.js.flow +49 -0
- package/store/RelayModernStore.js.flow +57 -17
- package/store/RelayOperationTracker.js.flow +56 -34
- package/store/RelayPublishQueue.js.flow +37 -11
- package/store/RelayReader.js.flow +186 -27
- package/store/RelayRecordSource.js.flow +72 -6
- package/store/RelayReferenceMarker.js.flow +51 -21
- package/store/RelayResponseNormalizer.js.flow +251 -67
- package/store/RelayStoreReactFlightUtils.js.flow +6 -9
- package/store/RelayStoreSubscriptions.js.flow +10 -3
- package/store/RelayStoreTypes.js.flow +144 -21
- package/store/RelayStoreUtils.js.flow +19 -4
- package/store/ResolverCache.js.flow +247 -0
- package/store/ResolverFragments.js.flow +128 -0
- package/store/createRelayContext.js.flow +1 -1
- package/store/defaultGetDataID.js.flow +3 -1
- package/subscription/requestSubscription.js.flow +43 -8
- package/util/NormalizationNode.js.flow +16 -3
- package/util/ReaderNode.js.flow +29 -2
- package/util/RelayConcreteNode.js.flow +3 -0
- package/util/RelayFeatureFlags.js.flow +10 -6
- package/util/RelayProfiler.js.flow +22 -194
- package/util/RelayReplaySubject.js.flow +7 -6
- package/util/RelayRuntimeTypes.js.flow +4 -2
- package/util/deepFreeze.js.flow +2 -1
- package/util/getPaginationMetadata.js.flow +74 -0
- package/util/getPaginationVariables.js.flow +112 -0
- package/util/getPendingOperationsForFragment.js.flow +62 -0
- package/util/getRefetchMetadata.js.flow +80 -0
- package/util/getValueAtPath.js.flow +46 -0
- package/util/isEmptyObject.js.flow +2 -1
- package/util/registerEnvironmentWithDevTools.js.flow +33 -0
- 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
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+relay
|
|
8
|
+
* @flow strict-local
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
import type {PayloadData, GraphQLResponse} from '../network/RelayNetworkTypes';
|
|
15
|
+
import type RelayObservable from '../network/RelayObservable';
|
|
16
|
+
import type RelayPublishQueue from '../store/RelayPublishQueue';
|
|
17
|
+
import type {
|
|
18
|
+
OperationAvailability,
|
|
19
|
+
OperationDescriptor,
|
|
20
|
+
OptimisticResponseConfig,
|
|
21
|
+
OptimisticUpdateFunction,
|
|
22
|
+
SelectorStoreUpdater,
|
|
23
|
+
SingularReaderSelector,
|
|
24
|
+
Snapshot,
|
|
25
|
+
StoreUpdater,
|
|
26
|
+
IEnvironment,
|
|
27
|
+
ExecuteMutationConfig,
|
|
28
|
+
RecordSourceProxy,
|
|
29
|
+
} from '../store/RelayStoreTypes';
|
|
30
|
+
import type {Disposable} from '../util/RelayRuntimeTypes';
|
|
31
|
+
import type {ActorIdentifier} from './ActorIdentifier';
|
|
32
|
+
|
|
33
|
+
export type MultiActorStoreUpdater = (
|
|
34
|
+
actorIdentifier: ActorIdentifier,
|
|
35
|
+
environment: IActorEnvironment,
|
|
36
|
+
store: RecordSourceProxy,
|
|
37
|
+
) => void;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Interface of actor specific sub-environment
|
|
41
|
+
*/
|
|
42
|
+
export interface IActorEnvironment extends IEnvironment {
|
|
43
|
+
/**
|
|
44
|
+
* Reference to the main MultiActorEnvironment that handles
|
|
45
|
+
* the network execution/and responsible for network integration
|
|
46
|
+
*/
|
|
47
|
+
+multiActorEnvironment: IMultiActorEnvironment;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Identifier of the actor for the current active environment
|
|
51
|
+
*/
|
|
52
|
+
+actorIdentifier: ActorIdentifier;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* TODO: this needs to move the the MultiActorEnvironment with different API.
|
|
56
|
+
*/
|
|
57
|
+
getPublishQueue(): RelayPublishQueue;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Optional. A human-readable identifier of the environment.
|
|
61
|
+
* This value should be visible in the dev tools.
|
|
62
|
+
*/
|
|
63
|
+
+configName: ?string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Interface for the main (or parent) multi-actor environment that contains
|
|
68
|
+
* the map of individual actor-specific sub-environments. These sub-environments
|
|
69
|
+
* implement the Relay IEnvironment interface.
|
|
70
|
+
*/
|
|
71
|
+
export interface IMultiActorEnvironment {
|
|
72
|
+
/**
|
|
73
|
+
* A factory of actor-specific environments.
|
|
74
|
+
*/
|
|
75
|
+
forActor(actorIdentifier: ActorIdentifier): IActorEnvironment;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Determine if the operation can be resolved with data in the store (i.e. no
|
|
79
|
+
* fields are missing).
|
|
80
|
+
*
|
|
81
|
+
* Note that this operation effectively "executes" the selector against the
|
|
82
|
+
* cache and therefore takes time proportional to the size/complexity of the
|
|
83
|
+
* selector.
|
|
84
|
+
*/
|
|
85
|
+
check(
|
|
86
|
+
actorEnvironment: IActorEnvironment,
|
|
87
|
+
operation: OperationDescriptor,
|
|
88
|
+
): OperationAvailability;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Subscribe to changes to the results of a selector. The callback is called
|
|
92
|
+
* when data has been committed to the store that would cause the results of
|
|
93
|
+
* the snapshot's selector to change.
|
|
94
|
+
*/
|
|
95
|
+
subscribe(
|
|
96
|
+
actorEnvironment: IActorEnvironment,
|
|
97
|
+
snapshot: Snapshot,
|
|
98
|
+
callback: (snapshot: Snapshot) => void,
|
|
99
|
+
): Disposable;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Ensure that all the records necessary to fulfill the given selector are
|
|
103
|
+
* retained in-memory. The records will not be eligible for garbage collection
|
|
104
|
+
* until the returned reference is disposed.
|
|
105
|
+
*/
|
|
106
|
+
retain(
|
|
107
|
+
actorEnvironment: IActorEnvironment,
|
|
108
|
+
operation: OperationDescriptor,
|
|
109
|
+
): Disposable;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Apply an optimistic update to the environment. The mutation can be reverted
|
|
113
|
+
* by calling `dispose()` on the returned value.
|
|
114
|
+
*/
|
|
115
|
+
applyUpdate(
|
|
116
|
+
actorEnvironment: IActorEnvironment,
|
|
117
|
+
optimisticUpdate: OptimisticUpdateFunction,
|
|
118
|
+
): Disposable;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Revert updates for the `update` function.
|
|
122
|
+
*/
|
|
123
|
+
revertUpdate(
|
|
124
|
+
actorEnvironment: IActorEnvironment,
|
|
125
|
+
update: OptimisticUpdateFunction,
|
|
126
|
+
): void;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Revert updates for the `update` function, and apply the `replacement` update.
|
|
130
|
+
*/
|
|
131
|
+
replaceUpdate(
|
|
132
|
+
actorEnvironment: IActorEnvironment,
|
|
133
|
+
update: OptimisticUpdateFunction,
|
|
134
|
+
replacement: OptimisticUpdateFunction,
|
|
135
|
+
): void;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Apply an optimistic mutation response and/or updater. The mutation can be
|
|
139
|
+
* reverted by calling `dispose()` on the returned value.
|
|
140
|
+
*/
|
|
141
|
+
applyMutation(
|
|
142
|
+
actorEnvironment: IActorEnvironment,
|
|
143
|
+
optimisticConfig: OptimisticResponseConfig,
|
|
144
|
+
): Disposable;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Commit an updater to the environment. This mutation cannot be reverted and
|
|
148
|
+
* should therefore not be used for optimistic updates. This is mainly
|
|
149
|
+
* intended for updating fields from client schema extensions.
|
|
150
|
+
*/
|
|
151
|
+
commitUpdate(
|
|
152
|
+
actorEnvironment: IActorEnvironment,
|
|
153
|
+
updater: StoreUpdater,
|
|
154
|
+
): void;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Commit store updates for each actor-specific environment known to MultiActorEnvironment
|
|
158
|
+
*/
|
|
159
|
+
commitMultiActorUpdate(updater: MultiActorStoreUpdater): void;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Commit a payload to the environment using the given operation selector.
|
|
163
|
+
*/
|
|
164
|
+
commitPayload(
|
|
165
|
+
actorEnvironment: IActorEnvironment,
|
|
166
|
+
operationDescriptor: OperationDescriptor,
|
|
167
|
+
payload: PayloadData,
|
|
168
|
+
): void;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Read the results of a selector from in-memory records in the store.
|
|
172
|
+
*/
|
|
173
|
+
lookup(
|
|
174
|
+
actorEnvironment: IActorEnvironment,
|
|
175
|
+
selector: SingularReaderSelector,
|
|
176
|
+
): Snapshot;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Send a query to the server with Observer semantics: one or more
|
|
180
|
+
* responses may be returned (via `next`) over time followed by either
|
|
181
|
+
* the request completing (`completed`) or an error (`error`).
|
|
182
|
+
*
|
|
183
|
+
* Networks/servers that support subscriptions may choose to hold the
|
|
184
|
+
* subscription open indefinitely such that `complete` is not called.
|
|
185
|
+
*
|
|
186
|
+
* Note: Observables are lazy, so calling this method will do nothing until
|
|
187
|
+
* the result is subscribed to: environment.execute({...}).subscribe({...}).
|
|
188
|
+
*/
|
|
189
|
+
execute(
|
|
190
|
+
actorEnvironment: IActorEnvironment,
|
|
191
|
+
config: {
|
|
192
|
+
operation: OperationDescriptor,
|
|
193
|
+
updater?: ?SelectorStoreUpdater,
|
|
194
|
+
},
|
|
195
|
+
): RelayObservable<GraphQLResponse>;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Returns an Observable of GraphQLResponse resulting from executing the
|
|
199
|
+
* provided Mutation operation, the result of which is then normalized and
|
|
200
|
+
* committed to the publish queue along with an optional optimistic response
|
|
201
|
+
* or updater.
|
|
202
|
+
*
|
|
203
|
+
* Note: Observables are lazy, so calling this method will do nothing until
|
|
204
|
+
* the result is subscribed to:
|
|
205
|
+
* environment.executeMutation({...}).subscribe({...}).
|
|
206
|
+
*/
|
|
207
|
+
executeMutation(
|
|
208
|
+
actorEnvironment: IActorEnvironment,
|
|
209
|
+
config: ExecuteMutationConfig,
|
|
210
|
+
): RelayObservable<GraphQLResponse>;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Returns an Observable of GraphQLResponse resulting from executing the
|
|
214
|
+
* provided Query or Subscription operation responses, the result of which is
|
|
215
|
+
* then normalized and committed to the publish queue.
|
|
216
|
+
*
|
|
217
|
+
* Note: Observables are lazy, so calling this method will do nothing until
|
|
218
|
+
* the result is subscribed to:
|
|
219
|
+
* environment.executeWithSource({...}).subscribe({...}).
|
|
220
|
+
*/
|
|
221
|
+
executeWithSource(
|
|
222
|
+
actorEnvironment: IActorEnvironment,
|
|
223
|
+
{
|
|
224
|
+
operation: OperationDescriptor,
|
|
225
|
+
source: RelayObservable<GraphQLResponse>,
|
|
226
|
+
},
|
|
227
|
+
): RelayObservable<GraphQLResponse>;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Returns true if a request is currently "active", meaning it's currently
|
|
231
|
+
* actively receiving payloads or downloading modules, and has not received
|
|
232
|
+
* a final payload yet. Note that a request might still be pending (or "in flight")
|
|
233
|
+
* without actively receiving payload, for example a live query or an
|
|
234
|
+
* active GraphQL subscription
|
|
235
|
+
*/
|
|
236
|
+
isRequestActive(
|
|
237
|
+
actorEnvironment: IActorEnvironment,
|
|
238
|
+
requestIdentifier: string,
|
|
239
|
+
): boolean;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Returns `true` if execute in the server environment
|
|
243
|
+
*/
|
|
244
|
+
isServer(): boolean;
|
|
245
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+relay
|
|
8
|
+
* @flow strict-local
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const MultiActorEnvironment = require('./MultiActorEnvironment');
|
|
15
|
+
|
|
16
|
+
const {getActorIdentifier} = require('./ActorIdentifier');
|
|
17
|
+
|
|
18
|
+
export type {ActorIdentifier} from './ActorIdentifier';
|
|
19
|
+
export type {
|
|
20
|
+
IActorEnvironment,
|
|
21
|
+
IMultiActorEnvironment,
|
|
22
|
+
} from './MultiActorEnvironmentTypes';
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
MultiActorEnvironment,
|
|
26
|
+
getActorIdentifier,
|
|
27
|
+
};
|
|
@@ -78,10 +78,15 @@ class RelayRecordSourceSelectorProxy implements RecordSourceSelectorProxy {
|
|
|
78
78
|
fieldName: string,
|
|
79
79
|
plural: boolean,
|
|
80
80
|
): ReaderLinkedField {
|
|
81
|
-
|
|
81
|
+
let field = selector.node.selections.find(
|
|
82
82
|
selection =>
|
|
83
|
-
selection.kind === 'LinkedField' && selection.name === fieldName
|
|
83
|
+
(selection.kind === 'LinkedField' && selection.name === fieldName) ||
|
|
84
|
+
(selection.kind === 'RequiredField' &&
|
|
85
|
+
selection.field.name === fieldName),
|
|
84
86
|
);
|
|
87
|
+
if (field && field.kind === 'RequiredField') {
|
|
88
|
+
field = field.field;
|
|
89
|
+
}
|
|
85
90
|
invariant(
|
|
86
91
|
field && field.kind === 'LinkedField',
|
|
87
92
|
'RelayRecordSourceSelectorProxy#getRootField(): Cannot find root ' +
|
|
@@ -54,7 +54,7 @@ export type DEPRECATED_MutationConfig<T> = {|
|
|
|
54
54
|
|
|
55
55
|
export type MutationParameters = {|
|
|
56
56
|
+response: {...},
|
|
57
|
-
+variables: {
|
|
57
|
+
+variables: interface {},
|
|
58
58
|
+rawResponse?: {...},
|
|
59
59
|
|};
|
|
60
60
|
|
|
@@ -113,6 +113,8 @@ function commitMutation<T: MutationParameters>(
|
|
|
113
113
|
} = config;
|
|
114
114
|
const operation = createOperationDescriptor(
|
|
115
115
|
mutation,
|
|
116
|
+
/* $FlowFixMe[class-object-subtyping] added when improving typing for this
|
|
117
|
+
* parameters */
|
|
116
118
|
variables,
|
|
117
119
|
cacheConfig,
|
|
118
120
|
generateUniqueClientID(),
|
|
@@ -30,8 +30,27 @@ type ValidationContext = {|
|
|
|
30
30
|
|
|
31
31
|
const warning = require('warning');
|
|
32
32
|
|
|
33
|
+
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
33
34
|
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
34
35
|
|
|
36
|
+
const {
|
|
37
|
+
ACTOR_CHANGE,
|
|
38
|
+
CONDITION,
|
|
39
|
+
CLIENT_COMPONENT,
|
|
40
|
+
CLIENT_EXTENSION,
|
|
41
|
+
DEFER,
|
|
42
|
+
FLIGHT_FIELD,
|
|
43
|
+
FRAGMENT_SPREAD,
|
|
44
|
+
INLINE_FRAGMENT,
|
|
45
|
+
LINKED_FIELD,
|
|
46
|
+
LINKED_HANDLE,
|
|
47
|
+
MODULE_IMPORT,
|
|
48
|
+
SCALAR_FIELD,
|
|
49
|
+
SCALAR_HANDLE,
|
|
50
|
+
STREAM,
|
|
51
|
+
TYPE_DISCRIMINATOR,
|
|
52
|
+
} = require('../util/RelayConcreteNode');
|
|
53
|
+
|
|
35
54
|
let validateMutation = () => {};
|
|
36
55
|
if (__DEV__) {
|
|
37
56
|
const addFieldToDiff = (path: string, diff: Object, isScalar) => {
|
|
@@ -96,21 +115,28 @@ if (__DEV__) {
|
|
|
96
115
|
context: ValidationContext,
|
|
97
116
|
) => {
|
|
98
117
|
switch (selection.kind) {
|
|
99
|
-
case
|
|
118
|
+
case CONDITION:
|
|
100
119
|
validateSelections(optimisticResponse, selection.selections, context);
|
|
101
120
|
return;
|
|
102
|
-
case
|
|
121
|
+
case CLIENT_COMPONENT:
|
|
122
|
+
case FRAGMENT_SPREAD:
|
|
103
123
|
validateSelections(
|
|
104
124
|
optimisticResponse,
|
|
105
125
|
selection.fragment.selections,
|
|
106
126
|
context,
|
|
107
127
|
);
|
|
108
128
|
return;
|
|
109
|
-
case
|
|
110
|
-
case
|
|
111
|
-
case
|
|
129
|
+
case SCALAR_FIELD:
|
|
130
|
+
case LINKED_FIELD:
|
|
131
|
+
case FLIGHT_FIELD:
|
|
112
132
|
return validateField(optimisticResponse, selection, context);
|
|
113
|
-
case
|
|
133
|
+
case ACTOR_CHANGE:
|
|
134
|
+
return validateField(
|
|
135
|
+
optimisticResponse,
|
|
136
|
+
selection.linkedField,
|
|
137
|
+
context,
|
|
138
|
+
);
|
|
139
|
+
case INLINE_FRAGMENT:
|
|
114
140
|
const type = selection.type;
|
|
115
141
|
const isConcreteType = selection.abstractKey == null;
|
|
116
142
|
selection.selections.forEach(subselection => {
|
|
@@ -120,18 +146,18 @@ if (__DEV__) {
|
|
|
120
146
|
validateSelection(optimisticResponse, subselection, context);
|
|
121
147
|
});
|
|
122
148
|
return;
|
|
123
|
-
case
|
|
149
|
+
case CLIENT_EXTENSION:
|
|
124
150
|
selection.selections.forEach(subselection => {
|
|
125
151
|
validateSelection(optimisticResponse, subselection, context);
|
|
126
152
|
});
|
|
127
153
|
return;
|
|
128
|
-
case
|
|
154
|
+
case MODULE_IMPORT:
|
|
129
155
|
return validateModuleImport(context);
|
|
130
|
-
case
|
|
131
|
-
case
|
|
132
|
-
case
|
|
133
|
-
case
|
|
134
|
-
case
|
|
156
|
+
case LINKED_HANDLE:
|
|
157
|
+
case SCALAR_HANDLE:
|
|
158
|
+
case DEFER:
|
|
159
|
+
case STREAM:
|
|
160
|
+
case TYPE_DISCRIMINATOR: {
|
|
135
161
|
// TODO(T35864292) - Add missing validations for these types
|
|
136
162
|
return;
|
|
137
163
|
}
|
|
@@ -154,12 +180,12 @@ if (__DEV__) {
|
|
|
154
180
|
const path = `${context.path}.${fieldName}`;
|
|
155
181
|
context.visitedPaths.add(path);
|
|
156
182
|
switch (field.kind) {
|
|
157
|
-
case
|
|
183
|
+
case SCALAR_FIELD:
|
|
158
184
|
if (hasOwnProperty.call(optimisticResponse, fieldName) === false) {
|
|
159
185
|
addFieldToDiff(path, context.missingDiff, true);
|
|
160
186
|
}
|
|
161
187
|
return;
|
|
162
|
-
case
|
|
188
|
+
case LINKED_FIELD:
|
|
163
189
|
const selections = field.selections;
|
|
164
190
|
if (
|
|
165
191
|
optimisticResponse[fieldName] === null ||
|
|
@@ -195,7 +221,7 @@ if (__DEV__) {
|
|
|
195
221
|
return;
|
|
196
222
|
}
|
|
197
223
|
}
|
|
198
|
-
case
|
|
224
|
+
case FLIGHT_FIELD:
|
|
199
225
|
if (
|
|
200
226
|
optimisticResponse[fieldName] === null ||
|
|
201
227
|
(hasOwnProperty.call(optimisticResponse, fieldName) &&
|
|
@@ -20,14 +20,15 @@ import type RelayObservable, {ObservableFromValue} from './RelayObservable';
|
|
|
20
20
|
* An interface for fetching the data for one or more (possibly interdependent)
|
|
21
21
|
* queries.
|
|
22
22
|
*/
|
|
23
|
-
export
|
|
24
|
-
execute: ExecuteFunction
|
|
25
|
-
|
|
23
|
+
export interface INetwork {
|
|
24
|
+
+execute: ExecuteFunction;
|
|
25
|
+
}
|
|
26
|
+
|
|
26
27
|
export type LogRequestInfoFunction = mixed => void;
|
|
27
28
|
|
|
28
|
-
export type PayloadData = {[key: string]: mixed
|
|
29
|
+
export type PayloadData = interface {[key: string]: mixed};
|
|
29
30
|
|
|
30
|
-
export type PayloadError = {
|
|
31
|
+
export type PayloadError = interface {
|
|
31
32
|
message: string,
|
|
32
33
|
locations?: Array<{
|
|
33
34
|
line: number,
|
|
@@ -36,14 +37,13 @@ export type PayloadError = {
|
|
|
36
37
|
}>,
|
|
37
38
|
// Not officially part of the spec, but used at Facebook
|
|
38
39
|
severity?: 'CRITICAL' | 'ERROR' | 'WARNING',
|
|
39
|
-
...
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export type PayloadExtensions = {[key: string]: mixed, ...};
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* The shape of a GraphQL response as dictated by the
|
|
46
|
-
* [spec](https://graphql.
|
|
46
|
+
* [spec](https://spec.graphql.org/June2018/#sec-Response-Format).
|
|
47
47
|
*/
|
|
48
48
|
export type GraphQLResponseWithData = {|
|
|
49
49
|
+data: PayloadData,
|
|
@@ -120,7 +120,7 @@ export type SubscribeFunction = (
|
|
|
120
120
|
) => RelayObservable<GraphQLResponse>;
|
|
121
121
|
|
|
122
122
|
export type Uploadable = File | Blob;
|
|
123
|
-
export type UploadableMap = {[key: string]: Uploadable
|
|
123
|
+
export type UploadableMap = interface {[key: string]: Uploadable};
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* React Flight tree created on the server.
|
|
@@ -132,6 +132,13 @@ export type ReactFlightPayloadQuery = {|
|
|
|
132
132
|
+response: GraphQLSingularResponse,
|
|
133
133
|
+variables: Variables,
|
|
134
134
|
|};
|
|
135
|
+
export type ReactFlightPayloadFragment = {|
|
|
136
|
+
+__id: string,
|
|
137
|
+
+__typename: string,
|
|
138
|
+
+module: mixed,
|
|
139
|
+
+response: GraphQLSingularResponse,
|
|
140
|
+
+variables: Variables,
|
|
141
|
+
|};
|
|
135
142
|
export type ReactFlightServerError = {
|
|
136
143
|
+message: string,
|
|
137
144
|
+stack: string,
|
|
@@ -147,10 +154,12 @@ export type ReactFlightServerError = {
|
|
|
147
154
|
* - queries: an array of queries that the server preloaded for the client.
|
|
148
155
|
* - errors: an array of errors that were encountered while rendering the
|
|
149
156
|
* Server Component.
|
|
157
|
+
* - fragments: an array of fragments that the server preloaded for the client.
|
|
150
158
|
*/
|
|
151
159
|
export type ReactFlightPayloadData = {|
|
|
152
160
|
+status: string,
|
|
153
161
|
+tree: ?Array<ReactFlightServerTree>,
|
|
154
162
|
+queries: Array<ReactFlightPayloadQuery>,
|
|
155
163
|
+errors: Array<ReactFlightServerError>,
|
|
164
|
+
+fragments: Array<ReactFlightPayloadFragment>,
|
|
156
165
|
|};
|
|
@@ -355,11 +355,13 @@ class RelayObservable<+T> implements Subscribable<T> {
|
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
// $FlowFixMe[incompatible-call]
|
|
358
359
|
this.subscribe({
|
|
359
360
|
start,
|
|
360
361
|
next(value) {
|
|
361
362
|
try {
|
|
362
363
|
if (!sink.closed) {
|
|
364
|
+
// $FlowFixMe[incompatible-call]
|
|
363
365
|
RelayObservable.from(fn(value)).subscribe({
|
|
364
366
|
start,
|
|
365
367
|
next: sink.next,
|
|
@@ -16,11 +16,14 @@ const invariant = require('invariant');
|
|
|
16
16
|
const stableCopy = require('../util/stableCopy');
|
|
17
17
|
|
|
18
18
|
import type {Variables} from '../util/RelayRuntimeTypes';
|
|
19
|
-
import type {
|
|
19
|
+
import type {
|
|
20
|
+
GraphQLResponse,
|
|
21
|
+
GraphQLSingularResponse,
|
|
22
|
+
} from './RelayNetworkTypes';
|
|
20
23
|
|
|
21
24
|
type Response = {
|
|
22
25
|
fetchTime: number,
|
|
23
|
-
payload:
|
|
26
|
+
payload: GraphQLResponse,
|
|
24
27
|
...
|
|
25
28
|
};
|
|
26
29
|
|
|
@@ -55,7 +58,7 @@ class RelayQueryResponseCache {
|
|
|
55
58
|
this._responses.clear();
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
get(queryID: string, variables: Variables): ?
|
|
61
|
+
get(queryID: string, variables: Variables): ?GraphQLResponse {
|
|
59
62
|
const cacheKey = getCacheKey(queryID, variables);
|
|
60
63
|
this._responses.forEach((response, key) => {
|
|
61
64
|
if (!isCurrent(response.fetchTime, this._ttl)) {
|
|
@@ -63,22 +66,33 @@ class RelayQueryResponseCache {
|
|
|
63
66
|
}
|
|
64
67
|
});
|
|
65
68
|
const response = this._responses.get(cacheKey);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
if (response == null) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(response.payload)) {
|
|
73
|
+
return response.payload.map(
|
|
74
|
+
payload =>
|
|
75
|
+
// $FlowFixMe[incompatible-cast]
|
|
76
|
+
({
|
|
77
|
+
...payload,
|
|
78
|
+
extensions: {
|
|
79
|
+
...payload.extensions,
|
|
80
|
+
cacheTimestamp: response.fetchTime,
|
|
81
|
+
},
|
|
82
|
+
}: GraphQLSingularResponse),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
// $FlowFixMe[incompatible-cast]
|
|
86
|
+
return ({
|
|
87
|
+
...response.payload,
|
|
88
|
+
extensions: {
|
|
89
|
+
...response.payload.extensions,
|
|
90
|
+
cacheTimestamp: response.fetchTime,
|
|
91
|
+
},
|
|
92
|
+
}: GraphQLSingularResponse);
|
|
75
93
|
}
|
|
76
94
|
|
|
77
|
-
set(
|
|
78
|
-
queryID: string,
|
|
79
|
-
variables: Variables,
|
|
80
|
-
payload: GraphQLSingularResponse,
|
|
81
|
-
): void {
|
|
95
|
+
set(queryID: string, variables: Variables, payload: GraphQLResponse): void {
|
|
82
96
|
const fetchTime = Date.now();
|
|
83
97
|
const cacheKey = getCacheKey(queryID, variables);
|
|
84
98
|
this._responses.delete(cacheKey); // deletion resets key ordering
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// flowlint ambiguous-object-type:error
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const generateID = require('../util/generateID');
|
|
16
|
+
|
|
17
|
+
import type ActorSpecificEnvironment from '../multi-actor-environment/ActorSpecificEnvironment';
|
|
18
|
+
import type RelayModernEnvironment from '../store/RelayModernEnvironment';
|
|
19
|
+
import type {RequestParameters} from '../util/RelayConcreteNode';
|
|
20
|
+
import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
|
|
21
|
+
import type {
|
|
22
|
+
INetwork,
|
|
23
|
+
GraphQLResponse,
|
|
24
|
+
UploadableMap,
|
|
25
|
+
} from './RelayNetworkTypes';
|
|
26
|
+
import type RelayObservable from './RelayObservable';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Wraps the network with logging to ensure that network requests are
|
|
30
|
+
* always logged. Relying on each network callsite to be wrapped is
|
|
31
|
+
* untenable and will eventually lead to holes in the logging.
|
|
32
|
+
* NOTE: This function takes an environment instance, because Relay
|
|
33
|
+
* devtools will mutate the `env.__log` method, and the devtools rely
|
|
34
|
+
* on it to receive network events.
|
|
35
|
+
*/
|
|
36
|
+
function wrapNetworkWithLogObserver(
|
|
37
|
+
env: RelayModernEnvironment | ActorSpecificEnvironment,
|
|
38
|
+
network: INetwork,
|
|
39
|
+
): INetwork {
|
|
40
|
+
return {
|
|
41
|
+
execute(
|
|
42
|
+
params: RequestParameters,
|
|
43
|
+
variables: Variables,
|
|
44
|
+
cacheConfig: CacheConfig,
|
|
45
|
+
uploadables?: ?UploadableMap,
|
|
46
|
+
): RelayObservable<GraphQLResponse> {
|
|
47
|
+
const networkRequestId = generateID();
|
|
48
|
+
const logObserver = {
|
|
49
|
+
start: subscription => {
|
|
50
|
+
env.__log({
|
|
51
|
+
name: 'network.start',
|
|
52
|
+
networkRequestId,
|
|
53
|
+
params,
|
|
54
|
+
variables,
|
|
55
|
+
cacheConfig,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
next: response => {
|
|
59
|
+
env.__log({
|
|
60
|
+
name: 'network.next',
|
|
61
|
+
networkRequestId,
|
|
62
|
+
response,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
error: error => {
|
|
66
|
+
env.__log({
|
|
67
|
+
name: 'network.error',
|
|
68
|
+
networkRequestId,
|
|
69
|
+
error,
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
complete: () => {
|
|
73
|
+
env.__log({
|
|
74
|
+
name: 'network.complete',
|
|
75
|
+
networkRequestId,
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
unsubscribe: () => {
|
|
79
|
+
env.__log({
|
|
80
|
+
name: 'network.unsubscribe',
|
|
81
|
+
networkRequestId,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const logRequestInfo = info => {
|
|
86
|
+
env.__log({
|
|
87
|
+
name: 'network.info',
|
|
88
|
+
networkRequestId,
|
|
89
|
+
info,
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return network
|
|
93
|
+
.execute(params, variables, cacheConfig, uploadables, logRequestInfo)
|
|
94
|
+
.do(logObserver);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = wrapNetworkWithLogObserver;
|