relay-runtime 11.0.1 → 13.0.0-rc.1

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 (169) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +2 -2
  2. package/handlers/connection/ConnectionHandler.js.flow +8 -17
  3. package/handlers/connection/MutationHandlers.js.flow +7 -11
  4. package/index.js +1 -1
  5. package/index.js.flow +60 -36
  6. package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
  7. package/lib/handlers/connection/ConnectionHandler.js +13 -19
  8. package/lib/handlers/connection/MutationHandlers.js +4 -7
  9. package/lib/index.js +58 -43
  10. package/lib/multi-actor-environment/ActorIdentifier.js +33 -0
  11. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +152 -0
  12. package/lib/multi-actor-environment/ActorUtils.js +27 -0
  13. package/lib/multi-actor-environment/MultiActorEnvironment.js +419 -0
  14. package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
  15. package/lib/multi-actor-environment/index.js +21 -0
  16. package/lib/mutations/RelayDeclarativeMutationConfig.js +4 -1
  17. package/lib/mutations/RelayRecordProxy.js +3 -2
  18. package/lib/mutations/RelayRecordSourceMutator.js +3 -2
  19. package/lib/mutations/RelayRecordSourceProxy.js +12 -4
  20. package/lib/mutations/RelayRecordSourceSelectorProxy.js +18 -5
  21. package/lib/mutations/applyOptimisticMutation.js +6 -6
  22. package/lib/mutations/commitMutation.js +14 -10
  23. package/lib/mutations/readUpdatableQuery_EXPERIMENTAL.js +238 -0
  24. package/lib/mutations/validateMutation.js +10 -5
  25. package/lib/network/ConvertToExecuteFunction.js +2 -1
  26. package/lib/network/RelayNetwork.js +3 -2
  27. package/lib/network/RelayQueryResponseCache.js +21 -5
  28. package/lib/network/wrapNetworkWithLogObserver.js +79 -0
  29. package/lib/query/GraphQLTag.js +3 -2
  30. package/lib/query/fetchQuery.js +6 -5
  31. package/lib/query/fetchQueryInternal.js +1 -1
  32. package/lib/query/fetchQuery_DEPRECATED.js +2 -1
  33. package/lib/store/ClientID.js +7 -1
  34. package/lib/store/DataChecker.js +123 -54
  35. package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +518 -200
  36. package/lib/store/RelayConcreteVariables.js +26 -8
  37. package/lib/store/RelayExperimentalGraphResponseHandler.js +153 -0
  38. package/lib/store/RelayExperimentalGraphResponseTransform.js +391 -0
  39. package/lib/store/RelayModernEnvironment.js +175 -240
  40. package/lib/store/RelayModernFragmentSpecResolver.js +52 -26
  41. package/lib/store/RelayModernOperationDescriptor.js +2 -1
  42. package/lib/store/RelayModernRecord.js +47 -12
  43. package/lib/store/RelayModernSelector.js +14 -8
  44. package/lib/store/RelayModernStore.js +56 -28
  45. package/lib/store/RelayOperationTracker.js +34 -24
  46. package/lib/store/RelayPublishQueue.js +41 -13
  47. package/lib/store/RelayReader.js +288 -48
  48. package/lib/store/RelayRecordSource.js +87 -3
  49. package/lib/store/RelayReferenceMarker.js +34 -22
  50. package/lib/store/RelayResponseNormalizer.js +211 -110
  51. package/lib/store/RelayStoreReactFlightUtils.js +4 -10
  52. package/lib/store/RelayStoreSubscriptions.js +14 -9
  53. package/lib/store/RelayStoreUtils.js +12 -7
  54. package/lib/store/ResolverCache.js +213 -0
  55. package/lib/store/ResolverFragments.js +61 -0
  56. package/lib/store/cloneRelayHandleSourceField.js +5 -4
  57. package/lib/store/cloneRelayScalarHandleSourceField.js +5 -4
  58. package/lib/store/createRelayContext.js +4 -2
  59. package/lib/store/readInlineData.js +6 -2
  60. package/lib/subscription/requestSubscription.js +34 -25
  61. package/lib/util/RelayConcreteNode.js +3 -0
  62. package/lib/util/RelayFeatureFlags.js +10 -4
  63. package/lib/util/RelayProfiler.js +17 -187
  64. package/lib/util/RelayReplaySubject.js +22 -7
  65. package/lib/util/RelayRuntimeTypes.js +0 -6
  66. package/lib/util/StringInterner.js +71 -0
  67. package/lib/util/getFragmentIdentifier.js +15 -7
  68. package/lib/util/getOperation.js +2 -1
  69. package/lib/util/getPaginationMetadata.js +41 -0
  70. package/lib/util/getPaginationVariables.js +66 -0
  71. package/lib/util/getPendingOperationsForFragment.js +55 -0
  72. package/lib/util/getRefetchMetadata.js +36 -0
  73. package/lib/util/getRelayHandleKey.js +2 -2
  74. package/lib/util/getRequestIdentifier.js +2 -2
  75. package/lib/util/getValueAtPath.js +51 -0
  76. package/lib/util/isEmptyObject.js +1 -1
  77. package/lib/util/registerEnvironmentWithDevTools.js +26 -0
  78. package/lib/util/withDuration.js +31 -0
  79. package/multi-actor-environment/ActorIdentifier.js.flow +43 -0
  80. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +225 -0
  81. package/multi-actor-environment/ActorUtils.js.flow +33 -0
  82. package/multi-actor-environment/MultiActorEnvironment.js.flow +506 -0
  83. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +261 -0
  84. package/multi-actor-environment/index.js.flow +26 -0
  85. package/mutations/RelayDeclarativeMutationConfig.js.flow +32 -26
  86. package/mutations/RelayRecordProxy.js.flow +4 -5
  87. package/mutations/RelayRecordSourceMutator.js.flow +4 -6
  88. package/mutations/RelayRecordSourceProxy.js.flow +19 -10
  89. package/mutations/RelayRecordSourceSelectorProxy.js.flow +22 -7
  90. package/mutations/applyOptimisticMutation.js.flow +13 -14
  91. package/mutations/commitLocalUpdate.js.flow +1 -1
  92. package/mutations/commitMutation.js.flow +35 -46
  93. package/mutations/readUpdatableQuery_EXPERIMENTAL.js.flow +309 -0
  94. package/mutations/validateMutation.js.flow +26 -16
  95. package/network/ConvertToExecuteFunction.js.flow +2 -2
  96. package/network/RelayNetwork.js.flow +4 -5
  97. package/network/RelayNetworkTypes.js.flow +5 -4
  98. package/network/RelayObservable.js.flow +1 -1
  99. package/network/RelayQueryResponseCache.js.flow +34 -21
  100. package/network/wrapNetworkWithLogObserver.js.flow +100 -0
  101. package/package.json +3 -2
  102. package/query/GraphQLTag.js.flow +9 -9
  103. package/query/PreloadableQueryRegistry.js.flow +2 -1
  104. package/query/fetchQuery.js.flow +11 -13
  105. package/query/fetchQueryInternal.js.flow +6 -9
  106. package/query/fetchQuery_DEPRECATED.js.flow +6 -6
  107. package/relay-runtime.js +2 -2
  108. package/relay-runtime.min.js +2 -2
  109. package/store/ClientID.js.flow +14 -3
  110. package/store/DataChecker.js.flow +141 -59
  111. package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +605 -303
  112. package/store/RelayConcreteVariables.js.flow +27 -8
  113. package/store/RelayExperimentalGraphResponseHandler.js.flow +124 -0
  114. package/store/RelayExperimentalGraphResponseTransform.js.flow +475 -0
  115. package/store/RelayModernEnvironment.js.flow +173 -240
  116. package/store/RelayModernFragmentSpecResolver.js.flow +55 -31
  117. package/store/RelayModernOperationDescriptor.js.flow +12 -7
  118. package/store/RelayModernRecord.js.flow +67 -11
  119. package/store/RelayModernSelector.js.flow +24 -14
  120. package/store/RelayModernStore.js.flow +66 -36
  121. package/store/RelayOperationTracker.js.flow +59 -43
  122. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  123. package/store/RelayPublishQueue.js.flow +79 -34
  124. package/store/RelayReader.js.flow +351 -73
  125. package/store/RelayRecordSource.js.flow +72 -6
  126. package/store/RelayReferenceMarker.js.flow +40 -26
  127. package/store/RelayResponseNormalizer.js.flow +258 -99
  128. package/store/RelayStoreReactFlightUtils.js.flow +4 -11
  129. package/store/RelayStoreSubscriptions.js.flow +19 -11
  130. package/store/RelayStoreTypes.js.flow +209 -43
  131. package/store/RelayStoreUtils.js.flow +24 -11
  132. package/store/ResolverCache.js.flow +249 -0
  133. package/store/ResolverFragments.js.flow +121 -0
  134. package/store/StoreInspector.js.flow +2 -2
  135. package/store/TypeID.js.flow +1 -1
  136. package/store/ViewerPattern.js.flow +2 -2
  137. package/store/cloneRelayHandleSourceField.js.flow +5 -6
  138. package/store/cloneRelayScalarHandleSourceField.js.flow +5 -6
  139. package/store/createFragmentSpecResolver.js.flow +3 -4
  140. package/store/createRelayContext.js.flow +3 -3
  141. package/store/normalizeRelayPayload.js.flow +6 -7
  142. package/store/readInlineData.js.flow +7 -8
  143. package/subscription/requestSubscription.js.flow +53 -41
  144. package/util/NormalizationNode.js.flow +10 -3
  145. package/util/ReaderNode.js.flow +38 -2
  146. package/util/RelayConcreteNode.js.flow +5 -0
  147. package/util/RelayFeatureFlags.js.flow +24 -10
  148. package/util/RelayProfiler.js.flow +22 -194
  149. package/util/RelayReplaySubject.js.flow +9 -9
  150. package/util/RelayRuntimeTypes.js.flow +72 -3
  151. package/util/StringInterner.js.flow +69 -0
  152. package/util/createPayloadFor3DField.js.flow +3 -3
  153. package/util/getFragmentIdentifier.js.flow +27 -15
  154. package/util/getOperation.js.flow +2 -2
  155. package/util/getPaginationMetadata.js.flow +72 -0
  156. package/util/getPaginationVariables.js.flow +108 -0
  157. package/util/getPendingOperationsForFragment.js.flow +62 -0
  158. package/util/getRefetchMetadata.js.flow +79 -0
  159. package/util/getRelayHandleKey.js.flow +1 -2
  160. package/util/getRequestIdentifier.js.flow +3 -3
  161. package/util/getValueAtPath.js.flow +46 -0
  162. package/util/isEmptyObject.js.flow +1 -0
  163. package/util/registerEnvironmentWithDevTools.js.flow +33 -0
  164. package/util/resolveImmediate.js.flow +1 -1
  165. package/util/withDuration.js.flow +32 -0
  166. package/lib/store/RelayRecordSourceMapImpl.js +0 -107
  167. package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +0 -318
  168. package/store/RelayRecordSourceMapImpl.js.flow +0 -91
  169. package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +0 -283
