relay-runtime 9.0.0 → 10.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 (142) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +47 -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 +199 -0
  5. package/index.js +1 -1
  6. package/index.js.flow +335 -0
  7. package/lib/handlers/RelayDefaultHandlerProvider.js +20 -0
  8. package/lib/handlers/connection/ConnectionHandler.js +1 -3
  9. package/lib/handlers/connection/MutationHandlers.js +212 -0
  10. package/lib/index.js +14 -2
  11. package/lib/mutations/RelayDeclarativeMutationConfig.js +22 -45
  12. package/lib/mutations/RelayRecordProxy.js +1 -3
  13. package/lib/mutations/RelayRecordSourceMutator.js +1 -3
  14. package/lib/mutations/RelayRecordSourceProxy.js +1 -3
  15. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -3
  16. package/lib/mutations/commitMutation.js +2 -3
  17. package/lib/mutations/validateMutation.js +40 -9
  18. package/lib/network/RelayObservable.js +9 -9
  19. package/lib/network/RelayQueryResponseCache.js +8 -6
  20. package/lib/query/GraphQLTag.js +2 -1
  21. package/lib/query/PreloadableQueryRegistry.js +70 -0
  22. package/lib/query/fetchQuery.js +2 -3
  23. package/lib/query/fetchQueryInternal.js +5 -14
  24. package/lib/store/DataChecker.js +200 -71
  25. package/lib/store/RelayConcreteVariables.js +6 -2
  26. package/lib/store/RelayModernEnvironment.js +124 -65
  27. package/lib/store/RelayModernFragmentSpecResolver.js +19 -14
  28. package/lib/store/RelayModernOperationDescriptor.js +6 -5
  29. package/lib/store/RelayModernQueryExecutor.js +122 -73
  30. package/lib/store/RelayModernRecord.js +14 -9
  31. package/lib/store/RelayModernSelector.js +6 -2
  32. package/lib/store/RelayModernStore.js +281 -131
  33. package/lib/store/RelayOperationTracker.js +35 -78
  34. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  35. package/lib/store/RelayPublishQueue.js +2 -4
  36. package/lib/store/RelayReader.js +304 -52
  37. package/lib/store/RelayRecordSource.js +1 -3
  38. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  39. package/lib/store/RelayReferenceMarker.js +125 -14
  40. package/lib/store/RelayResponseNormalizer.js +261 -66
  41. package/lib/store/RelayStoreReactFlightUtils.js +47 -0
  42. package/lib/store/RelayStoreUtils.js +1 -0
  43. package/lib/store/StoreInspector.js +8 -8
  44. package/lib/store/TypeID.js +28 -0
  45. package/lib/store/cloneRelayScalarHandleSourceField.js +44 -0
  46. package/lib/store/defaultRequiredFieldLogger.js +18 -0
  47. package/lib/store/normalizeRelayPayload.js +6 -2
  48. package/lib/store/readInlineData.js +1 -1
  49. package/lib/subscription/requestSubscription.js +4 -3
  50. package/lib/util/NormalizationNode.js +1 -5
  51. package/lib/util/RelayConcreteNode.js +11 -6
  52. package/lib/util/RelayError.js +39 -9
  53. package/lib/util/RelayFeatureFlags.js +6 -3
  54. package/lib/util/RelayReplaySubject.js +3 -3
  55. package/lib/util/createPayloadFor3DField.js +7 -2
  56. package/lib/util/getFragmentIdentifier.js +12 -3
  57. package/lib/util/getOperation.js +33 -0
  58. package/lib/util/getRequestIdentifier.js +2 -2
  59. package/lib/util/isEmptyObject.js +25 -0
  60. package/lib/util/recycleNodesInto.js +6 -7
  61. package/lib/util/reportMissingRequiredFields.js +48 -0
  62. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  63. package/mutations/RelayRecordProxy.js.flow +165 -0
  64. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  65. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  66. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  67. package/mutations/applyOptimisticMutation.js.flow +76 -0
  68. package/mutations/commitLocalUpdate.js.flow +24 -0
  69. package/mutations/commitMutation.js.flow +181 -0
  70. package/mutations/validateMutation.js.flow +242 -0
  71. package/network/ConvertToExecuteFunction.js.flow +49 -0
  72. package/network/RelayNetwork.js.flow +84 -0
  73. package/network/RelayNetworkTypes.js.flow +145 -0
  74. package/network/RelayObservable.js.flow +634 -0
  75. package/network/RelayQueryResponseCache.js.flow +111 -0
  76. package/package.json +2 -2
  77. package/query/GraphQLTag.js.flow +168 -0
  78. package/query/PreloadableQueryRegistry.js.flow +65 -0
  79. package/query/fetchQuery.js.flow +47 -0
  80. package/query/fetchQueryInternal.js.flow +343 -0
  81. package/relay-runtime.js +2 -2
  82. package/relay-runtime.min.js +2 -2
  83. package/store/ClientID.js.flow +43 -0
  84. package/store/DataChecker.js.flow +568 -0
  85. package/store/RelayConcreteVariables.js.flow +96 -0
  86. package/store/RelayModernEnvironment.js.flow +571 -0
  87. package/store/RelayModernFragmentSpecResolver.js.flow +438 -0
  88. package/store/RelayModernOperationDescriptor.js.flow +92 -0
  89. package/store/RelayModernQueryExecutor.js.flow +1345 -0
  90. package/store/RelayModernRecord.js.flow +403 -0
  91. package/store/RelayModernSelector.js.flow +455 -0
  92. package/store/RelayModernStore.js.flow +858 -0
  93. package/store/RelayOperationTracker.js.flow +164 -0
  94. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  95. package/store/RelayPublishQueue.js.flow +401 -0
  96. package/store/RelayReader.js.flow +638 -0
  97. package/store/RelayRecordSource.js.flow +29 -0
  98. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  99. package/store/RelayRecordState.js.flow +37 -0
  100. package/store/RelayReferenceMarker.js.flow +324 -0
  101. package/store/RelayResponseNormalizer.js.flow +791 -0
  102. package/store/RelayStoreReactFlightUtils.js.flow +64 -0
  103. package/store/RelayStoreTypes.js.flow +958 -0
  104. package/store/RelayStoreUtils.js.flow +219 -0
  105. package/store/StoreInspector.js.flow +171 -0
  106. package/store/TypeID.js.flow +28 -0
  107. package/store/ViewerPattern.js.flow +26 -0
  108. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  109. package/store/cloneRelayScalarHandleSourceField.js.flow +62 -0
  110. package/store/createFragmentSpecResolver.js.flow +55 -0
  111. package/store/createRelayContext.js.flow +44 -0
  112. package/store/defaultGetDataID.js.flow +27 -0
  113. package/store/defaultRequiredFieldLogger.js.flow +23 -0
  114. package/store/hasOverlappingIDs.js.flow +34 -0
  115. package/store/isRelayModernEnvironment.js.flow +27 -0
  116. package/store/normalizeRelayPayload.js.flow +51 -0
  117. package/store/readInlineData.js.flow +75 -0
  118. package/subscription/requestSubscription.js.flow +103 -0
  119. package/util/JSResourceTypes.flow.js.flow +20 -0
  120. package/util/NormalizationNode.js.flow +213 -0
  121. package/util/ReaderNode.js.flow +227 -0
  122. package/util/RelayConcreteNode.js.flow +99 -0
  123. package/util/RelayDefaultHandleKey.js.flow +17 -0
  124. package/util/RelayError.js.flow +62 -0
  125. package/util/RelayFeatureFlags.js.flow +37 -0
  126. package/util/RelayProfiler.js.flow +284 -0
  127. package/util/RelayReplaySubject.js.flow +135 -0
  128. package/util/RelayRuntimeTypes.js.flow +72 -0
  129. package/util/createPayloadFor3DField.js.flow +43 -0
  130. package/util/deepFreeze.js.flow +36 -0
  131. package/util/generateID.js.flow +21 -0
  132. package/util/getFragmentIdentifier.js.flow +76 -0
  133. package/util/getOperation.js.flow +40 -0
  134. package/util/getRelayHandleKey.js.flow +41 -0
  135. package/util/getRequestIdentifier.js.flow +42 -0
  136. package/util/isEmptyObject.js.flow +25 -0
  137. package/util/isPromise.js.flow +21 -0
  138. package/util/isScalarAndEqual.js.flow +26 -0
  139. package/util/recycleNodesInto.js.flow +87 -0
  140. package/util/reportMissingRequiredFields.js.flow +51 -0
  141. package/util/resolveImmediate.js.flow +30 -0
  142. package/util/stableCopy.js.flow +35 -0
