relay-runtime 11.0.0-rc.0 → 12.0.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.
- package/handlers/connection/ConnectionHandler.js.flow +7 -0
- package/handlers/connection/MutationHandlers.js.flow +28 -0
- package/index.js +1 -1
- package/index.js.flow +20 -3
- package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
- package/lib/handlers/connection/ConnectionHandler.js +12 -6
- package/lib/handlers/connection/MutationHandlers.js +67 -8
- package/lib/index.js +15 -0
- package/lib/multi-actor-environment/ActorIdentifier.js +33 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +148 -0
- package/lib/multi-actor-environment/ActorUtils.js +27 -0
- package/lib/multi-actor-environment/MultiActorEnvironment.js +406 -0
- package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
- package/lib/multi-actor-environment/index.js +21 -0
- package/lib/mutations/RelayRecordProxy.js +1 -1
- package/lib/mutations/RelayRecordSourceMutator.js +1 -1
- package/lib/mutations/RelayRecordSourceProxy.js +1 -1
- package/lib/mutations/RelayRecordSourceSelectorProxy.js +7 -2
- package/lib/mutations/applyOptimisticMutation.js +1 -1
- package/lib/mutations/commitMutation.js +5 -2
- package/lib/mutations/validateMutation.js +39 -17
- package/lib/network/RelayNetwork.js +1 -1
- package/lib/network/RelayObservable.js +3 -1
- package/lib/network/RelayQueryResponseCache.js +20 -3
- package/lib/network/wrapNetworkWithLogObserver.js +78 -0
- package/lib/query/GraphQLTag.js +1 -1
- package/lib/query/fetchQuery.js +1 -1
- package/lib/query/fetchQueryInternal.js +1 -1
- package/lib/store/DataChecker.js +132 -50
- package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +524 -187
- package/lib/store/RelayConcreteVariables.js +29 -4
- package/lib/store/RelayModernEnvironment.js +137 -220
- package/lib/store/RelayModernFragmentSpecResolver.js +49 -23
- package/lib/store/RelayModernRecord.js +36 -2
- package/lib/store/RelayModernSelector.js +1 -1
- package/lib/store/RelayModernStore.js +53 -22
- package/lib/store/RelayOperationTracker.js +34 -24
- package/lib/store/RelayPublishQueue.js +30 -8
- package/lib/store/RelayReader.js +177 -29
- package/lib/store/RelayRecordSource.js +87 -3
- package/lib/store/RelayReferenceMarker.js +53 -28
- package/lib/store/RelayResponseNormalizer.js +247 -108
- package/lib/store/RelayStoreReactFlightUtils.js +7 -11
- package/lib/store/RelayStoreSubscriptions.js +8 -5
- package/lib/store/RelayStoreUtils.js +10 -4
- package/lib/store/ResolverCache.js +213 -0
- package/lib/store/ResolverFragments.js +57 -0
- package/lib/store/cloneRelayHandleSourceField.js +1 -1
- package/lib/store/cloneRelayScalarHandleSourceField.js +1 -1
- package/lib/store/createRelayContext.js +2 -2
- package/lib/store/defaultGetDataID.js +3 -1
- package/lib/store/readInlineData.js +1 -1
- package/lib/subscription/requestSubscription.js +32 -6
- package/lib/util/RelayConcreteNode.js +3 -0
- package/lib/util/RelayFeatureFlags.js +5 -4
- package/lib/util/RelayProfiler.js +17 -187
- package/lib/util/RelayReplaySubject.js +22 -7
- package/lib/util/deepFreeze.js +1 -0
- package/lib/util/getPaginationMetadata.js +41 -0
- package/lib/util/getPaginationVariables.js +67 -0
- package/lib/util/getPendingOperationsForFragment.js +55 -0
- package/lib/util/getRefetchMetadata.js +36 -0
- package/lib/util/getRelayHandleKey.js +1 -1
- package/lib/util/getRequestIdentifier.js +1 -1
- package/lib/util/getValueAtPath.js +51 -0
- package/lib/util/isEmptyObject.js +1 -1
- package/lib/util/registerEnvironmentWithDevTools.js +26 -0
- package/lib/util/withDuration.js +31 -0
- package/multi-actor-environment/ActorIdentifier.js.flow +43 -0
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +217 -0
- package/multi-actor-environment/ActorUtils.js.flow +33 -0
- package/multi-actor-environment/MultiActorEnvironment.js.flow +485 -0
- package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +245 -0
- package/multi-actor-environment/index.js.flow +27 -0
- package/mutations/RelayRecordSourceSelectorProxy.js.flow +7 -2
- package/mutations/commitMutation.js.flow +3 -1
- package/mutations/validateMutation.js.flow +42 -16
- package/network/RelayNetworkTypes.js.flow +17 -8
- package/network/RelayObservable.js.flow +2 -0
- package/network/RelayQueryResponseCache.js.flow +31 -17
- package/network/wrapNetworkWithLogObserver.js.flow +99 -0
- package/package.json +3 -2
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/ClientID.js.flow +5 -1
- package/store/DataChecker.js.flow +148 -44
- package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +578 -237
- package/store/RelayConcreteVariables.js.flow +31 -1
- package/store/RelayModernEnvironment.js.flow +132 -220
- package/store/RelayModernFragmentSpecResolver.js.flow +40 -14
- package/store/RelayModernOperationDescriptor.js.flow +9 -3
- package/store/RelayModernRecord.js.flow +49 -0
- package/store/RelayModernStore.js.flow +57 -17
- package/store/RelayOperationTracker.js.flow +56 -34
- package/store/RelayPublishQueue.js.flow +37 -11
- package/store/RelayReader.js.flow +186 -27
- package/store/RelayRecordSource.js.flow +72 -6
- package/store/RelayReferenceMarker.js.flow +51 -21
- package/store/RelayResponseNormalizer.js.flow +251 -67
- package/store/RelayStoreReactFlightUtils.js.flow +6 -9
- package/store/RelayStoreSubscriptions.js.flow +10 -3
- package/store/RelayStoreTypes.js.flow +144 -21
- package/store/RelayStoreUtils.js.flow +19 -4
- package/store/ResolverCache.js.flow +247 -0
- package/store/ResolverFragments.js.flow +128 -0
- package/store/createRelayContext.js.flow +1 -1
- package/store/defaultGetDataID.js.flow +3 -1
- package/subscription/requestSubscription.js.flow +43 -8
- package/util/NormalizationNode.js.flow +16 -3
- package/util/ReaderNode.js.flow +29 -2
- package/util/RelayConcreteNode.js.flow +3 -0
- package/util/RelayFeatureFlags.js.flow +10 -6
- package/util/RelayProfiler.js.flow +22 -194
- package/util/RelayReplaySubject.js.flow +7 -6
- package/util/RelayRuntimeTypes.js.flow +4 -2
- package/util/deepFreeze.js.flow +2 -1
- package/util/getPaginationMetadata.js.flow +74 -0
- package/util/getPaginationVariables.js.flow +112 -0
- package/util/getPendingOperationsForFragment.js.flow +62 -0
- package/util/getRefetchMetadata.js.flow +80 -0
- package/util/getValueAtPath.js.flow +46 -0
- package/util/isEmptyObject.js.flow +2 -1
- package/util/registerEnvironmentWithDevTools.js.flow +33 -0
- package/util/withDuration.js.flow +32 -0
- package/lib/store/RelayRecordSourceMapImpl.js +0 -107
- package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +0 -318
- package/store/RelayRecordSourceMapImpl.js.flow +0 -91
- package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +0 -283
|
@@ -0,0 +1,128 @@
|
|
|
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 {getFragment} = require('../query/GraphQLTag');
|
|
18
|
+
const {getSelector} = require('./RelayModernSelector');
|
|
19
|
+
|
|
20
|
+
import type {GraphQLTaggedNode} from '../query/GraphQLTag';
|
|
21
|
+
import type {
|
|
22
|
+
FragmentReference,
|
|
23
|
+
SingularReaderSelector,
|
|
24
|
+
} from './RelayStoreTypes';
|
|
25
|
+
|
|
26
|
+
// When we call the user-supplied resolver function, it will in turn call
|
|
27
|
+
// `readFragment`, but that's a global function -- it needs information
|
|
28
|
+
// about what resolver is being executed, which is supplied by putting the
|
|
29
|
+
// info on this stack before we call the resolver function.
|
|
30
|
+
type ResolverContext = {|
|
|
31
|
+
getDataForResolverFragment: (
|
|
32
|
+
SingularReaderSelector,
|
|
33
|
+
FragmentReference,
|
|
34
|
+
) => mixed,
|
|
35
|
+
|};
|
|
36
|
+
const contextStack: Array<ResolverContext> = [];
|
|
37
|
+
|
|
38
|
+
function withResolverContext<T>(context: ResolverContext, cb: () => T): T {
|
|
39
|
+
contextStack.push(context);
|
|
40
|
+
try {
|
|
41
|
+
return cb();
|
|
42
|
+
} finally {
|
|
43
|
+
contextStack.pop();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// NOTE: these declarations are copied from 'useFragment'; it would be good
|
|
48
|
+
// to figure out how to share the same type signature between the two functions.
|
|
49
|
+
// The declarations ensure that the type of the returned data is:
|
|
50
|
+
// - non-nullable if the provided ref type is non-nullable
|
|
51
|
+
// - nullable if the provided ref type is nullable
|
|
52
|
+
// - array of non-nullable if the privoided ref type is an array of
|
|
53
|
+
// non-nullable refs
|
|
54
|
+
// - array of nullable if the privoided ref type is an array of nullable refs
|
|
55
|
+
|
|
56
|
+
declare function readFragment<
|
|
57
|
+
TKey: {+$data?: mixed, +$fragmentRefs: FragmentReference, ...},
|
|
58
|
+
>(
|
|
59
|
+
fragmentInput: GraphQLTaggedNode,
|
|
60
|
+
fragmentRef: TKey,
|
|
61
|
+
): $Call<<TFragmentData>({+$data?: TFragmentData, ...}) => TFragmentData, TKey>;
|
|
62
|
+
|
|
63
|
+
declare function readFragment<
|
|
64
|
+
TKey: ?{+$data?: mixed, +$fragmentRefs: FragmentReference, ...},
|
|
65
|
+
>(
|
|
66
|
+
fragmentInput: GraphQLTaggedNode,
|
|
67
|
+
fragmentRef: TKey,
|
|
68
|
+
): $Call<
|
|
69
|
+
<TFragmentData>(?{+$data?: TFragmentData, ...}) => ?TFragmentData,
|
|
70
|
+
TKey,
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
declare function readFragment<
|
|
74
|
+
TKey: $ReadOnlyArray<{
|
|
75
|
+
+$data?: mixed,
|
|
76
|
+
+$fragmentRefs: FragmentReference,
|
|
77
|
+
...
|
|
78
|
+
}>,
|
|
79
|
+
>(
|
|
80
|
+
fragmentInput: GraphQLTaggedNode,
|
|
81
|
+
fragmentRef: TKey,
|
|
82
|
+
): $Call<
|
|
83
|
+
<TFragmentData>(
|
|
84
|
+
$ReadOnlyArray<{+$data?: TFragmentData, ...}>,
|
|
85
|
+
) => TFragmentData,
|
|
86
|
+
TKey,
|
|
87
|
+
>;
|
|
88
|
+
|
|
89
|
+
declare function readFragment<
|
|
90
|
+
TKey: ?$ReadOnlyArray<{
|
|
91
|
+
+$data?: mixed,
|
|
92
|
+
+$fragmentRefs: FragmentReference,
|
|
93
|
+
...
|
|
94
|
+
}>,
|
|
95
|
+
>(
|
|
96
|
+
fragmentInput: GraphQLTaggedNode,
|
|
97
|
+
fragmentRef: TKey,
|
|
98
|
+
): $Call<
|
|
99
|
+
<TFragmentData>(
|
|
100
|
+
?$ReadOnlyArray<{+$data?: TFragmentData, ...}>,
|
|
101
|
+
) => ?TFragmentData,
|
|
102
|
+
TKey,
|
|
103
|
+
>;
|
|
104
|
+
|
|
105
|
+
function readFragment(
|
|
106
|
+
fragmentInput: GraphQLTaggedNode,
|
|
107
|
+
fragmentRef: FragmentReference,
|
|
108
|
+
): mixed {
|
|
109
|
+
if (!contextStack.length) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
'readFragment should be called only from within a Relay Resolver function.',
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const context = contextStack[contextStack.length - 1];
|
|
115
|
+
const fragmentNode = getFragment(fragmentInput);
|
|
116
|
+
const fragmentSelector = getSelector(fragmentNode, fragmentRef);
|
|
117
|
+
invariant(
|
|
118
|
+
fragmentSelector != null,
|
|
119
|
+
`Expected a selector for the fragment of the resolver ${fragmentNode.name}, but got null.`,
|
|
120
|
+
);
|
|
121
|
+
invariant(
|
|
122
|
+
fragmentSelector.kind === 'SingularReaderSelector',
|
|
123
|
+
`Expected a singular reader selector for the fragment of the resolver ${fragmentNode.name}, but it was plural.`,
|
|
124
|
+
);
|
|
125
|
+
return context.getDataForResolverFragment(fragmentSelector, fragmentRef);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = {readFragment, withResolverContext};
|
|
@@ -38,7 +38,7 @@ function createRelayContext(react: React): React$Context<RelayContext | null> {
|
|
|
38
38
|
}
|
|
39
39
|
invariant(
|
|
40
40
|
react === firstReact,
|
|
41
|
-
'[createRelayContext]: You passing a different instance of React',
|
|
41
|
+
'[createRelayContext]: You are passing a different instance of React',
|
|
42
42
|
react.version,
|
|
43
43
|
);
|
|
44
44
|
return relayContext;
|
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
const {VIEWER_ID, VIEWER_TYPE} = require('./ViewerPattern');
|
|
16
16
|
|
|
17
17
|
function defaultGetDataID(
|
|
18
|
-
fieldValue: {[string]: mixed
|
|
18
|
+
fieldValue: interface {[string]: mixed},
|
|
19
19
|
typeName: string,
|
|
20
20
|
): mixed {
|
|
21
21
|
if (typeName === VIEWER_TYPE) {
|
|
22
|
+
// $FlowFixMe[prop-missing]
|
|
22
23
|
return fieldValue.id == null ? VIEWER_ID : fieldValue.id;
|
|
23
24
|
}
|
|
25
|
+
// $FlowFixMe[prop-missing]
|
|
24
26
|
return fieldValue.id;
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
15
|
const RelayDeclarativeMutationConfig = require('../mutations/RelayDeclarativeMutationConfig');
|
|
16
|
+
const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
16
17
|
|
|
17
18
|
const warning = require('warning');
|
|
18
19
|
|
|
@@ -20,6 +21,7 @@ const {getRequest} = require('../query/GraphQLTag');
|
|
|
20
21
|
const {
|
|
21
22
|
createOperationDescriptor,
|
|
22
23
|
} = require('../store/RelayModernOperationDescriptor');
|
|
24
|
+
const {createReaderSelector} = require('../store/RelayModernSelector');
|
|
23
25
|
|
|
24
26
|
import type {DeclarativeMutationConfig} from '../mutations/RelayDeclarativeMutationConfig';
|
|
25
27
|
import type {GraphQLTaggedNode} from '../query/GraphQLTag';
|
|
@@ -33,7 +35,24 @@ import type {
|
|
|
33
35
|
Variables,
|
|
34
36
|
} from '../util/RelayRuntimeTypes';
|
|
35
37
|
|
|
36
|
-
export type
|
|
38
|
+
export type SubscriptionParameters = {|
|
|
39
|
+
+response: {...},
|
|
40
|
+
+variables: interface {},
|
|
41
|
+
+rawResponse?: {...},
|
|
42
|
+
|};
|
|
43
|
+
|
|
44
|
+
export type GraphQLSubscriptionConfig<T: SubscriptionParameters> = {|
|
|
45
|
+
configs?: Array<DeclarativeMutationConfig>,
|
|
46
|
+
cacheConfig?: CacheConfig,
|
|
47
|
+
subscription: GraphQLTaggedNode,
|
|
48
|
+
variables: $ElementType<T, 'variables'>,
|
|
49
|
+
onCompleted?: ?() => void,
|
|
50
|
+
onError?: ?(error: Error) => void,
|
|
51
|
+
onNext?: ?(response: ?$ElementType<T, 'response'>) => void,
|
|
52
|
+
updater?: ?SelectorStoreUpdater,
|
|
53
|
+
|};
|
|
54
|
+
|
|
55
|
+
export type DEPRECATED_GraphQLSubscriptionConfig<TSubscriptionPayload> = {|
|
|
37
56
|
configs?: Array<DeclarativeMutationConfig>,
|
|
38
57
|
cacheConfig?: CacheConfig,
|
|
39
58
|
subscription: GraphQLTaggedNode,
|
|
@@ -46,7 +65,7 @@ export type GraphQLSubscriptionConfig<TSubscriptionPayload> = {|
|
|
|
46
65
|
|
|
47
66
|
function requestSubscription<TSubscriptionPayload>(
|
|
48
67
|
environment: IEnvironment,
|
|
49
|
-
config:
|
|
68
|
+
config: DEPRECATED_GraphQLSubscriptionConfig<TSubscriptionPayload>,
|
|
50
69
|
): Disposable {
|
|
51
70
|
const subscription = getRequest(config.subscription);
|
|
52
71
|
if (subscription.params.operationKind !== 'subscription') {
|
|
@@ -85,13 +104,29 @@ function requestSubscription<TSubscriptionPayload>(
|
|
|
85
104
|
operation,
|
|
86
105
|
updater,
|
|
87
106
|
})
|
|
88
|
-
.map(() => {
|
|
89
|
-
const data = environment.lookup(operation.fragment).data;
|
|
90
|
-
// $FlowFixMe[incompatible-cast]
|
|
91
|
-
return (data: TSubscriptionPayload);
|
|
92
|
-
})
|
|
93
107
|
.subscribe({
|
|
94
|
-
next:
|
|
108
|
+
next: responses => {
|
|
109
|
+
if (onNext != null) {
|
|
110
|
+
let selector = operation.fragment;
|
|
111
|
+
let nextID;
|
|
112
|
+
if (Array.isArray(responses)) {
|
|
113
|
+
nextID = responses[0]?.extensions?.__relay_subscription_root_id;
|
|
114
|
+
} else {
|
|
115
|
+
nextID = responses.extensions?.__relay_subscription_root_id;
|
|
116
|
+
}
|
|
117
|
+
if (typeof nextID === 'string') {
|
|
118
|
+
selector = createReaderSelector(
|
|
119
|
+
selector.node,
|
|
120
|
+
nextID,
|
|
121
|
+
selector.variables,
|
|
122
|
+
selector.owner,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
const data = environment.lookup(selector).data;
|
|
126
|
+
// $FlowFixMe[incompatible-cast]
|
|
127
|
+
onNext((data: TSubscriptionPayload));
|
|
128
|
+
}
|
|
129
|
+
},
|
|
95
130
|
error: onError,
|
|
96
131
|
complete: onCompleted,
|
|
97
132
|
});
|
|
@@ -87,7 +87,7 @@ export type NormalizationInlineFragment = {|
|
|
|
87
87
|
|
|
88
88
|
export type NormalizationFragmentSpread = {|
|
|
89
89
|
+kind: 'FragmentSpread',
|
|
90
|
-
+fragment:
|
|
90
|
+
+fragment: NormalizationSplitOperation,
|
|
91
91
|
+args: ?$ReadOnlyArray<NormalizationArgument>,
|
|
92
92
|
|};
|
|
93
93
|
|
|
@@ -102,7 +102,13 @@ export type NormalizationLinkedField = {|
|
|
|
102
102
|
+selections: $ReadOnlyArray<NormalizationSelection>,
|
|
103
103
|
|};
|
|
104
104
|
|
|
105
|
+
export type NormalizationActorChange = {|
|
|
106
|
+
+kind: 'ActorChange',
|
|
107
|
+
+linkedField: NormalizationLinkedField,
|
|
108
|
+
|};
|
|
109
|
+
|
|
105
110
|
export type NormalizationModuleImport = {|
|
|
111
|
+
+args: ?$ReadOnlyArray<NormalizationArgument>,
|
|
106
112
|
+kind: 'ModuleImport',
|
|
107
113
|
+documentName: string,
|
|
108
114
|
+fragmentPropName: string,
|
|
@@ -154,6 +160,12 @@ export type NormalizationFlightField = {|
|
|
|
154
160
|
+storageKey: ?string,
|
|
155
161
|
|};
|
|
156
162
|
|
|
163
|
+
export type NormalizationClientComponent = {|
|
|
164
|
+
+args?: ?$ReadOnlyArray<NormalizationArgument>,
|
|
165
|
+
+kind: 'ClientComponent',
|
|
166
|
+
+fragment: NormalizationNode,
|
|
167
|
+
|};
|
|
168
|
+
|
|
157
169
|
export type NormalizationTypeDiscriminator = {|
|
|
158
170
|
+kind: 'TypeDiscriminator',
|
|
159
171
|
+abstractKey: string,
|
|
@@ -161,6 +173,7 @@ export type NormalizationTypeDiscriminator = {|
|
|
|
161
173
|
|
|
162
174
|
export type NormalizationSelection =
|
|
163
175
|
| NormalizationCondition
|
|
176
|
+
| NormalizationClientComponent
|
|
164
177
|
| NormalizationClientExtension
|
|
165
178
|
| NormalizationDefer
|
|
166
179
|
| NormalizationField
|
|
@@ -170,9 +183,11 @@ export type NormalizationSelection =
|
|
|
170
183
|
| NormalizationInlineFragment
|
|
171
184
|
| NormalizationModuleImport
|
|
172
185
|
| NormalizationStream
|
|
186
|
+
| NormalizationActorChange
|
|
173
187
|
| NormalizationTypeDiscriminator;
|
|
174
188
|
|
|
175
189
|
export type NormalizationSplitOperation = {|
|
|
190
|
+
+argumentDefinitions?: $ReadOnlyArray<NormalizationLocalArgumentDefinition>,
|
|
176
191
|
+kind: 'SplitOperation',
|
|
177
192
|
+name: string,
|
|
178
193
|
+metadata: ?{+[key: string]: mixed, ...},
|
|
@@ -183,8 +198,6 @@ export type NormalizationStream = {|
|
|
|
183
198
|
+if: string | null,
|
|
184
199
|
+kind: 'Stream',
|
|
185
200
|
+label: string,
|
|
186
|
-
+useCustomizedBatch: string | null,
|
|
187
|
-
+metadata: ?{+[key: string]: mixed, ...},
|
|
188
201
|
+selections: $ReadOnlyArray<NormalizationSelection>,
|
|
189
202
|
|};
|
|
190
203
|
|
package/util/ReaderNode.js.flow
CHANGED
|
@@ -108,7 +108,10 @@ export type ReaderClientExtension = {|
|
|
|
108
108
|
+selections: $ReadOnlyArray<ReaderSelection>,
|
|
109
109
|
|};
|
|
110
110
|
|
|
111
|
-
export type ReaderField =
|
|
111
|
+
export type ReaderField =
|
|
112
|
+
| ReaderScalarField
|
|
113
|
+
| ReaderLinkedField
|
|
114
|
+
| ReaderRelayResolver;
|
|
112
115
|
|
|
113
116
|
export type ReaderRootArgument = {|
|
|
114
117
|
+kind: 'RootArgument',
|
|
@@ -133,7 +136,17 @@ export type ReaderLinkedField = {|
|
|
|
133
136
|
+selections: $ReadOnlyArray<ReaderSelection>,
|
|
134
137
|
|};
|
|
135
138
|
|
|
139
|
+
export type ReaderActorChange = {|
|
|
140
|
+
+kind: 'ActorChange',
|
|
141
|
+
+alias: ?string,
|
|
142
|
+
+name: string,
|
|
143
|
+
+storageKey: ?string,
|
|
144
|
+
+args: ?$ReadOnlyArray<ReaderArgument>,
|
|
145
|
+
+fragmentSpread: ReaderFragmentSpread,
|
|
146
|
+
|};
|
|
147
|
+
|
|
136
148
|
export type ReaderModuleImport = {|
|
|
149
|
+
+args?: ?$ReadOnlyArray<ReaderArgument>,
|
|
137
150
|
+kind: 'ModuleImport',
|
|
138
151
|
+documentName: string,
|
|
139
152
|
+fragmentPropName: string,
|
|
@@ -206,18 +219,32 @@ export type ReaderRequiredField = {|
|
|
|
206
219
|
+path: string,
|
|
207
220
|
|};
|
|
208
221
|
|
|
222
|
+
export type ReaderRelayResolver = {|
|
|
223
|
+
+kind: 'RelayResolver',
|
|
224
|
+
+alias: ?string,
|
|
225
|
+
+name: string,
|
|
226
|
+
+fragment: ReaderFragmentSpread,
|
|
227
|
+
+resolverModule: (rootKey: {
|
|
228
|
+
+$data?: any, // flowlint-line unclear-type:off
|
|
229
|
+
+$fragmentRefs: any, // flowlint-line unclear-type:off
|
|
230
|
+
...
|
|
231
|
+
}) => mixed,
|
|
232
|
+
|};
|
|
233
|
+
|
|
209
234
|
export type ReaderSelection =
|
|
210
235
|
| ReaderCondition
|
|
211
236
|
| ReaderClientExtension
|
|
212
237
|
| ReaderDefer
|
|
213
238
|
| ReaderField
|
|
239
|
+
| ReaderActorChange
|
|
214
240
|
| ReaderFlightField
|
|
215
241
|
| ReaderFragmentSpread
|
|
216
242
|
| ReaderInlineDataFragmentSpread
|
|
217
243
|
| ReaderInlineFragment
|
|
218
244
|
| ReaderModuleImport
|
|
219
245
|
| ReaderStream
|
|
220
|
-
| ReaderRequiredField
|
|
246
|
+
| ReaderRequiredField
|
|
247
|
+
| ReaderRelayResolver;
|
|
221
248
|
|
|
222
249
|
export type ReaderVariableArgument = {|
|
|
223
250
|
+kind: 'Variable',
|
|
@@ -67,7 +67,9 @@ export type GeneratedNode =
|
|
|
67
67
|
| NormalizationSplitOperation;
|
|
68
68
|
|
|
69
69
|
const RelayConcreteNode = {
|
|
70
|
+
ACTOR_CHANGE: 'ActorChange',
|
|
70
71
|
CONDITION: 'Condition',
|
|
72
|
+
CLIENT_COMPONENT: 'ClientComponent',
|
|
71
73
|
CLIENT_EXTENSION: 'ClientExtension',
|
|
72
74
|
DEFER: 'Defer',
|
|
73
75
|
CONNECTION: 'Connection',
|
|
@@ -83,6 +85,7 @@ const RelayConcreteNode = {
|
|
|
83
85
|
LIST_VALUE: 'ListValue',
|
|
84
86
|
LOCAL_ARGUMENT: 'LocalArgument',
|
|
85
87
|
MODULE_IMPORT: 'ModuleImport',
|
|
88
|
+
RELAY_RESOLVER: 'RelayResolver',
|
|
86
89
|
REQUIRED_FIELD: 'RequiredField',
|
|
87
90
|
OBJECT_VALUE: 'ObjectValue',
|
|
88
91
|
OPERATION: 'Operation',
|
|
@@ -12,34 +12,38 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
import type {Disposable} from '../util/RelayRuntimeTypes';
|
|
16
|
+
|
|
15
17
|
type FeatureFlags = {|
|
|
16
18
|
ENABLE_VARIABLE_CONNECTION_KEY: boolean,
|
|
17
19
|
ENABLE_PARTIAL_RENDERING_DEFAULT: boolean,
|
|
18
|
-
ENABLE_RELAY_CONTAINERS_SUSPENSE: boolean,
|
|
19
|
-
ENABLE_PRECISE_TYPE_REFINEMENT: boolean,
|
|
20
20
|
ENABLE_REACT_FLIGHT_COMPONENT_FIELD: boolean,
|
|
21
21
|
ENABLE_REQUIRED_DIRECTIVES: boolean | string,
|
|
22
|
+
ENABLE_RELAY_RESOLVERS: boolean,
|
|
22
23
|
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: boolean,
|
|
23
24
|
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: boolean,
|
|
24
|
-
ENABLE_STORE_SUBSCRIPTIONS_REFACTOR: boolean,
|
|
25
25
|
ENABLE_LOAD_QUERY_REQUEST_DEDUPING: boolean,
|
|
26
26
|
ENABLE_DO_NOT_WRAP_LIVE_QUERY: boolean,
|
|
27
27
|
ENABLE_NOTIFY_SUBSCRIPTION: boolean,
|
|
28
|
+
BATCH_ASYNC_MODULE_UPDATES_FN: ?(() => void) => Disposable,
|
|
29
|
+
ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT: boolean,
|
|
30
|
+
ENABLE_QUERY_RENDERER_OFFSCREEN_SUPPORT: boolean,
|
|
28
31
|
|};
|
|
29
32
|
|
|
30
33
|
const RelayFeatureFlags: FeatureFlags = {
|
|
31
34
|
ENABLE_VARIABLE_CONNECTION_KEY: false,
|
|
32
35
|
ENABLE_PARTIAL_RENDERING_DEFAULT: true,
|
|
33
|
-
ENABLE_RELAY_CONTAINERS_SUSPENSE: true,
|
|
34
|
-
ENABLE_PRECISE_TYPE_REFINEMENT: false,
|
|
35
36
|
ENABLE_REACT_FLIGHT_COMPONENT_FIELD: false,
|
|
36
37
|
ENABLE_REQUIRED_DIRECTIVES: false,
|
|
38
|
+
ENABLE_RELAY_RESOLVERS: false,
|
|
37
39
|
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: false,
|
|
38
40
|
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: false,
|
|
39
|
-
ENABLE_STORE_SUBSCRIPTIONS_REFACTOR: false,
|
|
40
41
|
ENABLE_LOAD_QUERY_REQUEST_DEDUPING: true,
|
|
41
42
|
ENABLE_DO_NOT_WRAP_LIVE_QUERY: false,
|
|
42
43
|
ENABLE_NOTIFY_SUBSCRIPTION: false,
|
|
44
|
+
BATCH_ASYNC_MODULE_UPDATES_FN: null,
|
|
45
|
+
ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT: false,
|
|
46
|
+
ENABLE_QUERY_RENDERER_OFFSCREEN_SUPPORT: false,
|
|
43
47
|
};
|
|
44
48
|
|
|
45
49
|
module.exports = RelayFeatureFlags;
|
|
@@ -12,25 +12,15 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
type
|
|
16
|
-
type ProfileHandler = (name:
|
|
15
|
+
type EventName = 'fetchRelayQuery';
|
|
16
|
+
type ProfileHandler = (name: EventName, state?: any) => (error?: Error) => void;
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
const profileHandlersByName: {|
|
|
19
|
+
[name: EventName]: Array<ProfileHandler>,
|
|
20
|
+
|} = {};
|
|
19
21
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
};
|
|
23
|
-
const profileHandlersByName: {[name: string]: Array<ProfileHandler>, ...} = {
|
|
24
|
-
'*': [],
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const NOT_INVOKED = {};
|
|
28
|
-
const defaultProfiler = {stop: emptyFunction};
|
|
29
|
-
const shouldInstrument = name => {
|
|
30
|
-
if (__DEV__) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
return name.charAt(0) !== '@';
|
|
22
|
+
const defaultProfiler = {
|
|
23
|
+
stop() {},
|
|
34
24
|
};
|
|
35
25
|
|
|
36
26
|
/**
|
|
@@ -60,154 +50,8 @@ const shouldInstrument = name => {
|
|
|
60
50
|
* console.log(`Duration (${name})`, performance.now() - start);
|
|
61
51
|
* }
|
|
62
52
|
* });
|
|
63
|
-
*
|
|
64
|
-
* In order to reduce the impact on performance in production, instrumented
|
|
65
|
-
* methods and profilers with names that begin with `@` will only be measured
|
|
66
|
-
* if `__DEV__` is true. This should be used for very hot functions.
|
|
67
53
|
*/
|
|
68
54
|
const RelayProfiler = {
|
|
69
|
-
/**
|
|
70
|
-
* Instruments methods on a class or object. This re-assigns the method in
|
|
71
|
-
* order to preserve function names in stack traces (which are detected by
|
|
72
|
-
* modern debuggers via heuristics). Example usage:
|
|
73
|
-
*
|
|
74
|
-
* const RelayStore = { primeCache: function() {...} };
|
|
75
|
-
* RelayProfiler.instrumentMethods(RelayStore, {
|
|
76
|
-
* primeCache: 'RelayStore.primeCache'
|
|
77
|
-
* });
|
|
78
|
-
*
|
|
79
|
-
* RelayStore.primeCache.attachHandler(...);
|
|
80
|
-
*
|
|
81
|
-
* As a result, the methods will be replaced by wrappers that provide the
|
|
82
|
-
* `attachHandler` and `detachHandler` methods.
|
|
83
|
-
*/
|
|
84
|
-
instrumentMethods(
|
|
85
|
-
object: Function | Object,
|
|
86
|
-
names: {[key: string]: string, ...},
|
|
87
|
-
): void {
|
|
88
|
-
for (const key in names) {
|
|
89
|
-
if (names.hasOwnProperty(key)) {
|
|
90
|
-
if (typeof object[key] === 'function') {
|
|
91
|
-
object[key] = RelayProfiler.instrument(names[key], object[key]);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Wraps the supplied function with one that provides the `attachHandler` and
|
|
99
|
-
* `detachHandler` methods. Example usage:
|
|
100
|
-
*
|
|
101
|
-
* const printRelayQuery =
|
|
102
|
-
* RelayProfiler.instrument('printRelayQuery', printRelayQuery);
|
|
103
|
-
*
|
|
104
|
-
* printRelayQuery.attachHandler(...);
|
|
105
|
-
*
|
|
106
|
-
* NOTE: The instrumentation assumes that no handlers are attached or detached
|
|
107
|
-
* in the course of executing another handler.
|
|
108
|
-
*/
|
|
109
|
-
instrument<T: Function>(name: string, originalFunction: T): T {
|
|
110
|
-
if (!shouldInstrument(name)) {
|
|
111
|
-
originalFunction.attachHandler = emptyFunction;
|
|
112
|
-
originalFunction.detachHandler = emptyFunction;
|
|
113
|
-
return originalFunction;
|
|
114
|
-
}
|
|
115
|
-
if (!aggregateHandlersByName.hasOwnProperty(name)) {
|
|
116
|
-
aggregateHandlersByName[name] = [];
|
|
117
|
-
}
|
|
118
|
-
const catchallHandlers = aggregateHandlersByName['*'];
|
|
119
|
-
const aggregateHandlers = aggregateHandlersByName[name];
|
|
120
|
-
const handlers: Array<Handler> = [];
|
|
121
|
-
const contexts: Array<[number, number, number, any, any, any]> = [];
|
|
122
|
-
const invokeHandlers = function() {
|
|
123
|
-
const context = contexts[contexts.length - 1];
|
|
124
|
-
if (context[0]) {
|
|
125
|
-
context[0]--;
|
|
126
|
-
catchallHandlers[context[0]](name, invokeHandlers);
|
|
127
|
-
} else if (context[1]) {
|
|
128
|
-
context[1]--;
|
|
129
|
-
aggregateHandlers[context[1]](name, invokeHandlers);
|
|
130
|
-
} else if (context[2]) {
|
|
131
|
-
context[2]--;
|
|
132
|
-
handlers[context[2]](name, invokeHandlers);
|
|
133
|
-
} else {
|
|
134
|
-
context[5] = originalFunction.apply(context[3], context[4]);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
const instrumentedCallback = function() {
|
|
138
|
-
let returnValue;
|
|
139
|
-
if (
|
|
140
|
-
aggregateHandlers.length === 0 &&
|
|
141
|
-
handlers.length === 0 &&
|
|
142
|
-
catchallHandlers.length === 0
|
|
143
|
-
) {
|
|
144
|
-
returnValue = originalFunction.apply(this, arguments);
|
|
145
|
-
} else {
|
|
146
|
-
contexts.push([
|
|
147
|
-
catchallHandlers.length,
|
|
148
|
-
aggregateHandlers.length,
|
|
149
|
-
handlers.length,
|
|
150
|
-
this,
|
|
151
|
-
arguments,
|
|
152
|
-
NOT_INVOKED,
|
|
153
|
-
]);
|
|
154
|
-
invokeHandlers();
|
|
155
|
-
const context = contexts.pop();
|
|
156
|
-
returnValue = context[5];
|
|
157
|
-
if (returnValue === NOT_INVOKED) {
|
|
158
|
-
throw new Error(
|
|
159
|
-
'RelayProfiler: Handler did not invoke original function.',
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return returnValue;
|
|
164
|
-
};
|
|
165
|
-
instrumentedCallback.attachHandler = function(handler: Handler): void {
|
|
166
|
-
handlers.push(handler);
|
|
167
|
-
};
|
|
168
|
-
instrumentedCallback.detachHandler = function(handler: Handler): void {
|
|
169
|
-
removeFromArray(handlers, handler);
|
|
170
|
-
};
|
|
171
|
-
instrumentedCallback.displayName = '(instrumented ' + name + ')';
|
|
172
|
-
return (instrumentedCallback: any);
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Attaches a handler to all methods instrumented with the supplied name.
|
|
177
|
-
*
|
|
178
|
-
* function createRenderer() {
|
|
179
|
-
* return RelayProfiler.instrument('render', function() {...});
|
|
180
|
-
* }
|
|
181
|
-
* const renderA = createRenderer();
|
|
182
|
-
* const renderB = createRenderer();
|
|
183
|
-
*
|
|
184
|
-
* // Only profiles `renderA`.
|
|
185
|
-
* renderA.attachHandler(...);
|
|
186
|
-
*
|
|
187
|
-
* // Profiles both `renderA` and `renderB`.
|
|
188
|
-
* RelayProfiler.attachAggregateHandler('render', ...);
|
|
189
|
-
*
|
|
190
|
-
*/
|
|
191
|
-
attachAggregateHandler(name: string, handler: Handler): void {
|
|
192
|
-
if (shouldInstrument(name)) {
|
|
193
|
-
if (!aggregateHandlersByName.hasOwnProperty(name)) {
|
|
194
|
-
aggregateHandlersByName[name] = [];
|
|
195
|
-
}
|
|
196
|
-
aggregateHandlersByName[name].push(handler);
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Detaches a handler attached via `attachAggregateHandler`.
|
|
202
|
-
*/
|
|
203
|
-
detachAggregateHandler(name: string, handler: Handler): void {
|
|
204
|
-
if (shouldInstrument(name)) {
|
|
205
|
-
if (aggregateHandlersByName.hasOwnProperty(name)) {
|
|
206
|
-
removeFromArray(aggregateHandlersByName[name], handler);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
|
|
211
55
|
/**
|
|
212
56
|
* Instruments profiling for arbitrarily asynchronous code by a name.
|
|
213
57
|
*
|
|
@@ -221,28 +65,17 @@ const RelayProfiler = {
|
|
|
221
65
|
* Arbitrary state can also be passed into `profile` as a second argument. The
|
|
222
66
|
* attached profile handlers will receive this as the second argument.
|
|
223
67
|
*/
|
|
224
|
-
profile(name:
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
? profileHandlersByName[name].concat(profileHandlersByName['*'])
|
|
231
|
-
: hasNamedHandlers
|
|
232
|
-
? profileHandlersByName[name]
|
|
233
|
-
: profileHandlersByName['*'];
|
|
234
|
-
let stopHandlers;
|
|
235
|
-
for (let ii = profileHandlers.length - 1; ii >= 0; ii--) {
|
|
236
|
-
const profileHandler = profileHandlers[ii];
|
|
237
|
-
const stopHandler = profileHandler(name, state);
|
|
238
|
-
stopHandlers = stopHandlers || [];
|
|
68
|
+
profile(name: EventName, state?: any): {stop: (error?: Error) => void, ...} {
|
|
69
|
+
const handlers = profileHandlersByName[name];
|
|
70
|
+
if (handlers && handlers.length > 0) {
|
|
71
|
+
const stopHandlers = [];
|
|
72
|
+
for (let ii = handlers.length - 1; ii >= 0; ii--) {
|
|
73
|
+
const stopHandler = handlers[ii](name, state);
|
|
239
74
|
stopHandlers.unshift(stopHandler);
|
|
240
75
|
}
|
|
241
76
|
return {
|
|
242
77
|
stop(error?: Error): void {
|
|
243
|
-
|
|
244
|
-
stopHandlers.forEach(stopHandler => stopHandler(error));
|
|
245
|
-
}
|
|
78
|
+
stopHandlers.forEach(stopHandler => stopHandler(error));
|
|
246
79
|
},
|
|
247
80
|
};
|
|
248
81
|
}
|
|
@@ -250,26 +83,21 @@ const RelayProfiler = {
|
|
|
250
83
|
},
|
|
251
84
|
|
|
252
85
|
/**
|
|
253
|
-
* Attaches a handler to profiles with the supplied name.
|
|
254
|
-
* attach to the special name '*' which is a catch all.
|
|
86
|
+
* Attaches a handler to profiles with the supplied name.
|
|
255
87
|
*/
|
|
256
|
-
attachProfileHandler(name:
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
profileHandlersByName[name] = [];
|
|
260
|
-
}
|
|
261
|
-
profileHandlersByName[name].push(handler);
|
|
88
|
+
attachProfileHandler(name: EventName, handler: ProfileHandler): void {
|
|
89
|
+
if (!profileHandlersByName.hasOwnProperty(name)) {
|
|
90
|
+
profileHandlersByName[name] = [];
|
|
262
91
|
}
|
|
92
|
+
profileHandlersByName[name].push(handler);
|
|
263
93
|
},
|
|
264
94
|
|
|
265
95
|
/**
|
|
266
96
|
* Detaches a handler attached via `attachProfileHandler`.
|
|
267
97
|
*/
|
|
268
|
-
detachProfileHandler(name:
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
removeFromArray(profileHandlersByName[name], handler);
|
|
272
|
-
}
|
|
98
|
+
detachProfileHandler(name: EventName, handler: ProfileHandler): void {
|
|
99
|
+
if (profileHandlersByName.hasOwnProperty(name)) {
|
|
100
|
+
removeFromArray(profileHandlersByName[name], handler);
|
|
273
101
|
}
|
|
274
102
|
},
|
|
275
103
|
};
|