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.
Files changed (82) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +6 -0
  2. package/handlers/connection/MutationHandlers.js.flow +121 -3
  3. package/index.js +1 -1
  4. package/index.js.flow +16 -1
  5. package/lib/handlers/RelayDefaultHandlerProvider.js +9 -0
  6. package/lib/handlers/connection/MutationHandlers.js +147 -14
  7. package/lib/index.js +7 -0
  8. package/lib/mutations/RelayDeclarativeMutationConfig.js +5 -7
  9. package/lib/mutations/commitMutation.js +1 -4
  10. package/lib/mutations/validateMutation.js +28 -12
  11. package/lib/network/RelayQueryResponseCache.js +3 -7
  12. package/lib/query/GraphQLTag.js +2 -1
  13. package/lib/query/fetchQuery.js +2 -3
  14. package/lib/query/fetchQueryInternal.js +2 -3
  15. package/lib/store/DataChecker.js +85 -10
  16. package/lib/store/RelayConcreteVariables.js +2 -6
  17. package/lib/store/RelayModernEnvironment.js +81 -72
  18. package/lib/store/RelayModernFragmentSpecResolver.js +14 -7
  19. package/lib/store/RelayModernOperationDescriptor.js +6 -5
  20. package/lib/store/RelayModernQueryExecutor.js +46 -33
  21. package/lib/store/RelayModernRecord.js +3 -7
  22. package/lib/store/RelayModernStore.js +45 -143
  23. package/lib/store/RelayOperationTracker.js +7 -9
  24. package/lib/store/RelayOptimisticRecordSource.js +2 -6
  25. package/lib/store/RelayPublishQueue.js +1 -1
  26. package/lib/store/RelayReader.js +200 -49
  27. package/lib/store/RelayRecordSourceMapImpl.js +3 -5
  28. package/lib/store/RelayReferenceMarker.js +87 -5
  29. package/lib/store/RelayResponseNormalizer.js +123 -54
  30. package/lib/store/RelayStoreReactFlightUtils.js +47 -0
  31. package/lib/store/RelayStoreSubscriptions.js +162 -0
  32. package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +258 -0
  33. package/lib/store/StoreInspector.js +3 -9
  34. package/lib/store/createRelayContext.js +5 -0
  35. package/lib/store/defaultRequiredFieldLogger.js +18 -0
  36. package/lib/store/normalizeRelayPayload.js +2 -6
  37. package/lib/subscription/requestSubscription.js +2 -3
  38. package/lib/util/NormalizationNode.js +1 -5
  39. package/lib/util/RelayConcreteNode.js +2 -0
  40. package/lib/util/RelayFeatureFlags.js +6 -2
  41. package/lib/util/createPayloadFor3DField.js +2 -7
  42. package/lib/util/getFragmentIdentifier.js +12 -3
  43. package/lib/util/getOperation.js +33 -0
  44. package/lib/util/isEmptyObject.js +25 -0
  45. package/lib/util/recycleNodesInto.js +6 -9
  46. package/lib/util/reportMissingRequiredFields.js +48 -0
  47. package/mutations/commitMutation.js.flow +1 -2
  48. package/mutations/validateMutation.js.flow +34 -5
  49. package/network/RelayNetworkTypes.js.flow +22 -0
  50. package/package.json +2 -2
  51. package/query/GraphQLTag.js.flow +3 -1
  52. package/query/fetchQuery.js.flow +2 -2
  53. package/query/fetchQueryInternal.js.flow +0 -5
  54. package/relay-runtime.js +2 -2
  55. package/relay-runtime.min.js +2 -2
  56. package/store/DataChecker.js.flow +68 -2
  57. package/store/RelayModernEnvironment.js.flow +107 -87
  58. package/store/RelayModernFragmentSpecResolver.js.flow +13 -1
  59. package/store/RelayModernOperationDescriptor.js.flow +5 -1
  60. package/store/RelayModernQueryExecutor.js.flow +47 -23
  61. package/store/RelayModernStore.js.flow +40 -114
  62. package/store/RelayPublishQueue.js.flow +1 -1
  63. package/store/RelayReader.js.flow +184 -27
  64. package/store/RelayReferenceMarker.js.flow +72 -5
  65. package/store/RelayResponseNormalizer.js.flow +140 -50
  66. package/store/RelayStoreReactFlightUtils.js.flow +64 -0
  67. package/store/RelayStoreSubscriptions.js.flow +168 -0
  68. package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +259 -0
  69. package/store/RelayStoreTypes.js.flow +130 -37
  70. package/store/StoreInspector.js.flow +1 -3
  71. package/store/createRelayContext.js.flow +3 -0
  72. package/store/defaultRequiredFieldLogger.js.flow +23 -0
  73. package/subscription/requestSubscription.js.flow +5 -2
  74. package/util/NormalizationNode.js.flow +17 -2
  75. package/util/ReaderNode.js.flow +20 -1
  76. package/util/RelayConcreteNode.js.flow +6 -0
  77. package/util/RelayFeatureFlags.js.flow +10 -1
  78. package/util/getFragmentIdentifier.js.flow +33 -9
  79. package/util/getOperation.js.flow +40 -0
  80. package/util/isEmptyObject.js.flow +25 -0
  81. package/util/recycleNodesInto.js.flow +13 -8
  82. package/util/reportMissingRequiredFields.js.flow +51 -0
