relay-runtime 9.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 (111) 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/connection/ConnectionHandler.js +1 -3
  7. package/lib/index.js +1 -2
  8. package/lib/mutations/RelayDeclarativeMutationConfig.js +22 -45
  9. package/lib/mutations/RelayRecordProxy.js +1 -3
  10. package/lib/mutations/RelayRecordSourceMutator.js +1 -3
  11. package/lib/mutations/RelayRecordSourceProxy.js +1 -3
  12. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -3
  13. package/lib/mutations/commitMutation.js +2 -0
  14. package/lib/mutations/validateMutation.js +13 -4
  15. package/lib/network/RelayObservable.js +9 -9
  16. package/lib/network/RelayQueryResponseCache.js +8 -6
  17. package/lib/query/fetchQueryInternal.js +1 -8
  18. package/lib/store/DataChecker.js +23 -51
  19. package/lib/store/RelayConcreteVariables.js +6 -2
  20. package/lib/store/RelayModernEnvironment.js +30 -12
  21. package/lib/store/RelayModernFragmentSpecResolver.js +9 -13
  22. package/lib/store/RelayModernQueryExecutor.js +73 -37
  23. package/lib/store/RelayModernRecord.js +14 -9
  24. package/lib/store/RelayModernStore.js +107 -70
  25. package/lib/store/RelayOperationTracker.js +35 -78
  26. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  27. package/lib/store/RelayPublishQueue.js +1 -3
  28. package/lib/store/RelayReader.js +1 -3
  29. package/lib/store/RelayRecordSource.js +1 -3
  30. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  31. package/lib/store/RelayReferenceMarker.js +2 -6
  32. package/lib/store/RelayResponseNormalizer.js +9 -10
  33. package/lib/store/StoreInspector.js +7 -5
  34. package/lib/store/normalizeRelayPayload.js +6 -2
  35. package/lib/subscription/requestSubscription.js +4 -2
  36. package/lib/util/RelayFeatureFlags.js +1 -1
  37. package/lib/util/RelayReplaySubject.js +1 -3
  38. package/lib/util/createPayloadFor3DField.js +7 -2
  39. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  40. package/mutations/RelayRecordProxy.js.flow +165 -0
  41. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  42. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  43. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  44. package/mutations/applyOptimisticMutation.js.flow +76 -0
  45. package/mutations/commitLocalUpdate.js.flow +24 -0
  46. package/mutations/commitMutation.js.flow +184 -0
  47. package/mutations/validateMutation.js.flow +211 -0
  48. package/network/ConvertToExecuteFunction.js.flow +49 -0
  49. package/network/RelayNetwork.js.flow +84 -0
  50. package/network/RelayNetworkTypes.js.flow +123 -0
  51. package/network/RelayObservable.js.flow +634 -0
  52. package/network/RelayQueryResponseCache.js.flow +111 -0
  53. package/package.json +1 -1
  54. package/query/GraphQLTag.js.flow +166 -0
  55. package/query/fetchQuery.js.flow +47 -0
  56. package/query/fetchQueryInternal.js.flow +349 -0
  57. package/relay-runtime.js +2 -2
  58. package/relay-runtime.min.js +2 -2
  59. package/store/ClientID.js.flow +43 -0
  60. package/store/DataChecker.js.flow +426 -0
  61. package/store/RelayConcreteVariables.js.flow +96 -0
  62. package/store/RelayModernEnvironment.js.flow +526 -0
  63. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  64. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  65. package/store/RelayModernQueryExecutor.js.flow +1327 -0
  66. package/store/RelayModernRecord.js.flow +403 -0
  67. package/store/RelayModernSelector.js.flow +444 -0
  68. package/store/RelayModernStore.js.flow +757 -0
  69. package/store/RelayOperationTracker.js.flow +164 -0
  70. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  71. package/store/RelayPublishQueue.js.flow +401 -0
  72. package/store/RelayReader.js.flow +376 -0
  73. package/store/RelayRecordSource.js.flow +29 -0
  74. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  75. package/store/RelayRecordState.js.flow +37 -0
  76. package/store/RelayReferenceMarker.js.flow +236 -0
  77. package/store/RelayResponseNormalizer.js.flow +556 -0
  78. package/store/RelayStoreTypes.js.flow +873 -0
  79. package/store/RelayStoreUtils.js.flow +218 -0
  80. package/store/StoreInspector.js.flow +173 -0
  81. package/store/ViewerPattern.js.flow +26 -0
  82. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  83. package/store/createFragmentSpecResolver.js.flow +55 -0
  84. package/store/createRelayContext.js.flow +44 -0
  85. package/store/defaultGetDataID.js.flow +27 -0
  86. package/store/hasOverlappingIDs.js.flow +34 -0
  87. package/store/isRelayModernEnvironment.js.flow +27 -0
  88. package/store/normalizeRelayPayload.js.flow +51 -0
  89. package/store/readInlineData.js.flow +75 -0
  90. package/subscription/requestSubscription.js.flow +100 -0
  91. package/util/JSResourceTypes.flow.js.flow +20 -0
  92. package/util/NormalizationNode.js.flow +191 -0
  93. package/util/ReaderNode.js.flow +208 -0
  94. package/util/RelayConcreteNode.js.flow +80 -0
  95. package/util/RelayDefaultHandleKey.js.flow +17 -0
  96. package/util/RelayError.js.flow +33 -0
  97. package/util/RelayFeatureFlags.js.flow +30 -0
  98. package/util/RelayProfiler.js.flow +284 -0
  99. package/util/RelayReplaySubject.js.flow +134 -0
  100. package/util/RelayRuntimeTypes.js.flow +70 -0
  101. package/util/createPayloadFor3DField.js.flow +43 -0
  102. package/util/deepFreeze.js.flow +36 -0
  103. package/util/generateID.js.flow +21 -0
  104. package/util/getFragmentIdentifier.js.flow +52 -0
  105. package/util/getRelayHandleKey.js.flow +41 -0
  106. package/util/getRequestIdentifier.js.flow +41 -0
  107. package/util/isPromise.js.flow +21 -0
  108. package/util/isScalarAndEqual.js.flow +26 -0
  109. package/util/recycleNodesInto.js.flow +80 -0
  110. package/util/resolveImmediate.js.flow +30 -0
  111. package/util/stableCopy.js.flow +35 -0
