relay-runtime 8.0.0 → 10.0.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 (135) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +41 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/handlers/connection/MutationHandlers.js.flow +88 -0
  5. package/index.js +1 -1
  6. package/index.js.flow +320 -0
  7. package/lib/handlers/RelayDefaultHandlerProvider.js +13 -2
  8. package/lib/handlers/connection/{RelayConnectionHandler.js → ConnectionHandler.js} +33 -35
  9. package/lib/handlers/connection/{RelayConnectionInterface.js → ConnectionInterface.js} +2 -2
  10. package/lib/handlers/connection/MutationHandlers.js +86 -0
  11. package/lib/index.js +15 -19
  12. package/lib/mutations/RelayDeclarativeMutationConfig.js +29 -52
  13. package/lib/mutations/RelayRecordProxy.js +1 -3
  14. package/lib/mutations/RelayRecordSourceMutator.js +2 -9
  15. package/lib/mutations/RelayRecordSourceProxy.js +2 -4
  16. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -13
  17. package/lib/mutations/commitMutation.js +13 -3
  18. package/lib/mutations/validateMutation.js +16 -9
  19. package/lib/network/RelayObservable.js +9 -9
  20. package/lib/network/RelayQueryResponseCache.js +8 -6
  21. package/lib/query/PreloadableQueryRegistry.js +70 -0
  22. package/lib/query/fetchQueryInternal.js +31 -23
  23. package/lib/store/DataChecker.js +122 -110
  24. package/lib/store/RelayConcreteVariables.js +6 -2
  25. package/lib/store/RelayModernEnvironment.js +121 -67
  26. package/lib/store/RelayModernFragmentSpecResolver.js +12 -16
  27. package/lib/store/RelayModernQueryExecutor.js +389 -314
  28. package/lib/store/RelayModernRecord.js +14 -9
  29. package/lib/store/RelayModernSelector.js +7 -3
  30. package/lib/store/RelayModernStore.js +289 -484
  31. package/lib/store/RelayOperationTracker.js +35 -78
  32. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  33. package/lib/store/RelayPublishQueue.js +6 -33
  34. package/lib/store/RelayReader.js +113 -45
  35. package/lib/store/RelayRecordSource.js +2 -9
  36. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  37. package/lib/store/RelayReferenceMarker.js +40 -60
  38. package/lib/store/RelayResponseNormalizer.js +158 -193
  39. package/lib/store/RelayStoreUtils.js +1 -0
  40. package/lib/store/StoreInspector.js +8 -8
  41. package/lib/store/TypeID.js +28 -0
  42. package/lib/store/cloneRelayScalarHandleSourceField.js +44 -0
  43. package/lib/store/normalizeRelayPayload.js +6 -2
  44. package/lib/store/readInlineData.js +1 -1
  45. package/lib/subscription/requestSubscription.js +5 -3
  46. package/lib/util/RelayConcreteNode.js +9 -6
  47. package/lib/util/RelayError.js +39 -9
  48. package/lib/util/RelayFeatureFlags.js +2 -5
  49. package/lib/util/RelayReplaySubject.js +3 -3
  50. package/lib/util/createPayloadFor3DField.js +7 -2
  51. package/lib/util/getRequestIdentifier.js +2 -2
  52. package/lib/util/recycleNodesInto.js +2 -6
  53. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  54. package/mutations/RelayRecordProxy.js.flow +165 -0
  55. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  56. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  57. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  58. package/mutations/applyOptimisticMutation.js.flow +76 -0
  59. package/mutations/commitLocalUpdate.js.flow +24 -0
  60. package/mutations/commitMutation.js.flow +182 -0
  61. package/mutations/validateMutation.js.flow +213 -0
  62. package/network/ConvertToExecuteFunction.js.flow +49 -0
  63. package/network/RelayNetwork.js.flow +84 -0
  64. package/network/RelayNetworkTypes.js.flow +123 -0
  65. package/network/RelayObservable.js.flow +634 -0
  66. package/network/RelayQueryResponseCache.js.flow +111 -0
  67. package/package.json +1 -1
  68. package/query/GraphQLTag.js.flow +166 -0
  69. package/query/PreloadableQueryRegistry.js.flow +65 -0
  70. package/query/fetchQuery.js.flow +47 -0
  71. package/query/fetchQueryInternal.js.flow +348 -0
  72. package/relay-runtime.js +2 -2
  73. package/relay-runtime.min.js +2 -2
  74. package/store/ClientID.js.flow +43 -0
  75. package/store/DataChecker.js.flow +502 -0
  76. package/store/RelayConcreteVariables.js.flow +96 -0
  77. package/store/RelayModernEnvironment.js.flow +551 -0
  78. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  79. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  80. package/store/RelayModernQueryExecutor.js.flow +1321 -0
  81. package/store/RelayModernRecord.js.flow +403 -0
  82. package/store/RelayModernSelector.js.flow +455 -0
  83. package/store/RelayModernStore.js.flow +842 -0
  84. package/store/RelayOperationTracker.js.flow +164 -0
  85. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  86. package/store/RelayPublishQueue.js.flow +401 -0
  87. package/store/RelayReader.js.flow +473 -0
  88. package/store/RelayRecordSource.js.flow +29 -0
  89. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  90. package/store/RelayRecordState.js.flow +37 -0
  91. package/store/RelayReferenceMarker.js.flow +257 -0
  92. package/store/RelayResponseNormalizer.js.flow +680 -0
  93. package/store/RelayStoreTypes.js.flow +899 -0
  94. package/store/RelayStoreUtils.js.flow +219 -0
  95. package/store/StoreInspector.js.flow +171 -0
  96. package/store/TypeID.js.flow +28 -0
  97. package/store/ViewerPattern.js.flow +26 -0
  98. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  99. package/store/cloneRelayScalarHandleSourceField.js.flow +62 -0
  100. package/store/createFragmentSpecResolver.js.flow +55 -0
  101. package/store/createRelayContext.js.flow +44 -0
  102. package/store/defaultGetDataID.js.flow +27 -0
  103. package/store/hasOverlappingIDs.js.flow +34 -0
  104. package/store/isRelayModernEnvironment.js.flow +27 -0
  105. package/store/normalizeRelayPayload.js.flow +51 -0
  106. package/store/readInlineData.js.flow +75 -0
  107. package/subscription/requestSubscription.js.flow +100 -0
  108. package/util/JSResourceTypes.flow.js.flow +20 -0
  109. package/util/NormalizationNode.js.flow +198 -0
  110. package/util/ReaderNode.js.flow +208 -0
  111. package/util/RelayConcreteNode.js.flow +93 -0
  112. package/util/RelayDefaultHandleKey.js.flow +17 -0
  113. package/util/RelayError.js.flow +62 -0
  114. package/util/RelayFeatureFlags.js.flow +30 -0
  115. package/util/RelayProfiler.js.flow +284 -0
  116. package/util/RelayReplaySubject.js.flow +135 -0
  117. package/util/RelayRuntimeTypes.js.flow +72 -0
  118. package/util/createPayloadFor3DField.js.flow +43 -0
  119. package/util/deepFreeze.js.flow +36 -0
  120. package/util/generateID.js.flow +21 -0
  121. package/util/getFragmentIdentifier.js.flow +52 -0
  122. package/util/getRelayHandleKey.js.flow +41 -0
  123. package/util/getRequestIdentifier.js.flow +42 -0
  124. package/util/isPromise.js.flow +21 -0
  125. package/util/isScalarAndEqual.js.flow +26 -0
  126. package/util/recycleNodesInto.js.flow +76 -0
  127. package/util/resolveImmediate.js.flow +30 -0
  128. package/util/stableCopy.js.flow +35 -0
  129. package/lib/handlers/RelayDefaultMissingFieldHandlers.js +0 -26
  130. package/lib/handlers/getRelayDefaultMissingFieldHandlers.js +0 -36
  131. package/lib/query/RelayModernGraphQLTag.js +0 -104
  132. package/lib/store/RelayConnection.js +0 -37
  133. package/lib/store/RelayConnectionResolver.js +0 -178
  134. package/lib/store/RelayRecordSourceObjectImpl.js +0 -79
  135. package/lib/util/getFragmentSpecIdentifier.js +0 -27