@@ -12,6 +12,8 @@
12
12
 
13
13
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
14
14
 
15
+ var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
16
+
15
17
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
16
18
 
17
19
  var RelayFeatureFlags = require('../util/RelayFeatureFlags');
@@ -20,6 +22,8 @@ var RelayModernRecord = require('./RelayModernRecord');
20
22
 
21
23
  var RelayProfiler = require('../util/RelayProfiler');
22
24
 
25
+ var areEqual = require("fbjs/lib/areEqual");
26
+
23
27
  var invariant = require("fbjs/lib/invariant");
24
28
 
25
29
  var warning = require("fbjs/lib/warning");
@@ -28,6 +32,7 @@ var _require = require('../util/RelayConcreteNode'),
28
32
  CONDITION = _require.CONDITION,
29
33
  CLIENT_EXTENSION = _require.CLIENT_EXTENSION,
30
34
  DEFER = _require.DEFER,
35
+ FLIGHT_FIELD = _require.FLIGHT_FIELD,
31
36
  INLINE_FRAGMENT = _require.INLINE_FRAGMENT,
32
37
  LINKED_FIELD = _require.LINKED_FIELD,
33
38
  LINKED_HANDLE = _require.LINKED_HANDLE,
@@ -44,18 +49,25 @@ var _require2 = require('./ClientID'),
44
49
  var _require3 = require('./RelayModernSelector'),
45
50
  createNormalizationSelector = _require3.createNormalizationSelector;
46
51
 
47
- var _require4 = require('./RelayStoreUtils'),
48
- getArgumentValues = _require4.getArgumentValues,
49
- getHandleStorageKey = _require4.getHandleStorageKey,
50
- getModuleComponentKey = _require4.getModuleComponentKey,
51
- getModuleOperationKey = _require4.getModuleOperationKey,
52
- getStorageKey = _require4.getStorageKey,
53
- TYPENAME_KEY = _require4.TYPENAME_KEY,
54
- ROOT_ID = _require4.ROOT_ID;
55
-
56
- var _require5 = require('./TypeID'),
57
- generateTypeID = _require5.generateTypeID,
58
- TYPE_SCHEMA_TYPE = _require5.TYPE_SCHEMA_TYPE;
52
+ var _require4 = require('./RelayStoreReactFlightUtils'),
53
+ refineToReactFlightPayloadData = _require4.refineToReactFlightPayloadData,
54
+ REACT_FLIGHT_QUERIES_STORAGE_KEY = _require4.REACT_FLIGHT_QUERIES_STORAGE_KEY,
55
+ REACT_FLIGHT_TREE_STORAGE_KEY = _require4.REACT_FLIGHT_TREE_STORAGE_KEY,
56
+ REACT_FLIGHT_TYPE_NAME = _require4.REACT_FLIGHT_TYPE_NAME;
57
+
58
+ var _require5 = require('./RelayStoreUtils'),
59
+ getArgumentValues = _require5.getArgumentValues,
60
+ getHandleStorageKey = _require5.getHandleStorageKey,
61
+ getModuleComponentKey = _require5.getModuleComponentKey,
62
+ getModuleOperationKey = _require5.getModuleOperationKey,
63
+ getStorageKey = _require5.getStorageKey,
64
+ TYPENAME_KEY = _require5.TYPENAME_KEY,
65
+ ROOT_ID = _require5.ROOT_ID,
66
+ ROOT_TYPE = _require5.ROOT_TYPE;
67
+
68
+ var _require6 = require('./TypeID'),
69
+ generateTypeID = _require6.generateTypeID,
70
+ TYPE_SCHEMA_TYPE = _require6.TYPE_SCHEMA_TYPE;
59
71
 