@@ -0,0 +1,165 @@
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 invariant = require('invariant');
16
+
17
+ const {generateClientID} = require('../store/ClientID');
18
+ const {getStableStorageKey} = require('../store/RelayStoreUtils');
19
+
20
+ import type {RecordProxy} from '../store/RelayStoreTypes';
21
+ import type {Arguments} from '../store/RelayStoreUtils';
22
+ import type {DataID} from '../util/RelayRuntimeTypes';
23
+ import type RelayRecordSourceMutator from './RelayRecordSourceMutator';
24
+ import type RelayRecordSourceProxy from './RelayRecordSourceProxy';
25
+
26
+ /**
27
+ * @internal
28
+ *
29
+ * A helper class for manipulating a given record from a record source via an
30
+ * imperative/OO-style API.
31
+ */
32
+ class RelayRecordProxy implements RecordProxy {
33
+ _dataID: DataID;
34
+ _mutator: RelayRecordSourceMutator;
35
+ _source: RelayRecordSourceProxy;
36
+
37
+ constructor(
38
+ source: RelayRecordSourceProxy,
39
+ mutator: RelayRecordSourceMutator,
40
+ dataID: DataID,
41
+ ) {
42
+ this._dataID = dataID;
43
+ this._mutator = mutator;
44
+ this._source = source;
45
+ }
46
+
47
+ copyFieldsFrom(source: RecordProxy): void {
48
+ this._mutator.copyFields(source.getDataID(), this._dataID);
49
+ }
50
+
51
+ getDataID(): DataID {
52
+ return this._dataID;
53
+ }
54
+
55
+ getType(): string {
56
+ const type = this._mutator.getType(this._dataID);
57
+ invariant(
58
+ type != null,
59
+ 'RelayRecordProxy: Cannot get the type of deleted record `%s`.',
60
+ this._dataID,
61
+ );
62
+ return type;
63
+ }
64
+
65
+ getValue(name: string, args?: ?Arguments): mixed {
66
+ const storageKey = getStableStorageKey(name, args);
67
+ return this._mutator.getValue(this._dataID, storageKey);
68
+ }
69
+
70
+ setValue(value: mixed, name: string, args?: ?Arguments): RecordProxy {
71
+ invariant(
72
+ isValidLeafValue(value),
73
+ 'RelayRecordProxy#setValue(): Expected a scalar or array of scalars, ' +
74
+ 'got `%s`.',
75
+ JSON.stringify(value),
76
+ );
77
+ const storageKey = getStableStorageKey(name, args);
78
+ this._mutator.setValue(this._dataID, storageKey, value);
79
+ return this;
80
+ }
81
+
82
+ getLinkedRecord(name: string, args?: ?Arguments): ?RecordProxy {
83
+ const storageKey = getStableStorageKey(name, args);
84
+ const linkedID = this._mutator.getLinkedRecordID(this._dataID, storageKey);
85
+ return linkedID != null ? this._source.get(linkedID) : linkedID;
86
+ }
87
+
88
+ setLinkedRecord(
89
+ record: RecordProxy,
90
+ name: string,
91
+ args?: ?Arguments,
92
+ ): RecordProxy {
93
+ invariant(
94
+ record instanceof RelayRecordProxy,
95
+ 'RelayRecordProxy#setLinkedRecord(): Expected a record, got `%s`.',
96
+ record,
97
+ );
98
+ const storageKey = getStableStorageKey(name, args);
99
+ const linkedID = record.getDataID();
100
+ this._mutator.setLinkedRecordID(this._dataID, storageKey, linkedID);
101
+ return this;
102
+ }
103
+
104
+ getOrCreateLinkedRecord(
105
+ name: string,
106
+ typeName: string,
107
+ args?: ?Arguments,
108
+ ): RecordProxy {
109
+ let linkedRecord = this.getLinkedRecord(name, args);
110
+ if (!linkedRecord) {
111
+ const storageKey = getStableStorageKey(name, args);
112
+ const clientID = generateClientID(this.getDataID(), storageKey);
113
+ // NOTE: it's possible that a client record for this field exists
114
+ // but the field itself was unset.
115
+ linkedRecord =
116
+ this._source.get(clientID) ?? this._source.create(clientID, typeName);
117
+ this.setLinkedRecord(linkedRecord, name, args);
118
+ }
119
+ return linkedRecord;
120
+ }
121
+
122
+ getLinkedRecords(name: string, args?: ?Arguments): ?Array<?RecordProxy> {
123
+ const storageKey = getStableStorageKey(name, args);
124
+ const linkedIDs = this._mutator.getLinkedRecordIDs(
125
+ this._dataID,
126
+ storageKey,
127
+ );
128
+ if (linkedIDs == null) {
129
+ return linkedIDs;
130
+ }
131
+ return linkedIDs.map(linkedID => {
132
+ return linkedID != null ? this._source.get(linkedID) : linkedID;
133
+ });
134
+ }
135
+
136
+ setLinkedRecords(
137
+ records: Array<?RecordProxy>,
138
+ name: string,
139
+ args?: ?Arguments,
140
+ ): RecordProxy {
141
+ invariant(
142
+ Array.isArray(records),
143
+ 'RelayRecordProxy#setLinkedRecords(): Expected records to be an array, got `%s`.',
144
+ records,
145
+ );
146
+ const storageKey = getStableStorageKey(name, args);
147
+ const linkedIDs = records.map(record => record && record.getDataID());
148
+ this._mutator.setLinkedRecordIDs(this._dataID, storageKey, linkedIDs);
149
+ return this;
150
+ }
151
+
152
+ invalidateRecord(): void {
153
+ this._source.markIDForInvalidation(this._dataID);
154
+ }
155
+ }
156
+
157
+ function isValidLeafValue(value: mixed): boolean {
158
+ return (
159
+ value == null ||
160
+ typeof value !== 'object' ||
161
+ (Array.isArray(value) && value.every(isValidLeafValue))
162
+ );
163
+ }
164
+
165
+ module.exports = RelayRecordProxy;
@@ -0,0 +1,238 @@
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 RelayModernRecord = require('../store/RelayModernRecord');
16
+
17
+ const invariant = require('invariant');
18
+
19
+ const {EXISTENT} = require('../store/RelayRecordState');
20
+
21
+ import type {RecordState} from '../store/RelayRecordState';
22
+ import type {
23
+ MutableRecordSource,
24
+ Record,
25
+ RecordSource,
26
+ } from '../store/RelayStoreTypes';
27
+ import type {DataID} from '../util/RelayRuntimeTypes';
28
+
29
+ /**
30
+ * @internal
31
+ *
32
+ * Wrapper API that is an amalgam of the `RelayModernRecord` API and
33
+ * `MutableRecordSource` interface, implementing copy-on-write semantics for records
34
+ * in a record source.
35
+ *
36
+ * Modifications are applied to fresh copies of records:
37
+ * - Records in `base` are never modified.
38
+ * - Modifications cause a fresh version of a record to be created in `sink`.
39
+ * These sink records contain only modified fields.
40
+ */
41
+ class RelayRecordSourceMutator {
42
+ __sources: Array<RecordSource>;
43
+ _base: RecordSource;
44
+ _sink: MutableRecordSource;
45
+
46
+ constructor(base: RecordSource, sink: MutableRecordSource) {
47
+ this.__sources = [sink, base];
48
+ this._base = base;
49
+ this._sink = sink;
50
+ }
51
+
52
+ /**
53
+ * **UNSTABLE**
54
+ * This method is likely to be removed in an upcoming release
55
+ * and should not be relied upon.
56
+ * TODO T41593196: Remove unstable_getRawRecordWithChanges
57
+ */
58
+ unstable_getRawRecordWithChanges(dataID: DataID): ?Record {
59
+ const baseRecord = this._base.get(dataID);
60
+ const sinkRecord = this._sink.get(dataID);
61
+ if (sinkRecord === undefined) {
62
+ if (baseRecord == null) {
63
+ return baseRecord;
64
+ }
65
+ const nextRecord = RelayModernRecord.clone(baseRecord);
66
+ if (__DEV__) {
67
+ // Prevent mutation of a record from outside the store.
68
+ RelayModernRecord.freeze(nextRecord);
69
+ }
70
+ return nextRecord;
71
+ } else if (sinkRecord === null) {
72
+ return null;
73
+ } else if (baseRecord != null) {
74
+ const nextRecord = RelayModernRecord.update(baseRecord, sinkRecord);
75
+ if (__DEV__) {
76
+ if (nextRecord !== baseRecord) {
77
+ // Prevent mutation of a record from outside the store.
78
+ RelayModernRecord.freeze(nextRecord);
79
+ }
80
+ }
81
+ return nextRecord;
82
+ } else {
83
+ const nextRecord = RelayModernRecord.clone(sinkRecord);
84
+ if (__DEV__) {
85
+ // Prevent mutation of a record from outside the store.
86
+ RelayModernRecord.freeze(nextRecord);
87
+ }
88
+ return nextRecord;
89
+ }
90
+ }
91
+
92
+ _getSinkRecord(dataID: DataID): Record {
93
+ let sinkRecord = this._sink.get(dataID);
94
+ if (!sinkRecord) {
95
+ const baseRecord = this._base.get(dataID);
96
+ invariant(
97
+ baseRecord,
98
+ 'RelayRecordSourceMutator: Cannot modify non-existent record `%s`.',
99
+ dataID,
100
+ );
101
+ sinkRecord = RelayModernRecord.create(
102
+ dataID,
103
+ RelayModernRecord.getType(baseRecord),
104
+ );
105
+ this._sink.set(dataID, sinkRecord);
106
+ }
107
+ return sinkRecord;
108
+ }
109
+
110
+ copyFields(sourceID: DataID, sinkID: DataID): void {
111
+ const sinkSource = this._sink.get(sourceID);
112
+ const baseSource = this._base.get(sourceID);
113
+ invariant(
114
+ sinkSource || baseSource,
115
+ 'RelayRecordSourceMutator#copyFields(): Cannot copy fields from ' +
116
+ 'non-existent record `%s`.',
117
+ sourceID,
118
+ );
119
+ const sink = this._getSinkRecord(sinkID);
120
+ if (baseSource) {
121
+ RelayModernRecord.copyFields(baseSource, sink);
122
+ }
123
+ if (sinkSource) {
124
+ RelayModernRecord.copyFields(sinkSource, sink);
125
+ }
126
+ }
127
+
128
+ copyFieldsFromRecord(record: Record, sinkID: DataID): void {
129
+ const sink = this._getSinkRecord(sinkID);
130
+ RelayModernRecord.copyFields(record, sink);
131
+ }
132
+
133
+ create(dataID: DataID, typeName: string): void {
134
+ invariant(
135
+ this._base.getStatus(dataID) !== EXISTENT &&
136
+ this._sink.getStatus(dataID) !== EXISTENT,
137
+ 'RelayRecordSourceMutator#create(): Cannot create a record with id ' +
138
+ '`%s`, this record already exists.',
139
+ dataID,
140
+ );
141
+ const record = RelayModernRecord.create(dataID, typeName);
142
+ this._sink.set(dataID, record);
143
+ }
144
+
145
+ delete(dataID: DataID): void {
146
+ this._sink.delete(dataID);
147
+ }
148
+
149
+ getStatus(dataID: DataID): RecordState {
150
+ return this._sink.has(dataID)
151
+ ? this._sink.getStatus(dataID)
152
+ : this._base.getStatus(dataID);
153
+ }
154
+
155
+ getType(dataID: DataID): ?string {
156
+ for (let ii = 0; ii < this.__sources.length; ii++) {
157
+ const record = this.__sources[ii].get(dataID);
158
+ if (record) {
159
+ return RelayModernRecord.getType(record);
160
+ } else if (record === null) {
161
+ return null;
162
+ }
163
+ }
164
+ }
165
+
166
+ getValue(dataID: DataID, storageKey: string): mixed {
167
+ for (let ii = 0; ii < this.__sources.length; ii++) {
168
+ const record = this.__sources[ii].get(dataID);
169
+ if (record) {
170
+ const value = RelayModernRecord.getValue(record, storageKey);
171
+ if (value !== undefined) {
172
+ return value;
173
+ }
174
+ } else if (record === null) {
175
+ return null;
176
+ }
177
+ }
178
+ }
179
+
180
+ setValue(dataID: DataID, storageKey: string, value: mixed): void {
181
+ const sinkRecord = this._getSinkRecord(dataID);
182
+ RelayModernRecord.setValue(sinkRecord, storageKey, value);
183
+ }
184
+
185
+ getLinkedRecordID(dataID: DataID, storageKey: string): ?DataID {
186
+ for (let ii = 0; ii < this.__sources.length; ii++) {
187
+ const record = this.__sources[ii].get(dataID);
188
+ if (record) {
189
+ const linkedID = RelayModernRecord.getLinkedRecordID(
190
+ record,
191
+ storageKey,
192
+ );
193
+ if (linkedID !== undefined) {
194
+ return linkedID;
195
+ }
196
+ } else if (record === null) {
197
+ return null;
198
+ }
199
+ }
200
+ }
201
+
202
+ setLinkedRecordID(
203
+ dataID: DataID,
204
+ storageKey: string,
205
+ linkedID: DataID,
206
+ ): void {
207
+ const sinkRecord = this._getSinkRecord(dataID);
208
+ RelayModernRecord.setLinkedRecordID(sinkRecord, storageKey, linkedID);
209
+ }
210
+
211
+ getLinkedRecordIDs(dataID: DataID, storageKey: string): ?Array<?DataID> {
212
+ for (let ii = 0; ii < this.__sources.length; ii++) {
213
+ const record = this.__sources[ii].get(dataID);
214
+ if (record) {
215
+ const linkedIDs = RelayModernRecord.getLinkedRecordIDs(
216
+ record,
217
+ storageKey,
218
+ );
219
+ if (linkedIDs !== undefined) {
220
+ return linkedIDs;
221
+ }
222
+ } else if (record === null) {
223
+ return null;
224
+ }
225
+ }
226
+ }
227
+
228
+ setLinkedRecordIDs(
229
+ dataID: DataID,
230
+ storageKey: string,
231
+ linkedIDs: Array<?DataID>,
232
+ ): void {
233
+ const sinkRecord = this._getSinkRecord(dataID);
234
+ RelayModernRecord.setLinkedRecordIDs(sinkRecord, storageKey, linkedIDs);
235
+ }
236
+ }
237
+
238
+ module.exports = RelayRecordSourceMutator;
@@ -0,0 +1,164 @@
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
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const RelayModernRecord = require('../store/RelayModernRecord');
16
+ const RelayRecordProxy = require('./RelayRecordProxy');
17
+
18
+ const invariant = require('invariant');
19
+
20
+ const {EXISTENT, NONEXISTENT} = require('../store/RelayRecordState');
21
+ const {ROOT_ID, ROOT_TYPE} = require('../store/RelayStoreUtils');
22
+
23
+ import type {HandlerProvider} from '../handlers/RelayDefaultHandlerProvider';
24
+ import type {GetDataID} from '../store/RelayResponseNormalizer';
25
+ import type {
26
+ HandleFieldPayload,
27
+ RecordSource,
28
+ RecordProxy,
29
+ RecordSourceProxy,
30
+ } from '../store/RelayStoreTypes';
31
+ import type {DataID} from '../util/RelayRuntimeTypes';
32
+ import type RelayRecordSourceMutator from './RelayRecordSourceMutator';
33
+
34
+ /**
35
+ * @internal
36
+ *
37
+ * A helper for manipulating a `RecordSource` via an imperative/OO-style API.
38
+ */
39
+ class RelayRecordSourceProxy implements RecordSourceProxy {
40
+ _handlerProvider: ?HandlerProvider;
41
+ __mutator: RelayRecordSourceMutator;
42
+ _proxies: {[dataID: DataID]: ?RelayRecordProxy, ...};
43
+ _getDataID: GetDataID;
44
+ _invalidatedStore: boolean;
45
+ _idsMarkedForInvalidation: Set<DataID>;
46
+
47
+ constructor(
48
+ mutator: RelayRecordSourceMutator,
49
+ getDataID: GetDataID,
50
+ handlerProvider?: ?HandlerProvider,
51
+ ) {
52
+ this.__mutator = mutator;
53
+ this._handlerProvider = handlerProvider || null;
54
+ this._proxies = {};
55
+ this._getDataID = getDataID;
56
+ this._invalidatedStore = false;
57
+ this._idsMarkedForInvalidation = new Set();
58
+ }
59
+
60
+ publishSource(
61
+ source: RecordSource,
62
+ fieldPayloads?: ?Array<HandleFieldPayload>,
63
+ ): void {
64
+ const dataIDs = source.getRecordIDs();
65
+ dataIDs.forEach(dataID => {
66
+ const status = source.getStatus(dataID);
67
+ if (status === EXISTENT) {
68
+ const sourceRecord = source.get(dataID);
69
+ if (sourceRecord) {
70
+ if (this.__mutator.getStatus(dataID) !== EXISTENT) {
71
+ this.create(dataID, RelayModernRecord.getType(sourceRecord));
72
+ }
73
+ this.__mutator.copyFieldsFromRecord(sourceRecord, dataID);
74
+ }
75
+ } else if (status === NONEXISTENT) {
76
+ this.delete(dataID);
77
+ }
78
+ });
79
+
80
+ if (fieldPayloads && fieldPayloads.length) {
81
+ fieldPayloads.forEach(fieldPayload => {
82
+ const handler =
83
+ this._handlerProvider && this._handlerProvider(fieldPayload.handle);
84
+ invariant(
85
+ handler,
86
+ 'RelayModernEnvironment: Expected a handler to be provided for handle `%s`.',
87
+ fieldPayload.handle,
88
+ );
89
+ handler.update(this, fieldPayload);
90
+ });
91
+ }
92
+ }
93
+
94
+ create(dataID: DataID, typeName: string): RecordProxy {
95
+ this.__mutator.create(dataID, typeName);
96
+ delete this._proxies[dataID];
97
+ const record = this.get(dataID);
98
+ // For flow
99
+ invariant(
100
+ record,
101
+ 'RelayRecordSourceProxy#create(): Expected the created record to exist.',
102
+ );
103
+ return record;
104
+ }
105
+
106
+ delete(dataID: DataID): void {
107
+ invariant(
108
+ dataID !== ROOT_ID,
109
+ 'RelayRecordSourceProxy#delete(): Cannot delete the root record.',
110
+ );
111
+ delete this._proxies[dataID];
112
+ this.__mutator.delete(dataID);
113
+ }
114
+
115
+ get(dataID: DataID): ?RecordProxy {
116
+ if (!this._proxies.hasOwnProperty(dataID)) {
117
+ const status = this.__mutator.getStatus(dataID);
118
+ if (status === EXISTENT) {
119
+ this._proxies[dataID] = new RelayRecordProxy(
120
+ this,
121
+ this.__mutator,
122
+ dataID,
123
+ );
124
+ } else {
125
+ this._proxies[dataID] = status === NONEXISTENT ? null : undefined;
126
+ }
127
+ }
128
+ return this._proxies[dataID];
129
+ }
130
+
131
+ getRoot(): RecordProxy {
132
+ let root = this.get(ROOT_ID);
133
+ if (!root) {
134
+ root = this.create(ROOT_ID, ROOT_TYPE);
135
+ }
136
+ invariant(
137
+ root && root.getType() === ROOT_TYPE,
138
+ 'RelayRecordSourceProxy#getRoot(): Expected the source to contain a ' +
139
+ 'root record, %s.',
140
+ root == null
141
+ ? 'no root record found'
142
+ : `found a root record of type \`${root.getType()}\``,
143
+ );
144
+ return root;
145
+ }
146
+
147
+ invalidateStore(): void {
148
+ this._invalidatedStore = true;
149
+ }
150
+
151
+ isStoreMarkedForInvalidation(): boolean {
152
+ return this._invalidatedStore;
153
+ }
154
+
155
+ markIDForInvalidation(dataID: DataID): void {
156
+ this._idsMarkedForInvalidation.add(dataID);
157
+ }
158
+
159
+ getIDsMarkedForInvalidation(): Set<DataID> {
160
+ return this._idsMarkedForInvalidation;
161
+ }
162
+ }
163
+
164
+ module.exports = RelayRecordSourceProxy;
@@ -0,0 +1,119 @@
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 invariant = require('invariant');
16
+
17
+ const {getStorageKey, ROOT_TYPE} = require('../store/RelayStoreUtils');
18
+
19
+ import type {
20
+ RecordProxy,
21
+ RecordSourceProxy,
22
+ RecordSourceSelectorProxy,
23
+ SingularReaderSelector,
24
+ } from '../store/RelayStoreTypes';
25
+ import type {ReaderLinkedField} from '../util/ReaderNode';
26
+ import type {DataID} from '../util/RelayRuntimeTypes';
27
+ import type RelayRecordSourceMutator from './RelayRecordSourceMutator';
28
+
29
+ /**
30
+ * @internal
31
+ *
32
+ * A subclass of RecordSourceProxy that provides convenience methods for
33
+ * accessing the root fields of a given query/mutation. These fields accept
34
+ * complex arguments and it can be tedious to re-construct the correct sets of
35
+ * arguments to pass to e.g. `getRoot().getLinkedRecord()`.
36
+ */
37
+ class RelayRecordSourceSelectorProxy implements RecordSourceSelectorProxy {
38
+ __mutator: RelayRecordSourceMutator;
39
+ __recordSource: RecordSourceProxy;
40
+ _readSelector: SingularReaderSelector;
41
+
42
+ constructor(
43
+ mutator: RelayRecordSourceMutator,
44
+ recordSource: RecordSourceProxy,
45
+ readSelector: SingularReaderSelector,
46
+ ) {
47
+ this.__mutator = mutator;
48
+ this.__recordSource = recordSource;
49
+ this._readSelector = readSelector;
50
+ }
51
+
52
+ create(dataID: DataID, typeName: string): RecordProxy {
53
+ return this.__recordSource.create(dataID, typeName);
54
+ }
55
+
56
+ delete(dataID: DataID): void {
57
+ this.__recordSource.delete(dataID);
58
+ }
59
+
60
+ get(dataID: DataID): ?RecordProxy {
61
+ return this.__recordSource.get(dataID);
62
+ }
63
+
64
+ getRoot(): RecordProxy {
65
+ return this.__recordSource.getRoot();
66
+ }
67
+
68
+ getOperationRoot(): RecordProxy {
69
+ let root = this.__recordSource.get(this._readSelector.dataID);
70
+ if (!root) {
71
+ root = this.__recordSource.create(this._readSelector.dataID, ROOT_TYPE);
72
+ }
73
+ return root;
74
+ }
75
+
76
+ _getRootField(
77
+ selector: SingularReaderSelector,
78
+ fieldName: string,
79
+ plural: boolean,
80
+ ): ReaderLinkedField {
81
+ const field = selector.node.selections.find(
82
+ selection =>
83
+ selection.kind === 'LinkedField' && selection.name === fieldName,
84
+ );
85
+ invariant(
86
+ field && field.kind === 'LinkedField',
87
+ 'RelayRecordSourceSelectorProxy#getRootField(): Cannot find root ' +
88
+ 'field `%s`, no such field is defined on GraphQL document `%s`.',
89
+ fieldName,
90
+ selector.node.name,
91
+ );
92
+ invariant(
93
+ field.plural === plural,
94
+ 'RelayRecordSourceSelectorProxy#getRootField(): Expected root field ' +
95
+ '`%s` to be %s.',
96
+ fieldName,
97
+ plural ? 'plural' : 'singular',
98
+ );
99
+ return field;
100
+ }
101
+
102
+ getRootField(fieldName: string): ?RecordProxy {
103
+ const field = this._getRootField(this._readSelector, fieldName, false);
104
+ const storageKey = getStorageKey(field, this._readSelector.variables);
105
+ return this.getOperationRoot().getLinkedRecord(storageKey);
106
+ }
107
+
108
+ getPluralRootField(fieldName: string): ?Array<?RecordProxy> {
109
+ const field = this._getRootField(this._readSelector, fieldName, true);
110
+ const storageKey = getStorageKey(field, this._readSelector.variables);
111
+ return this.getOperationRoot().getLinkedRecords(storageKey);
112
+ }
113
+
114
+ invalidateStore(): void {
115
+ this.__recordSource.invalidateStore();
116
+ }
117
+ }
118
+
119
+ module.exports = RelayRecordSourceSelectorProxy;