relay-runtime 10.0.1 → 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.
- package/handlers/RelayDefaultHandlerProvider.js.flow +6 -0
- package/handlers/connection/MutationHandlers.js.flow +114 -3
- package/index.js +1 -1
- package/index.js.flow +16 -1
- package/lib/handlers/RelayDefaultHandlerProvider.js +9 -0
- package/lib/handlers/connection/MutationHandlers.js +138 -12
- package/lib/index.js +7 -0
- package/lib/mutations/RelayDeclarativeMutationConfig.js +2 -2
- package/lib/mutations/commitMutation.js +1 -4
- package/lib/mutations/validateMutation.js +27 -7
- package/lib/network/RelayQueryResponseCache.js +2 -2
- package/lib/query/GraphQLTag.js +2 -1
- package/lib/query/fetchQuery.js +2 -3
- package/lib/query/fetchQueryInternal.js +2 -3
- package/lib/store/DataChecker.js +82 -5
- package/lib/store/RelayModernEnvironment.js +18 -6
- package/lib/store/RelayModernFragmentSpecResolver.js +10 -1
- package/lib/store/RelayModernOperationDescriptor.js +6 -5
- package/lib/store/RelayModernQueryExecutor.js +44 -23
- package/lib/store/RelayModernStore.js +25 -14
- package/lib/store/RelayOperationTracker.js +2 -2
- package/lib/store/RelayPublishQueue.js +1 -1
- package/lib/store/RelayReader.js +196 -33
- package/lib/store/RelayRecordSourceMapImpl.js +2 -2
- package/lib/store/RelayReferenceMarker.js +89 -5
- package/lib/store/RelayResponseNormalizer.js +119 -19
- package/lib/store/RelayStoreReactFlightUtils.js +47 -0
- package/lib/store/defaultRequiredFieldLogger.js +18 -0
- package/lib/store/normalizeRelayPayload.js +1 -1
- package/lib/subscription/requestSubscription.js +2 -3
- package/lib/util/NormalizationNode.js +1 -5
- package/lib/util/RelayConcreteNode.js +2 -0
- package/lib/util/RelayFeatureFlags.js +5 -2
- package/lib/util/getFragmentIdentifier.js +12 -3
- package/lib/util/getOperation.js +33 -0
- package/lib/util/isEmptyObject.js +25 -0
- package/lib/util/recycleNodesInto.js +4 -1
- package/lib/util/reportMissingRequiredFields.js +48 -0
- package/mutations/commitMutation.js.flow +1 -2
- package/mutations/validateMutation.js.flow +34 -5
- package/network/RelayNetworkTypes.js.flow +22 -0
- package/package.json +2 -2
- package/query/GraphQLTag.js.flow +3 -1
- package/query/fetchQuery.js.flow +2 -2
- package/query/fetchQueryInternal.js.flow +0 -5
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/DataChecker.js.flow +68 -2
- package/store/RelayModernEnvironment.js.flow +29 -9
- package/store/RelayModernFragmentSpecResolver.js.flow +13 -1
- package/store/RelayModernOperationDescriptor.js.flow +5 -1
- package/store/RelayModernQueryExecutor.js.flow +47 -23
- package/store/RelayModernStore.js.flow +31 -15
- package/store/RelayPublishQueue.js.flow +1 -1
- package/store/RelayReader.js.flow +180 -15
- package/store/RelayReferenceMarker.js.flow +72 -5
- package/store/RelayResponseNormalizer.js.flow +130 -19
- package/store/RelayStoreReactFlightUtils.js.flow +64 -0
- package/store/RelayStoreTypes.js.flow +90 -31
- package/store/defaultRequiredFieldLogger.js.flow +23 -0
- package/subscription/requestSubscription.js.flow +5 -2
- package/util/NormalizationNode.js.flow +17 -2
- package/util/ReaderNode.js.flow +20 -1
- package/util/RelayConcreteNode.js.flow +6 -0
- package/util/RelayFeatureFlags.js.flow +8 -1
- package/util/getFragmentIdentifier.js.flow +33 -9
- package/util/getOperation.js.flow +40 -0
- package/util/isEmptyObject.js.flow +25 -0
- package/util/recycleNodesInto.js.flow +11 -0
- package/util/reportMissingRequiredFields.js.flow +51 -0
package/util/ReaderNode.js.flow
CHANGED
|
@@ -179,6 +179,14 @@ export type ReaderScalarField = {|
|
|
|
179
179
|
+storageKey: ?string,
|
|
180
180
|
|};
|
|
181
181
|
|
|
182
|
+
export type ReaderFlightField = {|
|
|
183
|
+
+kind: 'FlightField',
|
|
184
|
+
+alias: ?string,
|
|
185
|
+
+name: string,
|
|
186
|
+
+args: ?$ReadOnlyArray<ReaderArgument>,
|
|
187
|
+
+storageKey: ?string,
|
|
188
|
+
|};
|
|
189
|
+
|
|
182
190
|
export type ReaderDefer = {|
|
|
183
191
|
+kind: 'Defer',
|
|
184
192
|
+selections: $ReadOnlyArray<ReaderSelection>,
|
|
@@ -189,16 +197,27 @@ export type ReaderStream = {|
|
|
|
189
197
|
+selections: $ReadOnlyArray<ReaderSelection>,
|
|
190
198
|
|};
|
|
191
199
|
|
|
200
|
+
export type RequiredFieldAction = 'NONE' | 'LOG' | 'THROW';
|
|
201
|
+
|
|
202
|
+
export type ReaderRequiredField = {|
|
|
203
|
+
+kind: 'RequiredField',
|
|
204
|
+
+field: ReaderField,
|
|
205
|
+
+action: RequiredFieldAction,
|
|
206
|
+
+path: string,
|
|
207
|
+
|};
|
|
208
|
+
|
|
192
209
|
export type ReaderSelection =
|
|
193
210
|
| ReaderCondition
|
|
194
211
|
| ReaderClientExtension
|
|
195
212
|
| ReaderDefer
|
|
196
213
|
| ReaderField
|
|
214
|
+
| ReaderFlightField
|
|
197
215
|
| ReaderFragmentSpread
|
|
198
216
|
| ReaderInlineDataFragmentSpread
|
|
199
217
|
| ReaderInlineFragment
|
|
200
218
|
| ReaderModuleImport
|
|
201
|
-
| ReaderStream
|
|
219
|
+
| ReaderStream
|
|
220
|
+
| ReaderRequiredField;
|
|
202
221
|
|
|
203
222
|
export type ReaderVariableArgument = {|
|
|
204
223
|
+kind: 'Variable',
|
|
@@ -31,6 +31,10 @@ export type ConcreteRequest = {|
|
|
|
31
31
|
+params: RequestParameters,
|
|
32
32
|
|};
|
|
33
33
|
|
|
34
|
+
export type NormalizationRootNode =
|
|
35
|
+
| ConcreteRequest
|
|
36
|
+
| NormalizationSplitOperation;
|
|
37
|
+
|
|
34
38
|
/**
|
|
35
39
|
* Contains the parameters required for executing a GraphQL request.
|
|
36
40
|
* The operation can either be provided as a persisted `id` or `text`. If given
|
|
@@ -67,6 +71,7 @@ const RelayConcreteNode = {
|
|
|
67
71
|
CLIENT_EXTENSION: 'ClientExtension',
|
|
68
72
|
DEFER: 'Defer',
|
|
69
73
|
CONNECTION: 'Connection',
|
|
74
|
+
FLIGHT_FIELD: 'FlightField',
|
|
70
75
|
FRAGMENT: 'Fragment',
|
|
71
76
|
FRAGMENT_SPREAD: 'FragmentSpread',
|
|
72
77
|
INLINE_DATA_FRAGMENT_SPREAD: 'InlineDataFragmentSpread',
|
|
@@ -78,6 +83,7 @@ const RelayConcreteNode = {
|
|
|
78
83
|
LIST_VALUE: 'ListValue',
|
|
79
84
|
LOCAL_ARGUMENT: 'LocalArgument',
|
|
80
85
|
MODULE_IMPORT: 'ModuleImport',
|
|
86
|
+
REQUIRED_FIELD: 'RequiredField',
|
|
81
87
|
OBJECT_VALUE: 'ObjectValue',
|
|
82
88
|
OPERATION: 'Operation',
|
|
83
89
|
REQUEST: 'Request',
|
|
@@ -17,14 +17,21 @@ type FeatureFlags = {|
|
|
|
17
17
|
ENABLE_PARTIAL_RENDERING_DEFAULT: boolean,
|
|
18
18
|
ENABLE_RELAY_CONTAINERS_SUSPENSE: boolean,
|
|
19
19
|
ENABLE_PRECISE_TYPE_REFINEMENT: boolean,
|
|
20
|
+
ENABLE_REACT_FLIGHT_COMPONENT_FIELD: boolean,
|
|
21
|
+
ENABLE_REQUIRED_DIRECTIVES: boolean | string,
|
|
22
|
+
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: boolean,
|
|
23
|
+
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: boolean,
|
|
20
24
|
|};
|
|
21
25
|
|
|
22
26
|
const RelayFeatureFlags: FeatureFlags = {
|
|
23
|
-
// T45504512: new connection model
|
|
24
27
|
ENABLE_VARIABLE_CONNECTION_KEY: false,
|
|
25
28
|
ENABLE_PARTIAL_RENDERING_DEFAULT: false,
|
|
26
29
|
ENABLE_RELAY_CONTAINERS_SUSPENSE: false,
|
|
27
30
|
ENABLE_PRECISE_TYPE_REFINEMENT: false,
|
|
31
|
+
ENABLE_REACT_FLIGHT_COMPONENT_FIELD: false,
|
|
32
|
+
ENABLE_REQUIRED_DIRECTIVES: false,
|
|
33
|
+
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: false,
|
|
34
|
+
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: false,
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
module.exports = RelayFeatureFlags;
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
+
const RelayFeatureFlags = require('./RelayFeatureFlags');
|
|
17
|
+
|
|
18
|
+
const isEmptyObject = require('./isEmptyObject');
|
|
16
19
|
const stableCopy = require('./stableCopy');
|
|
17
20
|
|
|
18
21
|
const {
|
|
@@ -38,15 +41,36 @@ function getFragmentIdentifier(
|
|
|
38
41
|
']';
|
|
39
42
|
const fragmentVariables = getVariablesFromFragment(fragmentNode, fragmentRef);
|
|
40
43
|
const dataIDs = getDataIDsFromFragment(fragmentNode, fragmentRef);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
|
|
45
|
+
if (RelayFeatureFlags.ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION) {
|
|
46
|
+
return (
|
|
47
|
+
fragmentOwnerIdentifier +
|
|
48
|
+
'/' +
|
|
49
|
+
fragmentNode.name +
|
|
50
|
+
'/' +
|
|
51
|
+
(fragmentVariables == null || isEmptyObject(fragmentVariables)
|
|
52
|
+
? '{}'
|
|
53
|
+
: JSON.stringify(stableCopy(fragmentVariables))) +
|
|
54
|
+
'/' +
|
|
55
|
+
(typeof dataIDs === 'undefined'
|
|
56
|
+
? 'missing'
|
|
57
|
+
: dataIDs == null
|
|
58
|
+
? 'null'
|
|
59
|
+
: Array.isArray(dataIDs)
|
|
60
|
+
? '[' + dataIDs.join(',') + ']'
|
|
61
|
+
: dataIDs)
|
|
62
|
+
);
|
|
63
|
+
} else {
|
|
64
|
+
return (
|
|
65
|
+
fragmentOwnerIdentifier +
|
|
66
|
+
'/' +
|
|
67
|
+
fragmentNode.name +
|
|
68
|
+
'/' +
|
|
69
|
+
JSON.stringify(stableCopy(fragmentVariables)) +
|
|
70
|
+
'/' +
|
|
71
|
+
(JSON.stringify(dataIDs) ?? 'missing')
|
|
72
|
+
);
|
|
73
|
+
}
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
module.exports = getFragmentIdentifier;
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
* @emails oncall+relay
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// flowlint ambiguous-object-type:error
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const {REQUEST, SPLIT_OPERATION} = require('./RelayConcreteNode');
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
NormalizationOperation,
|
|
20
|
+
NormalizationRootNode,
|
|
21
|
+
NormalizationSplitOperation,
|
|
22
|
+
} from './NormalizationNode';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* OperationLoaders can return either a NormalizationSplitOperation or
|
|
26
|
+
* ConcreteRequest.
|
|
27
|
+
*/
|
|
28
|
+
function getOperation(
|
|
29
|
+
node: NormalizationRootNode,
|
|
30
|
+
): NormalizationSplitOperation | NormalizationOperation {
|
|
31
|
+
switch (node.kind) {
|
|
32
|
+
case REQUEST:
|
|
33
|
+
return node.operation;
|
|
34
|
+
case SPLIT_OPERATION:
|
|
35
|
+
default:
|
|
36
|
+
return node;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = getOperation;
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
|
8
|
+
* @format
|
|
9
|
+
* @emails oncall+relay
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
15
|
+
|
|
16
|
+
function isEmptyObject(obj: {+[key: string]: mixed}): boolean {
|
|
17
|
+
for (const key in obj) {
|
|
18
|
+
if (hasOwnProperty.call(obj, key)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = isEmptyObject;
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
const hasWeakSetDefined = typeof WeakSet !== 'undefined';
|
|
16
|
+
const hasWeakMapDefined = typeof WeakMap !== 'undefined';
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* Recycles subtrees from `prevData` by replacing equal subtrees in `nextData`.
|
|
17
20
|
*/
|
|
@@ -19,8 +22,16 @@ function recycleNodesInto<T>(prevData: T, nextData: T): T {
|
|
|
19
22
|
if (
|
|
20
23
|
prevData === nextData ||
|
|
21
24
|
typeof prevData !== 'object' ||
|
|
25
|
+
prevData instanceof Set ||
|
|
26
|
+
prevData instanceof Map ||
|
|
27
|
+
(hasWeakSetDefined && prevData instanceof WeakSet) ||
|
|
28
|
+
(hasWeakMapDefined && prevData instanceof WeakMap) ||
|
|
22
29
|
!prevData ||
|
|
23
30
|
typeof nextData !== 'object' ||
|
|
31
|
+
nextData instanceof Set ||
|
|
32
|
+
nextData instanceof Map ||
|
|
33
|
+
(hasWeakSetDefined && nextData instanceof WeakSet) ||
|
|
34
|
+
(hasWeakMapDefined && nextData instanceof WeakMap) ||
|
|
24
35
|
!nextData
|
|
25
36
|
) {
|
|
26
37
|
return nextData;
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
* @emails oncall+relay
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
IEnvironment,
|
|
16
|
+
MissingRequiredFields,
|
|
17
|
+
} from '../store/RelayStoreTypes';
|
|
18
|
+
|
|
19
|
+
function reportMissingRequiredFields(
|
|
20
|
+
environment: IEnvironment,
|
|
21
|
+
missingRequiredFields: MissingRequiredFields,
|
|
22
|
+
) {
|
|
23
|
+
switch (missingRequiredFields.action) {
|
|
24
|
+
case 'THROW': {
|
|
25
|
+
const {path, owner} = missingRequiredFields.field;
|
|
26
|
+
// This gives the consumer the chance to throw their own error if they so wish.
|
|
27
|
+
environment.requiredFieldLogger({
|
|
28
|
+
kind: 'missing_field.throw',
|
|
29
|
+
owner,
|
|
30
|
+
fieldPath: path,
|
|
31
|
+
});
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Relay: Missing @required value at path '${path}' in '${owner}'.`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
case 'LOG':
|
|
37
|
+
missingRequiredFields.fields.forEach(({path, owner}) => {
|
|
38
|
+
environment.requiredFieldLogger({
|
|
39
|
+
kind: 'missing_field.log',
|
|
40
|
+
owner,
|
|
41
|
+
fieldPath: path,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
break;
|
|
45
|
+
default: {
|
|
46
|
+
(missingRequiredFields.action: empty);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = reportMissingRequiredFields;
|