60
72
  /**
61
73
  * Normalizes the results of a query and standard GraphQL response, writing the
@@ -87,6 +99,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
87
99
  this._path = options.path ? (0, _toConsumableArray2["default"])(options.path) : [];
88
100
  this._recordSource = recordSource;
89
101
  this._variables = variables;
102
+ this._reactFlightPayloadDeserializer = options.reactFlightPayloadDeserializer;
90
103
  }
91
104
 
92
105
  var _proto = RelayResponseNormalizer.prototype;
@@ -252,6 +265,15 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
252
265
  this._isClientExtension = isClientExtension;
253
266
  break;
254
267
 
268
+ case FLIGHT_FIELD:
269
+ if (RelayFeatureFlags.ENABLE_REACT_FLIGHT_COMPONENT_FIELD) {
270
+ this._normalizeFlightField(node, selection, record, data);
271
+ } else {
272
+ throw new Error('Flight fields are not yet supported.');
273
+ }
274
+
275
+ break;
276
+
255
277
  default:
256
278
  selection;
257
279
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer(): Unexpected ast kind `%s`.', selection.kind) : invariant(false) : void 0;
@@ -366,8 +388,10 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
366
388
  }
367
389
  }
368
390
 
369
- if (selection.kind === SCALAR_FIELD && process.env.NODE_ENV !== "production") {
370
- this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
391
+ if (process.env.NODE_ENV !== "production") {
392
+ if (selection.kind === SCALAR_FIELD) {
393
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
394
+ }
371
395
  }
372
396
 
373
397
  RelayModernRecord.setValue(record, storageKey, null);
@@ -375,7 +399,9 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
375
399
  }
376
400
 
377
401
  if (selection.kind === SCALAR_FIELD) {
378
- this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
402
+ if (process.env.NODE_ENV !== "production") {
403
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
404
+ }
379
405
 
380
406
  RelayModernRecord.setValue(record, storageKey, fieldValue);
381
407
  } else if (selection.kind === LINKED_FIELD) {
@@ -394,20 +420,76 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
394
420
  }
395
421
  };
396
422
 
423
+ _proto._normalizeFlightField = function _normalizeFlightField(parent, selection, record, data) {
424
+ var responseKey = selection.alias || selection.name;
425
+ var storageKey = getStorageKey(selection, this._variables);
426
+ var fieldValue = data[responseKey];
427
+
428
+ if (fieldValue == null) {
429
+ RelayModernRecord.setValue(record, storageKey, null);
430
+ return;
431
+ }
432
+
433
+ var reactFlightPayload = refineToReactFlightPayloadData(fieldValue);
434
+ !(reactFlightPayload != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer(): Expected React Flight payload data ' + 'to be an object with `tree` and `queries` properties, got `%s`.', fieldValue) : invariant(false) : void 0;
435
+ !(typeof this._reactFlightPayloadDeserializer === 'function') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected reactFlightPayloadDeserializer to ' + 'be a function, got `%s`.', this._reactFlightPayloadDeserializer) : invariant(false) : void 0; // We store the deserialized reactFlightClientResponse in a separate
436
+ // record and link it to the parent record. This is so we can GC the Flight
437
+ // tree later even if the parent record is still reachable.
438
+
439
+ var reactFlightClientResponse = this._reactFlightPayloadDeserializer(reactFlightPayload.tree);
440
+
441
+ var reactFlightID = generateClientID(RelayModernRecord.getDataID(record), getStorageKey(selection, this._variables));
442
+
443
+ var reactFlightClientResponseRecord = this._recordSource.get(reactFlightID);
444
+
445
+ if (reactFlightClientResponseRecord == null) {
446
+ reactFlightClientResponseRecord = RelayModernRecord.create(reactFlightID, REACT_FLIGHT_TYPE_NAME);
447
+
448
+ this._recordSource.set(reactFlightID, reactFlightClientResponseRecord);
449
+ }
450
+
451
+ RelayModernRecord.setValue(reactFlightClientResponseRecord, REACT_FLIGHT_TREE_STORAGE_KEY, reactFlightClientResponse);
452
+ var reachableQueries = [];
453
+
454
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(reactFlightPayload.queries),
455
+ _step;
456
+
457
+ try {
458
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
459
+ var query = _step.value;
460
+
461
+ if (query.response.data != null) {
462
+ this._moduleImportPayloads.push({
463
+ data: query.response.data,
464
+ dataID: ROOT_ID,
465
+ operationReference: query.module,
466
+ path: [],
467
+ typeName: ROOT_TYPE,
468
+ variables: query.variables
469
+ });
470
+ }
471
+
472
+ reachableQueries.push({
473
+ module: query.module,
474
+ variables: query.variables
475
+ });
476
+ }
477
+ } catch (err) {
478
+ _iterator.e(err);
479
+ } finally {
480
+ _iterator.f();
481
+ }
482
+
483
+ RelayModernRecord.setValue(reactFlightClientResponseRecord, REACT_FLIGHT_QUERIES_STORAGE_KEY, reachableQueries);
484
+ RelayModernRecord.setLinkedRecordID(record, storageKey, reactFlightID);
485
+ };
486
+
397
487
  _proto._normalizeLink = function _normalizeLink(field, record, storageKey, fieldValue) {
398
488
  var _field$concreteType;
399
489
 
400
490
  !(typeof fieldValue === 'object' && fieldValue) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected data for field `%s` to be an object.', storageKey) : invariant(false) : void 0;
401
- var nextID = this._getDataId(
402
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
403
- * native_fb,oss) This comment suppresses an error found when Flow
404
- * v0.98 was deployed. To see the error delete this comment and run
405
- * Flow. */
406
- fieldValue,
407
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
408
- * native_fb,oss) This comment suppresses an error found when Flow
409
- * v0.98 was deployed. To see the error delete this comment and run
410
- * Flow. */
491
+ var nextID = this._getDataId( // $FlowFixMe[incompatible-variance]
492
+ fieldValue, // $FlowFixMe[incompatible-variance]
411
493
  (_field$concreteType = field.concreteType) !== null && _field$concreteType !== void 0 ? _field$concreteType : this._getRecordType(fieldValue)) || // Reuse previously generated client IDs