@@ -0,0 +1,403 @@
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 areEqual = require('areEqual');
16
+ const deepFreeze = require('../util/deepFreeze');
17
+ const invariant = require('invariant');
18
+ const warning = require('warning');
19
+
20
+ const {isClientID} = require('./ClientID');
21
+ const {
22
+ ID_KEY,
23
+ REF_KEY,
24
+ REFS_KEY,
25
+ TYPENAME_KEY,
26
+ INVALIDATED_AT_KEY,
27
+ ROOT_ID,
28
+ } = require('./RelayStoreUtils');
29
+
30
+ import type {DataID} from '../util/RelayRuntimeTypes';
31
+ import type {Record} from './RelayStoreTypes';
32
+
33
+ /**
34
+ * @public
35
+ *
36
+ * Low-level record manipulation methods.
37
+ *
38
+ * A note about perf: we use long-hand property access rather than computed
39
+ * properties in this file for speed ie.
40
+ *
41
+ * const object = {};
42
+ * object[KEY] = value;
43
+ * record[storageKey] = object;
44
+ *
45
+ * instead of:
46
+ *
47
+ * record[storageKey] = {
48
+ * [KEY]: value,
49
+ * };
50
+ *
51
+ * The latter gets transformed by Babel into something like:
52
+ *
53
+ * function _defineProperty(obj, key, value) {
54
+ * if (key in obj) {
55
+ * Object.defineProperty(obj, key, {
56
+ * value: value,
57
+ * enumerable: true,
58
+ * configurable: true,
59
+ * writable: true,
60
+ * });
61
+ * } else {
62
+ * obj[key] = value;
63
+ * }
64
+ * return obj;
65
+ * }
66
+ *
67
+ * record[storageKey] = _defineProperty({}, KEY, value);
68
+ *
69
+ * A quick benchmark shows that computed property access is an order of
70
+ * magnitude slower (times in seconds for 100,000 iterations):
71
+ *
72
+ * best avg sd
73
+ * computed 0.02175 0.02292 0.00113
74
+ * manual 0.00110 0.00123 0.00008
75
+ */
76
+
77
+ /**
78
+ * @public
79
+ *
80
+ * Clone a record.
81
+ */
82
+ function clone(record: Record): Record {
83
+ return {
84
+ ...record,
85
+ };
86
+ }
87
+
88
+ /**
89
+ * @public
90
+ *
91
+ * Copies all fields from `source` to `sink`, excluding `__id` and `__typename`.
92
+ *
93
+ * NOTE: This function does not treat `id` specially. To preserve the id,
94
+ * manually reset it after calling this function. Also note that values are
95
+ * copied by reference and not value; callers should ensure that values are
96
+ * copied on write.
97
+ */
98
+ function copyFields(source: Record, sink: Record): void {
99
+ for (const key in source) {
100
+ if (source.hasOwnProperty(key)) {
101
+ if (key !== ID_KEY && key !== TYPENAME_KEY) {
102
+ sink[key] = source[key];
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * @public
110
+ *
111
+ * Create a new record.
112
+ */
113
+ function create(dataID: DataID, typeName: string): Record {
114
+ // See perf note above for why we aren't using computed property access.
115
+ const record = {};
116
+ record[ID_KEY] = dataID;
117
+ record[TYPENAME_KEY] = typeName;
118
+ return record;
119
+ }
120
+
121
+ /**
122
+ * @public
123
+ *
124
+ * Get the record's `id` if available or the client-generated identifier.
125
+ */
126
+ function getDataID(record: Record): DataID {
127
+ return (record[ID_KEY]: any);
128
+ }
129
+
130
+ /**
131
+ * @public
132
+ *
133
+ * Get the concrete type of the record.
134
+ */
135
+ function getType(record: Record): string {
136
+ return (record[TYPENAME_KEY]: any);
137
+ }
138
+
139
+ /**
140
+ * @public
141
+ *
142
+ * Get a scalar (non-link) field value.
143
+ */
144
+ function getValue(record: Record, storageKey: string): mixed {
145
+ const value = record[storageKey];
146
+ if (value && typeof value === 'object') {
147
+ invariant(
148
+ !value.hasOwnProperty(REF_KEY) && !value.hasOwnProperty(REFS_KEY),
149
+ 'RelayModernRecord.getValue(): Expected a scalar (non-link) value for `%s.%s` ' +
150
+ 'but found %s.',
151
+ record[ID_KEY],
152
+ storageKey,
153
+ value.hasOwnProperty(REF_KEY)
154
+ ? 'a linked record'
155
+ : 'plural linked records',
156
+ );
157
+ }
158
+ return value;
159
+ }
160
+
161
+ /**
162
+ * @public
163
+ *
164
+ * Get the value of a field as a reference to another record. Throws if the
165
+ * field has a different type.
166
+ */
167
+ function getLinkedRecordID(record: Record, storageKey: string): ?DataID {
168
+ const link = record[storageKey];
169
+ if (link == null) {
170
+ return link;
171
+ }
172
+ invariant(
173
+ typeof link === 'object' && link && typeof link[REF_KEY] === 'string',
174
+ 'RelayModernRecord.getLinkedRecordID(): Expected `%s.%s` to be a linked ID, ' +
175
+ 'was `%s`.',
176
+ record[ID_KEY],
177
+ storageKey,
178
+ JSON.stringify(link),
179
+ );
180
+ return link[REF_KEY];
181
+ }
182
+
183
+ /**
184
+ * @public
185
+ *
186
+ * Get the value of a field as a list of references to other records. Throws if
187
+ * the field has a different type.
188
+ */
189
+ function getLinkedRecordIDs(
190
+ record: Record,
191
+ storageKey: string,
192
+ ): ?Array<?DataID> {
193
+ const links = record[storageKey];
194
+ if (links == null) {
195
+ return links;
196
+ }
197
+ invariant(
198
+ typeof links === 'object' && Array.isArray(links[REFS_KEY]),
199
+ 'RelayModernRecord.getLinkedRecordIDs(): Expected `%s.%s` to contain an array ' +
200
+ 'of linked IDs, got `%s`.',
201
+ record[ID_KEY],
202
+ storageKey,
203
+ JSON.stringify(links),
204
+ );
205
+ // assume items of the array are ids
206
+ return (links[REFS_KEY]: any);
207
+ }
208
+
209
+ /**
210
+ * @public
211
+ *
212
+ * Returns the epoch at which the record was invalidated, if it
213
+ * ever was; otherwise returns null;
214
+ */
215
+ function getInvalidationEpoch(record: ?Record): ?number {
216
+ if (record == null) {
217
+ return null;
218
+ }
219
+
220
+ const invalidatedAt = record[INVALIDATED_AT_KEY];
221
+ if (typeof invalidatedAt !== 'number') {
222
+ // If the record has never been invalidated, it isn't stale.
223
+ return null;
224
+ }
225
+ return invalidatedAt;
226
+ }
227
+
228
+ /**
229
+ * @public
230
+ *
231
+ * Compares the fields of a previous and new record, returning either the
232
+ * previous record if all fields are equal or a new record (with merged fields)
233
+ * if any fields have changed.
234
+ */
235
+ function update(prevRecord: Record, nextRecord: Record): Record {
236
+ if (__DEV__) {
237
+ const prevID = getDataID(prevRecord);
238
+ const nextID = getDataID(nextRecord);
239
+ warning(
240
+ prevID === nextID,
241
+ 'RelayModernRecord: Invalid record update, expected both versions of ' +
242
+ 'the record to have the same id, got `%s` and `%s`.',
243
+ prevID,
244
+ nextID,
245
+ );
246
+ // note: coalesce null/undefined to null
247
+ const prevType = getType(prevRecord) ?? null;
248
+ const nextType = getType(nextRecord) ?? null;
249
+ warning(
250
+ (isClientID(nextID) && nextID !== ROOT_ID) || prevType === nextType,
251
+ 'RelayModernRecord: Invalid record update, expected both versions of ' +
252
+ 'record `%s` to have the same `%s` but got conflicting types `%s` ' +
253
+ 'and `%s`. The GraphQL server likely violated the globally unique ' +
254
+ 'id requirement by returning the same id for different objects.',
255
+ prevID,
256
+ TYPENAME_KEY,
257
+ prevType,
258
+ nextType,
259
+ );
260
+ }
261
+ let updated: Record | null = null;
262
+ const keys = Object.keys(nextRecord);
263
+ for (let ii = 0; ii < keys.length; ii++) {
264
+ const key = keys[ii];
265
+ if (updated || !areEqual(prevRecord[key], nextRecord[key])) {
266
+ updated = updated !== null ? updated : {...prevRecord};
267
+ updated[key] = nextRecord[key];
268
+ }
269
+ }
270
+ return updated !== null ? updated : prevRecord;
271
+ }
272
+
273
+ /**
274
+ * @public
275
+ *
276
+ * Returns a new record with the contents of the given records. Fields in the
277
+ * second record will overwrite identical fields in the first record.
278
+ */
279
+ function merge(record1: Record, record2: Record): Record {
280
+ if (__DEV__) {
281
+ const prevID = getDataID(record1);
282
+ const nextID = getDataID(record2);
283
+ warning(
284
+ prevID === nextID,
285
+ 'RelayModernRecord: Invalid record merge, expected both versions of ' +
286
+ 'the record to have the same id, got `%s` and `%s`.',
287
+ prevID,
288
+ nextID,
289
+ );
290
+ // note: coalesce null/undefined to null
291
+ const prevType = getType(record1) ?? null;
292
+ const nextType = getType(record2) ?? null;
293
+ warning(
294
+ (isClientID(nextID) && nextID !== ROOT_ID) || prevType === nextType,
295
+ 'RelayModernRecord: Invalid record merge, expected both versions of ' +
296
+ 'record `%s` to have the same `%s` but got conflicting types `%s` ' +
297
+ 'and `%s`. The GraphQL server likely violated the globally unique ' +
298
+ 'id requirement by returning the same id for different objects.',
299
+ prevID,
300
+ TYPENAME_KEY,
301
+ prevType,
302
+ nextType,
303
+ );
304
+ }
305
+ return Object.assign({}, record1, record2);
306
+ }
307
+
308
+ /**
309
+ * @public
310
+ *
311
+ * Prevent modifications to the record. Attempts to call `set*` functions on a
312
+ * frozen record will fatal at runtime.
313
+ */
314
+ function freeze(record: Record): void {
315
+ deepFreeze(record);
316
+ }
317
+
318
+ /**
319
+ * @public
320
+ *
321
+ * Set the value of a storageKey to a scalar.
322
+ */
323
+ function setValue(record: Record, storageKey: string, value: mixed): void {
324
+ if (__DEV__) {
325
+ const prevID = getDataID(record);
326
+ if (storageKey === ID_KEY) {
327
+ warning(
328
+ prevID === value,
329
+ 'RelayModernRecord: Invalid field update, expected both versions of ' +
330
+ 'the record to have the same id, got `%s` and `%s`.',
331
+ prevID,
332
+ value,
333
+ );
334
+ } else if (storageKey === TYPENAME_KEY) {
335
+ // note: coalesce null/undefined to null
336
+ const prevType = getType(record) ?? null;
337
+ const nextType = value ?? null;
338
+ warning(
339
+ (isClientID(getDataID(record)) && getDataID(record) !== ROOT_ID) ||
340
+ prevType === nextType,
341
+ 'RelayModernRecord: Invalid field update, expected both versions of ' +
342
+ 'record `%s` to have the same `%s` but got conflicting types `%s` ' +
343
+ 'and `%s`. The GraphQL server likely violated the globally unique ' +
344
+ 'id requirement by returning the same id for different objects.',
345
+ prevID,
346
+ TYPENAME_KEY,
347
+ prevType,
348
+ nextType,
349
+ );
350
+ }
351
+ }
352
+ record[storageKey] = value;
353
+ }
354
+
355
+ /**
356
+ * @public
357
+ *
358
+ * Set the value of a field to a reference to another record.
359
+ */
360
+ function setLinkedRecordID(
361
+ record: Record,
362
+ storageKey: string,
363
+ linkedID: DataID,
364
+ ): void {
365
+ // See perf note above for why we aren't using computed property access.
366
+ const link = {};
367
+ link[REF_KEY] = linkedID;
368
+ record[storageKey] = link;
369
+ }
370
+
371
+ /**
372
+ * @public
373
+ *
374
+ * Set the value of a field to a list of references other records.
375
+ */
376
+ function setLinkedRecordIDs(
377
+ record: Record,
378
+ storageKey: string,
379
+ linkedIDs: Array<?DataID>,
380
+ ): void {
381
+ // See perf note above for why we aren't using computed property access.
382
+ const links = {};
383
+ links[REFS_KEY] = linkedIDs;
384
+ record[storageKey] = links;
385
+ }
386
+
387
+ module.exports = {
388
+ clone,
389
+ copyFields,
390
+ create,
391
+ freeze,
392
+ getDataID,
393
+ getInvalidationEpoch,
394
+ getLinkedRecordID,
395
+ getLinkedRecordIDs,
396
+ getType,
397
+ getValue,
398
+ merge,
399
+ setValue,
400
+ setLinkedRecordID,
401
+ setLinkedRecordIDs,
402
+ update,
403
+ };