@@ -0,0 +1,111 @@
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
+ const stableCopy = require('../util/stableCopy');
17
+
18
+ import type {Variables} from '../util/RelayRuntimeTypes';
19
+ import type {GraphQLSingularResponse} from './RelayNetworkTypes';
20
+
21
+ type Response = {
22
+ fetchTime: number,
23
+ payload: GraphQLSingularResponse,
24
+ ...
25
+ };
26
+
27
+ /**
28
+ * A cache for storing query responses, featuring:
29
+ * - `get` with TTL
30
+ * - cache size limiting, with least-recently *updated* entries purged first
31
+ */
32
+ class RelayQueryResponseCache {
33
+ _responses: Map<string, Response>;
34
+ _size: number;
35
+ _ttl: number;
36
+
37
+ constructor({size, ttl}: {size: number, ttl: number, ...}) {
38
+ invariant(
39
+ size > 0,
40
+ 'RelayQueryResponseCache: Expected the max cache size to be > 0, got ' +
41
+ '`%s`.',
42
+ size,
43
+ );
44
+ invariant(
45
+ ttl > 0,
46
+ 'RelayQueryResponseCache: Expected the max ttl to be > 0, got `%s`.',
47
+ ttl,
48
+ );
49
+ this._responses = new Map();
50
+ this._size = size;
51
+ this._ttl = ttl;
52
+ }
53
+
54
+ clear(): void {
55
+ this._responses.clear();
56
+ }
57
+
58
+ get(queryID: string, variables: Variables): ?GraphQLSingularResponse {
59
+ const cacheKey = getCacheKey(queryID, variables);
60
+ this._responses.forEach((response, key) => {
61
+ if (!isCurrent(response.fetchTime, this._ttl)) {
62
+ this._responses.delete(key);
63
+ }
64
+ });
65
+ const response = this._responses.get(cacheKey);
66
+ return response != null
67
+ ? ({
68
+ ...response.payload,
69
+ extensions: {
70
+ ...response.payload.extensions,
71
+ cacheTimestamp: response.fetchTime,
72
+ },
73
+ }: GraphQLSingularResponse)
74
+ : null;
75
+ }
76
+
77
+ set(
78
+ queryID: string,
79
+ variables: Variables,
80
+ payload: GraphQLSingularResponse,
81
+ ): void {
82
+ const fetchTime = Date.now();
83
+ const cacheKey = getCacheKey(queryID, variables);
84
+ this._responses.delete(cacheKey); // deletion resets key ordering
85
+ this._responses.set(cacheKey, {
86
+ fetchTime,
87
+ payload,
88
+ });
89
+ // Purge least-recently updated key when max size reached
90
+ if (this._responses.size > this._size) {
91
+ const firstKey = this._responses.keys().next();
92
+ if (!firstKey.done) {
93
+ this._responses.delete(firstKey.value);
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ function getCacheKey(queryID: string, variables: Variables): string {
100
+ return JSON.stringify(stableCopy({queryID, variables}));
101
+ }
102
+
103
+ /**
104
+ * Determine whether a response fetched at `fetchTime` is still valid given
105
+ * some `ttl`.
106
+ */
107
+ function isCurrent(fetchTime: number, ttl: number): boolean {
108
+ return fetchTime + ttl >= Date.now();
109
+ }
110
+
111
+ module.exports = RelayQueryResponseCache;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "relay-runtime",
3
3
  "description": "A core runtime for building GraphQL-driven applications.",
4
- "version": "9.0.0",
4
+ "version": "10.1.0",
5
5
  "keywords": [
6
6
  "graphql",
7
7
  "relay"
@@ -12,7 +12,7 @@
12
12
  "repository": "facebook/relay",
13
13
  "dependencies": {
14
14
  "@babel/runtime": "^7.0.0",
15
- "fbjs": "^1.0.0"
15
+ "fbjs": "^3.0.0"
16
16
  },
17
17
  "directories": {
18
18
  "": "./"
@@ -0,0 +1,168 @@
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 RelayConcreteNode = require('../util/RelayConcreteNode');
16
+
17
+ const invariant = require('invariant');
18
+ const warning = require('warning');
19
+
20
+ import type {
21
+ ReaderFragment,
22
+ ReaderRefetchableFragment,
23
+ ReaderPaginationFragment,
24
+ ReaderInlineDataFragment,
25
+ } from '../util/ReaderNode';
26
+ import type {ConcreteRequest} from '../util/RelayConcreteNode';
27
+
28
+ // The type of a graphql`...` tagged template expression.
29
+ export type GraphQLTaggedNode =
30
+ | ReaderFragment
31
+ | ConcreteRequest
32
+ | {
33
+ // This is this case when we `require()` a generated ES6 module
34
+ default: ReaderFragment | ConcreteRequest,
35
+ ...
36
+ };
37
+
38
+ /**
39
+ * Runtime function to correspond to the `graphql` tagged template function.
40
+ * All calls to this function should be transformed by the plugin.
41
+ */
42
+ function graphql(strings: Array<string>): GraphQLTaggedNode {
43
+ invariant(
44
+ false,
45
+ 'graphql: Unexpected invocation at runtime. Either the Babel transform ' +
46
+ 'was not set up, or it failed to identify this call site. Make sure it ' +
47
+ 'is being used verbatim as `graphql`. Note also that there cannot be ' +
48
+ 'a space between graphql and the backtick that follows.',
49
+ );
50
+ }
51
+
52
+ function getNode(
53
+ taggedNode: GraphQLTaggedNode,
54
+ ): ReaderFragment | ConcreteRequest {
55
+ let node = taggedNode;
56
+ if (typeof node === 'function') {
57
+ node = (node(): ReaderFragment | ConcreteRequest);
58
+ warning(
59
+ false,
60
+ 'RelayGraphQLTag: node `%s` unexpectedly wrapped in a function.',
61
+ node.kind === 'Fragment' ? node.name : node.operation.name,
62
+ );
63
+ } else if (node.default) {
64
+ // Support for languages that work (best) with ES6 modules, such as TypeScript.
65
+ node = node.default;
66
+ }
67
+ return node;
68
+ }
69
+
70
+ function isFragment(node: GraphQLTaggedNode): boolean {
71
+ const fragment = getNode(node);
72
+ return (
73
+ typeof fragment === 'object' &&
74
+ fragment !== null &&
75
+ fragment.kind === RelayConcreteNode.FRAGMENT
76
+ );
77
+ }
78
+
79
+ function isRequest(node: GraphQLTaggedNode): boolean {
80
+ const request = getNode(node);
81
+ return (
82
+ typeof request === 'object' &&
83
+ request !== null &&
84
+ request.kind === RelayConcreteNode.REQUEST
85
+ );
86
+ }
87
+
88
+ function isInlineDataFragment(node: GraphQLTaggedNode): boolean {
89
+ const fragment = getNode(node);
90
+ return (
91
+ typeof fragment === 'object' &&
92
+ fragment !== null &&
93
+ fragment.kind === RelayConcreteNode.INLINE_DATA_FRAGMENT
94
+ );
95
+ }
96
+
97
+ function getFragment(taggedNode: GraphQLTaggedNode): ReaderFragment {
98
+ const fragment = getNode(taggedNode);
99
+ invariant(
100
+ isFragment(fragment),
101
+ 'GraphQLTag: Expected a fragment, got `%s`.',
102
+ JSON.stringify(fragment),
103
+ );
104
+ return (fragment: any);
105
+ }
106
+
107
+ function getPaginationFragment(
108
+ taggedNode: GraphQLTaggedNode,
109
+ ): ReaderPaginationFragment | null {
110
+ const fragment = getFragment(taggedNode);
111
+ const refetch = fragment.metadata?.refetch;
112
+ const connection = refetch?.connection;
113
+ if (
114
+ refetch === null ||
115
+ typeof refetch !== 'object' ||
116
+ connection === null ||
117
+ typeof connection !== 'object'
118
+ ) {
119
+ return null;
120
+ }
121
+ return (fragment: any);
122
+ }
123
+
124
+ function getRefetchableFragment(
125
+ taggedNode: GraphQLTaggedNode,
126
+ ): ReaderRefetchableFragment | null {
127
+ const fragment = getFragment(taggedNode);
128
+ const refetch = fragment.metadata?.refetch;
129
+ if (refetch === null || typeof refetch !== 'object') {
130
+ return null;
131
+ }
132
+ return (fragment: any);
133
+ }
134
+
135
+ function getRequest(taggedNode: GraphQLTaggedNode): ConcreteRequest {
136
+ const request = getNode(taggedNode);
137
+ invariant(
138
+ isRequest(request),
139
+ 'GraphQLTag: Expected a request, got `%s`.',
140
+ JSON.stringify(request),
141
+ );
142
+ return (request: any);
143
+ }
144
+
145
+ function getInlineDataFragment(
146
+ taggedNode: GraphQLTaggedNode,
147
+ ): ReaderInlineDataFragment {
148
+ const fragment = getNode(taggedNode);
149
+ invariant(
150
+ isInlineDataFragment(fragment),
151
+ 'GraphQLTag: Expected an inline data fragment, got `%s`.',
152
+ JSON.stringify(fragment),
153
+ );
154
+ return (fragment: any);
155
+ }
156
+
157
+ module.exports = {
158
+ getFragment,
159
+ getNode,
160
+ getPaginationFragment,
161
+ getRefetchableFragment,
162
+ getRequest,
163
+ getInlineDataFragment,
164
+ graphql,
165
+ isFragment,
166
+ isRequest,
167
+ isInlineDataFragment,
168
+ };
@@ -0,0 +1,65 @@
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
+ * @emails oncall+relay
8
+ * @flow strict-local
9
+ * @format
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ import type {ConcreteRequest, Disposable} from 'relay-runtime';
15
+
16
+ type Callback = (concreteRequest: ConcreteRequest) => void;
17
+
18
+ class PreloadableQueryRegistry {
19
+ _preloadableQueries: Map<string, ConcreteRequest>;
20
+ _callbacks: Map<string, Set<Callback>>;
21
+ constructor() {
22
+ this._preloadableQueries = new Map();
23
+ this._callbacks = new Map();
24
+ }
25
+
26
+ set(key: string, value: ConcreteRequest) {
27
+ this._preloadableQueries.set(key, value);
28
+ const callbacks = this._callbacks.get(key);
29
+ if (callbacks != null) {
30
+ callbacks.forEach(cb => {
31
+ try {
32
+ cb(value);
33
+ } catch (e) {
34
+ // We do *not* want to throw in this tick, as this callback is executed
35
+ // while a query is required for the very first time.
36
+ setTimeout(() => {
37
+ throw e;
38
+ }, 0);
39
+ }
40
+ });
41
+ }
42
+ }
43
+
44
+ get(key: string): ?ConcreteRequest {
45
+ return this._preloadableQueries.get(key);
46
+ }
47
+
48
+ onLoad(key: string, callback: Callback): Disposable {
49
+ const callbacks = this._callbacks.get(key) ?? new Set();
50
+ callbacks.add(callback);
51
+ const dispose = () => {
52
+ callbacks.delete(callback);
53
+ };
54
+ this._callbacks.set(key, callbacks);
55
+ return {dispose};
56
+ }
57
+
58
+ clear() {
59
+ this._preloadableQueries.clear();
60
+ }
61
+ }
62
+
63
+ const preloadableQueryRegistry: PreloadableQueryRegistry = new PreloadableQueryRegistry();
64
+
65
+ module.exports = preloadableQueryRegistry;
@@ -0,0 +1,47 @@
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 {
16
+ createOperationDescriptor,
17
+ } = require('../store/RelayModernOperationDescriptor');
18
+ const {getRequest} = require('./GraphQLTag');
19
+
20
+ import type {IEnvironment} from '../store/RelayStoreTypes';
21
+ import type {CacheConfig, OperationType} from '../util/RelayRuntimeTypes';
22
+ import type {GraphQLTaggedNode} from './GraphQLTag';
23
+
24
+ /**
25
+ * A helper function to fetch the results of a query. Note that results for
26
+ * fragment spreads are masked: fields must be explicitly listed in the query in
27
+ * order to be accessible in the result object.
28
+ */
29
+
30
+ function fetchQuery<T: OperationType>(
31
+ environment: IEnvironment,
32
+ taggedNode: GraphQLTaggedNode,
33
+ variables: $PropertyType<T, 'variables'>,
34
+ cacheConfig?: ?CacheConfig,
35
+ ): Promise<$PropertyType<T, 'response'>> {
36
+ const query = getRequest(taggedNode);
37
+ if (query.params.operationKind !== 'query') {
38
+ throw new Error('fetchQuery: Expected query operation');
39
+ }
40
+ const operation = createOperationDescriptor(query, variables, cacheConfig);
41
+ return environment
42
+ .execute({operation})
43
+ .map(() => environment.lookup(operation.fragment).data)
44
+ .toPromise();
45
+ }
46
+
47
+ module.exports = fetchQuery;