relay-runtime 10.0.1 → 10.1.3
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 +152 -20
- package/index.js +1 -1
- package/index.js.flow +17 -1
- package/lib/handlers/RelayDefaultHandlerProvider.js +9 -0
- package/lib/handlers/connection/MutationHandlers.js +185 -21
- package/lib/index.js +7 -0
- package/lib/mutations/RelayDeclarativeMutationConfig.js +5 -7
- package/lib/mutations/commitMutation.js +1 -4
- package/lib/mutations/validateMutation.js +28 -12
- package/lib/network/RelayQueryResponseCache.js +3 -7
- 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 +85 -10
- package/lib/store/RelayConcreteVariables.js +2 -6
- package/lib/store/RelayModernEnvironment.js +81 -72
- package/lib/store/RelayModernFragmentSpecResolver.js +14 -7
- package/lib/store/RelayModernOperationDescriptor.js +6 -5
- package/lib/store/RelayModernQueryExecutor.js +46 -33
- package/lib/store/RelayModernRecord.js +3 -7
- package/lib/store/RelayModernStore.js +39 -137
- package/lib/store/RelayOperationTracker.js +7 -9
- package/lib/store/RelayOptimisticRecordSource.js +2 -6
- package/lib/store/RelayPublishQueue.js +1 -1
- package/lib/store/RelayReader.js +196 -33
- package/lib/store/RelayRecordSourceMapImpl.js +3 -5
- package/lib/store/RelayReferenceMarker.js +87 -5
- package/lib/store/RelayResponseNormalizer.js +115 -19
- package/lib/store/RelayStoreReactFlightUtils.js +47 -0
- package/lib/store/RelayStoreSubscriptions.js +162 -0
- package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +258 -0
- package/lib/store/StoreInspector.js +2 -6
- package/lib/store/createRelayContext.js +5 -0
- package/lib/store/defaultRequiredFieldLogger.js +18 -0
- package/lib/store/normalizeRelayPayload.js +2 -6
- 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 +7 -2
- package/lib/util/createPayloadFor3DField.js +2 -7
- 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 +107 -87
- 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 +33 -107
- 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/RelayStoreSubscriptions.js.flow +168 -0
- package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +259 -0
- package/store/RelayStoreTypes.js.flow +130 -37
- package/store/createRelayContext.js.flow +3 -0
- 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 +12 -1
- package/util/getFragmentIdentifier.js.flow +33 -9
- package/util/getOperation.js.flow +40 -0
- package/util/getRequestIdentifier.js.flow +1 -1
- package/util/isEmptyObject.js.flow +25 -0
- package/util/recycleNodesInto.js.flow +11 -0
- package/util/reportMissingRequiredFields.js.flow +51 -0
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
import type {ConcreteRequest} from './RelayConcreteNode';
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
18
|
* Represents a single operation used to processing and normalize runtime
|
|
17
19
|
* request results.
|
|
@@ -34,7 +36,6 @@ export type NormalizationLinkedHandle = {|
|
|
|
34
36
|
+args: ?$ReadOnlyArray<NormalizationArgument>,
|
|
35
37
|
+handle: string,
|
|
36
38
|
+key: string,
|
|
37
|
-
// T45504512: new connection model
|
|
38
39
|
// NOTE: this property is optional because it's expected to be rarely used
|
|
39
40
|
+dynamicKey?: ?NormalizationArgument,
|
|
40
41
|
+filters: ?$ReadOnlyArray<string>,
|
|
@@ -48,10 +49,10 @@ export type NormalizationScalarHandle = {|
|
|
|
48
49
|
+args: ?$ReadOnlyArray<NormalizationArgument>,
|
|
49
50
|
+handle: string,
|
|
50
51
|
+key: string,
|
|
51
|
-
// T45504512: new connection model
|
|
52
52
|
// NOTE: this property is optional because it's expected to be rarely used
|
|
53
53
|
+dynamicKey?: ?NormalizationArgument,
|
|
54
54
|
+filters: ?$ReadOnlyArray<string>,
|
|
55
|
+
+handleArgs?: $ReadOnlyArray<NormalizationArgument>,
|
|
55
56
|
|};
|
|
56
57
|
|
|
57
58
|
export type NormalizationArgument =
|
|
@@ -73,6 +74,7 @@ export type NormalizationClientExtension = {|
|
|
|
73
74
|
|};
|
|
74
75
|
|
|
75
76
|
export type NormalizationField =
|
|
77
|
+
| NormalizationFlightField
|
|
76
78
|
| NormalizationScalarField
|
|
77
79
|
| NormalizationLinkedField;
|
|
78
80
|
|
|
@@ -138,6 +140,14 @@ export type NormalizationScalarField = {|
|
|
|
138
140
|
+storageKey: ?string,
|
|
139
141
|
|};
|
|
140
142
|
|
|
143
|
+
export type NormalizationFlightField = {|
|
|
144
|
+
+kind: 'FlightField',
|
|
145
|
+
+alias: ?string,
|
|
146
|
+
+name: string,
|
|
147
|
+
+args: ?$ReadOnlyArray<NormalizationArgument>,
|
|
148
|
+
+storageKey: ?string,
|
|
149
|
+
|};
|
|
150
|
+
|
|
141
151
|
export type NormalizationTypeDiscriminator = {|
|
|
142
152
|
+kind: 'TypeDiscriminator',
|
|
143
153
|
+abstractKey: string,
|
|
@@ -148,6 +158,7 @@ export type NormalizationSelection =
|
|
|
148
158
|
| NormalizationClientExtension
|
|
149
159
|
| NormalizationDefer
|
|
150
160
|
| NormalizationField
|
|
161
|
+
| NormalizationFlightField
|
|
151
162
|
| NormalizationHandle
|
|
152
163
|
| NormalizationInlineFragment
|
|
153
164
|
| NormalizationModuleImport
|
|
@@ -196,3 +207,7 @@ export type NormalizationSelectableNode =
|
|
|
196
207
|
| NormalizationOperation
|
|
197
208
|
| NormalizationSplitOperation
|
|
198
209
|
| NormalizationStream;
|
|
210
|
+
|
|
211
|
+
export type NormalizationRootNode =
|
|
212
|
+
| ConcreteRequest
|
|
213
|
+
| NormalizationSplitOperation;
|
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,25 @@ 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,
|
|
24
|
+
ENABLE_STORE_SUBSCRIPTIONS_REFACTOR: boolean,
|
|
25
|
+
ENABLE_LOAD_QUERY_REQUEST_DEDUPING: boolean,
|
|
20
26
|
|};
|
|
21
27
|
|
|
22
28
|
const RelayFeatureFlags: FeatureFlags = {
|
|
23
|
-
// T45504512: new connection model
|
|
24
29
|
ENABLE_VARIABLE_CONNECTION_KEY: false,
|
|
25
30
|
ENABLE_PARTIAL_RENDERING_DEFAULT: false,
|
|
26
31
|
ENABLE_RELAY_CONTAINERS_SUSPENSE: false,
|
|
27
32
|
ENABLE_PRECISE_TYPE_REFINEMENT: false,
|
|
33
|
+
ENABLE_REACT_FLIGHT_COMPONENT_FIELD: false,
|
|
34
|
+
ENABLE_REQUIRED_DIRECTIVES: false,
|
|
35
|
+
ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: false,
|
|
36
|
+
ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: false,
|
|
37
|
+
ENABLE_STORE_SUBSCRIPTIONS_REFACTOR: false,
|
|
38
|
+
ENABLE_LOAD_QUERY_REQUEST_DEDUPING: true,
|
|
28
39
|
};
|
|
29
40
|
|
|
30
41
|
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;
|
|
@@ -18,7 +18,7 @@ const stableCopy = require('./stableCopy');
|
|
|
18
18
|
import type {RequestParameters} from './RelayConcreteNode';
|
|
19
19
|
import type {Variables} from './RelayRuntimeTypes';
|
|
20
20
|
|
|
21
|
-
export
|
|
21
|
+
export type RequestIdentifier = string;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Returns a stable identifier for the given pair of `RequestParameters` +
|
|
@@ -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;
|