relay-runtime 7.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +34 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/index.js +1 -1
  5. package/index.js.flow +314 -0
  6. package/lib/handlers/RelayDefaultHandlerProvider.js +3 -2
  7. package/lib/handlers/connection/{RelayConnectionHandler.js → ConnectionHandler.js} +34 -35
  8. package/lib/handlers/connection/{RelayConnectionInterface.js → ConnectionInterface.js} +3 -30
  9. package/lib/index.js +29 -27
  10. package/lib/mutations/RelayDeclarativeMutationConfig.js +30 -52
  11. package/lib/mutations/RelayRecordProxy.js +6 -3
  12. package/lib/mutations/RelayRecordSourceMutator.js +3 -9
  13. package/lib/mutations/RelayRecordSourceProxy.js +21 -24
  14. package/lib/mutations/RelayRecordSourceSelectorProxy.js +18 -14
  15. package/lib/mutations/applyOptimisticMutation.js +2 -1
  16. package/lib/mutations/commitLocalUpdate.js +1 -0
  17. package/lib/mutations/commitMutation.js +26 -8
  18. package/lib/mutations/validateMutation.js +21 -11
  19. package/lib/network/ConvertToExecuteFunction.js +1 -0
  20. package/lib/network/RelayNetwork.js +1 -0
  21. package/lib/network/RelayNetworkTypes.js +1 -0
  22. package/lib/network/RelayObservable.js +10 -9
  23. package/lib/network/RelayQueryResponseCache.js +9 -7
  24. package/lib/query/{RelayModernGraphQLTag.js → GraphQLTag.js} +15 -8
  25. package/lib/query/fetchQuery.js +2 -1
  26. package/lib/query/fetchQueryInternal.js +30 -20
  27. package/lib/store/ClientID.js +1 -0
  28. package/lib/store/DataChecker.js +47 -97
  29. package/lib/store/RelayConcreteVariables.js +7 -2
  30. package/lib/store/RelayModernEnvironment.js +82 -41
  31. package/lib/store/RelayModernFragmentSpecResolver.js +61 -21
  32. package/lib/store/RelayModernOperationDescriptor.js +2 -1
  33. package/lib/store/RelayModernQueryExecutor.js +476 -333
  34. package/lib/store/RelayModernRecord.js +39 -9
  35. package/lib/store/RelayModernSelector.js +2 -1
  36. package/lib/store/RelayModernStore.js +359 -371
  37. package/lib/store/RelayOperationTracker.js +36 -78
  38. package/lib/store/RelayOptimisticRecordSource.js +8 -5
  39. package/lib/store/RelayPublishQueue.js +66 -53
  40. package/lib/store/RelayReader.js +2 -24
  41. package/lib/store/RelayRecordSource.js +3 -9
  42. package/lib/store/RelayRecordSourceMapImpl.js +14 -18
  43. package/lib/store/RelayRecordState.js +1 -0
  44. package/lib/store/RelayReferenceMarker.js +8 -58
  45. package/lib/store/RelayResponseNormalizer.js +15 -144
  46. package/lib/store/RelayStoreTypes.js +1 -0
  47. package/lib/store/RelayStoreUtils.js +34 -10
  48. package/lib/store/StoreInspector.js +11 -5
  49. package/lib/store/ViewerPattern.js +1 -0
  50. package/lib/store/cloneRelayHandleSourceField.js +1 -0
  51. package/lib/store/createFragmentSpecResolver.js +1 -0
  52. package/lib/store/createRelayContext.js +1 -0
  53. package/lib/store/defaultGetDataID.js +1 -0
  54. package/lib/store/hasOverlappingIDs.js +1 -0
  55. package/lib/store/isRelayModernEnvironment.js +1 -0
  56. package/lib/store/normalizeRelayPayload.js +8 -4
  57. package/lib/store/readInlineData.js +2 -1
  58. package/lib/subscription/requestSubscription.js +6 -3
  59. package/lib/util/JSResourceTypes.flow.js +12 -0
  60. package/lib/util/NormalizationNode.js +1 -0
  61. package/lib/util/ReaderNode.js +1 -0
  62. package/lib/util/RelayConcreteNode.js +3 -0
  63. package/lib/util/RelayDefaultHandleKey.js +1 -0
  64. package/lib/util/RelayError.js +2 -1
  65. package/lib/util/RelayFeatureFlags.js +3 -2
  66. package/lib/util/RelayProfiler.js +1 -0
  67. package/lib/util/RelayReplaySubject.js +2 -3
  68. package/lib/util/RelayRuntimeTypes.js +1 -0
  69. package/lib/util/createPayloadFor3DField.js +34 -0
  70. package/lib/util/deepFreeze.js +1 -0
  71. package/lib/util/generateID.js +1 -0
  72. package/lib/util/getFragmentIdentifier.js +1 -0
  73. package/lib/util/getRelayHandleKey.js +1 -0
  74. package/lib/util/getRequestIdentifier.js +1 -0
  75. package/lib/util/isPromise.js +1 -0
  76. package/lib/util/isScalarAndEqual.js +1 -0
  77. package/lib/util/recycleNodesInto.js +1 -0
  78. package/lib/util/resolveImmediate.js +1 -0
  79. package/lib/util/stableCopy.js +1 -0
  80. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  81. package/mutations/RelayRecordProxy.js.flow +165 -0
  82. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  83. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  84. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  85. package/mutations/applyOptimisticMutation.js.flow +76 -0
  86. package/mutations/commitLocalUpdate.js.flow +24 -0
  87. package/mutations/commitMutation.js.flow +184 -0
  88. package/mutations/validateMutation.js.flow +211 -0
  89. package/network/ConvertToExecuteFunction.js.flow +49 -0
  90. package/network/RelayNetwork.js.flow +84 -0
  91. package/network/RelayNetworkTypes.js.flow +123 -0
  92. package/network/RelayObservable.js.flow +634 -0
  93. package/network/RelayQueryResponseCache.js.flow +111 -0
  94. package/package.json +1 -1
  95. package/query/GraphQLTag.js.flow +166 -0
  96. package/query/fetchQuery.js.flow +47 -0
  97. package/query/fetchQueryInternal.js.flow +349 -0
  98. package/relay-runtime.js +2 -2
  99. package/relay-runtime.min.js +2 -2
  100. package/store/ClientID.js.flow +43 -0
  101. package/store/DataChecker.js.flow +426 -0
  102. package/store/RelayConcreteVariables.js.flow +96 -0
  103. package/store/RelayModernEnvironment.js.flow +526 -0
  104. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  105. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  106. package/store/RelayModernQueryExecutor.js.flow +1327 -0
  107. package/store/RelayModernRecord.js.flow +403 -0
  108. package/store/RelayModernSelector.js.flow +444 -0
  109. package/store/RelayModernStore.js.flow +757 -0
  110. package/store/RelayOperationTracker.js.flow +164 -0
  111. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  112. package/store/RelayPublishQueue.js.flow +401 -0
  113. package/store/RelayReader.js.flow +376 -0
  114. package/store/RelayRecordSource.js.flow +29 -0
  115. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  116. package/store/RelayRecordState.js.flow +37 -0
  117. package/store/RelayReferenceMarker.js.flow +236 -0
  118. package/store/RelayResponseNormalizer.js.flow +556 -0
  119. package/store/RelayStoreTypes.js.flow +873 -0
  120. package/store/RelayStoreUtils.js.flow +218 -0
  121. package/store/StoreInspector.js.flow +173 -0
  122. package/store/ViewerPattern.js.flow +26 -0
  123. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  124. package/store/createFragmentSpecResolver.js.flow +55 -0
  125. package/store/createRelayContext.js.flow +44 -0
  126. package/store/defaultGetDataID.js.flow +27 -0
  127. package/store/hasOverlappingIDs.js.flow +34 -0
  128. package/store/isRelayModernEnvironment.js.flow +27 -0
  129. package/store/normalizeRelayPayload.js.flow +51 -0
  130. package/store/readInlineData.js.flow +75 -0
  131. package/subscription/requestSubscription.js.flow +100 -0
  132. package/util/JSResourceTypes.flow.js.flow +20 -0
  133. package/util/NormalizationNode.js.flow +191 -0
  134. package/util/ReaderNode.js.flow +208 -0
  135. package/util/RelayConcreteNode.js.flow +80 -0
  136. package/util/RelayDefaultHandleKey.js.flow +17 -0
  137. package/util/RelayError.js.flow +33 -0
  138. package/util/RelayFeatureFlags.js.flow +30 -0
  139. package/util/RelayProfiler.js.flow +284 -0
  140. package/util/RelayReplaySubject.js.flow +134 -0
  141. package/util/RelayRuntimeTypes.js.flow +70 -0
  142. package/util/createPayloadFor3DField.js.flow +43 -0
  143. package/util/deepFreeze.js.flow +36 -0
  144. package/util/generateID.js.flow +21 -0
  145. package/util/getFragmentIdentifier.js.flow +52 -0
  146. package/util/getRelayHandleKey.js.flow +41 -0
  147. package/util/getRequestIdentifier.js.flow +41 -0
  148. package/util/isPromise.js.flow +21 -0
  149. package/util/isScalarAndEqual.js.flow +26 -0
  150. package/util/recycleNodesInto.js.flow +80 -0
  151. package/util/resolveImmediate.js.flow +30 -0
  152. package/util/stableCopy.js.flow +35 -0
  153. package/lib/handlers/RelayDefaultMissingFieldHandlers.js +0 -26
  154. package/lib/store/RelayConnection.js +0 -36
  155. package/lib/store/RelayConnectionResolver.js +0 -177
  156. package/lib/store/RelayRecordSourceObjectImpl.js +0 -78
  157. package/lib/util/getFragmentSpecIdentifier.js +0 -26
