relay-runtime 11.0.2 → 13.0.0-rc.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 (219) hide show
  1. package/README.md +67 -0
  2. package/handlers/RelayDefaultHandlerProvider.js.flow +3 -3
  3. package/handlers/connection/ConnectionHandler.js.flow +9 -18
  4. package/handlers/connection/ConnectionInterface.js.flow +1 -1
  5. package/handlers/connection/MutationHandlers.js.flow +8 -12
  6. package/index.js +1 -1
  7. package/index.js.flow +57 -35
  8. package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
  9. package/lib/handlers/connection/ConnectionHandler.js +13 -19
  10. package/lib/handlers/connection/ConnectionInterface.js +1 -1
  11. package/lib/handlers/connection/MutationHandlers.js +4 -7
  12. package/lib/index.js +59 -44
  13. package/lib/multi-actor-environment/ActorIdentifier.js +12 -2
  14. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +64 -20
  15. package/lib/multi-actor-environment/ActorUtils.js +27 -0
  16. package/lib/multi-actor-environment/MultiActorEnvironment.js +324 -61
  17. package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +1 -1
  18. package/lib/multi-actor-environment/index.js +6 -2
  19. package/lib/mutations/RelayDeclarativeMutationConfig.js +5 -2
  20. package/lib/mutations/RelayRecordProxy.js +4 -3
  21. package/lib/mutations/RelayRecordSourceMutator.js +4 -3
  22. package/lib/mutations/RelayRecordSourceProxy.js +13 -5
  23. package/lib/mutations/RelayRecordSourceSelectorProxy.js +19 -6
  24. package/lib/mutations/applyOptimisticMutation.js +7 -7
  25. package/lib/mutations/commitLocalUpdate.js +1 -1
  26. package/lib/mutations/commitMutation.js +15 -11
  27. package/lib/mutations/readUpdatableQuery_EXPERIMENTAL.js +242 -0
  28. package/lib/mutations/validateMutation.js +11 -6
  29. package/lib/network/ConvertToExecuteFunction.js +3 -2
  30. package/lib/network/RelayNetwork.js +4 -3
  31. package/lib/network/RelayNetworkTypes.js +1 -1
  32. package/lib/network/RelayObservable.js +1 -1
  33. package/lib/network/RelayQueryResponseCache.js +22 -6
  34. package/lib/network/wrapNetworkWithLogObserver.js +79 -0
  35. package/lib/query/GraphQLTag.js +3 -2
  36. package/lib/query/PreloadableQueryRegistry.js +1 -1
  37. package/lib/query/fetchQuery.js +7 -6
  38. package/lib/query/fetchQueryInternal.js +1 -1
  39. package/lib/query/fetchQuery_DEPRECATED.js +3 -2
  40. package/lib/store/ClientID.js +8 -2
  41. package/lib/store/DataChecker.js +124 -55
  42. package/lib/store/OperationExecutor.js +489 -215
  43. package/lib/store/RelayConcreteVariables.js +27 -9
  44. package/lib/store/RelayExperimentalGraphResponseHandler.js +153 -0
  45. package/lib/store/RelayExperimentalGraphResponseTransform.js +391 -0
  46. package/lib/store/RelayModernEnvironment.js +100 -120
  47. package/lib/store/RelayModernFragmentSpecResolver.js +53 -27
  48. package/lib/store/RelayModernOperationDescriptor.js +3 -2
  49. package/lib/store/RelayModernRecord.js +48 -13
  50. package/lib/store/RelayModernSelector.js +15 -9
  51. package/lib/store/RelayModernStore.js +56 -23
  52. package/lib/store/RelayOperationTracker.js +34 -24
  53. package/lib/store/RelayOptimisticRecordSource.js +1 -1
  54. package/lib/store/RelayPublishQueue.js +35 -11
  55. package/lib/store/RelayReader.js +257 -72
  56. package/lib/store/RelayRecordSource.js +88 -4
  57. package/lib/store/RelayRecordState.js +1 -1
  58. package/lib/store/RelayReferenceMarker.js +34 -22
  59. package/lib/store/RelayResponseNormalizer.js +172 -96
  60. package/lib/store/RelayStoreReactFlightUtils.js +5 -11
  61. package/lib/store/RelayStoreSubscriptions.js +15 -10
  62. package/lib/store/RelayStoreTypes.js +1 -1
  63. package/lib/store/RelayStoreUtils.js +13 -8
  64. package/lib/store/ResolverCache.js +213 -0
  65. package/lib/store/ResolverFragments.js +10 -6
  66. package/lib/store/StoreInspector.js +1 -1
  67. package/lib/store/TypeID.js +1 -1
  68. package/lib/store/ViewerPattern.js +1 -1
  69. package/lib/store/cloneRelayHandleSourceField.js +6 -5
  70. package/lib/store/cloneRelayScalarHandleSourceField.js +6 -5
  71. package/lib/store/createFragmentSpecResolver.js +1 -1
  72. package/lib/store/createRelayContext.js +5 -3
  73. package/lib/store/defaultGetDataID.js +1 -1
  74. package/lib/store/defaultRequiredFieldLogger.js +1 -1
  75. package/lib/store/hasOverlappingIDs.js +1 -1
  76. package/lib/store/isRelayModernEnvironment.js +1 -1
  77. package/lib/store/normalizeRelayPayload.js +1 -1
  78. package/lib/store/readInlineData.js +7 -3
  79. package/lib/subscription/requestSubscription.js +32 -34
  80. package/lib/util/JSResourceTypes.flow.js +1 -1
  81. package/lib/util/NormalizationNode.js +1 -1
  82. package/lib/util/ReaderNode.js +1 -1
  83. package/lib/util/RelayConcreteNode.js +3 -1
  84. package/lib/util/RelayDefaultHandleKey.js +1 -1
  85. package/lib/util/RelayError.js +1 -1
  86. package/lib/util/RelayFeatureFlags.js +10 -7
  87. package/lib/util/RelayProfiler.js +1 -1
  88. package/lib/util/RelayReplaySubject.js +22 -7
  89. package/lib/util/RelayRuntimeTypes.js +1 -7
  90. package/lib/util/StringInterner.js +71 -0
  91. package/lib/util/createPayloadFor3DField.js +1 -1
  92. package/lib/util/deepFreeze.js +1 -1
  93. package/lib/util/generateID.js +1 -1
  94. package/lib/util/getAllRootVariables.js +29 -0
  95. package/lib/util/getFragmentIdentifier.js +16 -8
  96. package/lib/util/getOperation.js +3 -2
  97. package/lib/util/getPaginationMetadata.js +41 -0
  98. package/lib/util/getPaginationVariables.js +66 -0
  99. package/lib/util/getPendingOperationsForFragment.js +55 -0
  100. package/lib/util/getRefetchMetadata.js +36 -0
  101. package/lib/util/getRelayHandleKey.js +3 -3
  102. package/lib/util/getRequestIdentifier.js +3 -3
  103. package/lib/util/getValueAtPath.js +51 -0
  104. package/lib/util/isEmptyObject.js +2 -2
  105. package/lib/util/isPromise.js +1 -1
  106. package/lib/util/isScalarAndEqual.js +1 -1
  107. package/lib/util/recycleNodesInto.js +1 -1
  108. package/lib/util/registerEnvironmentWithDevTools.js +26 -0
  109. package/lib/util/reportMissingRequiredFields.js +1 -1
  110. package/lib/util/resolveImmediate.js +1 -1
  111. package/lib/util/stableCopy.js +1 -1
  112. package/lib/util/withDuration.js +31 -0
  113. package/multi-actor-environment/ActorIdentifier.js.flow +18 -2
  114. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +94 -58
  115. package/multi-actor-environment/ActorUtils.js.flow +33 -0
  116. package/multi-actor-environment/MultiActorEnvironment.js.flow +366 -93
  117. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +88 -23
  118. package/multi-actor-environment/index.js.flow +3 -1
  119. package/mutations/RelayDeclarativeMutationConfig.js.flow +33 -27
  120. package/mutations/RelayRecordProxy.js.flow +5 -6
  121. package/mutations/RelayRecordSourceMutator.js.flow +5 -7
  122. package/mutations/RelayRecordSourceProxy.js.flow +20 -11
  123. package/mutations/RelayRecordSourceSelectorProxy.js.flow +23 -8
  124. package/mutations/applyOptimisticMutation.js.flow +14 -15
  125. package/mutations/commitLocalUpdate.js.flow +2 -2
  126. package/mutations/commitMutation.js.flow +36 -47
  127. package/mutations/readUpdatableQuery_EXPERIMENTAL.js.flow +318 -0
  128. package/mutations/validateMutation.js.flow +27 -17
  129. package/network/ConvertToExecuteFunction.js.flow +3 -3
  130. package/network/RelayNetwork.js.flow +5 -6
  131. package/network/RelayNetworkTypes.js.flow +1 -1
  132. package/network/RelayObservable.js.flow +2 -2
  133. package/network/RelayQueryResponseCache.js.flow +35 -22
  134. package/network/wrapNetworkWithLogObserver.js.flow +99 -0
  135. package/package.json +2 -2
  136. package/query/GraphQLTag.js.flow +11 -11
  137. package/query/PreloadableQueryRegistry.js.flow +5 -3
  138. package/query/fetchQuery.js.flow +19 -19
  139. package/query/fetchQueryInternal.js.flow +7 -10
  140. package/query/fetchQuery_DEPRECATED.js.flow +7 -7
  141. package/relay-runtime.js +2 -2
  142. package/relay-runtime.min.js +2 -2
  143. package/store/ClientID.js.flow +15 -4
  144. package/store/DataChecker.js.flow +142 -60
  145. package/store/OperationExecutor.js.flow +575 -320
  146. package/store/RelayConcreteVariables.js.flow +28 -9
  147. package/store/RelayExperimentalGraphResponseHandler.js.flow +121 -0
  148. package/store/RelayExperimentalGraphResponseTransform.js.flow +470 -0
  149. package/store/RelayModernEnvironment.js.flow +91 -115
  150. package/store/RelayModernFragmentSpecResolver.js.flow +56 -32
  151. package/store/RelayModernOperationDescriptor.js.flow +13 -8
  152. package/store/RelayModernRecord.js.flow +68 -12
  153. package/store/RelayModernSelector.js.flow +25 -15
  154. package/store/RelayModernStore.js.flow +67 -32
  155. package/store/RelayOperationTracker.js.flow +60 -44
  156. package/store/RelayOptimisticRecordSource.js.flow +3 -3
  157. package/store/RelayPublishQueue.js.flow +74 -32
  158. package/store/RelayReader.js.flow +319 -100
  159. package/store/RelayRecordSource.js.flow +73 -7
  160. package/store/RelayRecordState.js.flow +1 -1
  161. package/store/RelayReferenceMarker.js.flow +41 -27
  162. package/store/RelayResponseNormalizer.js.flow +204 -86
  163. package/store/RelayStoreReactFlightUtils.js.flow +5 -12
  164. package/store/RelayStoreSubscriptions.js.flow +20 -12
  165. package/store/RelayStoreTypes.js.flow +200 -41
  166. package/store/RelayStoreUtils.js.flow +25 -12
  167. package/store/ResolverCache.js.flow +249 -0
  168. package/store/ResolverFragments.js.flow +16 -20
  169. package/store/StoreInspector.js.flow +3 -3
  170. package/store/TypeID.js.flow +2 -2
  171. package/store/ViewerPattern.js.flow +3 -3
  172. package/store/cloneRelayHandleSourceField.js.flow +6 -7
  173. package/store/cloneRelayScalarHandleSourceField.js.flow +6 -7
  174. package/store/createFragmentSpecResolver.js.flow +4 -5
  175. package/store/createRelayContext.js.flow +4 -4
  176. package/store/defaultGetDataID.js.flow +1 -1
  177. package/store/defaultRequiredFieldLogger.js.flow +1 -1
  178. package/store/hasOverlappingIDs.js.flow +1 -1
  179. package/store/isRelayModernEnvironment.js.flow +1 -1
  180. package/store/normalizeRelayPayload.js.flow +7 -8
  181. package/store/readInlineData.js.flow +8 -9
  182. package/subscription/requestSubscription.js.flow +55 -51
  183. package/util/JSResourceTypes.flow.js.flow +1 -1
  184. package/util/NormalizationNode.js.flow +11 -4
  185. package/util/ReaderNode.js.flow +25 -2
  186. package/util/RelayConcreteNode.js.flow +5 -1
  187. package/util/RelayDefaultHandleKey.js.flow +1 -1
  188. package/util/RelayError.js.flow +1 -1
  189. package/util/RelayFeatureFlags.js.flow +23 -15
  190. package/util/RelayProfiler.js.flow +1 -1
  191. package/util/RelayReplaySubject.js.flow +10 -10
  192. package/util/RelayRuntimeTypes.js.flow +70 -3
  193. package/util/StringInterner.js.flow +69 -0
  194. package/util/createPayloadFor3DField.js.flow +4 -4
  195. package/util/deepFreeze.js.flow +1 -1
  196. package/util/generateID.js.flow +1 -1
  197. package/util/getAllRootVariables.js.flow +36 -0
  198. package/util/getFragmentIdentifier.js.flow +28 -16
  199. package/util/getOperation.js.flow +3 -3
  200. package/util/getPaginationMetadata.js.flow +69 -0
  201. package/util/getPaginationVariables.js.flow +108 -0
  202. package/util/getPendingOperationsForFragment.js.flow +62 -0
  203. package/util/getRefetchMetadata.js.flow +76 -0
  204. package/util/getRelayHandleKey.js.flow +2 -3
  205. package/util/getRequestIdentifier.js.flow +4 -4
  206. package/util/getValueAtPath.js.flow +46 -0
  207. package/util/isEmptyObject.js.flow +2 -1
  208. package/util/isPromise.js.flow +1 -1
  209. package/util/isScalarAndEqual.js.flow +1 -1
  210. package/util/recycleNodesInto.js.flow +1 -1
  211. package/util/registerEnvironmentWithDevTools.js.flow +33 -0
  212. package/util/reportMissingRequiredFields.js.flow +1 -1
  213. package/util/resolveImmediate.js.flow +2 -2
  214. package/util/stableCopy.js.flow +1 -1
  215. package/util/withDuration.js.flow +32 -0
  216. package/lib/store/RelayRecordSourceMapImpl.js +0 -107
  217. package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +0 -318
  218. package/store/RelayRecordSourceMapImpl.js.flow +0 -91
  219. package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +0 -283
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,23 +12,24 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const areEqual = require('areEqual');
16
- const deepFreeze = require('../util/deepFreeze');
17
- const invariant = require('invariant');
18
- const warning = require('warning');
15
+ import type {ActorIdentifier} from '../multi-actor-environment/ActorIdentifier';
16
+ import type {DataID} from '../util/RelayRuntimeTypes';
17
+ import type {Record} from './RelayStoreTypes';
19
18
 