@@ -12,23 +12,11 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const RelayDeclarativeMutationConfig = require('./RelayDeclarativeMutationConfig');
16
-
17
- const invariant = require('invariant');
18
- const isRelayModernEnvironment = require('../store/isRelayModernEnvironment');
19
- const validateMutation = require('./validateMutation');
20
- const warning = require('warning');
21
-
22
- const {getRequest} = require('../query/GraphQLTag');
23
- const {generateUniqueClientID} = require('../store/ClientID');
24
- const {
25
- createOperationDescriptor,
26
- } = require('../store/RelayModernOperationDescriptor');
27
-
28
15
  import type {PayloadError, UploadableMap} from '../network/RelayNetworkTypes';
29
16
  import type {GraphQLTaggedNode} from '../query/GraphQLTag';
30
17
  import type {
31
18
  IEnvironment,
19
+ MutationParameters,
32
20
  SelectorStoreUpdater,
33
21
  } from '../store/RelayStoreTypes';
34
22
  import type {
@@ -38,57 +26,63 @@ import type {
38
26
  } from '../util/RelayRuntimeTypes';
39
27
  import type {DeclarativeMutationConfig} from './RelayDeclarativeMutationConfig';
40
28
 
41
- export type DEPRECATED_MutationConfig<T> = {|
29
+ const {getRequest} = require('../query/GraphQLTag');
30
+ const {generateUniqueClientID} = require('../store/ClientID');
31
+ const isRelayModernEnvironment = require('../store/isRelayModernEnvironment');
32
+ const {
33
+ createOperationDescriptor,
34
+ } = require('../store/RelayModernOperationDescriptor');
35
+ const RelayDeclarativeMutationConfig = require('./RelayDeclarativeMutationConfig');
36
+ const validateMutation = require('./validateMutation');
37
+ const invariant = require('invariant');
38
+ const warning = require('warning');
39
+
40
+ export type DEPRECATED_MutationConfig<TMutationResponse> = {|
42
41
  configs?: Array<DeclarativeMutationConfig>,
43
42
  cacheConfig?: CacheConfig,
44
43
  mutation: GraphQLTaggedNode,
45
44
  variables: Variables,
46
45
  uploadables?: UploadableMap,
47
- onCompleted?: ?(response: T, errors: ?Array<PayloadError>) => void,
46
+ onCompleted?: ?(
47
+ response: TMutationResponse,
48
+ errors: ?Array<PayloadError>,
49
+ ) => void,
48
50
  onError?: ?(error: Error) => void,
49
51
  onUnsubscribe?: ?() => void,
50
- optimisticUpdater?: ?SelectorStoreUpdater,
52
+ optimisticUpdater?: ?SelectorStoreUpdater<TMutationResponse>,
51
53
  optimisticResponse?: Object,
52
- updater?: ?SelectorStoreUpdater,
54
+ updater?: ?SelectorStoreUpdater<TMutationResponse>,
53
55
  |};
54
56
 
55
- export type MutationParameters = {|
56
- +response: {...},
57
- +variables: interface {},
58
- +rawResponse?: {...},
59
- |};
60
-
61
- export type MutationConfig<T: MutationParameters> = {|
57
+ export type MutationConfig<TMutation: MutationParameters> = {|
62
58
  configs?: Array<DeclarativeMutationConfig>,
63
59
  cacheConfig?: CacheConfig,
64
60
  mutation: GraphQLTaggedNode,
65
61
  onError?: ?(error: Error) => void,
66
62
  onCompleted?: ?(
67
- response: $ElementType<T, 'response'>,
63
+ response: TMutation['response'],
68
64
  errors: ?Array<PayloadError>,
69
65
  ) => void,
66
+ onNext?: ?() => void,
70
67
  onUnsubscribe?: ?() => void,
71
- optimisticResponse?: $ElementType<
72
- {
73
- +rawResponse?: {...},
74
- ...T,
75
- ...
76
- },
77
- 'rawResponse',
78
- >,
79
- optimisticUpdater?: ?SelectorStoreUpdater,
80
- updater?: ?SelectorStoreUpdater,
68
+ optimisticResponse?: {
69
+ +rawResponse?: {...},
70
+ ...TMutation,
71
+ ...
72
+ }['rawResponse'],
73
+ optimisticUpdater?: ?SelectorStoreUpdater<TMutation['response']>,
74
+ updater?: ?SelectorStoreUpdater<TMutation['response']>,
81
75
  uploadables?: UploadableMap,
82
- variables: $ElementType<T, 'variables'>,
76
+ variables: TMutation['variables'],
83
77
  |};
84
78
 
85
79
  /**
86
80
  * Higher-level helper function to execute a mutation against a specific
87
81
  * environment.
88
82
  */
89
- function commitMutation<T: MutationParameters>(
83
+ function commitMutation<TMutation: MutationParameters>(
90
84
  environment: IEnvironment,
91
- config: MutationConfig<T>,
85
+ config: MutationConfig<TMutation>,
92
86
  ): Disposable {
93
87
  invariant(
94
88
  isRelayModernEnvironment(environment),
@@ -103,14 +97,8 @@ function commitMutation<T: MutationParameters>(
103
97
  throw new Error('commitMutation: Expected mutation to be of type request');
104
98
  }
105
99
  let {optimisticResponse, optimisticUpdater, updater} = config;
106
- const {
107
- configs,
108
- cacheConfig,
109
- onError,
110
- onUnsubscribe,
111
- variables,
112
- uploadables,
113
- } = config;
100
+ const {configs, cacheConfig, onError, onUnsubscribe, variables, uploadables} =
101
+ config;
114
102
  const operation = createOperationDescriptor(
115
103
  mutation,
116
104
  variables,
@@ -161,6 +149,7 @@ function commitMutation<T: MutationParameters>(
161
149
  errors.push(...payload.errors);
162
150
  }
163
151
  }
152
+ config.onNext?.();
164
153
  },
165
154
  complete: () => {
166
155
  const {onCompleted} = config;
@@ -0,0 +1,309 @@
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
+ * @emails oncall+relay
9
+ * @format
10
+ */
11
+
12
+ // flowlint ambiguous-object-type:error
13
+
14
+ 'use strict';
15
+
16
+ import type {GraphQLTaggedNode} from '../query/GraphQLTag';
17
+ import type {RecordProxy, RecordSourceProxy} from '../store/RelayStoreTypes';
18
+ import type {ReaderLinkedField, ReaderSelection} from '../util/ReaderNode';
19
+ import type {OperationType} from '../util/RelayRuntimeTypes';
20
+
21
+ const {getRequest} = require('../query/GraphQLTag');
22
+ const {getArgumentValues} = require('../store/RelayStoreUtils');
23
+
24
+ const nonUpdatableKeys = ['id', '__id', '__typename'];
25
+
26
+ function readUpdatableQuery_EXPERIMENTAL<TQuery: OperationType>(
27
+ query: GraphQLTaggedNode,
28
+ variables: TQuery['variables'],
29
+ proxy: RecordSourceProxy,
30
+ ): TQuery['response'] {
31
+ // TODO assert that the concrete request is an updatable query
32
+ const request = getRequest(query);
33
+
34
+ const updatableProxy = {};
35
+ updateProxyFromSelections(
36
+ updatableProxy,
37
+ proxy.getRoot(),
38
+ variables,
39
+ request.fragment.selections,
40
+ proxy,
41
+ );
42
+ if (__DEV__) {
43
+ Object.freeze(updatableProxy);
44
+ }
45
+ return updatableProxy;
46
+ }
47
+
48
+ function updateProxyFromSelections<TQuery: OperationType>(
49
+ mutableUpdatableProxy: TQuery['response'],
50
+ recordProxy: RecordProxy,
51
+ queryVariables: TQuery['variables'],
52
+ selections: $ReadOnlyArray<ReaderSelection>,
53
+ root: RecordSourceProxy,
54
+ ) {
55
+ for (const selection of selections) {
56
+ switch (selection.kind) {
57
+ case 'LinkedField':
58
+ // Linked fields are assignable if they contain fragment spreads or
59
+ // read-only otherwise.
60
+ const isAssignable = selection.selections.some(
61
+ item => item.kind === 'FragmentSpread',
62
+ );
63
+
64
+ const set = !isAssignable
65
+ ? undefined
66
+ : selection.plural
67
+ ? createSetterForPluralLinkedField(
68
+ selection,
69
+ queryVariables,
70
+ recordProxy,
71
+ root,
72
+ )
73
+ : createSetterForSingularLinkedField(
74
+ selection,
75
+ queryVariables,
76
+ recordProxy,
77
+ root,
78
+ );
79
+
80
+ const get = selection.plural
81
+ ? createGetterForPluralLinkedField(
82
+ selection,
83
+ queryVariables,
84
+ recordProxy,
85
+ root,
86
+ )
87
+ : createGetterForSingularLinkedField(
88
+ selection,
89
+ queryVariables,
90
+ recordProxy,
91
+ root,
92
+ );
93
+
94
+ Object.defineProperty(
95
+ mutableUpdatableProxy,
96
+ selection.alias ?? selection.name,
97
+ {
98
+ get,
99
+ set,
100
+ },
101
+ );
102
+ break;
103
+ case 'ScalarField':
104
+ const scalarFieldName = selection.alias ?? selection.name;
105
+ Object.defineProperty(mutableUpdatableProxy, scalarFieldName, {
106
+ get: function () {
107
+ const variables = getArgumentValues(
108
+ selection.args ?? [],
109
+ queryVariables,
110
+ );
111
+ // Flow incorrect assumes that the return value for the get method must match
112
+ // the set parameter.
113
+ return (recordProxy.getValue(
114
+ selection.name,
115
+ // $FlowFixMe[unclear-type] No good way to type these variables
116
+ (variables: any),
117
+ // $FlowFixMe[unclear-type] Typed by the generated updatable query flow type
118
+ ): any);
119
+ },
120
+ set: nonUpdatableKeys.includes(selection.name)
121
+ ? undefined
122
+ : // $FlowFixMe[unclear-type] Typed by the generated updatable query flow type
123
+ function (newValue: ?any) {
124
+ const variables = getArgumentValues(
125
+ selection.args ?? [],
126
+ queryVariables,
127
+ );
128
+ recordProxy.setValue(
129
+ newValue,
130
+ selection.name,
131
+ // $FlowFixMe[unclear-type] No good way to type these variables
132
+ (variables: any),
133
+ );
134
+ },
135
+ });
136
+ break;
137
+ case 'InlineFragment':
138
+ if (recordProxy.getType() === selection.type) {
139
+ updateProxyFromSelections(
140
+ mutableUpdatableProxy,
141
+ recordProxy,
142
+ queryVariables,
143
+ selection.selections,
144
+ root,
145
+ );
146
+ }
147
+ break;
148
+ case 'FragmentSpread':
149
+ // Explicitly ignore
150
+ break;
151
+ default:
152
+ throw new Error(
153
+ 'Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.',
154
+ );
155
+ }
156
+ }
157
+ }
158
+
159
+ function createSetterForPluralLinkedField<TQuery: OperationType>(
160
+ selection: ReaderLinkedField,
161
+ queryVariables: TQuery['variables'],
162
+ recordProxy: RecordProxy,
163
+ root: RecordSourceProxy,
164
+ ) {
165
+ return function set(newValue: ?$ReadOnlyArray<{__id: string, ...}>) {
166
+ const variables = getArgumentValues(selection.args ?? [], queryVariables);
167
+ if (newValue == null) {
168
+ // $FlowFixMe[unclear-type] No good way to type these variables
169
+ recordProxy.setValue(null, selection.name, (variables: any));
170
+ } else {
171
+ const recordProxies = newValue.map(item => {
172
+ if (item == null) {
173
+ throw new Error(
174
+ 'When assigning an array of items, none of the items should be null or undefined.',
175
+ );
176
+ }
177
+ const {__id} = item;
178
+ if (__id == null) {
179
+ throw new Error(
180
+ 'The __id field must be present on each item passed to the setter. This indicates a bug in Relay.',
181
+ );
182
+ }
183
+ const newValueRecord = root.get(__id);
184
+ if (newValueRecord == null) {
185
+ throw new Error(
186
+ `Did not find item with data id ${__id} in the store.`,
187
+ );
188
+ }
189
+ return newValueRecord;
190
+ });
191
+ recordProxy.setLinkedRecords(
192
+ recordProxies,
193
+ selection.name,
194
+ // $FlowFixMe[unclear-type] No good way to type these variables
195
+ (variables: any),
196
+ );
197
+ }
198
+ };
199
+ }
200
+ function createSetterForSingularLinkedField<TQuery: OperationType>(
201
+ selection: ReaderLinkedField,
202
+ queryVariables: TQuery['variables'],
203
+ recordProxy: RecordProxy,
204
+ root: RecordSourceProxy,
205
+ ) {
206
+ return function set(newValue: ?{__id: string, ...}) {
207
+ const variables = getArgumentValues(selection.args ?? [], queryVariables);
208
+ if (newValue == null) {
209
+ // $FlowFixMe[unclear-type] No good way to type these variables
210
+ recordProxy.setValue(null, selection.name, (variables: any));
211
+ } else {
212
+ const {__id} = newValue;
213
+ if (__id == null) {
214
+ throw new Error(
215
+ 'The __id field must be present on the argument. This indicates a bug in Relay.',
216
+ );
217
+ }
218
+ const newValueRecord = root.get(__id);
219
+ if (newValueRecord == null) {
220
+ throw new Error(`Did not find item with data id ${__id} in the store.`);
221
+ }
222
+ recordProxy.setLinkedRecord(
223
+ newValueRecord,
224
+ selection.name,
225
+ // $FlowFixMe[unclear-type] No good way to type these variables
226
+ (variables: any),
227
+ );
228
+ }
229
+ };
230
+ }
231
+
232
+ function createGetterForPluralLinkedField<TQuery: OperationType>(
233
+ selection: ReaderLinkedField,
234
+ queryVariables: TQuery['variables'],
235
+ recordProxy: RecordProxy,
236
+ root: RecordSourceProxy,
237
+ ) {
238
+ return function () {
239
+ const variables = getArgumentValues(selection.args ?? [], queryVariables);
240
+ const linkedRecords = recordProxy.getLinkedRecords(
241
+ selection.name,
242
+ // $FlowFixMe[unclear-type] No good way to type these variables
243
+ (variables: any),
244
+ );
245
+ if (linkedRecords != null) {
246
+ return (linkedRecords.map(linkedRecord => {
247
+ if (linkedRecord != null) {
248
+ const updatableProxy = {};
249
+ updateProxyFromSelections(
250
+ updatableProxy,
251
+ linkedRecord,
252
+ queryVariables,
253
+ selection.selections,
254
+ root,
255
+ );
256
+ if (__DEV__) {
257
+ Object.freeze(updatableProxy);
258
+ }
259
+ // Flow incorrect assumes that the return value for the get method must match
260
+ // the set parameter.
261
+ // $FlowFixMe[unclear-type] Typed by the generated updatable query flow type
262
+ return (updatableProxy: any);
263
+ } else {
264
+ return linkedRecord;
265
+ }
266
+ // $FlowFixMe[unclear-type] Typed by the generated updatable query flow type
267
+ }): any);
268
+ } else {
269
+ return linkedRecords;
270
+ }
271
+ };
272
+ }
273
+
274
+ function createGetterForSingularLinkedField<TQuery: OperationType>(
275
+ selection: ReaderLinkedField,
276
+ queryVariables: TQuery['variables'],
277
+ recordProxy: RecordProxy,
278
+ root: RecordSourceProxy,
279
+ ) {
280
+ return function () {
281
+ const variables = getArgumentValues(selection.args ?? [], queryVariables);
282
+ const linkedRecord = recordProxy.getLinkedRecord(
283
+ selection.name,
284
+ // $FlowFixMe[unclear-type] No good way to type these variables
285
+ (variables: any),
286
+ );
287
+ if (linkedRecord != null) {
288
+ const updatableProxy = {};
289
+ updateProxyFromSelections(
290
+ updatableProxy,
291
+ linkedRecord,
292
+ queryVariables,
293
+ selection.selections,
294
+ root,
295
+ );
296
+ if (__DEV__) {
297
+ Object.freeze(updatableProxy);
298
+ }
299
+ // Flow incorrect assumes that the return value for the get method must match
300
+ // the set parameter.
301
+ // $FlowFixMe[unclear-type] Typed by the generated updatable query flow type
302
+ return (updatableProxy: any);
303
+ } else {
304
+ return linkedRecord;
305
+ }
306
+ };
307
+ }
308
+
309
+ module.exports = {readUpdatableQuery_EXPERIMENTAL};
@@ -13,29 +13,17 @@
13
13
  'use strict';
14
14
 
15
15
  import type {
16
- NormalizationSelection,
17
16
  NormalizationField,
17
+ NormalizationSelection,
18
18
  } from '../util/NormalizationNode';
19
19
  import type {ConcreteRequest} from '../util/RelayConcreteNode';
20
20
  import type {Variables} from '../util/RelayRuntimeTypes';
21
21
 
22
- type ValidationContext = {|
23
- visitedPaths: Set<string>,
24
- path: string,
25
- variables: Variables,
26
- missingDiff: Object,
27
- extraDiff: Object,
28
- moduleImportPaths: Set<string>,
29
- |};
30
-
31
- const warning = require('warning');
32
-
33
- const hasOwnProperty = Object.prototype.hasOwnProperty;
34
-
35
22
  const {
36
- CONDITION,
23
+ ACTOR_CHANGE,
37
24
  CLIENT_COMPONENT,
38
25
  CLIENT_EXTENSION,
26
+ CONDITION,
39
27
  DEFER,
40
28
  FLIGHT_FIELD,
41
29
  FRAGMENT_SPREAD,
@@ -48,10 +36,26 @@ const {
48
36
  STREAM,
49
37
  TYPE_DISCRIMINATOR,
50
38
  } = require('../util/RelayConcreteNode');
39
+ const warning = require('warning');
40
+
41
+ type ValidationContext = {|
42
+ visitedPaths: Set<string>,
43
+ path: string,
44
+ variables: Variables,
45
+ missingDiff: Object,
46
+ extraDiff: Object,
47
+ moduleImportPaths: Set<string>,
48
+ |};
49
+ // $FlowFixMe[method-unbinding] added when improving typing for this parameters
50
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
51
51
 
52
52
  let validateMutation = () => {};
53
53
  if (__DEV__) {
54
- const addFieldToDiff = (path: string, diff: Object, isScalar) => {
54
+ const addFieldToDiff = (
55
+ path: string,
56
+ diff: Object,
57
+ isScalar: void | boolean,
58
+ ) => {
55
59
  let deepLoc = diff;
56
60
  path.split('.').forEach((key, index, arr) => {
57
61
  if (deepLoc[key] == null) {
@@ -128,6 +132,12 @@ if (__DEV__) {
128
132
  case LINKED_FIELD:
129
133
  case FLIGHT_FIELD:
130
134
  return validateField(optimisticResponse, selection, context);
135
+ case ACTOR_CHANGE:
136
+ return validateField(
137
+ optimisticResponse,
138
+ selection.linkedField,
139
+ context,
140
+ );
131
141
  case INLINE_FRAGMENT:
132
142
  const type = selection.type;
133
143
  const isConcreteType = selection.abstractKey == null;
@@ -12,10 +12,10 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const RelayObservable = require('./RelayObservable');
16
-
17
15
  import type {ExecuteFunction, FetchFunction} from './RelayNetworkTypes';
18
16
 
17
+ const RelayObservable = require('./RelayObservable');
18
+
19
19
  /**
20
20
  * Converts a FetchFunction into an ExecuteFunction for use by RelayNetwork.
21
21
  */
@@ -12,22 +12,21 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const invariant = require('invariant');
16
-
17
- const {convertFetch} = require('./ConvertToExecuteFunction');
18
-
19
15
  import type {RequestParameters} from '../util/RelayConcreteNode';
20
16
  import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
21
17
  import type {
22
18
  FetchFunction,
23
19
  GraphQLResponse,
24
- LogRequestInfoFunction,
25
20
  INetwork,
21
+ LogRequestInfoFunction,
26
22
  SubscribeFunction,
27
23
  UploadableMap,
28
24
  } from './RelayNetworkTypes';
29
25
  import type RelayObservable from './RelayObservable';
30
26
 
27
+ const {convertFetch} = require('./ConvertToExecuteFunction');
28
+ const invariant = require('invariant');
29
+
31
30
  /**
32
31
  * Creates an implementation of the `Network` interface defined in
33
32
  * `RelayNetworkTypes` given `fetch` and `subscribe` functions.
@@ -20,9 +20,10 @@ import type RelayObservable, {ObservableFromValue} from './RelayObservable';
20
20
  * An interface for fetching the data for one or more (possibly interdependent)
21
21
  * queries.
22
22
  */
23
- export type INetwork = {|
24
- execute: ExecuteFunction,
25
- |};
23
+ export interface INetwork {
24
+ +execute: ExecuteFunction;
25
+ }
26
+
26
27
  export type LogRequestInfoFunction = mixed => void;
27
28
 
28
29
  export type PayloadData = interface {[key: string]: mixed};
@@ -42,7 +43,7 @@ export type PayloadExtensions = {[key: string]: mixed, ...};
42
43
 
43
44
  /**
44
45
  * The shape of a GraphQL response as dictated by the
45
- * [spec](https://graphql.github.io/graphql-spec/June2018/#sec-Response-Format)
46
+ * [spec](https://spec.graphql.org/June2018/#sec-Response-Format).
46
47
  */
47
48
  export type GraphQLResponseWithData = {|
48
49
  +data: PayloadData,
@@ -223,7 +223,7 @@ class RelayObservable<+T> implements Subscribable<T> {
223
223
  do(observer: Observer<T>): RelayObservable<T> {
224
224
  return RelayObservable.create(sink => {
225
225
  const both = (action: any) =>
226
- function() {
226
+ function () {
227
227
  try {
228
228
  observer[action] && observer[action].apply(observer, arguments);
229
229
  } catch (error) {
@@ -12,15 +12,18 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const invariant = require('invariant');
16
- const stableCopy = require('../util/stableCopy');
17
-
18
15
  import type {Variables} from '../util/RelayRuntimeTypes';
19
- import type {GraphQLSingularResponse} from './RelayNetworkTypes';
16
+ import type {
17
+ GraphQLResponse,
18
+ GraphQLSingularResponse,
19
+ } from './RelayNetworkTypes';
20
+
21
+ const stableCopy = require('../util/stableCopy');
22
+ const invariant = require('invariant');
20
23
 
21
24
  type Response = {
22
25
  fetchTime: number,
23
- payload: GraphQLSingularResponse,
26
+ payload: GraphQLResponse,
24
27
  ...
25
28
  };
26
29
 
@@ -55,7 +58,7 @@ class RelayQueryResponseCache {
55
58
  this._responses.clear();
56
59
  }
57
60
 
58
- get(queryID: string, variables: Variables): ?GraphQLSingularResponse {
61
+ get(queryID: string, variables: Variables): ?GraphQLResponse {
59
62
  const cacheKey = getCacheKey(queryID, variables);
60
63
  this._responses.forEach((response, key) => {
61
64
  if (!isCurrent(response.fetchTime, this._ttl)) {
@@ -63,23 +66,33 @@ class RelayQueryResponseCache {
63
66
  }
64
67
  });
65
68
  const response = this._responses.get(cacheKey);
66
- return response != null
67
- ? // $FlowFixMe[speculation-ambiguous]
68
- ({
69
- ...response.payload,
70
- extensions: {
71
- ...response.payload.extensions,
72
- cacheTimestamp: response.fetchTime,
73
- },
74
- }: GraphQLSingularResponse)
75
- : null;
69
+ if (response == null) {
70
+ return null;
71
+ }
72
+ if (Array.isArray(response.payload)) {
73
+ return response.payload.map(
74
+ payload =>
75
+ // $FlowFixMe[incompatible-cast]
76
+ ({
77
+ ...payload,
78
+ extensions: {
79
+ ...payload.extensions,
80
+ cacheTimestamp: response.fetchTime,
81
+ },
82
+ }: GraphQLSingularResponse),
83
+ );
84
+ }
85
+ // $FlowFixMe[incompatible-cast]
86
+ return ({
87
+ ...response.payload,
88
+ extensions: {
89
+ ...response.payload.extensions,
90
+ cacheTimestamp: response.fetchTime,
91
+ },
92
+ }: GraphQLSingularResponse);
76
93
  }
77
94
 
78
- set(
79
- queryID: string,
80
- variables: Variables,
81
- payload: GraphQLSingularResponse,
82
- ): void {
95
+ set(queryID: string, variables: Variables, payload: GraphQLResponse): void {
83
96
  const fetchTime = Date.now();
84
97
  const cacheKey = getCacheKey(queryID, variables);
85
98
  this._responses.delete(cacheKey); // deletion resets key ordering