@@ -0,0 +1,444 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
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
+ } = require('./RelayStoreUtils');
25
+
26
+ import type {NormalizationSelectableNode} from '../util/NormalizationNode';
27
+ import type {ReaderFragment} from '../util/ReaderNode';
28
+ import type {DataID, Variables} from '../util/RelayRuntimeTypes';
29
+ import type {
30
+ NormalizationSelector,
31
+ PluralReaderSelector,
32
+ ReaderSelector,
33
+ RequestDescriptor,
34
+ SingularReaderSelector,
35
+ } from './RelayStoreTypes';
36
+
37
+ /**
38
+ * @public
39
+ *
40
+ * Given the result `item` from a parent that fetched `fragment`, creates a
41
+ * selector that can be used to read the results of that fragment for that item.
42
+ *
43
+ * Example:
44
+ *
45
+ * Given two fragments as follows:
46
+ *
47
+ * ```
48
+ * fragment Parent on User {
49
+ * id
50
+ * ...Child
51
+ * }
52
+ * fragment Child on User {
53
+ * name
54
+ * }
55
+ * ```
56
+ *
57
+ * And given some object `parent` that is the results of `Parent` for id "4",
58
+ * the results of `Child` can be accessed by first getting a selector and then
59
+ * using that selector to `lookup()` the results against the environment:
60
+ *
61
+ * ```
62
+ * const childSelector = getSingularSelector(queryVariables, Child, parent);
63
+ * const childData = environment.lookup(childSelector).data;
64
+ * ```
65
+ */
66
+ function getSingularSelector(
67
+ fragment: ReaderFragment,
68
+ item: mixed,
69
+ ): ?SingularReaderSelector {
70
+ invariant(
71
+ typeof item === 'object' && item !== null && !Array.isArray(item),
72
+ 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' +
73
+ '`%s`.',
74
+ fragment.name,
75
+ JSON.stringify(item),
76
+ );
77
+ const dataID = item[ID_KEY];
78
+ const fragments = item[FRAGMENTS_KEY];
79
+ const mixedOwner = item[FRAGMENT_OWNER_KEY];
80
+ if (
81
+ typeof dataID === 'string' &&
82
+ typeof fragments === 'object' &&
83
+ fragments !== null &&
84
+ typeof fragments[fragment.name] === 'object' &&
85
+ fragments[fragment.name] !== null &&
86
+ typeof mixedOwner === 'object' &&
87
+ mixedOwner !== null
88
+ ) {
89
+ const owner: RequestDescriptor = (mixedOwner: $FlowFixMe);
90
+ const argumentVariables = fragments[fragment.name];
91
+
92
+ const fragmentVariables = getFragmentVariables(
93
+ fragment,
94
+ owner.variables,
95
+ argumentVariables,
96
+ );
97
+ return createReaderSelector(fragment, dataID, fragmentVariables, owner);
98
+ }
99
+
100
+ if (__DEV__) {
101
+ let stringifiedItem = JSON.stringify(item);
102
+ if (stringifiedItem.length > 499) {
103
+ stringifiedItem = stringifiedItem.substr(0, 498) + '\u2026';
104
+ }
105
+
106
+ warning(
107
+ false,
108
+ 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' +
109
+ '`%s`. Make sure that the parent operation/fragment included fragment ' +
110
+ '`...%s` without `@relay(mask: false)`.',
111
+ fragment.name,
112
+ stringifiedItem,
113
+ fragment.name,
114
+ );
115
+ }
116
+
117
+ return null;
118
+ }
119
+
120
+ /**
121
+ * @public
122
+ *
123
+ * Given the result `items` from a parent that fetched `fragment`, creates a
124
+ * selector that can be used to read the results of that fragment on those
125
+ * items. This is similar to `getSingularSelector` but for "plural" fragments that
126
+ * expect an array of results and therefore return an array of selectors.
127
+ */
128
+ function getPluralSelector(
129
+ fragment: ReaderFragment,
130
+ items: $ReadOnlyArray<mixed>,
131
+ ): ?PluralReaderSelector {
132
+ let selectors = null;
133
+ items.forEach((item, ii) => {
134
+ const selector = item != null ? getSingularSelector(fragment, item) : null;
135
+ if (selector != null) {
136
+ selectors = selectors || [];
137
+ selectors.push(selector);
138
+ }
139
+ });
140
+ if (selectors == null) {
141
+ return null;
142
+ } else {
143
+ return {
144
+ kind: 'PluralReaderSelector',
145
+ selectors,
146
+ };
147
+ }
148
+ }
149
+
150
+ function getSelector(
151
+ fragment: ReaderFragment,
152
+ item: mixed | Array<mixed>,
153
+ ): ?ReaderSelector {
154
+ if (item == null) {
155
+ return item;
156
+ } else if (fragment.metadata && fragment.metadata.plural === true) {
157
+ invariant(
158
+ Array.isArray(item),
159
+ 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' +
160
+ 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.',
161
+ fragment.name,
162
+ JSON.stringify(item),
163
+ fragment.name,
164
+ );
165
+ return getPluralSelector(fragment, item);
166
+ } else {
167
+ invariant(
168
+ !Array.isArray(item),
169
+ 'RelayModernSelector: Expected value for fragment `%s` to be an object, got `%s`. ' +
170
+ 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.',
171
+ fragment.name,
172
+ JSON.stringify(item),
173
+ fragment.name,
174
+ );
175
+ return getSingularSelector(fragment, item);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * @public
181
+ *
182
+ * Given a mapping of keys -> results and a mapping of keys -> fragments,
183
+ * extracts the selectors for those fragments from the results.
184
+ *
185
+ * The canonical use-case for this function is ReactRelayFragmentContainer, which
186
+ * uses this function to convert (props, fragments) into selectors so that it
187
+ * can read the results to pass to the inner component.
188
+ */
189
+ function getSelectorsFromObject(
190
+ fragments: {[key: string]: ReaderFragment, ...},
191
+ object: {[key: string]: mixed, ...},
192
+ ): {[key: string]: ?ReaderSelector, ...} {
193
+ const selectors = {};
194
+ for (const key in fragments) {
195
+ if (fragments.hasOwnProperty(key)) {
196
+ const fragment = fragments[key];
197
+ const item = object[key];
198
+ selectors[key] = getSelector(fragment, item);
199
+ }
200
+ }
201
+ return selectors;
202
+ }
203
+
204
+ /**
205
+ * @public
206
+ *
207
+ * Given a mapping of keys -> results and a mapping of keys -> fragments,
208
+ * extracts a mapping of keys -> id(s) of the results.
209
+ *
210
+ * Similar to `getSelectorsFromObject()`, this function can be useful in
211
+ * determining the "identity" of the props passed to a component.
212
+ */
213
+ function getDataIDsFromObject(
214
+ fragments: {[key: string]: ReaderFragment, ...},
215
+ object: {[key: string]: mixed, ...},
216
+ ): {[key: string]: ?(DataID | Array<DataID>), ...} {
217
+ const ids = {};
218
+ for (const key in fragments) {
219
+ if (fragments.hasOwnProperty(key)) {
220
+ const fragment = fragments[key];
221
+ const item = object[key];
222
+ ids[key] = getDataIDsFromFragment(fragment, item);
223
+ }
224
+ }
225
+ return ids;
226
+ }
227
+
228
+ function getDataIDsFromFragment(
229
+ fragment: ReaderFragment,
230
+ item: mixed | Array<mixed>,
231
+ ): ?DataID | ?$ReadOnlyArray<DataID> {
232
+ if (item == null) {
233
+ return item;
234
+ } else if (fragment.metadata && fragment.metadata.plural === true) {
235
+ invariant(
236
+ Array.isArray(item),
237
+ 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' +
238
+ 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.',
239
+ fragment.name,
240
+ JSON.stringify(item),
241
+ fragment.name,
242
+ );
243
+ return getDataIDs(fragment, item);
244
+ } else {
245
+ invariant(
246
+ !Array.isArray(item),
247
+ 'RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. ' +
248
+ 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.',
249
+ fragment.name,
250
+ JSON.stringify(item),
251
+ fragment.name,
252
+ );
253
+ return getDataID(fragment, item);
254
+ }
255
+ }
256
+
257
+ /**
258
+ * @internal
259
+ */
260
+ function getDataIDs(
261
+ fragment: ReaderFragment,
262
+ items: $ReadOnlyArray<mixed>,
263
+ ): ?$ReadOnlyArray<DataID> {
264
+ let ids = null;
265
+ items.forEach(item => {
266
+ const id = item != null ? getDataID(fragment, item) : null;
267
+ if (id != null) {
268
+ ids = ids || [];
269
+ ids.push(id);
270
+ }
271
+ });
272
+ return ids;
273
+ }
274
+
275
+ /**
276
+ * @internal
277
+ */
278
+ function getDataID(fragment: ReaderFragment, item: mixed): ?DataID {
279
+ invariant(
280
+ typeof item === 'object' && item !== null && !Array.isArray(item),
281
+ 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' +
282
+ '`%s`.',
283
+ fragment.name,
284
+ JSON.stringify(item),
285
+ );
286
+ const dataID = item[ID_KEY];
287
+ if (typeof dataID === 'string') {
288
+ return dataID;
289
+ }
290
+ warning(
291
+ false,
292
+ 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' +
293
+ '`%s`. Make sure that the parent operation/fragment included fragment ' +
294
+ '`...%s` without `@relay(mask: false)`, or `null` is passed as the fragment ' +
295
+ "reference for `%s` if it's conditonally included and the condition isn't met.",
296
+ fragment.name,
297
+ JSON.stringify(item),
298
+ fragment.name,
299
+ fragment.name,
300
+ );
301
+ return null;
302
+ }
303
+
304
+ /**
305
+ * @public
306
+ *
307
+ * Given a mapping of keys -> results and a mapping of keys -> fragments,
308
+ * extracts the merged variables that would be in scope for those
309
+ * fragments/results.
310
+ *
311
+ * This can be useful in determing what varaibles were used to fetch the data
312
+ * for a Relay container, for example.
313
+ */
314
+ function getVariablesFromObject(
315
+ fragments: {[key: string]: ReaderFragment, ...},
316
+ object: {[key: string]: mixed, ...},
317
+ ): Variables {
318
+ const variables = {};
319
+ for (const key in fragments) {
320
+ if (fragments.hasOwnProperty(key)) {
321
+ const fragment = fragments[key];
322
+ const item = object[key];
323
+ const itemVariables = getVariablesFromFragment(fragment, item);
324
+ Object.assign(variables, itemVariables);
325
+ }
326
+ }
327
+ return variables;
328
+ }
329
+
330
+ function getVariablesFromFragment(
331
+ fragment: ReaderFragment,
332
+ item: mixed | $ReadOnlyArray<mixed>,
333
+ ): Variables {
334
+ if (item == null) {
335
+ return {};
336
+ } else if (fragment.metadata?.plural === true) {
337
+ invariant(
338
+ Array.isArray(item),
339
+ 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' +
340
+ 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.',
341
+ fragment.name,
342
+ JSON.stringify(item),
343
+ fragment.name,
344
+ );
345
+
346
+ return getVariablesFromPluralFragment(fragment, item);
347
+ } else {
348
+ invariant(
349
+ !Array.isArray(item),
350
+ 'RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. ' +
351
+ 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.',
352
+ fragment.name,
353
+ JSON.stringify(item),
354
+ fragment.name,
355
+ );
356
+
357
+ return getVariablesFromSingularFragment(fragment, item) || {};
358
+ }
359
+ }
360
+
361
+ function getVariablesFromSingularFragment(
362
+ fragment: ReaderFragment,
363
+ item: mixed,
364
+ ): ?Variables {
365
+ const selector = getSingularSelector(fragment, item);
366
+ if (!selector) {
367
+ return null;
368
+ }
369
+ return selector.variables;
370
+ }
371
+
372
+ function getVariablesFromPluralFragment(
373
+ fragment: ReaderFragment,
374
+ items: $ReadOnlyArray<mixed>,
375
+ ): Variables {
376
+ const variables = {};
377
+ items.forEach((value, ii) => {
378
+ if (value != null) {
379
+ const itemVariables = getVariablesFromSingularFragment(fragment, value);
380
+ if (itemVariables != null) {
381
+ Object.assign(variables, itemVariables);
382
+ }
383
+ }
384
+ });
385
+ return variables;
386
+ }
387
+
388
+ /**
389
+ * @public
390
+ *
391
+ * Determine if two selectors are equal (represent the same selection). Note
392
+ * that this function returns `false` when the two queries/fragments are
393
+ * different objects, even if they select the same fields.
394
+ */
395
+ function areEqualSelectors(
396
+ thisSelector: SingularReaderSelector,
397
+ thatSelector: SingularReaderSelector,
398
+ ): boolean {
399
+ return (
400
+ thisSelector.owner === thatSelector.owner &&
401
+ thisSelector.dataID === thatSelector.dataID &&
402
+ thisSelector.node === thatSelector.node &&
403
+ areEqual(thisSelector.variables, thatSelector.variables)
404
+ );
405
+ }
406
+
407
+ function createReaderSelector(
408
+ fragment: ReaderFragment,
409
+ dataID: DataID,
410
+ variables: Variables,
411
+ request: RequestDescriptor,
412
+ ): SingularReaderSelector {
413
+ return {
414
+ kind: 'SingularReaderSelector',
415
+ dataID,
416
+ node: fragment,
417
+ variables,
418
+ owner: request,
419
+ };
420
+ }
421
+
422
+ function createNormalizationSelector(
423
+ node: NormalizationSelectableNode,
424
+ dataID: DataID,
425
+ variables: Variables,
426
+ ): NormalizationSelector {
427
+ return {dataID, node, variables};
428
+ }
429
+
430
+ module.exports = {
431
+ areEqualSelectors,
432
+ createReaderSelector,
433
+ createNormalizationSelector,
434
+ getDataIDsFromFragment,
435
+ getDataIDsFromObject,
436
+ getSingularSelector,
437
+ getPluralSelector,
438
+ getSelector,
439
+ getSelectorsFromObject,
440
+ getVariablesFromSingularFragment,
441
+ getVariablesFromPluralFragment,
442
+ getVariablesFromFragment,
443
+ getVariablesFromObject,
444
+ };