412
494
  RelayModernRecord.getLinkedRecordID(record, storageKey) || generateClientID(RelayModernRecord.getDataID(record), storageKey);
413
495
  !(typeof nextID === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected id on field `%s` to be a string.', storageKey) : invariant(false) : void 0;
@@ -421,9 +503,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
421
503
  var nextRecord = this._recordSource.get(nextID);
422
504
 
423
505
  if (!nextRecord) {
424
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
425
- * native_fb,oss) This comment suppresses an error found when Flow v0.98
426
- * was deployed. To see the error delete this comment and run Flow. */
506
+ // $FlowFixMe[incompatible-variance]
427
507
  var _typeName4 = field.concreteType || this._getRecordType(fieldValue);
428
508
 
429
509
  nextRecord = RelayModernRecord.create(nextID, _typeName4);
@@ -431,10 +511,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
431
511
  this._recordSource.set(nextID, nextRecord);
432
512
  } else if (process.env.NODE_ENV !== "production") {
433
513
  this._validateRecordType(nextRecord, field, fieldValue);
434
- }
435
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_native_
436
- * fb,oss) This comment suppresses an error found when Flow v0.98 was
437
- * deployed. To see the error delete this comment and run Flow. */
514
+ } // $FlowFixMe[incompatible-variance]
438
515
 
439
516
 
440
517
  this._traverseSelections(field, nextRecord, fieldValue);
@@ -458,16 +535,8 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
458
535
  _this._path.push(String(nextIndex));
459
536
 
460
537
  !(typeof item === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected elements for field `%s` to be ' + 'objects.', storageKey) : invariant(false) : void 0;
461
- var nextID = _this._getDataId(
462
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
463
- * native_fb,oss) This comment suppresses an error found when Flow
464
- * v0.98 was deployed. To see the error delete this comment and run
465
- * Flow. */
466
- item,
467
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
468
- * native_fb,oss) This comment suppresses an error found when Flow
469
- * v0.98 was deployed. To see the error delete this comment and run
470
- * Flow. */
538
+ var nextID = _this._getDataId( // $FlowFixMe[incompatible-variance]
539
+ item, // $FlowFixMe[incompatible-variance]
471
540
  (_field$concreteType2 = field.concreteType) !== null && _field$concreteType2 !== void 0 ? _field$concreteType2 : _this._getRecordType(item)) || prevIDs && prevIDs[nextIndex] || // Reuse previously generated client IDs:
472
541
  generateClientID(RelayModernRecord.getDataID(record), storageKey, nextIndex);
473
542
  !(typeof nextID === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected id of elements of field `%s` to ' + 'be strings.', storageKey) : invariant(false) : void 0;
@@ -476,10 +545,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
476
545
  var nextRecord = _this._recordSource.get(nextID);
477
546
 
478
547
  if (!nextRecord) {
479
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
480
- * native_fb,oss) This comment suppresses an error found when Flow
481
- * v0.98 was deployed. To see the error delete this comment and run
482
- * Flow. */
548
+ // $FlowFixMe[incompatible-variance]
483
549
  var _typeName5 = field.concreteType || _this._getRecordType(item);
484
550
 
485
551
  nextRecord = RelayModernRecord.create(nextID, _typeName5);
@@ -487,14 +553,15 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
487
553
  _this._recordSource.set(nextID, nextRecord);
488
554
  } else if (process.env.NODE_ENV !== "production") {
489
555
  _this._validateRecordType(nextRecord, field, item);
490
- }
556
+ } // NOTE: the check to strip __DEV__ code only works for simple
557
+ // `if (__DEV__)`
491
558
 
492
- if (prevIDs && process.env.NODE_ENV !== "production") {
493
- _this._validateConflictingLinkedFieldsWithIdenticalId(record, prevIDs[nextIndex], nextID, storageKey);
494
- }
495
- /* $FlowFixMe[incompatible-variance] (>=0.98.0 site=www,mobile,react_
496
- * native_fb,oss) This comment suppresses an error found when Flow v0.98
497
- * was deployed. To see the error delete this comment and run Flow. */
559
+
560
+ if (process.env.NODE_ENV !== "production") {
561
+ if (prevIDs) {
562
+ _this._validateConflictingLinkedFieldsWithIdenticalId(record, prevIDs[nextIndex], nextID, storageKey);
563
+ }
564
+ } // $FlowFixMe[incompatible-variance]
498
565
 
499
566
 
500
567
  _this._traverseSelections(field, nextRecord, item);
@@ -521,10 +588,11 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
521
588
  ;
522
589
 
523
590
  _proto._validateConflictingFieldsWithIdenticalId = function _validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue) {
591
+ // NOTE: Only call this function in DEV
524
592
  if (process.env.NODE_ENV !== "production") {
525
593
  var dataID = RelayModernRecord.getDataID(record);
526
594
  var previousValue = RelayModernRecord.getValue(record, storageKey);
527
- process.env.NODE_ENV !== "production" ? warning(storageKey === TYPENAME_KEY || previousValue === undefined || previousValue === fieldValue, 'RelayResponseNormalizer: Invalid record. The record contains two ' + 'instances of the same id: `%s` with conflicting field, %s and its values: %s and %s.' + 'If two fields are different but share' + 'the same id, one field will overwrite the other.', dataID, storageKey, previousValue, fieldValue) : void 0;
595
+ process.env.NODE_ENV !== "production" ? warning(storageKey === TYPENAME_KEY || previousValue === undefined || areEqual(previousValue, fieldValue), 'RelayResponseNormalizer: Invalid record. The record contains two ' + 'instances of the same id: `%s` with conflicting field, %s and its values: %s and %s. ' + 'If two fields are different but share ' + 'the same id, one field will overwrite the other.', dataID, storageKey, previousValue, fieldValue) : void 0;
528
596
  }
529
597
  }