19
+ const deepFreeze = require('../util/deepFreeze');
20
20
  const {isClientID} = require('./ClientID');
21
21
  const {
22
+ ACTOR_IDENTIFIER_KEY,
22
23
  ID_KEY,
24
+ INVALIDATED_AT_KEY,
23
25
  REF_KEY,
24
26
  REFS_KEY,
25
- TYPENAME_KEY,
26
- INVALIDATED_AT_KEY,
27
27
  ROOT_ID,
28
+ TYPENAME_KEY,
28
29
  } = require('./RelayStoreUtils');
29
-
30
- import type {DataID} from '../util/RelayRuntimeTypes';
31
- import type {Record} from './RelayStoreTypes';
30
+ const areEqual = require('areEqual');
31
+ const invariant = require('invariant');
32
+ const warning = require('warning');
32
33
 
33
34
  /**
34
35
  * @public
@@ -172,10 +173,14 @@ function getLinkedRecordID(record: Record, storageKey: string): ?DataID {
172
173
  invariant(
173
174
  typeof link === 'object' && link && typeof link[REF_KEY] === 'string',
174
175
  'RelayModernRecord.getLinkedRecordID(): Expected `%s.%s` to be a linked ID, ' +
175
- 'was `%s`.',
176
+ 'was `%s`.%s',
176
177
  record[ID_KEY],
177
178
  storageKey,
178
179
  JSON.stringify(link),
180
+ typeof link === 'object' && link[REFS_KEY] !== undefined
181
+ ? ' It appears to be a plural linked record: did you mean to call ' +
182
+ 'getLinkedRecords() instead of getLinkedRecord()?'
183
+ : '',
179
184
  );
180
185
  return link[REF_KEY];
181
186
  }
@@ -197,10 +202,14 @@ function getLinkedRecordIDs(
197
202
  invariant(
198
203
  typeof links === 'object' && Array.isArray(links[REFS_KEY]),
199
204
  'RelayModernRecord.getLinkedRecordIDs(): Expected `%s.%s` to contain an array ' +
200
- 'of linked IDs, got `%s`.',
205
+ 'of linked IDs, got `%s`.%s',
201
206
  record[ID_KEY],
202
207
  storageKey,
203
208
  JSON.stringify(links),
209
+ typeof links === 'object' && links[REF_KEY] !== undefined
210
+ ? ' It appears to be a singular linked record: did you mean to call ' +
211
+ 'getLinkedRecord() instead of getLinkedRecords()?'
212
+ : '',
204
213
  );
205
214
  // assume items of the array are ids
206
215
  return (links[REFS_KEY]: any);
@@ -384,6 +393,51 @@ function setLinkedRecordIDs(
384
393
  record[storageKey] = links;
385
394
  }
386
395
 
396
+ /**
397
+ * @public
398
+ *
399
+ * Set the value of a field to a reference to another record in the actor specific store.
400
+ */
401
+ function setActorLinkedRecordID(
402
+ record: Record,
403
+ storageKey: string,
404
+ actorIdentifier: ActorIdentifier,
405
+ linkedID: DataID,
406
+ ): void {
407
+ // See perf note above for why we aren't using computed property access.
408
+ const link = {};
409
+ link[REF_KEY] = linkedID;
410
+ link[ACTOR_IDENTIFIER_KEY] = actorIdentifier;
411
+ record[storageKey] = link;
412
+ }
413
+
414
+ /**
415
+ * @public
416
+ *
417
+ * Get link to a record and the actor identifier for the store.
418
+ */
419
+ function getActorLinkedRecordID(
420
+ record: Record,
421
+ storageKey: string,
422
+ ): ?[ActorIdentifier, DataID] {
423
+ const link = record[storageKey];
424
+ if (link == null) {
425
+ return link;
426
+ }
427
+ invariant(
428
+ typeof link === 'object' &&
429
+ typeof link[REF_KEY] === 'string' &&
430
+ link[ACTOR_IDENTIFIER_KEY] != null,
431
+ 'RelayModernRecord.getActorLinkedRecordID(): Expected `%s.%s` to be an actor specific linked ID, ' +
432
+ 'was `%s`.',
433
+ record[ID_KEY],
434
+ storageKey,
435
+ JSON.stringify(link),
436
+ );
437
+
438
+ return [(link[ACTOR_IDENTIFIER_KEY]: any), (link[REF_KEY]: any)];
439
+ }
440
+
387
441
  module.exports = {
388
442
  clone,
389
443
  copyFields,
@@ -400,4 +454,6 @@ module.exports = {
400
454
  setLinkedRecordID,
401
455
  setLinkedRecordIDs,
402
456
  update,
457
+ getActorLinkedRecordID,
458
+ setActorLinkedRecordID,
403
459
  };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,22 +12,11 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const areEqual = require('areEqual');
16
- const invariant = require('invariant');
17
- const warning = require('warning');
18
-
19
- const {getFragmentVariables} = require('./RelayConcreteVariables');
20
- const {
21
- FRAGMENT_OWNER_KEY,
22
- FRAGMENTS_KEY,
23
- ID_KEY,
24
- IS_WITHIN_UNMATCHED_TYPE_REFINEMENT,
25
- } = require('./RelayStoreUtils');
26
-
27
15
  import type {NormalizationSelectableNode} from '../util/NormalizationNode';
28
16
  import type {ReaderFragment} from '../util/ReaderNode';
29
17
  import type {DataID, Variables} from '../util/RelayRuntimeTypes';
30
18
  import type {
19
+ ClientEdgeTraversalPath,
31
20
  NormalizationSelector,
32
21
  PluralReaderSelector,
33
22
  ReaderSelector,
@@ -35,6 +24,18 @@ import type {
35
24
  SingularReaderSelector,
36
25
  } from './RelayStoreTypes';
37
26
 
27
+ const {getFragmentVariables} = require('./RelayConcreteVariables');
28
+ const {
29
+ CLIENT_EDGE_TRAVERSAL_PATH,
30
+ FRAGMENT_OWNER_KEY,
31
+ FRAGMENTS_KEY,
32
+ ID_KEY,
33
+ IS_WITHIN_UNMATCHED_TYPE_REFINEMENT,
34
+ } = require('./RelayStoreUtils');
35
+ const areEqual = require('areEqual');
36
+ const invariant = require('invariant');
37
+ const warning = require('warning');
38
+
38
39
  /**
39
40
  * @public
40
41
  *
@@ -80,6 +81,7 @@ function getSingularSelector(
80
81
  const mixedOwner = item[FRAGMENT_OWNER_KEY];
81
82
  const isWithinUnmatchedTypeRefinement =
82
83
  item[IS_WITHIN_UNMATCHED_TYPE_REFINEMENT] === true;
84
+ const mixedClientEdgeTraversalPath = item[CLIENT_EDGE_TRAVERSAL_PATH];
83
85
  if (
84
86
  typeof dataID === 'string' &&
85
87
  typeof fragments === 'object' &&
@@ -87,22 +89,28 @@ function getSingularSelector(
87
89
  typeof fragments[fragment.name] === 'object' &&
88
90
  fragments[fragment.name] !== null &&
89
91
  typeof mixedOwner === 'object' &&
90
- mixedOwner !== null
92
+ mixedOwner !== null &&
93
+ (mixedClientEdgeTraversalPath == null ||
94
+ Array.isArray(mixedClientEdgeTraversalPath))
91
95
  ) {
92
96
  const owner: RequestDescriptor = (mixedOwner: $FlowFixMe);
93
- const argumentVariables = fragments[fragment.name];
97
+ const clientEdgeTraversalPath: ?ClientEdgeTraversalPath =
98
+ (mixedClientEdgeTraversalPath: $FlowFixMe);
94
99
 
100
+ const argumentVariables = fragments[fragment.name];
95
101
  const fragmentVariables = getFragmentVariables(
96
102
  fragment,
97
103
  owner.variables,
98
104
  argumentVariables,
99
105
  );
106
+
100
107
  return createReaderSelector(
101
108
  fragment,
102
109
  dataID,
103
110
  fragmentVariables,
104
111
  owner,
105
112
  isWithinUnmatchedTypeRefinement,
113
+ clientEdgeTraversalPath,
106
114
  );
107
115
  }
108
116
 
@@ -419,11 +427,13 @@ function createReaderSelector(
419
427
  variables: Variables,
420
428
  request: RequestDescriptor,
421
429
  isWithinUnmatchedTypeRefinement: boolean = false,
430
+ clientEdgeTraversalPath: ?ClientEdgeTraversalPath,
422
431
  ): SingularReaderSelector {
423
432
  return {
424
433
  kind: 'SingularReaderSelector',
425
434
  dataID,
426
435
  isWithinUnmatchedTypeRefinement,
436
+ clientEdgeTraversalPath: clientEdgeTraversalPath ?? null,
427
437
  node: fragment,
428
438
  variables,
429
439
  owner: request,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,29 +12,13 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const DataChecker = require('./DataChecker');
16
- const RelayFeatureFlags = require('../util/RelayFeatureFlags');
17
- const RelayModernRecord = require('./RelayModernRecord');
18
- const RelayOptimisticRecordSource = require('./RelayOptimisticRecordSource');
19
- const RelayReader = require('./RelayReader');
20
- const RelayReferenceMarker = require('./RelayReferenceMarker');
21
- const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
22
- const RelayStoreSubscriptions = require('./RelayStoreSubscriptions');
23
- const RelayStoreSubscriptionsUsingMapByID = require('./RelayStoreSubscriptionsUsingMapByID');
24
- const RelayStoreUtils = require('./RelayStoreUtils');
25
-
26
- const deepFreeze = require('../util/deepFreeze');
27
- const defaultGetDataID = require('./defaultGetDataID');
28
- const invariant = require('invariant');
29
- const resolveImmediate = require('../util/resolveImmediate');
30
-
31
- const {ROOT_ID, ROOT_TYPE} = require('./RelayStoreUtils');
32
-
15
+ import type {ActorIdentifier} from '../multi-actor-environment/ActorIdentifier';
33
16
  import type {DataID, Disposable} from '../util/RelayRuntimeTypes';
34
17
  import type {Availability} from './DataChecker';
35
18
  import type {GetDataID} from './RelayResponseNormalizer';
36
19
  import type {
37
20
  CheckOptions,
21
+ DataIDSet,
38
22
  LogFunction,
39
23
  MutableRecordSource,
40
24
  OperationAvailability,
@@ -47,8 +31,28 @@ import type {
47
31
  Snapshot,
48
32
  Store,
49
33
  StoreSubscriptions,
50
- DataIDSet,
51
34
  } from './RelayStoreTypes';
35
+ import type {ResolverCache} from './ResolverCache';
36
+
37
+ const {
38
+ INTERNAL_ACTOR_IDENTIFIER_DO_NOT_USE,
39
+ assertInternalActorIndentifier,
40
+ } = require('../multi-actor-environment/ActorIdentifier');
41
+ const deepFreeze = require('../util/deepFreeze');
42
+ const RelayFeatureFlags = require('../util/RelayFeatureFlags');
43
+ const resolveImmediate = require('../util/resolveImmediate');
44
+ const DataChecker = require('./DataChecker');
45
+ const defaultGetDataID = require('./defaultGetDataID');
46
+ const RelayModernRecord = require('./RelayModernRecord');
47
+ const RelayOptimisticRecordSource = require('./RelayOptimisticRecordSource');
48
+ const RelayReader = require('./RelayReader');
49
+ const RelayReferenceMarker = require('./RelayReferenceMarker');
50
+ const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
51
+ const RelayStoreSubscriptions = require('./RelayStoreSubscriptions');
52
+ const RelayStoreUtils = require('./RelayStoreUtils');
53
+ const {ROOT_ID, ROOT_TYPE} = require('./RelayStoreUtils');
54
+ const {RecordResolverCache} = require('./ResolverCache');
55
+ const invariant = require('invariant');
52
56
 
53
57
  export opaque type InvalidationState = {|
54
58
  dataIDs: $ReadOnlyArray<DataID>,
@@ -89,6 +93,7 @@ class RelayModernStore implements Store {
89
93
  _operationLoader: ?OperationLoader;
90
94
  _optimisticSource: ?MutableRecordSource;
91
95
  _recordSource: MutableRecordSource;
96
+ _resolverCache: ResolverCache;
92
97
  _releaseBuffer: Array<string>;
93
98
  _roots: Map<
94
99
  string,
@@ -144,10 +149,13 @@ class RelayModernStore implements Store {
144
149
  this._releaseBuffer = [];
145
150
  this._roots = new Map();
146
151
  this._shouldScheduleGC = false;
147
- this._storeSubscriptions =
148
- RelayFeatureFlags.ENABLE_STORE_SUBSCRIPTIONS_REFACTOR === true
149
- ? new RelayStoreSubscriptionsUsingMapByID(options?.log)
150
- : new RelayStoreSubscriptions(options?.log);
152
+ this._resolverCache = new RecordResolverCache(() =>
153
+ this._getMutableRecordSource(),
154
+ );
155
+ this._storeSubscriptions = new RelayStoreSubscriptions(
156
+ options?.log,
157
+ this._resolverCache,
158
+ );
151
159
  this._updatedRecordIDs = new Set();
152
160
  this._shouldProcessClientComponents =
153
161
  options?.shouldProcessClientComponents;
@@ -159,12 +167,16 @@ class RelayModernStore implements Store {
159
167
  return this._optimisticSource ?? this._recordSource;
160
168
  }
161
169
 
170
+ _getMutableRecordSource(): MutableRecordSource {
171
+ return this._optimisticSource ?? this._recordSource;
172
+ }
173
+
162
174
  check(
163
175
  operation: OperationDescriptor,
164
176
  options?: CheckOptions,
165
177
  ): OperationAvailability {
166
178
  const selector = operation.root;
167
- const source = this._optimisticSource ?? this._recordSource;
179
+ const source = this._getMutableRecordSource();
168
180
  const globalInvalidationEpoch = this._globalInvalidationEpoch;
169
181
 
170
182
  const rootEntry = this._roots.get(operation.request.identifier);
@@ -173,7 +185,7 @@ class RelayModernStore implements Store {
173
185
  // Check if store has been globally invalidated
174
186
  if (globalInvalidationEpoch != null) {
175
187
  // If so, check if the operation we're checking was last written
176
- // before or after invalidation occured.
188
+ // before or after invalidation occurred.
177
189
  if (
178
190
  operationLastWrittenAt == null ||
179
191
  operationLastWrittenAt <= globalInvalidationEpoch
@@ -186,11 +198,24 @@ class RelayModernStore implements Store {
186
198
  }
187
199
  }
188
200
 
189
- const target = options?.target ?? source;
190
201
  const handlers = options?.handlers ?? [];
202
+ const getSourceForActor =
203
+ options?.getSourceForActor ??
204
+ (actorIdentifier => {
205
+ assertInternalActorIndentifier(actorIdentifier);
206
+ return source;
207
+ });
208
+ const getTargetForActor =
209
+ options?.getTargetForActor ??
210
+ (actorIdentifier => {
211
+ assertInternalActorIndentifier(actorIdentifier);
212
+ return source;
213
+ });
214
+
191
215
  const operationAvailability = DataChecker.check(
192
- source,
193
- target,
216
+ getSourceForActor,
217
+ getTargetForActor,
218
+ options?.defaultActorIdentifier ?? INTERNAL_ACTOR_IDENTIFIER_DO_NOT_USE,
194
219
  selector,
195
220
  handlers,
196
221
  this._operationLoader,
@@ -274,7 +299,7 @@ class RelayModernStore implements Store {
274
299
 
275
300
  lookup(selector: SingularReaderSelector): Snapshot {
276
301
  const source = this.getSource();
277
- const snapshot = RelayReader.read(source, selector);
302
+ const snapshot = RelayReader.read(source, selector, this._resolverCache);
278
303
  if (__DEV__) {
279
304
  deepFreeze(snapshot);
280
305
  }
@@ -302,6 +327,13 @@ class RelayModernStore implements Store {
302
327
  this._globalInvalidationEpoch = this._currentWriteEpoch;
303
328
  }
304
329
 
330
+ if (RelayFeatureFlags.ENABLE_RELAY_RESOLVERS) {
331
+ // When a record is updated, we need to also handle records that depend on it,
332
+ // specifically Relay Resolver result records containing results based on the
333
+ // updated records. This both adds to updatedRecordIDs and invalidates any
334
+ // cached data as needed.
335
+ this._resolverCache.invalidateDataIDs(this._updatedRecordIDs);
336
+ }
305
337
  const source = this.getSource();
306
338
  const updatedOwners = [];
307
339
  this._storeSubscriptions.updateSubscriptions(
@@ -364,7 +396,7 @@ class RelayModernStore implements Store {
364
396
  }
365
397
 
366
398
  publish(source: RecordSource, idsMarkedForInvalidation?: DataIDSet): void {
367
- const target = this._optimisticSource ?? this._recordSource;
399
+ const target = this._getMutableRecordSource();
368
400
  updateTargetFromSource(
369
401
  target,
370
402
  source,
@@ -417,6 +449,10 @@ class RelayModernStore implements Store {
417
449
  return 'RelayModernStore()';
418
450
  }
419
451
 
452
+ getEpoch(): number {
453
+ return this._currentWriteEpoch;
454
+ }
455
+
420
456
  // Internal API
421
457
  __getUpdatedRecordIDs(): DataIDSet {
422
458
  return this._updatedRecordIDs;
@@ -677,7 +713,6 @@ function updateTargetFromSource(
677
713
  currentWriteEpoch,
678
714
  );
679
715
  invalidatedRecordIDs.add(dataID);
680
- // $FlowFixMe[incompatible-call]
681
716
  target.set(dataID, nextRecord);
682
717
  });
683
718
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,22 +12,26 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const invariant = require('invariant');
16
-
17
15
  import type {RequestDescriptor} from './RelayStoreTypes';
18
16
 
17
+ const invariant = require('invariant');
18
+
19
19
  class RelayOperationTracker {
20
- _ownersToPendingOperationsIdentifier: Map<string, Set<string>>;
21
- _pendingOperationsToOwnersIdentifier: Map<string, Set<string>>;
22
- _ownersIdentifierToPromise: Map<
20
+ _ownersToPendingOperations: Map<string, Map<string, RequestDescriptor>>;
21
+ _pendingOperationsToOwners: Map<string, Set<string>>;
22
+ _ownersToPendingPromise: Map<
23
23
  string,
24
- {|promise: Promise<void>, resolve: () => void|},
24
+ {|
25
+ promise: Promise<void>,
26
+ resolve: () => void,
27
+ pendingOperations: $ReadOnlyArray<RequestDescriptor>,
28
+ |},
25
29
  >;
26
30
 
27
31
  constructor() {
28
- this._ownersToPendingOperationsIdentifier = new Map();
29
- this._pendingOperationsToOwnersIdentifier = new Map();
30
- this._ownersIdentifierToPromise = new Map();
32
+ this._ownersToPendingOperations = new Map();
33
+ this._pendingOperationsToOwners = new Map();
34
+ this._ownersToPendingPromise = new Map();
31
35
  }
32
36
 
33
37
  /**
@@ -45,22 +49,24 @@ class RelayOperationTracker {
45
49
  const newlyAffectedOwnersIdentifier = new Set();
46
50
  for (const owner of affectedOwners) {
47
51
  const ownerIdentifier = owner.identifier;
48
- const pendingOperationsAffectingOwner = this._ownersToPendingOperationsIdentifier.get(
49
- ownerIdentifier,
50
- );
52
+ const pendingOperationsAffectingOwner =
53
+ this._ownersToPendingOperations.get(ownerIdentifier);
51
54
  if (pendingOperationsAffectingOwner != null) {
52
55
  // In this case the `ownerIdentifier` already affected by some operations
53
56
  // We just need to detect, is it the same operation that we already
54
57
  // have in the list, or it's a new operation
55
58
  if (!pendingOperationsAffectingOwner.has(pendingOperationIdentifier)) {
56
- pendingOperationsAffectingOwner.add(pendingOperationIdentifier);
59
+ pendingOperationsAffectingOwner.set(
60
+ pendingOperationIdentifier,
61
+ pendingOperation,
62
+ );
57
63
  newlyAffectedOwnersIdentifier.add(ownerIdentifier);
58
64
  }
59
65
  } else {
60
66
  // This is a new `ownerIdentifier` that is affected by the operation
61
- this._ownersToPendingOperationsIdentifier.set(
67
+ this._ownersToPendingOperations.set(
62
68
  ownerIdentifier,
63
- new Set([pendingOperationIdentifier]),
69
+ new Map([[pendingOperationIdentifier, pendingOperation]]),
64
70
  );
65
71
  newlyAffectedOwnersIdentifier.add(ownerIdentifier);
66
72
  }
@@ -72,19 +78,18 @@ class RelayOperationTracker {
72
78
  }
73
79
 
74
80
  // But, if some owners were affected we need to add them to
75
- // the `_pendingOperationsToOwnersIdentifier` set
76
- const ownersAffectedByOperationIdentifier =
77
- this._pendingOperationsToOwnersIdentifier.get(
78
- pendingOperationIdentifier,
79
- ) || new Set();
81
+ // the `_pendingOperationsToOwners` set
82
+ const ownersAffectedByPendingOperation =
83
+ this._pendingOperationsToOwners.get(pendingOperationIdentifier) ||
84
+ new Set();
80
85
 
81
86
  for (const ownerIdentifier of newlyAffectedOwnersIdentifier) {
82
87
  this._resolveOwnerResolvers(ownerIdentifier);
83
- ownersAffectedByOperationIdentifier.add(ownerIdentifier);
88
+ ownersAffectedByPendingOperation.add(ownerIdentifier);
84
89
  }
85
- this._pendingOperationsToOwnersIdentifier.set(
90
+ this._pendingOperationsToOwners.set(
86
91
  pendingOperationIdentifier,
87
- ownersAffectedByOperationIdentifier,
92
+ ownersAffectedByPendingOperation,
88
93
  );
89
94
  }
90
95
 
@@ -94,7 +99,7 @@ class RelayOperationTracker {
94
99
  */
95
100
  complete(pendingOperation: RequestDescriptor): void {
96
101
  const pendingOperationIdentifier = pendingOperation.identifier;
97
- const affectedOwnersIdentifier = this._pendingOperationsToOwnersIdentifier.get(
102
+ const affectedOwnersIdentifier = this._pendingOperationsToOwners.get(
98
103
  pendingOperationIdentifier,
99
104
  );
100
105
  if (affectedOwnersIdentifier == null) {
@@ -107,9 +112,8 @@ class RelayOperationTracker {
107
112
  // and some other operations
108
113
  const updatedOwnersIdentifier = new Set();
109
114
  for (const ownerIdentifier of affectedOwnersIdentifier) {
110
- const pendingOperationsAffectingOwner = this._ownersToPendingOperationsIdentifier.get(
111
- ownerIdentifier,
112
- );
115
+ const pendingOperationsAffectingOwner =
116
+ this._ownersToPendingOperations.get(ownerIdentifier);
113
117
  if (!pendingOperationsAffectingOwner) {
114
118
  continue;
115
119
  }
@@ -124,7 +128,7 @@ class RelayOperationTracker {
124
128
  // Complete subscriptions for all owners, affected by `pendingOperationIdentifier`
125
129
  for (const ownerIdentifier of completedOwnersIdentifier) {
126
130
  this._resolveOwnerResolvers(ownerIdentifier);
127
- this._ownersToPendingOperationsIdentifier.delete(ownerIdentifier);
131
+ this._ownersToPendingOperations.delete(ownerIdentifier);
128
132
  }
129
133
 
130
134
  // Update all ownerIdentifier that were updated by `pendingOperationIdentifier` but still
@@ -134,31 +138,38 @@ class RelayOperationTracker {
134
138
  }
135
139
 
136
140
  // Finally, remove pending operation identifier
137
- this._pendingOperationsToOwnersIdentifier.delete(
138
- pendingOperationIdentifier,
139
- );
141
+ this._pendingOperationsToOwners.delete(pendingOperationIdentifier);
140
142
  }
141
143
 
142
144
  _resolveOwnerResolvers(ownerIdentifier: string): void {
143
- const promiseEntry = this._ownersIdentifierToPromise.get(ownerIdentifier);
145
+ const promiseEntry = this._ownersToPendingPromise.get(ownerIdentifier);
144
146
  if (promiseEntry != null) {
145
147
  promiseEntry.resolve();
146
148
  }
147
- this._ownersIdentifierToPromise.delete(ownerIdentifier);
149
+ this._ownersToPendingPromise.delete(ownerIdentifier);
148
150
  }
149
151
 
150
- getPromiseForPendingOperationsAffectingOwner(
151
- owner: RequestDescriptor,
152
- ): Promise<void> | null {
152
+ getPendingOperationsAffectingOwner(owner: RequestDescriptor): {|
153
+ promise: Promise<void>,
154
+ pendingOperations: $ReadOnlyArray<RequestDescriptor>,
155
+ |} | null {
153
156
  const ownerIdentifier = owner.identifier;
154
- if (!this._ownersToPendingOperationsIdentifier.has(ownerIdentifier)) {
157
+ const pendingOperationsForOwner =
158
+ this._ownersToPendingOperations.get(ownerIdentifier);
159
+ if (
160
+ pendingOperationsForOwner == null ||
161
+ pendingOperationsForOwner.size === 0
162
+ ) {
155
163
  return null;
156
164
  }
157
- const cachedPromiseEntry = this._ownersIdentifierToPromise.get(
158
- ownerIdentifier,
159
- );
165
+
166
+ const cachedPromiseEntry =
167
+ this._ownersToPendingPromise.get(ownerIdentifier);
160
168
  if (cachedPromiseEntry != null) {
161
- return cachedPromiseEntry.promise;
169
+ return {
170
+ promise: cachedPromiseEntry.promise,
171
+ pendingOperations: cachedPromiseEntry.pendingOperations,
172
+ };
162
173
  }
163
174
  let resolve;
164
175
  const promise = new Promise(r => {
@@ -169,8 +180,13 @@ class RelayOperationTracker {
169
180
  'RelayOperationTracker: Expected resolver to be defined. If you' +
170
181
  'are seeing this, it is likely a bug in Relay.',
171
182
  );
172
- this._ownersIdentifierToPromise.set(ownerIdentifier, {promise, resolve});
173
- return promise;
183
+ const pendingOperations = Array.from(pendingOperationsForOwner.values());
184
+ this._ownersToPendingPromise.set(ownerIdentifier, {
185
+ promise,
186
+ resolve,
187
+ pendingOperations,
188
+ });
189
+ return {promise, pendingOperations};
174
190
  }
175
191
  }
176
192
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,8 +12,6 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const RelayRecordSource = require('./RelayRecordSource');
16
-
17
15
  import type {DataID} from '../util/RelayRuntimeTypes';
18
16
  import type {RecordState} from './RelayRecordState';
19
17
  import type {
@@ -22,6 +20,8 @@ import type {
22
20
  RecordSource,
23
21
  } from './RelayStoreTypes';
24
22
 
23
+ const RelayRecordSource = require('./RelayRecordSource');
24
+
25
25
  const UNPUBLISH_RECORD_SENTINEL = Object.freeze({
26
26
  __UNPUBLISH_RECORD_SENTINEL: true,
27
27
  });