relay-runtime 10.0.0 → 10.1.2
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 +6 -0
- package/handlers/connection/MutationHandlers.js.flow +121 -3
- package/index.js +1 -1
- package/index.js.flow +16 -1
- package/lib/handlers/RelayDefaultHandlerProvider.js +9 -0
- package/lib/handlers/connection/MutationHandlers.js +147 -14
- package/lib/index.js +7 -0
- package/lib/mutations/RelayDeclarativeMutationConfig.js +5 -7
- package/lib/mutations/commitMutation.js +1 -4
- package/lib/mutations/validateMutation.js +28 -12
- package/lib/network/RelayQueryResponseCache.js +3 -7
- package/lib/query/GraphQLTag.js +2 -1
- package/lib/query/fetchQuery.js +2 -3
- package/lib/query/fetchQueryInternal.js +2 -3
- package/lib/store/DataChecker.js +85 -10
- package/lib/store/RelayConcreteVariables.js +2 -6
- package/lib/store/RelayModernEnvironment.js +81 -72
- package/lib/store/RelayModernFragmentSpecResolver.js +14 -7
- package/lib/store/RelayModernOperationDescriptor.js +6 -5
- package/lib/store/RelayModernQueryExecutor.js +46 -33
- package/lib/store/RelayModernRecord.js +3 -7
- package/lib/store/RelayModernStore.js +45 -143
- package/lib/store/RelayOperationTracker.js +7 -9
- package/lib/store/RelayOptimisticRecordSource.js +2 -6
- package/lib/store/RelayPublishQueue.js +1 -1
- package/lib/store/RelayReader.js +200 -49
- package/lib/store/RelayRecordSourceMapImpl.js +3 -5
- package/lib/store/RelayReferenceMarker.js +87 -5
- package/lib/store/RelayResponseNormalizer.js +123 -54
- package/lib/store/RelayStoreReactFlightUtils.js +47 -0
- package/lib/store/RelayStoreSubscriptions.js +162 -0
- package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +258 -0
- package/lib/store/StoreInspector.js +3 -9
- package/lib/store/createRelayContext.js +5 -0
- package/lib/store/defaultRequiredFieldLogger.js +18 -0
- package/lib/store/normalizeRelayPayload.js +2 -6
- package/lib/subscription/requestSubscription.js +2 -3
- package/lib/util/NormalizationNode.js +1 -5
- package/lib/util/RelayConcreteNode.js +2 -0
- package/lib/util/RelayFeatureFlags.js +6 -2
- package/lib/util/createPayloadFor3DField.js +2 -7
- package/lib/util/getFragmentIdentifier.js +12 -3
- package/lib/util/getOperation.js +33 -0
- package/lib/util/isEmptyObject.js +25 -0
- package/lib/util/recycleNodesInto.js +6 -9
- package/lib/util/reportMissingRequiredFields.js +48 -0
- package/mutations/commitMutation.js.flow +1 -2
- package/mutations/validateMutation.js.flow +34 -5
- package/network/RelayNetworkTypes.js.flow +22 -0
- package/package.json +2 -2
- package/query/GraphQLTag.js.flow +3 -1
- package/query/fetchQuery.js.flow +2 -2
- package/query/fetchQueryInternal.js.flow +0 -5
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/DataChecker.js.flow +68 -2
- package/store/RelayModernEnvironment.js.flow +107 -87
- package/store/RelayModernFragmentSpecResolver.js.flow +13 -1
- package/store/RelayModernOperationDescriptor.js.flow +5 -1
- package/store/RelayModernQueryExecutor.js.flow +47 -23
- package/store/RelayModernStore.js.flow +40 -114
- package/store/RelayPublishQueue.js.flow +1 -1
- package/store/RelayReader.js.flow +184 -27
- package/store/RelayReferenceMarker.js.flow +72 -5
- package/store/RelayResponseNormalizer.js.flow +140 -50
- package/store/RelayStoreReactFlightUtils.js.flow +64 -0
- package/store/RelayStoreSubscriptions.js.flow +168 -0
- package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +259 -0
- package/store/RelayStoreTypes.js.flow +130 -37
- package/store/StoreInspector.js.flow +1 -3
- package/store/createRelayContext.js.flow +3 -0
- package/store/defaultRequiredFieldLogger.js.flow +23 -0
- package/subscription/requestSubscription.js.flow +5 -2
- package/util/NormalizationNode.js.flow +17 -2
- package/util/ReaderNode.js.flow +20 -1
- package/util/RelayConcreteNode.js.flow +6 -0
- package/util/RelayFeatureFlags.js.flow +10 -1
- package/util/getFragmentIdentifier.js.flow +33 -9
- package/util/getOperation.js.flow +40 -0
- package/util/isEmptyObject.js.flow +25 -0
- package/util/recycleNodesInto.js.flow +13 -8
- package/util/reportMissingRequiredFields.js.flow +51 -0
|
@@ -18,10 +18,12 @@ const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
|
18
18
|
const RelayModernRecord = require('./RelayModernRecord');
|
|
19
19
|
const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
|
|
20
20
|
const RelayRecordSourceProxy = require('../mutations/RelayRecordSourceProxy');
|
|
21
|
+
const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
|
|
21
22
|
const RelayStoreUtils = require('./RelayStoreUtils');
|
|
22
23
|
|
|
23
24
|
const cloneRelayHandleSourceField = require('./cloneRelayHandleSourceField');
|
|
24
25
|
const cloneRelayScalarHandleSourceField = require('./cloneRelayScalarHandleSourceField');
|
|
26
|
+
const getOperation = require('../util/getOperation');
|
|
25
27
|
const invariant = require('invariant');
|
|
26
28
|
|
|
27
29
|
const {isClientID} = require('./ClientID');
|
|
@@ -30,6 +32,7 @@ const {generateTypeID} = require('./TypeID');
|
|
|
30
32
|
|
|
31
33
|
import type {
|
|
32
34
|
NormalizationField,
|
|
35
|
+
NormalizationFlightField,
|
|
33
36
|
NormalizationLinkedField,
|
|
34
37
|
NormalizationModuleImport,
|
|
35
38
|
NormalizationNode,
|
|
@@ -43,6 +46,7 @@ import type {
|
|
|
43
46
|
MutableRecordSource,
|
|
44
47
|
NormalizationSelector,
|
|
45
48
|
OperationLoader,
|
|
49
|
+
ReactFlightReachableQuery,
|
|
46
50
|
Record,
|
|
47
51
|
RecordSource,
|
|
48
52
|
} from './RelayStoreTypes';
|
|
@@ -56,6 +60,7 @@ const {
|
|
|
56
60
|
CONDITION,
|
|
57
61
|
CLIENT_EXTENSION,
|
|
58
62
|
DEFER,
|
|
63
|
+
FLIGHT_FIELD,
|
|
59
64
|
FRAGMENT_SPREAD,
|
|
60
65
|
INLINE_FRAGMENT,
|
|
61
66
|
LINKED_FIELD,
|
|
@@ -67,6 +72,7 @@ const {
|
|
|
67
72
|
TYPE_DISCRIMINATOR,
|
|
68
73
|
} = RelayConcreteNode;
|
|
69
74
|
const {
|
|
75
|
+
ROOT_ID,
|
|
70
76
|
getModuleOperationKey,
|
|
71
77
|
getStorageKey,
|
|
72
78
|
getArgumentValues,
|
|
@@ -375,6 +381,7 @@ class DataChecker {
|
|
|
375
381
|
case STREAM:
|
|
376
382
|
this._traverseSelections(selection.selections, dataID);
|
|
377
383
|
break;
|
|
384
|
+
// $FlowFixMe[incompatible-type]
|
|
378
385
|
case FRAGMENT_SPREAD:
|
|
379
386
|
invariant(
|
|
380
387
|
false,
|
|
@@ -409,6 +416,13 @@ class DataChecker {
|
|
|
409
416
|
} // else: if it does or doesn't implement, we don't need to check or skip anything else
|
|
410
417
|
}
|
|
411
418
|
break;
|
|
419
|
+
case FLIGHT_FIELD:
|
|
420
|
+
if (RelayFeatureFlags.ENABLE_REACT_FLIGHT_COMPONENT_FIELD) {
|
|
421
|
+
this._checkFlightField(selection, dataID);
|
|
422
|
+
} else {
|
|
423
|
+
throw new Error('Flight fields are not yet supported.');
|
|
424
|
+
}
|
|
425
|
+
break;
|
|
412
426
|
default:
|
|
413
427
|
(selection: empty);
|
|
414
428
|
invariant(
|
|
@@ -437,8 +451,9 @@ class DataChecker {
|
|
|
437
451
|
}
|
|
438
452
|
return;
|
|
439
453
|
}
|
|
440
|
-
const
|
|
441
|
-
if (
|
|
454
|
+
const normalizationRootNode = operationLoader.get(operationReference);
|
|
455
|
+
if (normalizationRootNode != null) {
|
|
456
|
+
const operation = getOperation(normalizationRootNode);
|
|
442
457
|
this._traverse(operation, dataID);
|
|
443
458
|
} else {
|
|
444
459
|
// If the fragment is not available, we assume that the data cannot have been
|
|
@@ -495,6 +510,57 @@ class DataChecker {
|
|
|
495
510
|
});
|
|
496
511
|
}
|
|
497
512
|
}
|
|
513
|
+
|
|
514
|
+
_checkFlightField(field: NormalizationFlightField, dataID: DataID): void {
|
|
515
|
+
const storageKey = getStorageKey(field, this._variables);
|
|
516
|
+
const linkedID = this._mutator.getLinkedRecordID(dataID, storageKey);
|
|
517
|
+
|
|
518
|
+
if (linkedID == null) {
|
|
519
|
+
if (linkedID === undefined) {
|
|
520
|
+
this._handleMissing();
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const tree = this._mutator.getValue(
|
|
527
|
+
linkedID,
|
|
528
|
+
RelayStoreReactFlightUtils.REACT_FLIGHT_TREE_STORAGE_KEY,
|
|
529
|
+
);
|
|
530
|
+
const reachableQueries = this._mutator.getValue(
|
|
531
|
+
linkedID,
|
|
532
|
+
RelayStoreReactFlightUtils.REACT_FLIGHT_QUERIES_STORAGE_KEY,
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
if (tree == null || !Array.isArray(reachableQueries)) {
|
|
536
|
+
this._handleMissing();
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const operationLoader = this._operationLoader;
|
|
541
|
+
invariant(
|
|
542
|
+
operationLoader !== null,
|
|
543
|
+
'DataChecker: Expected an operationLoader to be configured when using ' +
|
|
544
|
+
'React Flight.',
|
|
545
|
+
);
|
|
546
|
+
// In Flight, the variables that are in scope for reachable queries aren't
|
|
547
|
+
// the same as what's in scope for the outer query.
|
|
548
|
+
const prevVariables = this._variables;
|
|
549
|
+
// $FlowFixMe[incompatible-cast]
|
|
550
|
+
for (const query of (reachableQueries: Array<ReactFlightReachableQuery>)) {
|
|
551
|
+
this._variables = query.variables;
|
|
552
|
+
const normalizationRootNode = operationLoader.get(query.module);
|
|
553
|
+
if (normalizationRootNode != null) {
|
|
554
|
+
const operation = getOperation(normalizationRootNode);
|
|
555
|
+
this._traverseSelections(operation.selections, ROOT_ID);
|
|
556
|
+
} else {
|
|
557
|
+
// If the fragment is not available, we assume that the data cannot have
|
|
558
|
+
// been processed yet and must therefore be missing.
|
|
559
|
+
this._handleMissing();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
this._variables = prevVariables;
|
|
563
|
+
}
|
|
498
564
|
}
|
|
499
565
|
|
|
500
566
|
module.exports = {
|
|
@@ -22,6 +22,7 @@ const RelayPublishQueue = require('./RelayPublishQueue');
|
|
|
22
22
|
const RelayRecordSource = require('./RelayRecordSource');
|
|
23
23
|
|
|
24
24
|
const defaultGetDataID = require('./defaultGetDataID');
|
|
25
|
+
const defaultRequiredFieldLogger = require('./defaultRequiredFieldLogger');
|
|
25
26
|
const generateID = require('../util/generateID');
|
|
26
27
|
const invariant = require('invariant');
|
|
27
28
|
|
|
@@ -29,7 +30,6 @@ import type {HandlerProvider} from '../handlers/RelayDefaultHandlerProvider';
|
|
|
29
30
|
import type {
|
|
30
31
|
GraphQLResponse,
|
|
31
32
|
INetwork,
|
|
32
|
-
LogRequestInfoFunction,
|
|
33
33
|
PayloadData,
|
|
34
34
|
UploadableMap,
|
|
35
35
|
} from '../network/RelayNetworkTypes';
|
|
@@ -48,6 +48,7 @@ import type {
|
|
|
48
48
|
IEnvironment,
|
|
49
49
|
LogFunction,
|
|
50
50
|
MissingFieldHandler,
|
|
51
|
+
RequiredFieldLogger,
|
|
51
52
|
OperationAvailability,
|
|
52
53
|
OperationDescriptor,
|
|
53
54
|
OperationLoader,
|
|
@@ -55,6 +56,7 @@ import type {
|
|
|
55
56
|
OptimisticResponseConfig,
|
|
56
57
|
OptimisticUpdateFunction,
|
|
57
58
|
PublishQueue,
|
|
59
|
+
ReactFlightPayloadDeserializer,
|
|
58
60
|
SelectorStoreUpdater,
|
|
59
61
|
SingularReaderSelector,
|
|
60
62
|
Snapshot,
|
|
@@ -68,6 +70,7 @@ export type EnvironmentConfig = {|
|
|
|
68
70
|
+treatMissingFieldsAsNull?: boolean,
|
|
69
71
|
+log?: ?LogFunction,
|
|
70
72
|
+operationLoader?: ?OperationLoader,
|
|
73
|
+
+reactFlightPayloadDeserializer?: ?ReactFlightPayloadDeserializer,
|
|
71
74
|
+network: INetwork,
|
|
72
75
|
+scheduler?: ?TaskScheduler,
|
|
73
76
|
+store: Store,
|
|
@@ -82,12 +85,14 @@ export type EnvironmentConfig = {|
|
|
|
82
85
|
+UNSTABLE_defaultRenderPolicy?: ?RenderPolicy,
|
|
83
86
|
+options?: mixed,
|
|
84
87
|
+isServer?: boolean,
|
|
88
|
+
+requiredFieldLogger?: ?RequiredFieldLogger,
|
|
85
89
|
|};
|
|
86
90
|
|
|
87
91
|
class RelayModernEnvironment implements IEnvironment {
|
|
88
92
|
__log: LogFunction;
|
|
89
93
|
+_defaultRenderPolicy: RenderPolicy;
|
|
90
94
|
_operationLoader: ?OperationLoader;
|
|
95
|
+
_reactFlightPayloadDeserializer: ?ReactFlightPayloadDeserializer;
|
|
91
96
|
_network: INetwork;
|
|
92
97
|
_publishQueue: PublishQueue;
|
|
93
98
|
_scheduler: ?TaskScheduler;
|
|
@@ -100,6 +105,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
100
105
|
_operationExecutions: Map<string, ActiveState>;
|
|
101
106
|
+options: mixed;
|
|
102
107
|
+_isServer: boolean;
|
|
108
|
+
requiredFieldLogger: RequiredFieldLogger;
|
|
103
109
|
|
|
104
110
|
constructor(config: EnvironmentConfig) {
|
|
105
111
|
this.configName = config.configName;
|
|
@@ -108,6 +114,8 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
108
114
|
: RelayDefaultHandlerProvider;
|
|
109
115
|
this._treatMissingFieldsAsNull = config.treatMissingFieldsAsNull === true;
|
|
110
116
|
const operationLoader = config.operationLoader;
|
|
117
|
+
const reactFlightPayloadDeserializer =
|
|
118
|
+
config.reactFlightPayloadDeserializer;
|
|
111
119
|
if (__DEV__) {
|
|
112
120
|
if (operationLoader != null) {
|
|
113
121
|
invariant(
|
|
@@ -119,8 +127,18 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
119
127
|
operationLoader,
|
|
120
128
|
);
|
|
121
129
|
}
|
|
130
|
+
if (reactFlightPayloadDeserializer != null) {
|
|
131
|
+
invariant(
|
|
132
|
+
typeof reactFlightPayloadDeserializer === 'function',
|
|
133
|
+
'RelayModernEnvironment: Expected `reactFlightPayloadDeserializer` ' +
|
|
134
|
+
' to be a function, got `%s`.',
|
|
135
|
+
reactFlightPayloadDeserializer,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
122
138
|
}
|
|
123
139
|
this.__log = config.log ?? emptyFunction;
|
|
140
|
+
this.requiredFieldLogger =
|
|
141
|
+
config.requiredFieldLogger ?? defaultRequiredFieldLogger;
|
|
124
142
|
this._defaultRenderPolicy =
|
|
125
143
|
config.UNSTABLE_defaultRenderPolicy ??
|
|
126
144
|
RelayFeatureFlags.ENABLE_PARTIAL_RENDERING_DEFAULT === true
|
|
@@ -128,7 +146,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
128
146
|
: 'full';
|
|
129
147
|
this._operationLoader = operationLoader;
|
|
130
148
|
this._operationExecutions = new Map();
|
|
131
|
-
this._network = config.network;
|
|
149
|
+
this._network = this.__wrapNetworkWithLogObserver(config.network);
|
|
132
150
|
this._getDataID = config.UNSTABLE_DO_NOT_USE_getDataID ?? defaultGetDataID;
|
|
133
151
|
this._publishQueue = new RelayPublishQueue(
|
|
134
152
|
config.store,
|
|
@@ -140,7 +158,8 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
140
158
|
this.options = config.options;
|
|
141
159
|
this._isServer = config.isServer ?? false;
|
|
142
160
|
|
|
143
|
-
(this: any).__setNet = newNet =>
|
|
161
|
+
(this: any).__setNet = newNet =>
|
|
162
|
+
(this._network = this.__wrapNetworkWithLogObserver(newNet));
|
|
144
163
|
|
|
145
164
|
if (__DEV__) {
|
|
146
165
|
const {inspect} = require('./StoreInspector');
|
|
@@ -162,6 +181,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
162
181
|
this._missingFieldHandlers = config.missingFieldHandlers;
|
|
163
182
|
this._operationTracker =
|
|
164
183
|
config.operationTracker ?? new RelayOperationTracker();
|
|
184
|
+
this._reactFlightPayloadDeserializer = reactFlightPayloadDeserializer;
|
|
165
185
|
}
|
|
166
186
|
|
|
167
187
|
getStore(): Store {
|
|
@@ -226,6 +246,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
226
246
|
operationLoader: this._operationLoader,
|
|
227
247
|
optimisticConfig,
|
|
228
248
|
publishQueue: this._publishQueue,
|
|
249
|
+
reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
|
|
229
250
|
scheduler: this._scheduler,
|
|
230
251
|
sink,
|
|
231
252
|
source,
|
|
@@ -263,6 +284,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
263
284
|
operationLoader: this._operationLoader,
|
|
264
285
|
optimisticConfig: null,
|
|
265
286
|
publishQueue: this._publishQueue,
|
|
287
|
+
reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
|
|
266
288
|
scheduler: this._scheduler,
|
|
267
289
|
sink,
|
|
268
290
|
source: RelayObservable.from({
|
|
@@ -339,34 +361,25 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
339
361
|
*/
|
|
340
362
|
execute({
|
|
341
363
|
operation,
|
|
342
|
-
cacheConfig,
|
|
343
364
|
updater,
|
|
344
|
-
}: {
|
|
365
|
+
}: {|
|
|
345
366
|
operation: OperationDescriptor,
|
|
346
|
-
cacheConfig?: ?CacheConfig,
|
|
347
367
|
updater?: ?SelectorStoreUpdater,
|
|
348
|
-
|
|
349
|
-
}): RelayObservable<GraphQLResponse> {
|
|
350
|
-
const [logObserver, logRequestInfo] = this.__createLogObserver(
|
|
351
|
-
operation.request.node.params,
|
|
352
|
-
operation.request.variables,
|
|
353
|
-
);
|
|
368
|
+
|}): RelayObservable<GraphQLResponse> {
|
|
354
369
|
return RelayObservable.create(sink => {
|
|
355
|
-
const source = this._network
|
|
356
|
-
.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
logRequestInfo,
|
|
362
|
-
)
|
|
363
|
-
.do(logObserver);
|
|
370
|
+
const source = this._network.execute(
|
|
371
|
+
operation.request.node.params,
|
|
372
|
+
operation.request.variables,
|
|
373
|
+
operation.request.cacheConfig || {},
|
|
374
|
+
null,
|
|
375
|
+
);
|
|
364
376
|
const executor = RelayModernQueryExecutor.execute({
|
|
365
377
|
operation,
|
|
366
378
|
operationExecutions: this._operationExecutions,
|
|
367
379
|
operationLoader: this._operationLoader,
|
|
368
380
|
optimisticConfig: null,
|
|
369
381
|
publishQueue: this._publishQueue,
|
|
382
|
+
reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
|
|
370
383
|
scheduler: this._scheduler,
|
|
371
384
|
sink,
|
|
372
385
|
source,
|
|
@@ -391,24 +404,18 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
391
404
|
* environment.executeMutation({...}).subscribe({...}).
|
|
392
405
|
*/
|
|
393
406
|
executeMutation({
|
|
394
|
-
cacheConfig,
|
|
395
407
|
operation,
|
|
396
408
|
optimisticResponse,
|
|
397
409
|
optimisticUpdater,
|
|
398
410
|
updater,
|
|
399
411
|
uploadables,
|
|
400
412
|
}: {|
|
|
401
|
-
cacheConfig?: ?CacheConfig,
|
|
402
413
|
operation: OperationDescriptor,
|
|
403
414
|
optimisticUpdater?: ?SelectorStoreUpdater,
|
|
404
415
|
optimisticResponse?: ?Object,
|
|
405
416
|
updater?: ?SelectorStoreUpdater,
|
|
406
417
|
uploadables?: ?UploadableMap,
|
|
407
418
|
|}): RelayObservable<GraphQLResponse> {
|
|
408
|
-
const [logObserver, logRequestInfo] = this.__createLogObserver(
|
|
409
|
-
operation.request.node.params,
|
|
410
|
-
operation.request.variables,
|
|
411
|
-
);
|
|
412
419
|
return RelayObservable.create(sink => {
|
|
413
420
|
let optimisticConfig;
|
|
414
421
|
if (optimisticResponse || optimisticUpdater) {
|
|
@@ -418,24 +425,22 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
418
425
|
updater: optimisticUpdater,
|
|
419
426
|
};
|
|
420
427
|
}
|
|
421
|
-
const source = this._network
|
|
422
|
-
.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
logRequestInfo,
|
|
431
|
-
)
|
|
432
|
-
.do(logObserver);
|
|
428
|
+
const source = this._network.execute(
|
|
429
|
+
operation.request.node.params,
|
|
430
|
+
operation.request.variables,
|
|
431
|
+
{
|
|
432
|
+
...operation.request.cacheConfig,
|
|
433
|
+
force: true,
|
|
434
|
+
},
|
|
435
|
+
uploadables,
|
|
436
|
+
);
|
|
433
437
|
const executor = RelayModernQueryExecutor.execute({
|
|
434
438
|
operation,
|
|
435
439
|
operationExecutions: this._operationExecutions,
|
|
436
440
|
operationLoader: this._operationLoader,
|
|
437
441
|
optimisticConfig,
|
|
438
442
|
publishQueue: this._publishQueue,
|
|
443
|
+
reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
|
|
439
444
|
scheduler: this._scheduler,
|
|
440
445
|
sink,
|
|
441
446
|
source,
|
|
@@ -473,6 +478,7 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
473
478
|
operationTracker: this._operationTracker,
|
|
474
479
|
optimisticConfig: null,
|
|
475
480
|
publishQueue: this._publishQueue,
|
|
481
|
+
reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
|
|
476
482
|
scheduler: this._scheduler,
|
|
477
483
|
sink,
|
|
478
484
|
source,
|
|
@@ -488,56 +494,70 @@ class RelayModernEnvironment implements IEnvironment {
|
|
|
488
494
|
return `RelayModernEnvironment(${this.configName ?? ''})`;
|
|
489
495
|
}
|
|
490
496
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Wraps the network with logging to ensure that network requests are
|
|
499
|
+
* always logged. Relying on each network callsite to be wrapped is
|
|
500
|
+
* untenable and will eventually lead to holes in the logging.
|
|
501
|
+
*/
|
|
502
|
+
__wrapNetworkWithLogObserver(network: INetwork): INetwork {
|
|
503
|
+
const that = this;
|
|
504
|
+
return {
|
|
505
|
+
execute(
|
|
506
|
+
params: RequestParameters,
|
|
507
|
+
variables: Variables,
|
|
508
|
+
cacheConfig: CacheConfig,
|
|
509
|
+
uploadables?: ?UploadableMap,
|
|
510
|
+
): RelayObservable<GraphQLResponse> {
|
|
511
|
+
const transactionID = generateID();
|
|
512
|
+
const log = that.__log;
|
|
513
|
+
const logObserver = {
|
|
514
|
+
start: subscription => {
|
|
515
|
+
log({
|
|
516
|
+
name: 'network.start',
|
|
517
|
+
transactionID,
|
|
518
|
+
params,
|
|
519
|
+
variables,
|
|
520
|
+
});
|
|
521
|
+
},
|
|
522
|
+
next: response => {
|
|
523
|
+
log({
|
|
524
|
+
name: 'network.next',
|
|
525
|
+
transactionID,
|
|
526
|
+
response,
|
|
527
|
+
});
|
|
528
|
+
},
|
|
529
|
+
error: error => {
|
|
530
|
+
log({
|
|
531
|
+
name: 'network.error',
|
|
532
|
+
transactionID,
|
|
533
|
+
error,
|
|
534
|
+
});
|
|
535
|
+
},
|
|
536
|
+
complete: () => {
|
|
537
|
+
log({
|
|
538
|
+
name: 'network.complete',
|
|
539
|
+
transactionID,
|
|
540
|
+
});
|
|
541
|
+
},
|
|
542
|
+
unsubscribe: () => {
|
|
543
|
+
log({
|
|
544
|
+
name: 'network.unsubscribe',
|
|
545
|
+
transactionID,
|
|
546
|
+
});
|
|
547
|
+
},
|
|
548
|
+
};
|
|
549
|
+
const logRequestInfo = info => {
|
|
550
|
+
log({
|
|
551
|
+
name: 'network.info',
|
|
552
|
+
transactionID,
|
|
553
|
+
info,
|
|
554
|
+
});
|
|
555
|
+
};
|
|
556
|
+
return network
|
|
557
|
+
.execute(params, variables, cacheConfig, uploadables, logRequestInfo)
|
|
558
|
+
.do(logObserver);
|
|
531
559
|
},
|
|
532
560
|
};
|
|
533
|
-
const logRequestInfo = info => {
|
|
534
|
-
log({
|
|
535
|
-
name: 'execute.info',
|
|
536
|
-
transactionID,
|
|
537
|
-
info,
|
|
538
|
-
});
|
|
539
|
-
};
|
|
540
|
-
return [logObserver, logRequestInfo];
|
|
541
561
|
}
|
|
542
562
|
}
|
|
543
563
|
|
|
@@ -17,6 +17,7 @@ const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
|
17
17
|
const areEqual = require('areEqual');
|
|
18
18
|
const invariant = require('invariant');
|
|
19
19
|
const isScalarAndEqual = require('../util/isScalarAndEqual');
|
|
20
|
+
const reportMissingRequiredFields = require('../util/reportMissingRequiredFields');
|
|
20
21
|
const warning = require('warning');
|
|
21
22
|
|
|
22
23
|
const {getPromiseForActiveRequest} = require('../query/fetchQueryInternal');
|
|
@@ -34,6 +35,7 @@ import type {
|
|
|
34
35
|
FragmentMap,
|
|
35
36
|
FragmentSpecResolver,
|
|
36
37
|
FragmentSpecResults,
|
|
38
|
+
MissingRequiredFields,
|
|
37
39
|
PluralReaderSelector,
|
|
38
40
|
RelayContext,
|
|
39
41
|
SelectorData,
|
|
@@ -216,6 +218,7 @@ class SelectorResolver {
|
|
|
216
218
|
_data: ?SelectorData;
|
|
217
219
|
_environment: IEnvironment;
|
|
218
220
|
_isMissingData: boolean;
|
|
221
|
+
_missingRequiredFields: ?MissingRequiredFields;
|
|
219
222
|
_selector: SingularReaderSelector;
|
|
220
223
|
_subscription: ?Disposable;
|
|
221
224
|
|
|
@@ -228,6 +231,7 @@ class SelectorResolver {
|
|
|
228
231
|
this._callback = callback;
|
|
229
232
|
this._data = snapshot.data;
|
|
230
233
|
this._isMissingData = snapshot.isMissingData;
|
|
234
|
+
this._missingRequiredFields = snapshot.missingRequiredFields;
|
|
231
235
|
this._environment = environment;
|
|
232
236
|
this._selector = selector;
|
|
233
237
|
this._subscription = environment.subscribe(snapshot, this._onChange);
|
|
@@ -282,6 +286,12 @@ class SelectorResolver {
|
|
|
282
286
|
throw promise;
|
|
283
287
|
}
|
|
284
288
|
}
|
|
289
|
+
if (this._missingRequiredFields != null) {
|
|
290
|
+
reportMissingRequiredFields(
|
|
291
|
+
this._environment,
|
|
292
|
+
this._missingRequiredFields,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
285
295
|
return this._data;
|
|
286
296
|
}
|
|
287
297
|
|
|
@@ -296,6 +306,7 @@ class SelectorResolver {
|
|
|
296
306
|
const snapshot = this._environment.lookup(selector);
|
|
297
307
|
this._data = snapshot.data;
|
|
298
308
|
this._isMissingData = snapshot.isMissingData;
|
|
309
|
+
this._missingRequiredFields = snapshot.missingRequiredFields;
|
|
299
310
|
this._selector = selector;
|
|
300
311
|
this._subscription = this._environment.subscribe(snapshot, this._onChange);
|
|
301
312
|
}
|
|
@@ -314,7 +325,7 @@ class SelectorResolver {
|
|
|
314
325
|
// NOTE: We manually create the request descriptor here instead of
|
|
315
326
|
// calling createOperationDescriptor() because we want to set a
|
|
316
327
|
// descriptor with *unaltered* variables as the fragment owner.
|
|
317
|
-
// This is a hack that allows us to preserve
|
|
328
|
+
// This is a hack that allows us to preserve existing (broken)
|
|
318
329
|
// behavior of RelayModern containers while using fragment ownership
|
|
319
330
|
// to propagate variables instead of Context.
|
|
320
331
|
// For more details, see the summary of D13999308
|
|
@@ -331,6 +342,7 @@ class SelectorResolver {
|
|
|
331
342
|
_onChange = (snapshot: Snapshot): void => {
|
|
332
343
|
this._data = snapshot.data;
|
|
333
344
|
this._isMissingData = snapshot.isMissingData;
|
|
345
|
+
this._missingRequiredFields = snapshot.missingRequiredFields;
|
|
334
346
|
this._callback();
|
|
335
347
|
};
|
|
336
348
|
}
|
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
const {ROOT_ID} = require('./RelayStoreUtils');
|
|
24
24
|
|
|
25
25
|
import type {ConcreteRequest} from '../util/RelayConcreteNode';
|
|
26
|
-
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
26
|
+
import type {CacheConfig, DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
27
27
|
import type {OperationDescriptor, RequestDescriptor} from './RelayStoreTypes';
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -35,6 +35,7 @@ import type {OperationDescriptor, RequestDescriptor} from './RelayStoreTypes';
|
|
|
35
35
|
function createOperationDescriptor(
|
|
36
36
|
request: ConcreteRequest,
|
|
37
37
|
variables: Variables,
|
|
38
|
+
cacheConfig?: ?CacheConfig,
|
|
38
39
|
dataID?: DataID = ROOT_ID,
|
|
39
40
|
): OperationDescriptor {
|
|
40
41
|
const operation = request.operation;
|
|
@@ -42,6 +43,7 @@ function createOperationDescriptor(
|
|
|
42
43
|
const requestDescriptor = createRequestDescriptor(
|
|
43
44
|
request,
|
|
44
45
|
operationVariables,
|
|
46
|
+
cacheConfig,
|
|
45
47
|
);
|
|
46
48
|
const operationDescriptor = {
|
|
47
49
|
fragment: createReaderSelector(
|
|
@@ -68,11 +70,13 @@ function createOperationDescriptor(
|
|
|
68
70
|
function createRequestDescriptor(
|
|
69
71
|
request: ConcreteRequest,
|
|
70
72
|
variables: Variables,
|
|
73
|
+
cacheConfig?: ?CacheConfig,
|
|
71
74
|
): RequestDescriptor {
|
|
72
75
|
const requestDescriptor = {
|
|
73
76
|
identifier: getRequestIdentifier(request.params, variables),
|
|
74
77
|
node: request,
|
|
75
78
|
variables: variables,
|
|
79
|
+
cacheConfig: cacheConfig,
|
|
76
80
|
};
|
|
77
81
|
if (__DEV__) {
|
|
78
82
|
deepFreeze(variables);
|