530
598
  /**
@@ -533,6 +601,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
533
601
  ;
534
602
 
535
603
  _proto._validateConflictingLinkedFieldsWithIdenticalId = function _validateConflictingLinkedFieldsWithIdenticalId(record, prevID, nextID, storageKey) {
604
+ // NOTE: Only call this function in DEV
536
605
  if (process.env.NODE_ENV !== "production") {
537
606
  process.env.NODE_ENV !== "production" ? warning(prevID === undefined || prevID === nextID, 'RelayResponseNormalizer: Invalid record. The record contains ' + 'references to the conflicting field, %s and its id values: %s and %s. ' + 'We need to make sure that the record the field points ' + 'to remains consistent or one field will overwrite the other.', storageKey, prevID, nextID) : void 0;
538
607
  }
@@ -0,0 +1,47 @@
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
+ *
8
+ * @format
9
+ */
10
+ // flowlint ambiguous-object-type:error
11
+ 'use strict';
12
+
13
+ var invariant = require("fbjs/lib/invariant");
14
+
15
+ var _require = require('./RelayModernRecord'),
16
+ getType = _require.getType;
17
+
18
+ var REACT_FLIGHT_QUERIES_STORAGE_KEY = 'queries';
19
+ var REACT_FLIGHT_TREE_STORAGE_KEY = 'tree';
20
+ var REACT_FLIGHT_TYPE_NAME = 'ReactFlightComponent';
21
+
22
+ function refineToReactFlightPayloadData(payload) {
23
+ if (payload == null || typeof payload !== 'object' || !Array.isArray(payload.tree) || !Array.isArray(payload.queries)) {
24
+ return null;
25
+ }
26
+
27
+ return payload;
28
+ }
29
+
30
+ function getReactFlightClientResponse(record) {
31
+ !(getType(record) === REACT_FLIGHT_TYPE_NAME) ? process.env.NODE_ENV !== "production" ? invariant(false, 'getReactFlightClientResponse(): Expected a ReactFlightComponentRecord, ' + 'got %s.', record) : invariant(false) : void 0;
32
+ var response = record[REACT_FLIGHT_TREE_STORAGE_KEY];
33
+
34
+ if (response != null) {
35
+ return response;
36
+ }
37
+
38
+ return null;
39
+ }
40
+
41
+ module.exports = {
42
+ REACT_FLIGHT_QUERIES_STORAGE_KEY: REACT_FLIGHT_QUERIES_STORAGE_KEY,
43
+ REACT_FLIGHT_TREE_STORAGE_KEY: REACT_FLIGHT_TREE_STORAGE_KEY,
44
+ REACT_FLIGHT_TYPE_NAME: REACT_FLIGHT_TYPE_NAME,
45
+ getReactFlightClientResponse: getReactFlightClientResponse,
46
+ refineToReactFlightPayloadData: refineToReactFlightPayloadData
47
+ };
@@ -0,0 +1,162 @@
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
+ *
8
+ * @format
9
+ */
10
+ // flowlint ambiguous-object-type:error
11
+ 'use strict';
12
+
13
+ var RelayReader = require('./RelayReader');
14
+
15
+ var deepFreeze = require('../util/deepFreeze');
16
+
17
+ var hasOverlappingIDs = require('./hasOverlappingIDs');
18
+
19
+ var isEmptyObject = require('../util/isEmptyObject');
20
+
21
+ var recycleNodesInto = require('../util/recycleNodesInto');
22
+
23
+ var RelayStoreSubscriptions = /*#__PURE__*/function () {
24
+ function RelayStoreSubscriptions() {
25
+ this._subscriptions = new Set();
26
+ }
27
+
28
+ var _proto = RelayStoreSubscriptions.prototype;
29
+
30
+ _proto.subscribe = function subscribe(snapshot, callback) {
31
+ var _this = this;
32
+
33
+ var subscription = {
34
+ backup: null,
35
+ callback: callback,
36
+ snapshot: snapshot,
37
+ stale: false
38
+ };
39
+
40
+ var dispose = function dispose() {
41
+ _this._subscriptions["delete"](subscription);
42
+ };
43
+
44
+ this._subscriptions.add(subscription);
45
+
46
+ return {
47
+ dispose: dispose
48
+ };
49
+ };
50
+
51
+ _proto.snapshotSubscriptions = function snapshotSubscriptions(source) {
52
+ this._subscriptions.forEach(function (subscription) {
53
+ // Backup occurs after writing a new "final" payload(s) and before (re)applying
54
+ // optimistic changes. Each subscription's `snapshot` represents what was *last
55
+ // published to the subscriber*, which notably may include previous optimistic
56
+ // updates. Therefore a subscription can be in any of the following states:
57
+ // - stale=true: This subscription was restored to a different value than
58
+ // `snapshot`. That means this subscription has changes relative to its base,
59
+ // but its base has changed (we just applied a final payload): recompute
60
+ // a backup so that we can later restore to the state the subscription
61
+ // should be in.
62
+ // - stale=false: This subscription was restored to the same value than
63
+ // `snapshot`. That means this subscription does *not* have changes relative
64
+ // to its base, so the current `snapshot` is valid to use as a backup.
65
+ if (!subscription.stale) {
66
+ subscription.backup = subscription.snapshot;
67
+ return;
68
+ }
69
+
70
+ var snapshot = subscription.snapshot;
71
+ var backup = RelayReader.read(source, snapshot.selector);
72
+ var nextData = recycleNodesInto(snapshot.data, backup.data);
73
+ backup.data = nextData; // backup owns the snapshot and can safely mutate
74
+
75
+ subscription.backup = backup;
76
+ });
77
+ };
78
+
79
+ _proto.restoreSubscriptions = function restoreSubscriptions() {
80
+ this._subscriptions.forEach(function (subscription) {
81
+ var backup = subscription.backup;
82
+ subscription.backup = null;
83
+
84
+ if (backup) {
85
+ if (backup.data !== subscription.snapshot.data) {
86
+ subscription.stale = true;
87
+ }
88
+
89
+ subscription.snapshot = {
90
+ data: subscription.snapshot.data,
91
+ isMissingData: backup.isMissingData,
92
+ seenRecords: backup.seenRecords,
93
+ selector: backup.selector,
94
+ missingRequiredFields: backup.missingRequiredFields
95
+ };
96
+ } else {
97
+ subscription.stale = true;
98
+ }
99
+ });
100
+ };
101
+
102
+ _proto.updateSubscriptions = function updateSubscriptions(source, updatedRecordIDs, updatedOwners) {
103
+ var _this2 = this;
104
+
105
+ var hasUpdatedRecords = !isEmptyObject(updatedRecordIDs);
106
+
107
+ this._subscriptions.forEach(function (subscription) {
108
+ var owner = _this2._updateSubscription(source, subscription, updatedRecordIDs, hasUpdatedRecords);
109
+
110
+ if (owner != null) {
111
+ updatedOwners.push(owner);
112
+ }
113
+ });
114
+ }
115
+ /**
116
+ * Notifies the callback for the subscription if the data for the associated
117
+ * snapshot has changed.
118
+ * Additionally, updates the subscription snapshot with the latest snapshot,
119
+ * and marks it as not stale.
120
+ * Returns the owner (RequestDescriptor) if the subscription was affected by the
121
+ * latest update, or null if it was not affected.
122
+ */
123
+ ;
124
+
125
+ _proto._updateSubscription = function _updateSubscription(source, subscription, updatedRecordIDs, hasUpdatedRecords) {
126
+ var backup = subscription.backup,
127
+ callback = subscription.callback,
128
+ snapshot = subscription.snapshot,
129
+ stale = subscription.stale;
130
+ var hasOverlappingUpdates = hasUpdatedRecords && hasOverlappingIDs(snapshot.seenRecords, updatedRecordIDs);
131
+
132
+ if (!stale && !hasOverlappingUpdates) {
133
+ return;
134
+ }
135
+
136
+ var nextSnapshot = hasOverlappingUpdates || !backup ? RelayReader.read(source, snapshot.selector) : backup;
137
+ var nextData = recycleNodesInto(snapshot.data, nextSnapshot.data);
138
+ nextSnapshot = {
139
+ data: nextData,
140
+ isMissingData: nextSnapshot.isMissingData,
141
+ seenRecords: nextSnapshot.seenRecords,
142
+ selector: nextSnapshot.selector,
143
+ missingRequiredFields: nextSnapshot.missingRequiredFields
144
+ };
145
+
146
+ if (process.env.NODE_ENV !== "production") {
147
+ deepFreeze(nextSnapshot);
148
+ }
149
+
150
+ subscription.snapshot = nextSnapshot;
151
+ subscription.stale = false;
152
+
153
+ if (nextSnapshot.data !== snapshot.data) {
154
+ callback(nextSnapshot);
155
+ return snapshot.selector.owner;
156
+ }
157
+ };
158
+
159
+ return RelayStoreSubscriptions;
160
+ }();
161
+
162
+ module.exports = RelayStoreSubscriptions;