relay-compiler 11.0.1 → 13.0.0-rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. package/cli.js +23 -0
  2. package/index.js +21 -3
  3. package/linux-x64/relay +0 -0
  4. package/macos-arm64/relay +0 -0
  5. package/macos-x64/relay +0 -0
  6. package/package.json +2 -25
  7. package/win-x64/relay.exe +0 -0
  8. package/bin/RelayCompilerBin.js.flow +0 -169
  9. package/bin/RelayCompilerMain.js.flow +0 -515
  10. package/bin/__fixtures__/plugin-module.js.flow +0 -17
  11. package/bin/relay-compiler +0 -19007
  12. package/codegen/CodegenDirectory.js.flow +0 -375
  13. package/codegen/CodegenRunner.js.flow +0 -432
  14. package/codegen/CodegenTypes.js.flow +0 -28
  15. package/codegen/CodegenWatcher.js.flow +0 -254
  16. package/codegen/NormalizationCodeGenerator.js.flow +0 -571
  17. package/codegen/ReaderCodeGenerator.js.flow +0 -512
  18. package/codegen/RelayCodeGenerator.js.flow +0 -85
  19. package/codegen/RelayFileWriter.js.flow +0 -367
  20. package/codegen/SourceControl.js.flow +0 -58
  21. package/codegen/compileRelayArtifacts.js.flow +0 -182
  22. package/codegen/createPrintRequireModuleDependency.js.flow +0 -21
  23. package/codegen/sortObjectByKey.js.flow +0 -25
  24. package/codegen/writeRelayGeneratedFile.js.flow +0 -239
  25. package/core/ASTCache.js.flow +0 -74
  26. package/core/ASTConvert.js.flow +0 -233
  27. package/core/CompilerContext.js.flow +0 -191
  28. package/core/CompilerError.js.flow +0 -255
  29. package/core/DotGraphQLParser.js.flow +0 -39
  30. package/core/GraphQLCompilerProfiler.js.flow +0 -341
  31. package/core/GraphQLDerivedFromMetadata.js.flow +0 -36
  32. package/core/GraphQLWatchmanClient.js.flow +0 -111
  33. package/core/IR.js.flow +0 -326
  34. package/core/IRPrinter.js.flow +0 -478
  35. package/core/IRTransformer.js.flow +0 -377
  36. package/core/IRValidator.js.flow +0 -260
  37. package/core/IRVisitor.js.flow +0 -150
  38. package/core/JSModuleParser.js.flow +0 -24
  39. package/core/RelayCompilerScope.js.flow +0 -199
  40. package/core/RelayFindGraphQLTags.js.flow +0 -119
  41. package/core/RelayGraphQLEnumsGenerator.js.flow +0 -55
  42. package/core/RelayIRTransforms.js.flow +0 -138
  43. package/core/RelayParser.js.flow +0 -1734
  44. package/core/RelaySourceModuleParser.js.flow +0 -135
  45. package/core/Schema.js.flow +0 -2037
  46. package/core/SchemaUtils.js.flow +0 -120
  47. package/core/filterContextForNode.js.flow +0 -50
  48. package/core/getFieldDefinition.js.flow +0 -156
  49. package/core/getIdentifierForArgumentValue.js.flow +0 -49
  50. package/core/getIdentifierForSelection.js.flow +0 -69
  51. package/core/getLiteralArgumentValues.js.flow +0 -32
  52. package/core/getNormalizationOperationName.js.flow +0 -19
  53. package/core/inferRootArgumentDefinitions.js.flow +0 -323
  54. package/index.js.flow +0 -200
  55. package/language/RelayLanguagePluginInterface.js.flow +0 -283
  56. package/language/javascript/FindGraphQLTags.js.flow +0 -137
  57. package/language/javascript/RelayFlowBabelFactories.js.flow +0 -176
  58. package/language/javascript/RelayFlowGenerator.js.flow +0 -1100
  59. package/language/javascript/RelayFlowTypeTransformers.js.flow +0 -184
  60. package/language/javascript/RelayLanguagePluginJavaScript.js.flow +0 -34
  61. package/language/javascript/formatGeneratedModule.js.flow +0 -65
  62. package/lib/bin/RelayCompilerBin.js +0 -143
  63. package/lib/bin/RelayCompilerMain.js +0 -486
  64. package/lib/bin/__fixtures__/plugin-module.js +0 -16
  65. package/lib/codegen/CodegenDirectory.js +0 -336
  66. package/lib/codegen/CodegenRunner.js +0 -433
  67. package/lib/codegen/CodegenTypes.js +0 -11
  68. package/lib/codegen/CodegenWatcher.js +0 -271
  69. package/lib/codegen/NormalizationCodeGenerator.js +0 -481
  70. package/lib/codegen/ReaderCodeGenerator.js +0 -472
  71. package/lib/codegen/RelayCodeGenerator.js +0 -68
  72. package/lib/codegen/RelayFileWriter.js +0 -270
  73. package/lib/codegen/SourceControl.js +0 -60
  74. package/lib/codegen/compileRelayArtifacts.js +0 -157
  75. package/lib/codegen/createPrintRequireModuleDependency.js +0 -19
  76. package/lib/codegen/sortObjectByKey.js +0 -41
  77. package/lib/codegen/writeRelayGeneratedFile.js +0 -208
  78. package/lib/core/ASTCache.js +0 -70
  79. package/lib/core/ASTConvert.js +0 -198
  80. package/lib/core/CompilerContext.js +0 -165
  81. package/lib/core/CompilerError.js +0 -251
  82. package/lib/core/DotGraphQLParser.js +0 -40
  83. package/lib/core/GraphQLCompilerProfiler.js +0 -299
  84. package/lib/core/GraphQLDerivedFromMetadata.js +0 -31
  85. package/lib/core/GraphQLWatchmanClient.js +0 -150
  86. package/lib/core/IR.js +0 -11
  87. package/lib/core/IRPrinter.js +0 -389
  88. package/lib/core/IRTransformer.js +0 -345
  89. package/lib/core/IRValidator.js +0 -226
  90. package/lib/core/IRVisitor.js +0 -45
  91. package/lib/core/JSModuleParser.js +0 -18
  92. package/lib/core/RelayCompilerScope.js +0 -149
  93. package/lib/core/RelayFindGraphQLTags.js +0 -79
  94. package/lib/core/RelayGraphQLEnumsGenerator.js +0 -50
  95. package/lib/core/RelayIRTransforms.js +0 -109
  96. package/lib/core/RelayParser.js +0 -1382
  97. package/lib/core/RelaySourceModuleParser.js +0 -104
  98. package/lib/core/Schema.js +0 -1877
  99. package/lib/core/SchemaUtils.js +0 -98
  100. package/lib/core/filterContextForNode.js +0 -49
  101. package/lib/core/getFieldDefinition.js +0 -145
  102. package/lib/core/getIdentifierForArgumentValue.js +0 -53
  103. package/lib/core/getIdentifierForSelection.js +0 -48
  104. package/lib/core/getLiteralArgumentValues.js +0 -26
  105. package/lib/core/getNormalizationOperationName.js +0 -17
  106. package/lib/core/inferRootArgumentDefinitions.js +0 -351
  107. package/lib/index.js +0 -178
  108. package/lib/language/RelayLanguagePluginInterface.js +0 -14
  109. package/lib/language/javascript/FindGraphQLTags.js +0 -126
  110. package/lib/language/javascript/RelayFlowBabelFactories.js +0 -160
  111. package/lib/language/javascript/RelayFlowGenerator.js +0 -857
  112. package/lib/language/javascript/RelayFlowTypeTransformers.js +0 -119
  113. package/lib/language/javascript/RelayLanguagePluginJavaScript.js +0 -30
  114. package/lib/language/javascript/formatGeneratedModule.js +0 -36
  115. package/lib/reporters/ConsoleReporter.js +0 -61
  116. package/lib/reporters/MultiReporter.js +0 -45
  117. package/lib/reporters/Reporter.js +0 -11
  118. package/lib/runner/Artifacts.js +0 -323
  119. package/lib/runner/BufferedFilesystem.js +0 -261
  120. package/lib/runner/GraphQLASTNodeGroup.js +0 -256
  121. package/lib/runner/GraphQLASTUtils.js +0 -23
  122. package/lib/runner/GraphQLNodeMap.js +0 -81
  123. package/lib/runner/Sources.js +0 -271
  124. package/lib/runner/StrictMap.js +0 -134
  125. package/lib/runner/compileArtifacts.js +0 -39
  126. package/lib/runner/extractAST.js +0 -77
  127. package/lib/runner/getChangedNodeNames.js +0 -82
  128. package/lib/runner/getSchemaInstance.js +0 -30
  129. package/lib/runner/types.js +0 -12
  130. package/lib/transforms/ApplyFragmentArgumentTransform.js +0 -393
  131. package/lib/transforms/ClientExtensionsTransform.js +0 -221
  132. package/lib/transforms/ConnectionTransform.js +0 -639
  133. package/lib/transforms/DeclarativeConnectionMutationTransform.js +0 -218
  134. package/lib/transforms/DeferStreamTransform.js +0 -246
  135. package/lib/transforms/DisallowIdAsAlias.js +0 -40
  136. package/lib/transforms/DisallowTypenameOnRoot.js +0 -53
  137. package/lib/transforms/FieldHandleTransform.js +0 -79
  138. package/lib/transforms/FilterCompilerDirectivesTransform.js +0 -29
  139. package/lib/transforms/FilterDirectivesTransform.js +0 -41
  140. package/lib/transforms/FlattenTransform.js +0 -306
  141. package/lib/transforms/GenerateIDFieldTransform.js +0 -135
  142. package/lib/transforms/GenerateTypeNameTransform.js +0 -149
  143. package/lib/transforms/InlineDataFragmentTransform.js +0 -100
  144. package/lib/transforms/InlineFragmentsTransform.js +0 -61
  145. package/lib/transforms/MaskTransform.js +0 -117
  146. package/lib/transforms/MatchTransform.js +0 -434
  147. package/lib/transforms/ReactFlightComponentTransform.js +0 -158
  148. package/lib/transforms/RefetchableFragmentTransform.js +0 -249
  149. package/lib/transforms/RelayDirectiveTransform.js +0 -83
  150. package/lib/transforms/RequiredFieldTransform.js +0 -369
  151. package/lib/transforms/SkipClientExtensionsTransform.js +0 -46
  152. package/lib/transforms/SkipHandleFieldTransform.js +0 -44
  153. package/lib/transforms/SkipRedundantNodesTransform.js +0 -254
  154. package/lib/transforms/SkipSplitOperationTransform.js +0 -32
  155. package/lib/transforms/SkipUnreachableNodeTransform.js +0 -158
  156. package/lib/transforms/SkipUnusedVariablesTransform.js +0 -74
  157. package/lib/transforms/SplitModuleImportTransform.js +0 -82
  158. package/lib/transforms/TestOperationTransform.js +0 -144
  159. package/lib/transforms/TransformUtils.js +0 -21
  160. package/lib/transforms/ValidateGlobalVariablesTransform.js +0 -91
  161. package/lib/transforms/ValidateRequiredArgumentsTransform.js +0 -114
  162. package/lib/transforms/ValidateServerOnlyDirectivesTransform.js +0 -108
  163. package/lib/transforms/ValidateUnusedVariablesTransform.js +0 -96
  164. package/lib/transforms/query-generators/FetchableQueryGenerator.js +0 -157
  165. package/lib/transforms/query-generators/NodeQueryGenerator.js +0 -166
  166. package/lib/transforms/query-generators/QueryQueryGenerator.js +0 -48
  167. package/lib/transforms/query-generators/ViewerQueryGenerator.js +0 -77
  168. package/lib/transforms/query-generators/index.js +0 -60
  169. package/lib/transforms/query-generators/utils.js +0 -92
  170. package/lib/util/CodeMarker.js +0 -80
  171. package/lib/util/DefaultHandleKey.js +0 -15
  172. package/lib/util/RelayCompilerCache.js +0 -98
  173. package/lib/util/Rollout.js +0 -40
  174. package/lib/util/TimeReporter.js +0 -83
  175. package/lib/util/areEqualOSS.js +0 -133
  176. package/lib/util/argumentContainsVariables.js +0 -37
  177. package/lib/util/dedupeJSONStringify.js +0 -160
  178. package/lib/util/generateAbstractTypeRefinementKey.js +0 -24
  179. package/lib/util/getDefinitionNodeHash.js +0 -22
  180. package/lib/util/getModuleName.js +0 -32
  181. package/lib/util/joinArgumentDefinitions.js +0 -66
  182. package/lib/util/md5.js +0 -17
  183. package/lib/util/murmurHash.js +0 -86
  184. package/lib/util/nullthrowsOSS.js +0 -23
  185. package/lib/util/orList.js +0 -36
  186. package/lib/util/partitionArray.js +0 -35
  187. package/relay-compiler.js +0 -17
  188. package/relay-compiler.min.js +0 -22
  189. package/reporters/ConsoleReporter.js.flow +0 -81
  190. package/reporters/MultiReporter.js.flow +0 -43
  191. package/reporters/Reporter.js.flow +0 -19
  192. package/runner/Artifacts.js.flow +0 -219
  193. package/runner/BufferedFilesystem.js.flow +0 -194
  194. package/runner/GraphQLASTNodeGroup.js.flow +0 -176
  195. package/runner/GraphQLASTUtils.js.flow +0 -26
  196. package/runner/GraphQLNodeMap.js.flow +0 -55
  197. package/runner/Sources.js.flow +0 -228
  198. package/runner/StrictMap.js.flow +0 -96
  199. package/runner/compileArtifacts.js.flow +0 -76
  200. package/runner/extractAST.js.flow +0 -100
  201. package/runner/getChangedNodeNames.js.flow +0 -48
  202. package/runner/getSchemaInstance.js.flow +0 -36
  203. package/runner/types.js.flow +0 -37
  204. package/transforms/ApplyFragmentArgumentTransform.js.flow +0 -526
  205. package/transforms/ClientExtensionsTransform.js.flow +0 -225
  206. package/transforms/ConnectionTransform.js.flow +0 -855
  207. package/transforms/DeclarativeConnectionMutationTransform.js.flow +0 -247
  208. package/transforms/DeferStreamTransform.js.flow +0 -265
  209. package/transforms/DisallowIdAsAlias.js.flow +0 -47
  210. package/transforms/DisallowTypenameOnRoot.js.flow +0 -45
  211. package/transforms/FieldHandleTransform.js.flow +0 -79
  212. package/transforms/FilterCompilerDirectivesTransform.js.flow +0 -33
  213. package/transforms/FilterDirectivesTransform.js.flow +0 -45
  214. package/transforms/FlattenTransform.js.flow +0 -457
  215. package/transforms/GenerateIDFieldTransform.js.flow +0 -152
  216. package/transforms/GenerateTypeNameTransform.js.flow +0 -161
  217. package/transforms/InlineDataFragmentTransform.js.flow +0 -125
  218. package/transforms/InlineFragmentsTransform.js.flow +0 -71
  219. package/transforms/MaskTransform.js.flow +0 -126
  220. package/transforms/MatchTransform.js.flow +0 -589
  221. package/transforms/ReactFlightComponentTransform.js.flow +0 -195
  222. package/transforms/RefetchableFragmentTransform.js.flow +0 -272
  223. package/transforms/RelayDirectiveTransform.js.flow +0 -97
  224. package/transforms/RequiredFieldTransform.js.flow +0 -415
  225. package/transforms/SkipClientExtensionsTransform.js.flow +0 -54
  226. package/transforms/SkipHandleFieldTransform.js.flow +0 -44
  227. package/transforms/SkipRedundantNodesTransform.js.flow +0 -258
  228. package/transforms/SkipSplitOperationTransform.js.flow +0 -37
  229. package/transforms/SkipUnreachableNodeTransform.js.flow +0 -149
  230. package/transforms/SkipUnusedVariablesTransform.js.flow +0 -59
  231. package/transforms/SplitModuleImportTransform.js.flow +0 -98
  232. package/transforms/TestOperationTransform.js.flow +0 -142
  233. package/transforms/TransformUtils.js.flow +0 -26
  234. package/transforms/ValidateGlobalVariablesTransform.js.flow +0 -81
  235. package/transforms/ValidateRequiredArgumentsTransform.js.flow +0 -127
  236. package/transforms/ValidateServerOnlyDirectivesTransform.js.flow +0 -112
  237. package/transforms/ValidateUnusedVariablesTransform.js.flow +0 -89
  238. package/transforms/query-generators/FetchableQueryGenerator.js.flow +0 -189
  239. package/transforms/query-generators/NodeQueryGenerator.js.flow +0 -219
  240. package/transforms/query-generators/QueryQueryGenerator.js.flow +0 -57
  241. package/transforms/query-generators/ViewerQueryGenerator.js.flow +0 -97
  242. package/transforms/query-generators/index.js.flow +0 -90
  243. package/transforms/query-generators/utils.js.flow +0 -76
  244. package/util/CodeMarker.js.flow +0 -79
  245. package/util/DefaultHandleKey.js.flow +0 -17
  246. package/util/RelayCompilerCache.js.flow +0 -88
  247. package/util/Rollout.js.flow +0 -39
  248. package/util/TimeReporter.js.flow +0 -79
  249. package/util/areEqualOSS.js.flow +0 -123
  250. package/util/argumentContainsVariables.js.flow +0 -38
  251. package/util/dedupeJSONStringify.js.flow +0 -152
  252. package/util/generateAbstractTypeRefinementKey.js.flow +0 -29
  253. package/util/getDefinitionNodeHash.js.flow +0 -25
  254. package/util/getModuleName.js.flow +0 -39
  255. package/util/joinArgumentDefinitions.js.flow +0 -105
  256. package/util/md5.js.flow +0 -22
  257. package/util/murmurHash.js.flow +0 -94
  258. package/util/nullthrowsOSS.js.flow +0 -25
  259. package/util/orList.js.flow +0 -37
  260. package/util/partitionArray.js.flow +0 -37
@@ -1,1734 +0,0 @@
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
- */
10
-
11
- // flowlint ambiguous-object-type:error
12
-
13
- 'use strict';
14
-
15
- const Profiler = require('./GraphQLCompilerProfiler');
16
-
17
- const orList = require('../util/orList');
18
- const partitionArray = require('../util/partitionArray');
19
-
20
- const {DEFAULT_HANDLE_KEY} = require('../util/DefaultHandleKey');
21
- const {
22
- createCompilerError,
23
- createUserError,
24
- eachWithCombinedError,
25
- } = require('./CompilerError');
26
- const {isExecutableDefinitionAST} = require('./SchemaUtils');
27
- const {getFieldDefinitionLegacy} = require('./getFieldDefinition');
28
- const {parse: parseGraphQL, parseType, print, Source} = require('graphql');
29
-
30
- import type {
31
- Argument,
32
- ArgumentValue,
33
- Condition,
34
- Directive,
35
- Field,
36
- Fragment,
37
- FragmentSpread,
38
- Handle,
39
- InlineFragment,
40
- LocalArgumentDefinition,
41
- Location,
42
- Root,
43
- Selection,
44
- Variable,
45
- } from './IR';
46
- import type {
47
- CompositeTypeID,
48
- Argument as FieldArgument,
49
- FieldID,
50
- InputTypeID,
51
- Schema,
52
- TypeID,
53
- } from './Schema';
54
- import type {GetFieldDefinitionFn} from './getFieldDefinition';
55
- import type {
56
- ASTNode,
57
- ArgumentNode,
58
- BooleanValueNode,
59
- DefinitionNode,
60
- DirectiveLocationEnum,
61
- DirectiveNode,
62
- EnumValueNode,
63
- FieldNode,
64
- FloatValueNode,
65
- FragmentDefinitionNode,
66
- FragmentSpreadNode,
67
- InlineFragmentNode,
68
- IntValueNode,
69
- ListValueNode,
70
- Location as ASTLocation,
71
- ObjectValueNode,
72
- OperationDefinitionNode,
73
- SelectionSetNode,
74
- StringValueNode,
75
- TypeNode,
76
- ValueNode,
77
- VariableNode,
78
- } from 'graphql';
79
-
80
- type ASTDefinitionNode = FragmentDefinitionNode | OperationDefinitionNode;
81
- type NonNullLiteralValueNode =
82
- | IntValueNode
83
- | FloatValueNode
84
- | StringValueNode
85
- | BooleanValueNode
86
- | EnumValueNode
87
- | ListValueNode
88
- | ObjectValueNode;
89
-
90
- type VariableDefinitions = Map<string, VariableDefinition>;
91
- type VariableDefinition = {|
92
- ast: ASTNode,
93
- name: string,
94
- defaultValue: mixed,
95
- type: InputTypeID,
96
- defined: boolean,
97
- |};
98
-
99
- type UnknownVariable = {|
100
- ast: VariableNode,
101
- type: ?TypeID,
102
- |};
103
-
104
- const ARGUMENT_DEFINITIONS = 'argumentDefinitions';
105
- const ARGUMENTS = 'arguments';
106
- const DEPRECATED_UNCHECKED_ARGUMENTS = 'uncheckedArguments_DEPRECATED';
107
- const DIRECTIVE_WHITELIST: $ReadOnlySet<string> = new Set([
108
- ARGUMENT_DEFINITIONS,
109
- DEPRECATED_UNCHECKED_ARGUMENTS,
110
- ARGUMENTS,
111
- ]);
112
-
113
- /**
114
- * @internal
115
- *
116
- * This directive is not intended for use by developers directly. To set a field
117
- * handle in product code use a compiler plugin.
118
- */
119
- const CLIENT_FIELD = '__clientField';
120
- const CLIENT_FIELD_HANDLE = 'handle';
121
- const CLIENT_FIELD_KEY = 'key';
122
- const CLIENT_FIELD_FILTERS = 'filters';
123
-
124
- const INCLUDE = 'include';
125
- const SKIP = 'skip';
126
- const IF = 'if';
127
-
128
- /**
129
- * Transforms GraphQL text into Relay Compiler's internal, strongly-typed
130
- * intermediate representation (IR).
131
- */
132
- function parse(
133
- schema: Schema,
134
- text: string,
135
- filename?: string,
136
- ): $ReadOnlyArray<Root | Fragment> {
137
- const ast = parseGraphQL(new Source(text, filename));
138
- const parser = new RelayParser(schema.extend(ast), ast.definitions);
139
- return parser.transform();
140
- }
141
-
142
- /**
143
- * Transforms untyped GraphQL parse trees (ASTs) into Relay Compiler's
144
- * internal, strongly-typed intermediate representation (IR).
145
- */
146
- function transform(
147
- schema: Schema,
148
- definitions: $ReadOnlyArray<DefinitionNode>,
149
- ): $ReadOnlyArray<Root | Fragment> {
150
- return Profiler.run('RelayParser.transform', () => {
151
- const parser = new RelayParser(schema, definitions);
152
- return parser.transform();
153
- });
154
- }
155
-
156
- /**
157
- * @private
158
- */
159
- class RelayParser {
160
- _definitions: Map<string, ASTDefinitionNode>;
161
- _getFieldDefinition: GetFieldDefinitionFn;
162
- +_schema: Schema;
163
-
164
- constructor(schema: Schema, definitions: $ReadOnlyArray<DefinitionNode>) {
165
- this._definitions = new Map();
166
- // leaving this configurable to make it easy to experiment w changing later
167
- this._getFieldDefinition = getFieldDefinitionLegacy;
168
- this._schema = schema;
169
-
170
- const duplicated = new Set();
171
- definitions.forEach(def => {
172
- if (isExecutableDefinitionAST(def)) {
173
- const name = getName(def);
174
- if (this._definitions.has(name)) {
175
- duplicated.add(name);
176
- return;
177
- }
178
- this._definitions.set(name, def);
179
- }
180
- });
181
- if (duplicated.size) {
182
- throw createUserError(
183
- 'RelayParser: Encountered duplicate definitions for one or more ' +
184
- 'documents: each document must have a unique name. Duplicated documents:\n' +
185
- Array.from(duplicated, name => `- ${name}`).join('\n'),
186
- );
187
- }
188
- }
189
-
190
- transform(): $ReadOnlyArray<Root | Fragment> {
191
- const nodes = [];
192
- const entries = new Map();
193
- // Construct a mapping of name to definition ast + variable definitions.
194
- // This allows the subsequent AST -> IR tranformation to reference the
195
- // defined arguments of referenced fragments.
196
- eachWithCombinedError(this._definitions, ([name, definition]) => {
197
- const variableDefinitions = this._buildArgumentDefinitions(definition);
198
- entries.set(name, {definition, variableDefinitions});
199
- });
200
- // Convert the ASTs to IR.
201
- eachWithCombinedError(
202
- entries.values(),
203
- ({definition, variableDefinitions}) => {
204
- const node = parseDefinition(
205
- this._schema,
206
- this._getFieldDefinition,
207
- entries,
208
- definition,
209
- variableDefinitions,
210
- );
211
- nodes.push(node);
212
- },
213
- );
214
- return nodes;
215
- }
216
-
217
- /**
218
- * Constructs a mapping of variable names to definitions for the given
219
- * operation/fragment definition.
220
- */
221
- _buildArgumentDefinitions(
222
- definition: ASTDefinitionNode,
223
- ): VariableDefinitions {
224
- switch (definition.kind) {
225
- case 'OperationDefinition':
226
- return this._buildOperationArgumentDefinitions(definition);
227
- case 'FragmentDefinition':
228
- return this._buildFragmentArgumentDefinitions(definition);
229
- default:
230
- (definition: empty);
231
- throw createCompilerError(`Unexpected ast kind '${definition.kind}'.`, [
232
- definition,
233
- ]);
234
- }
235
- }
236
-
237
- /**
238
- * Constructs a mapping of variable names to definitions using the
239
- * variables defined in `@argumentDefinitions`.
240
- */
241
- _buildFragmentArgumentDefinitions(
242
- fragment: FragmentDefinitionNode,
243
- ): VariableDefinitions {
244
- const variableDirectives = (fragment.directives || []).filter(
245
- directive => getName(directive) === ARGUMENT_DEFINITIONS,
246
- );
247
- if (!variableDirectives.length) {
248
- return new Map();
249
- }
250
- if (variableDirectives.length !== 1) {
251
- throw createUserError(
252
- `Directive @${ARGUMENT_DEFINITIONS} may be defined at most once per ` +
253
- 'fragment.',
254
- null,
255
- variableDirectives,
256
- );
257
- }
258
- const variableDirective = variableDirectives[0];
259
- // work, below accesses all report arguments could still be null/undefined.
260
- const args = variableDirective.arguments;
261
- if (variableDirective == null || !Array.isArray(args)) {
262
- return new Map();
263
- }
264
- if (!args.length) {
265
- throw createUserError(
266
- `Directive @${ARGUMENT_DEFINITIONS} requires arguments: remove the ` +
267
- 'directive to skip defining local variables for this fragment.',
268
- null,
269
- [variableDirective],
270
- );
271
- }
272
- const variables = new Map();
273
- args.forEach(arg => {
274
- const argName = getName(arg);
275
- const previousVariable = variables.get(argName);
276
- if (previousVariable != null) {
277
- throw createUserError(
278
- `Duplicate definition for variable '\$${argName}'.`,
279
- null,
280
- [previousVariable.ast, arg],
281
- );
282
- }
283
- if (arg.value.kind !== 'ObjectValue') {
284
- throw createUserError(
285
- `Expected definition for variable '\$${argName}' to be an object ` +
286
- "with the shape: '{type: string, defaultValue?: mixed}.",
287
- null,
288
- [arg.value],
289
- );
290
- }
291
- let defaultValueNode;
292
- let typeString;
293
- arg.value.fields.forEach(field => {
294
- const name = getName(field);
295
- if (name === 'type') {
296
- typeString = transformLiteralValue(field.value, field);
297
- } else if (name === 'defaultValue') {
298
- defaultValueNode = field.value;
299
- } else {
300
- throw createUserError(
301
- `Expected definition for variable '\$${argName}' to be an object ` +
302
- "with the shape: '{type: string, defaultValue?: mixed}.",
303
- null,
304
- [arg.value],
305
- );
306
- }
307
- });
308
- if (typeof typeString !== 'string') {
309
- throw createUserError(
310
- `Expected definition for variable '\$${argName}' to be an object ` +
311
- "with the shape: '{type: string, defaultValue?: mixed}.",
312
- null,
313
- [arg.value],
314
- );
315
- }
316
- const typeFromAST = this._schema.getTypeFromAST(parseType(typeString));
317
- if (typeFromAST == null) {
318
- throw createUserError(
319
- // $FlowFixMe[incompatible-type]
320
- `Unknown type "${typeString}" referenced in the argument definitions.`,
321
- null,
322
- [arg],
323
- );
324
- }
325
- const type = this._schema.asInputType(typeFromAST);
326
- if (type == null) {
327
- throw createUserError(
328
- // $FlowFixMe[incompatible-type]
329
- `Expected type "${typeString}" to be an input type in the "${arg.name.value}" argument definitions.`,
330
- null,
331
- [arg.value],
332
- );
333
- }
334
- const defaultValue =
335
- defaultValueNode != null
336
- ? transformValue(
337
- this._schema,
338
- defaultValueNode,
339
- type,
340
- variableAst => {
341
- throw createUserError(
342
- "Expected 'defaultValue' to be a literal, got a variable.",
343
- null,
344
- [variableAst],
345
- );
346
- },
347
- )
348
- : null;
349
- if (defaultValue != null && defaultValue.kind !== 'Literal') {
350
- throw createUserError(
351
- "Expected 'defaultValue' to be a literal, got a variable.",
352
- [defaultValue.loc],
353
- );
354
- }
355
- variables.set(argName, {
356
- ast: arg,
357
- defaultValue: defaultValue?.value ?? null,
358
- defined: true,
359
- name: argName,
360
- type,
361
- });
362
- });
363
- return variables;
364
- }
365
-
366
- /**
367
- * Constructs a mapping of variable names to definitions using the
368
- * standard GraphQL syntax for variable definitions.
369
- */
370
- _buildOperationArgumentDefinitions(
371
- operation: OperationDefinitionNode,
372
- ): VariableDefinitions {
373
- const schema = this._schema;
374
- const variableDefinitions = new Map();
375
- (operation.variableDefinitions || []).forEach(def => {
376
- const name = getName(def.variable);
377
- const typeFromAST = schema.getTypeFromAST(def.type);
378
- if (typeFromAST == null) {
379
- throw createUserError(
380
- `Unknown type: '${getTypeName(def.type)}'.`,
381
- null,
382
- [def.type],
383
- );
384
- }
385
-
386
- const type = schema.asInputType(typeFromAST);
387
- if (type == null) {
388
- throw createUserError(
389
- `Expected type "${getTypeName(def.type)}" to be an input type.`,
390
- null,
391
- [def.type],
392
- );
393
- }
394
-
395
- const defaultValue = def.defaultValue
396
- ? transformLiteralValue(def.defaultValue, def)
397
- : null;
398
- const previousDefinition = variableDefinitions.get(name);
399
- if (previousDefinition != null) {
400
- throw createUserError(
401
- `Duplicate definition for variable '\$${name}'.`,
402
- null,
403
- [previousDefinition.ast, def],
404
- );
405
- }
406
- variableDefinitions.set(name, {
407
- ast: def,
408
- defaultValue,
409
- defined: true,
410
- name,
411
- type,
412
- });
413
- });
414
- return variableDefinitions;
415
- }
416
- }
417
-
418
- /**
419
- * @private
420
- */
421
- function parseDefinition(
422
- schema: Schema,
423
- getFieldDefinition: GetFieldDefinitionFn,
424
- entries: Map<
425
- string,
426
- {|definition: ASTDefinitionNode, variableDefinitions: VariableDefinitions|},
427
- >,
428
- definition: ASTDefinitionNode,
429
- variableDefinitions: VariableDefinitions,
430
- ): Fragment | Root {
431
- const parser = new GraphQLDefinitionParser(
432
- schema,
433
- getFieldDefinition,
434
- entries,
435
- definition,
436
- variableDefinitions,
437
- );
438
- return parser.transform();
439
- }
440
-
441
- /**
442
- * @private
443
- */
444
- class GraphQLDefinitionParser {
445
- _definition: ASTDefinitionNode;
446
- _entries: Map<
447
- string,
448
- {|
449
- definition: ASTDefinitionNode,
450
- variableDefinitions: VariableDefinitions,
451
- |},
452
- >;
453
- _getFieldDefinition: GetFieldDefinitionFn;
454
- _schema: Schema;
455
- _variableDefinitions: VariableDefinitions;
456
- _unknownVariables: Map<string, UnknownVariable>;
457
- _directiveLocations: ?Map<string, $ReadOnlyArray<DirectiveLocationEnum>>;
458
-
459
- constructor(
460
- schema: Schema,
461
- getFieldDefinition: GetFieldDefinitionFn,
462
- entries: Map<
463
- string,
464
- {|
465
- definition: ASTDefinitionNode,
466
- variableDefinitions: VariableDefinitions,
467
- |},
468
- >,
469
- definition: ASTDefinitionNode,
470
- variableDefinitions: VariableDefinitions,
471
- ): void {
472
- this._definition = definition;
473
- this._entries = entries;
474
- this._getFieldDefinition = getFieldDefinition;
475
- this._schema = schema;
476
- this._variableDefinitions = variableDefinitions;
477
- this._unknownVariables = new Map();
478
- }
479
-
480
- transform(): Root | Fragment {
481
- const definition = this._definition;
482
- switch (definition.kind) {
483
- case 'OperationDefinition':
484
- return this._transformOperation(definition);
485
- case 'FragmentDefinition':
486
- return this._transformFragment(definition);
487
- default:
488
- (definition: empty);
489
- throw createCompilerError(
490
- `Unsupported definition type ${definition.kind}`,
491
- [definition],
492
- );
493
- }
494
- }
495
-
496
- _recordAndVerifyVariableReference(
497
- variable: VariableNode,
498
- name: string,
499
- usedAsType: ?TypeID,
500
- ): void {
501
- // Special case for variables used in @arguments where we currently
502
- // aren't guaranteed to be able to resolve the type.
503
- if (usedAsType == null) {
504
- if (
505
- !this._variableDefinitions.has(name) &&
506
- !this._unknownVariables.has(name)
507
- ) {
508
- this._unknownVariables.set(name, {
509
- ast: variable,
510
- type: null,
511
- });
512
- }
513
- return;
514
- }
515
- const variableDefinition = this._variableDefinitions.get(name);
516
- if (variableDefinition != null) {
517
- // If the variable is defined, all usages must be compatible
518
- let effectiveType = variableDefinition.type;
519
- if (variableDefinition.defaultValue != null) {
520
- // If a default value is defined then it is guaranteed to be used
521
- // at runtime such that the effective type of the variable is non-null
522
- effectiveType = this._schema.getNonNullType(
523
- this._schema.getNullableType(effectiveType),
524
- );
525
- }
526
-
527
- if (!this._schema.isTypeSubTypeOf(effectiveType, usedAsType)) {
528
- throw createUserError(
529
- `Variable '\$${name}' was defined as type '${String(
530
- variableDefinition.type,
531
- )}' but used in a location expecting the type '${String(
532
- usedAsType,
533
- )}'`,
534
- null,
535
- [variableDefinition.ast, variable],
536
- );
537
- }
538
- } else {
539
- const previous = this._unknownVariables.get(name);
540
-
541
- if (!previous || !previous.type) {
542
- // No previous usage, current type is strongest
543
- this._unknownVariables.set(name, {
544
- ast: variable,
545
- type: usedAsType,
546
- });
547
- } else {
548
- const {ast: previousVariable, type: previousType} = previous;
549
- if (
550
- !(
551
- this._schema.isTypeSubTypeOf(usedAsType, previousType) ||
552
- this._schema.isTypeSubTypeOf(previousType, usedAsType)
553
- )
554
- ) {
555
- throw createUserError(
556
- `Variable '\$${name}' was used in locations expecting the conflicting types '${String(
557
- previousType,
558
- )}' and '${String(usedAsType)}'.`,
559
- null,
560
- [previousVariable, variable],
561
- );
562
- }
563
-
564
- // If the new used type has stronger requirements, use that type as reference,
565
- // otherwise keep referencing the previous type
566
- if (this._schema.isTypeSubTypeOf(usedAsType, previousType)) {
567
- this._unknownVariables.set(name, {
568
- ast: variable,
569
- type: usedAsType,
570
- });
571
- }
572
- }
573
- }
574
- }
575
-
576
- _getDirectiveLocations(): Map<string, $ReadOnlyArray<DirectiveLocationEnum>> {
577
- if (!this._directiveLocations) {
578
- const directiveDefs = this._schema.getDirectives();
579
- this._directiveLocations = new Map();
580
- for (const def of directiveDefs) {
581
- this._directiveLocations.set(def.name, def.locations);
582
- }
583
- }
584
- return this._directiveLocations;
585
- }
586
-
587
- _validateDirectivesLocation(
588
- directives: ?$ReadOnlyArray<DirectiveNode>,
589
- allowedLocaction: DirectiveLocationEnum,
590
- ): void {
591
- if (!directives || !directives.length) {
592
- return;
593
- }
594
- const directiveLocs = this._getDirectiveLocations();
595
- const mismatches = directives.filter(directive => {
596
- const name = getName(directive);
597
- if (DIRECTIVE_WHITELIST.has(name)) {
598
- return false;
599
- }
600
- const locs = directiveLocs.get(name);
601
- if (locs == null) {
602
- throw createUserError(`Unknown directive '${name}'.`, null, [
603
- directive,
604
- ]);
605
- }
606
- return !locs.some(loc => loc === allowedLocaction);
607
- });
608
- if (mismatches.length) {
609
- const invalidDirectives = mismatches
610
- .map(directive => '@' + getName(directive))
611
- .join(', ');
612
- throw createUserError(
613
- `Invalid directives ${invalidDirectives} found on ${allowedLocaction}.`,
614
- null,
615
- mismatches,
616
- );
617
- }
618
- }
619
-
620
- _transformFragment(fragment: FragmentDefinitionNode): Fragment {
621
- const directives = this._transformDirectives(
622
- (fragment.directives || []).filter(
623
- directive => getName(directive) !== ARGUMENT_DEFINITIONS,
624
- ),
625
- 'FRAGMENT_DEFINITION',
626
- );
627
-
628
- const typeFromAST = this._schema.getTypeFromAST(fragment.typeCondition);
629
- if (typeFromAST == null) {
630
- throw createUserError(
631
- `Fragment "${fragment.name.value}" cannot condition on unknown ` +
632
- `type "${String(fragment.typeCondition.name.value)}".`,
633
- null,
634
- [fragment.typeCondition],
635
- );
636
- }
637
-
638
- const type = this._schema.asCompositeType(typeFromAST);
639
- if (type == null) {
640
- throw createUserError(
641
- `Fragment "${fragment.name.value}" cannot condition on non composite ` +
642
- `type "${String(type)}".`,
643
- null,
644
- [fragment.typeCondition],
645
- );
646
- }
647
-
648
- const selections = this._transformSelections(
649
- fragment.selectionSet,
650
- type,
651
- fragment.typeCondition,
652
- );
653
- const argumentDefinitions = [
654
- ...buildArgumentDefinitions(this._variableDefinitions),
655
- ];
656
- for (const [name, variableReference] of this._unknownVariables) {
657
- argumentDefinitions.push({
658
- kind: 'RootArgumentDefinition',
659
- loc: buildLocation(variableReference.ast.loc),
660
- name,
661
- type: variableReference.type,
662
- });
663
- }
664
- return {
665
- kind: 'Fragment',
666
- directives,
667
- loc: buildLocation(fragment.loc),
668
- metadata: null,
669
- name: getName(fragment),
670
- selections,
671
- type,
672
- // $FlowFixMe[incompatible-return] - could be null
673
- argumentDefinitions,
674
- };
675
- }
676
-
677
- _getLocationFromOperation(
678
- definition: OperationDefinitionNode,
679
- ): DirectiveLocationEnum {
680
- switch (definition.operation) {
681
- case 'query':
682
- return 'QUERY';
683
- case 'mutation':
684
- return 'MUTATION';
685
- case 'subscription':
686
- return 'SUBSCRIPTION';
687
- default:
688
- (definition.operation: empty);
689
- throw createCompilerError(
690
- `Unknown operation type '${definition.operation}'.`,
691
- null,
692
- [definition],
693
- );
694
- }
695
- }
696
-
697
- _transformOperation(definition: OperationDefinitionNode): Root {
698
- const name = getName(definition);
699
- const directives = this._transformDirectives(
700
- definition.directives || [],
701
- this._getLocationFromOperation(definition),
702
- );
703
- let type: TypeID;
704
- let operation;
705
- const schema = this._schema;
706
- switch (definition.operation) {
707
- case 'query':
708
- operation = 'query';
709
- type = schema.expectQueryType();
710
- break;
711
- case 'mutation':
712
- operation = 'mutation';
713
- type = schema.expectMutationType();
714
- break;
715
- case 'subscription':
716
- operation = 'subscription';
717
- type = schema.expectSubscriptionType();
718
- break;
719
- default:
720
- (definition.operation: empty);
721
- throw createCompilerError(
722
- `Unknown operation type '${definition.operation}'.`,
723
- null,
724
- [definition],
725
- );
726
- }
727
- if (!definition.selectionSet) {
728
- throw createUserError('Expected operation to have selections.', null, [
729
- definition,
730
- ]);
731
- }
732
- const selections = this._transformSelections(definition.selectionSet, type);
733
- const argumentDefinitions = buildArgumentDefinitions(
734
- this._variableDefinitions,
735
- );
736
- if (this._unknownVariables.size !== 0) {
737
- throw createUserError(
738
- `Query '${name}' references undefined variables.`,
739
- null,
740
- Array.from(
741
- this._unknownVariables.values(),
742
- variableReference => variableReference.ast,
743
- ),
744
- );
745
- }
746
- return {
747
- kind: 'Root',
748
- operation,
749
- loc: buildLocation(definition.loc),
750
- metadata: null,
751
- name,
752
- argumentDefinitions,
753
- directives,
754
- selections,
755
- // $FlowFixMe[incompatible-return]
756
- type,
757
- };
758
- }
759
-
760
- _transformSelections(
761
- selectionSet: SelectionSetNode,
762
- parentType: TypeID,
763
- parentTypeAST?: TypeNode,
764
- ): $ReadOnlyArray<Selection> {
765
- return selectionSet.selections.map(selection => {
766
- let node;
767
- if (selection.kind === 'Field') {
768
- node = this._transformField(selection, parentType);
769
- } else if (selection.kind === 'FragmentSpread') {
770
- node = this._transformFragmentSpread(
771
- selection,
772
- parentType,
773
- parentTypeAST,
774
- );
775
- } else if (selection.kind === 'InlineFragment') {
776
- node = this._transformInlineFragment(
777
- selection,
778
- parentType,
779
- parentTypeAST,
780
- );
781
- } else {
782
- (selection.kind: empty);
783
- throw createCompilerError(`Unknown ast kind '${selection.kind}'.`, [
784
- selection,
785
- ]);
786
- }
787
- const [conditions, directives] = this._splitConditions(node.directives);
788
- const conditionalNodes = applyConditions(
789
- conditions,
790
- // $FlowFixMe[incompatible-call]
791
- [{...node, directives}],
792
- );
793
- if (conditionalNodes.length !== 1) {
794
- throw createCompilerError(
795
- 'Expected exactly one condition node.',
796
- null,
797
- selection.directives,
798
- );
799
- }
800
- return conditionalNodes[0];
801
- });
802
- }
803
-
804
- _transformInlineFragment(
805
- fragment: InlineFragmentNode,
806
- parentType: TypeID,
807
- parentTypeAST: ?TypeNode,
808
- ): InlineFragment {
809
- const schema = this._schema;
810
- let typeCondition =
811
- fragment.typeCondition != null
812
- ? schema.getTypeFromAST(fragment.typeCondition)
813
- : parentType;
814
-
815
- if (typeCondition == null) {
816
- throw createUserError(
817
- 'Inline fragments can only be on object, interface or union types' +
818
- `, got unknown type '${getTypeName(fragment.typeCondition)}'.`,
819
- null,
820
- [fragment.typeCondition ?? fragment],
821
- );
822
- }
823
- const typeConditionName = schema.getTypeString(typeCondition);
824
- typeCondition = schema.asCompositeType(typeCondition);
825
- if (typeCondition == null) {
826
- throw createUserError(
827
- 'Inline fragments can only be on object, interface or union types' +
828
- `, got '${typeConditionName}'.`,
829
- null,
830
- [fragment.typeCondition ?? fragment],
831
- );
832
- }
833
- const rawParentType = this._schema.assertCompositeType(
834
- this._schema.getRawType(parentType),
835
- );
836
-
837
- checkFragmentSpreadTypeCompatibility(
838
- this._schema,
839
- typeCondition,
840
- rawParentType,
841
- null,
842
- fragment.typeCondition,
843
- parentTypeAST,
844
- );
845
-
846
- const directives = this._transformDirectives(
847
- fragment.directives || [],
848
- 'INLINE_FRAGMENT',
849
- );
850
- const selections = this._transformSelections(
851
- fragment.selectionSet,
852
- typeCondition,
853
- fragment.typeCondition,
854
- );
855
- return {
856
- kind: 'InlineFragment',
857
- directives,
858
- loc: buildLocation(fragment.loc),
859
- metadata: null,
860
- selections,
861
- typeCondition,
862
- };
863
- }
864
-
865
- _transformFragmentSpread(
866
- fragmentSpread: FragmentSpreadNode,
867
- parentType: TypeID,
868
- parentTypeAST: ?TypeNode,
869
- ): FragmentSpread {
870
- const fragmentName = getName(fragmentSpread);
871
- const [argumentDirectives, otherDirectives] = partitionArray(
872
- fragmentSpread.directives || [],
873
- directive => {
874
- const name = getName(directive);
875
- return name === ARGUMENTS || name === DEPRECATED_UNCHECKED_ARGUMENTS;
876
- },
877
- );
878
- if (argumentDirectives.length > 1) {
879
- throw createUserError(
880
- `Directive @${ARGUMENTS} may be used at most once per a fragment spread.`,
881
- null,
882
- argumentDirectives,
883
- );
884
- }
885
- const fragmentDefinition = this._entries.get(fragmentName);
886
- if (fragmentDefinition == null) {
887
- throw createUserError(`Unknown fragment '${fragmentName}'.`, null, [
888
- fragmentSpread.name,
889
- ]);
890
- }
891
-
892
- const fragmentTypeNode = getFragmentType(fragmentDefinition.definition);
893
- const fragmentType = this._schema.assertCompositeType(
894
- this._schema.expectTypeFromAST(fragmentTypeNode),
895
- );
896
- const rawParentType = this._schema.assertCompositeType(
897
- this._schema.getRawType(parentType),
898
- );
899
-
900
- checkFragmentSpreadTypeCompatibility(
901
- this._schema,
902
- fragmentType,
903
- rawParentType,
904
- fragmentSpread.name.value,
905
- fragmentSpread,
906
- parentTypeAST,
907
- );
908
-
909
- const fragmentArgumentDefinitions = fragmentDefinition.variableDefinitions;
910
- const argumentsDirective = argumentDirectives[0];
911
- let args;
912
- if (argumentsDirective != null) {
913
- const isDeprecatedUncheckedArguments =
914
- getName(argumentsDirective) === DEPRECATED_UNCHECKED_ARGUMENTS;
915
- let hasInvalidArgument = false;
916
- args = (argumentsDirective.arguments || []).map(arg => {
917
- const argName = getName(arg);
918
- const argValue = arg.value;
919
- const argumentDefinition = fragmentArgumentDefinitions.get(argName);
920
- const argumentType = argumentDefinition?.type ?? null;
921
-
922
- if (argValue.kind === 'Variable') {
923
- if (argumentDefinition == null && !isDeprecatedUncheckedArguments) {
924
- throw createUserError(
925
- `Variable @${ARGUMENTS} values are only supported when the ` +
926
- `argument is defined with @${ARGUMENT_DEFINITIONS}. Check ` +
927
- `the definition of fragment '${fragmentName}'.`,
928
- null,
929
- [arg.value, fragmentDefinition.definition],
930
- );
931
- }
932
- hasInvalidArgument = hasInvalidArgument || argumentDefinition == null;
933
- // TODO: check the type of the variable and use the type
934
- return {
935
- kind: 'Argument',
936
- loc: buildLocation(arg.loc),
937
- name: argName,
938
- value: this._transformVariable(argValue, null),
939
- type: null,
940
- };
941
- } else {
942
- if (argumentType == null) {
943
- throw createUserError(
944
- `Literal @${ARGUMENTS} values are only supported when the ` +
945
- `argument is defined with @${ARGUMENT_DEFINITIONS}. Check ` +
946
- `the definition of fragment '${fragmentName}'.`,
947
- null,
948
- [arg.value, fragmentDefinition.definition],
949
- );
950
- }
951
- const value = this._transformValue(argValue, argumentType);
952
- return {
953
- kind: 'Argument',
954
- loc: buildLocation(arg.loc),
955
- name: argName,
956
- value,
957
- type: argumentType,
958
- };
959
- }
960
- });
961
- if (isDeprecatedUncheckedArguments && !hasInvalidArgument) {
962
- throw createUserError(
963
- `Invalid use of @${DEPRECATED_UNCHECKED_ARGUMENTS}: all arguments ` +
964
- `are defined, use @${ARGUMENTS} instead.`,
965
- null,
966
- [argumentsDirective],
967
- );
968
- }
969
- }
970
- const directives = this._transformDirectives(
971
- otherDirectives,
972
- 'FRAGMENT_SPREAD',
973
- );
974
- return {
975
- kind: 'FragmentSpread',
976
- args: args || [],
977
- metadata: null,
978
- loc: buildLocation(fragmentSpread.loc),
979
- name: fragmentName,
980
- directives,
981
- };
982
- }
983
-
984
- _transformField(field: FieldNode, parentType: TypeID): Field {
985
- const schema = this._schema;
986
- const name = getName(field);
987
- const fieldDef = this._getFieldDefinition(schema, parentType, name, field);
988
- if (fieldDef == null) {
989
- throw createUserError(
990
- `Unknown field '${name}' on type '${schema.getTypeString(
991
- parentType,
992
- )}'.`,
993
- null,
994
- [field],
995
- );
996
- }
997
- const alias = field.alias?.value ?? name;
998
- const args = this._transformArguments(
999
- field.arguments || [],
1000
- schema.getFieldArgs(fieldDef),
1001
- fieldDef,
1002
- );
1003
- const [otherDirectives, clientFieldDirectives] = partitionArray(
1004
- field.directives || [],
1005
- directive => getName(directive) !== CLIENT_FIELD,
1006
- );
1007
- const directives = this._transformDirectives(otherDirectives, 'FIELD');
1008
- const type = schema.getFieldType(fieldDef);
1009
-
1010
- const handles = this._transformHandle(name, args, clientFieldDirectives);
1011
- if (schema.isLeafType(schema.getRawType(type))) {
1012
- if (
1013
- field.selectionSet &&
1014
- field.selectionSet.selections &&
1015
- field.selectionSet.selections.length
1016
- ) {
1017
- throw createUserError(
1018
- `Expected no selections for scalar field '${name}'.`,
1019
- null,
1020
- [field],
1021
- );
1022
- }
1023
- return {
1024
- kind: 'ScalarField',
1025
- alias,
1026
- args,
1027
- directives,
1028
- handles,
1029
- loc: buildLocation(field.loc),
1030
- metadata: null,
1031
- name,
1032
- type: schema.assertScalarFieldType(type),
1033
- };
1034
- } else {
1035
- const selections = field.selectionSet
1036
- ? this._transformSelections(field.selectionSet, type)
1037
- : null;
1038
- if (selections == null || selections.length === 0) {
1039
- throw createUserError(
1040
- `Expected at least one selection for non-scalar field '${name}' on type '${schema.getTypeString(
1041
- type,
1042
- )}'.`,
1043
- null,
1044
- [field],
1045
- );
1046
- }
1047
- return {
1048
- kind: 'LinkedField',
1049
- alias,
1050
- args,
1051
- connection: false,
1052
- directives,
1053
- handles,
1054
- loc: buildLocation(field.loc),
1055
- metadata: null,
1056
- name,
1057
- selections,
1058
- type: schema.assertLinkedFieldType(type),
1059
- };
1060
- }
1061
- }
1062
-
1063
- _transformHandle(
1064
- fieldName: string,
1065
- fieldArgs: $ReadOnlyArray<Argument>,
1066
- clientFieldDirectives: $ReadOnlyArray<DirectiveNode>,
1067
- ): ?$ReadOnlyArray<Handle> {
1068
- let handles: ?Array<Handle> = null;
1069
- clientFieldDirectives.forEach(clientFieldDirective => {
1070
- const handleArgument = (clientFieldDirective.arguments || []).find(
1071
- arg => getName(arg) === CLIENT_FIELD_HANDLE,
1072
- );
1073
- if (handleArgument) {
1074
- let name = null;
1075
- let key = DEFAULT_HANDLE_KEY;
1076
- let filters = null;
1077
- const maybeHandle = transformLiteralValue(
1078
- handleArgument.value,
1079
- handleArgument,
1080
- );
1081
- if (typeof maybeHandle !== 'string') {
1082
- throw createUserError(
1083
- `Expected a string literal argument for the @${CLIENT_FIELD} directive.`,
1084
- null,
1085
- [handleArgument.value],
1086
- );
1087
- }
1088
- name = maybeHandle;
1089
-
1090
- const keyArgument = (clientFieldDirective.arguments || []).find(
1091
- arg => getName(arg) === CLIENT_FIELD_KEY,
1092
- );
1093
- if (keyArgument) {
1094
- const maybeKey = transformLiteralValue(
1095
- keyArgument.value,
1096
- keyArgument,
1097
- );
1098
- if (typeof maybeKey !== 'string') {
1099
- throw createUserError(
1100
- `Expected a string literal argument for the @${CLIENT_FIELD} directive.`,
1101
- null,
1102
- [keyArgument.value],
1103
- );
1104
- }
1105
- key = maybeKey;
1106
- }
1107
- const filtersArgument = (clientFieldDirective.arguments || []).find(
1108
- arg => getName(arg) === CLIENT_FIELD_FILTERS,
1109
- );
1110
- if (filtersArgument) {
1111
- const maybeFilters = transformLiteralValue(
1112
- filtersArgument.value,
1113
- filtersArgument,
1114
- );
1115
- if (
1116
- !(
1117
- Array.isArray(maybeFilters) &&
1118
- maybeFilters.every(
1119
- filter =>
1120
- typeof filter === 'string' &&
1121
- fieldArgs.some(fieldArg => fieldArg.name === filter),
1122
- )
1123
- )
1124
- ) {
1125
- throw createUserError(
1126
- `Expected an array of argument names on field '${fieldName}'.`,
1127
- null,
1128
- [filtersArgument.value],
1129
- );
1130
- }
1131
- // $FlowFixMe[incompatible-cast]
1132
- filters = (maybeFilters: Array<string>);
1133
- }
1134
- const dynamicKeyArgument = (clientFieldDirective.arguments || []).find(
1135
- arg => getName(arg) === 'dynamicKey_UNSTABLE',
1136
- );
1137
- if (dynamicKeyArgument != null) {
1138
- throw createUserError(
1139
- 'Dynamic keys are only supported with @connection.',
1140
- null,
1141
- [dynamicKeyArgument.value],
1142
- );
1143
- }
1144
- handles = handles || [];
1145
- handles.push({name, key, filters, dynamicKey: null});
1146
- }
1147
- });
1148
- return handles;
1149
- }
1150
-
1151
- _transformDirectives(
1152
- directives: $ReadOnlyArray<DirectiveNode>,
1153
- location: DirectiveLocationEnum,
1154
- ): $ReadOnlyArray<Directive> {
1155
- this._validateDirectivesLocation(directives, location);
1156
- return directives.map(directive => {
1157
- const name = getName(directive);
1158
- const directiveDef = this._schema.getDirective(name);
1159
- if (directiveDef == null) {
1160
- throw createUserError(`Unknown directive '${name}'.`, null, [
1161
- directive,
1162
- ]);
1163
- }
1164
- const args = this._transformArguments(
1165
- directive.arguments || [],
1166
- directiveDef.args.map(item => {
1167
- return {
1168
- name: item.name,
1169
- type: item.type,
1170
- defaultValue: item.defaultValue,
1171
- };
1172
- }),
1173
- null,
1174
- name,
1175
- );
1176
- return {
1177
- kind: 'Directive',
1178
- loc: buildLocation(directive.loc),
1179
- name,
1180
- args,
1181
- };
1182
- });
1183
- }
1184
-
1185
- _transformArguments(
1186
- args: $ReadOnlyArray<ArgumentNode>,
1187
- argumentDefinitions: $ReadOnlyArray<FieldArgument>,
1188
- field?: ?FieldID,
1189
- directiveName?: ?string,
1190
- ): $ReadOnlyArray<Argument> {
1191
- return args.map(arg => {
1192
- const argName = getName(arg);
1193
- const argDef = argumentDefinitions.find(def => def.name === argName);
1194
- if (argDef == null) {
1195
- const message =
1196
- `Unknown argument '${argName}'` +
1197
- (field
1198
- ? ` on field '${this._schema.getFieldName(field)}'` +
1199
- ` of type '${this._schema.getTypeString(
1200
- this._schema.getFieldParentType(field),
1201
- )}'.`
1202
- : directiveName != null
1203
- ? ` on directive '@${directiveName}'.`
1204
- : '.');
1205
-
1206
- throw createUserError(message, null, [arg]);
1207
- }
1208
-
1209
- const value = this._transformValue(arg.value, argDef.type);
1210
- return {
1211
- kind: 'Argument',
1212
- loc: buildLocation(arg.loc),
1213
- name: argName,
1214
- value,
1215
- type: argDef.type,
1216
- };
1217
- });
1218
- }
1219
-
1220
- _splitConditions(
1221
- mixedDirectives: $ReadOnlyArray<Directive>,
1222
- ): [$ReadOnlyArray<Condition>, $ReadOnlyArray<Directive>] {
1223
- const [conditionDirectives, otherDirectives] = partitionArray(
1224
- mixedDirectives,
1225
- directive => directive.name === INCLUDE || directive.name === SKIP,
1226
- );
1227
- const conditions = conditionDirectives.map(directive => {
1228
- const passingValue = directive.name === INCLUDE;
1229
- const arg = directive.args[0];
1230
- if (arg == null || arg.name !== IF) {
1231
- throw createUserError(
1232
- `Expected an 'if' argument to @${directive.name}.`,
1233
- [directive.loc],
1234
- );
1235
- }
1236
- if (!(arg.value.kind === 'Variable' || arg.value.kind === 'Literal')) {
1237
- throw createUserError(
1238
- `Expected the 'if' argument to @${directive.name} to be a variable or literal.`,
1239
- [directive.loc],
1240
- );
1241
- }
1242
- return {
1243
- kind: 'Condition',
1244
- condition: arg.value,
1245
- loc: directive.loc,
1246
- passingValue,
1247
- selections: [],
1248
- };
1249
- });
1250
- const sortedConditions = conditions.sort((a, b) => {
1251
- if (a.condition.kind === 'Variable' && b.condition.kind === 'Variable') {
1252
- return a.condition.variableName < b.condition.variableName
1253
- ? -1
1254
- : a.condition.variableName > b.condition.variableName
1255
- ? 1
1256
- : 0;
1257
- } else {
1258
- // sort literals earlier, variables later
1259
- return a.condition.kind === 'Variable'
1260
- ? 1
1261
- : b.condition.kind === 'Variable'
1262
- ? -1
1263
- : 0;
1264
- }
1265
- });
1266
- return [sortedConditions, otherDirectives];
1267
- }
1268
-
1269
- _transformVariable(ast: VariableNode, usedAsType: ?InputTypeID): Variable {
1270
- const variableName = getName(ast);
1271
- this._recordAndVerifyVariableReference(ast, variableName, usedAsType);
1272
- return {
1273
- kind: 'Variable',
1274
- loc: buildLocation(ast.loc),
1275
- variableName,
1276
- type: usedAsType,
1277
- };
1278
- }
1279
-
1280
- _transformValue(ast: ValueNode, type: InputTypeID): ArgumentValue {
1281
- return transformValue(
1282
- this._schema,
1283
- ast,
1284
- type,
1285
- (variableAst, variableType) =>
1286
- this._transformVariable(variableAst, variableType),
1287
- );
1288
- }
1289
- }
1290
-
1291
- /**
1292
- * Transforms and validates argument values according to the expected
1293
- * type.
1294
- */
1295
- function transformValue(
1296
- schema: Schema,
1297
- ast: ValueNode,
1298
- type: InputTypeID,
1299
- transformVariable: (
1300
- variableAst: VariableNode,
1301
- variableType: InputTypeID,
1302
- ) => ArgumentValue,
1303
- ): ArgumentValue {
1304
- if (ast.kind === 'Variable') {
1305
- // Special case variables since there is no value to parse
1306
- return transformVariable(ast, type);
1307
- } else if (ast.kind === 'NullValue') {
1308
- // Special case null literals since there is no value to parse
1309
- if (schema.isNonNull(type)) {
1310
- throw createUserError(
1311
- `Expected a value matching type '${String(type)}'.`,
1312
- null,
1313
- [ast],
1314
- );
1315
- }
1316
- return {
1317
- kind: 'Literal',
1318
- loc: buildLocation(ast.loc),
1319
- value: null,
1320
- };
1321
- } else {
1322
- return transformNonNullLiteral(schema, ast, type, transformVariable);
1323
- }
1324
- }
1325
-
1326
- /**
1327
- * Transforms and validates non-null literal (non-variable) values
1328
- * according to the expected type.
1329
- */
1330
- function transformNonNullLiteral(
1331
- schema: Schema,
1332
- ast: NonNullLiteralValueNode,
1333
- type: InputTypeID,
1334
- transformVariable: (
1335
- variableAst: VariableNode,
1336
- variableType: InputTypeID,
1337
- ) => ArgumentValue,
1338
- ): ArgumentValue {
1339
- // Transform the value based on the type without a non-null wrapper.
1340
- // Note that error messages should still use the original `type`
1341
- // since that accurately describes to the user what the expected
1342
- // type is (using nullableType would suggest that `null` is legal
1343
- // even when it may not be, for example).
1344
- const nullableType = schema.getNullableType(type);
1345
- if (schema.isList(nullableType)) {
1346
- if (ast.kind !== 'ListValue') {
1347
- // Parse singular (non-list) values flowing into a list type
1348
- // as scalars, ie without wrapping them in an array.
1349
- if (!schema.isInputType(schema.getListItemType(nullableType))) {
1350
- throw createUserError(
1351
- `Expected type ${schema.getTypeString(
1352
- nullableType,
1353
- )} to be an input type.`,
1354
- null,
1355
- [ast],
1356
- );
1357
- }
1358
- return transformValue(
1359
- schema,
1360
- ast,
1361
- schema.assertInputType(schema.getListItemType(nullableType)),
1362
- transformVariable,
1363
- );
1364
- }
1365
- const itemType = schema.assertInputType(
1366
- schema.getListItemType(nullableType),
1367
- );
1368
- const literalList = [];
1369
- const items = [];
1370
- let areAllItemsScalar = true;
1371
- ast.values.forEach(item => {
1372
- const itemValue = transformValue(
1373
- schema,
1374
- item,
1375
- itemType,
1376
- transformVariable,
1377
- );
1378
- if (itemValue.kind === 'Literal') {
1379
- literalList.push(itemValue.value);
1380
- }
1381
- items.push(itemValue);
1382
- areAllItemsScalar = areAllItemsScalar && itemValue.kind === 'Literal';
1383
- });
1384
- if (areAllItemsScalar) {
1385
- return {
1386
- kind: 'Literal',
1387
- loc: buildLocation(ast.loc),
1388
- value: literalList,
1389
- };
1390
- } else {
1391
- return {
1392
- kind: 'ListValue',
1393
- loc: buildLocation(ast.loc),
1394
- items,
1395
- };
1396
- }
1397
- } else if (schema.isInputObject(nullableType)) {
1398
- if (ast.kind !== 'ObjectValue') {
1399
- throw createUserError(
1400
- `Expected a value matching type '${schema.getTypeString(type)}'.`,
1401
- null,
1402
- [ast],
1403
- );
1404
- }
1405
- const literalObject = {};
1406
- const fields = [];
1407
- let areAllFieldsScalar = true;
1408
- const inputType = schema.assertInputObjectType(nullableType);
1409
- const requiredFieldNames = new Set(
1410
- schema
1411
- .getFields(inputType)
1412
- .filter(field => {
1413
- return schema.isNonNull(schema.getFieldType(field));
1414
- })
1415
- .map(field => schema.getFieldName(field)),
1416
- );
1417
-
1418
- const seenFields = new Map();
1419
- ast.fields.forEach(field => {
1420
- const fieldName = getName(field);
1421
- const seenField = seenFields.get(fieldName);
1422
- if (seenField) {
1423
- throw createUserError(
1424
- `Duplicated field name '${fieldName}' in the input object.`,
1425
- null,
1426
- [field, seenField],
1427
- );
1428
- }
1429
- const fieldID = schema.getFieldByName(inputType, fieldName);
1430
- if (!fieldID) {
1431
- throw createUserError(
1432
- `Unknown field '${fieldName}' on type '${schema.getTypeString(
1433
- inputType,
1434
- )}'.`,
1435
- null,
1436
- [field],
1437
- );
1438
- }
1439
- const fieldConfig = schema.getFieldConfig(fieldID);
1440
- const fieldType = schema.assertInputType(fieldConfig.type);
1441
- const fieldValue = transformValue(
1442
- schema,
1443
- field.value,
1444
- fieldType,
1445
- transformVariable,
1446
- );
1447
- if (fieldValue.kind === 'Literal') {
1448
- literalObject[field.name.value] = fieldValue.value;
1449
- }
1450
- fields.push({
1451
- kind: 'ObjectFieldValue',
1452
- loc: buildLocation(field.loc),
1453
- name: fieldName,
1454
- value: fieldValue,
1455
- });
1456
- seenFields.set(fieldName, field);
1457
- requiredFieldNames.delete(fieldName);
1458
- areAllFieldsScalar = areAllFieldsScalar && fieldValue.kind === 'Literal';
1459
- });
1460
- if (requiredFieldNames.size > 0) {
1461
- const requiredFieldStr = Array.from(requiredFieldNames)
1462
- .map(item => `'${item}'`)
1463
- .join(', ');
1464
- throw createUserError(
1465
- `Missing non-optional field${
1466
- requiredFieldNames.size > 1 ? 's:' : ''
1467
- } ${requiredFieldStr} for input type '${schema.getTypeString(
1468
- inputType,
1469
- )}'.`,
1470
- null,
1471
- [ast],
1472
- );
1473
- }
1474
- if (areAllFieldsScalar) {
1475
- return {
1476
- kind: 'Literal',
1477
- loc: buildLocation(ast.loc),
1478
- value: literalObject,
1479
- };
1480
- } else {
1481
- return {
1482
- kind: 'ObjectValue',
1483
- loc: buildLocation(ast.loc),
1484
- fields,
1485
- };
1486
- }
1487
- } else if (schema.isId(nullableType)) {
1488
- // GraphQLID's parseLiteral() always returns the string value. However
1489
- // the int/string distinction may be important at runtime, so this
1490
- // transform parses int/string literals into the corresponding JS types.
1491
- if (ast.kind === 'IntValue') {
1492
- return {
1493
- kind: 'Literal',
1494
- loc: buildLocation(ast.loc),
1495
- value: parseInt(ast.value, 10),
1496
- };
1497
- } else if (ast.kind === 'StringValue') {
1498
- return {
1499
- kind: 'Literal',
1500
- loc: buildLocation(ast.loc),
1501
- value: ast.value,
1502
- };
1503
- } else {
1504
- throw createUserError(
1505
- `Invalid value, expected a value matching type '${schema.getTypeString(
1506
- type,
1507
- )}'.`,
1508
- null,
1509
- [ast],
1510
- );
1511
- }
1512
- } else if (schema.isEnum(nullableType)) {
1513
- const enumType = schema.assertEnumType(nullableType);
1514
- const value = schema.parseLiteral(enumType, ast);
1515
- if (value == null) {
1516
- const suggestions = schema.getEnumValues(enumType);
1517
-
1518
- // parseLiteral() should return a non-null JavaScript value
1519
- // if the ast value is valid for the type.
1520
- throw createUserError(
1521
- `Expected a value matching type '${schema.getTypeString(
1522
- type,
1523
- )}'. Possible values: ${orList(suggestions)}?'`,
1524
- null,
1525
- [ast],
1526
- );
1527
- }
1528
- return {
1529
- kind: 'Literal',
1530
- loc: buildLocation(ast.loc),
1531
- value,
1532
- };
1533
- } else if (schema.isScalar(nullableType)) {
1534
- const value = schema.parseLiteral(
1535
- schema.assertScalarType(nullableType),
1536
- ast,
1537
- );
1538
- if (value == null) {
1539
- // parseLiteral() should return a non-null JavaScript value
1540
- // if the ast value is valid for the type.
1541
- throw createUserError(
1542
- `Expected a value matching type '${schema.getTypeString(type)}'.`,
1543
- null,
1544
- [ast],
1545
- );
1546
- }
1547
- return {
1548
- kind: 'Literal',
1549
- loc: buildLocation(ast.loc),
1550
- value,
1551
- };
1552
- } else {
1553
- throw createCompilerError(
1554
- `Unsupported type '${schema.getTypeString(
1555
- type,
1556
- )}' for input value, expected a GraphQLList, ` +
1557
- 'GraphQLInputObjectType, GraphQLEnumType, or GraphQLScalarType.',
1558
- null,
1559
- [ast],
1560
- );
1561
- }
1562
- }
1563
-
1564
- /**
1565
- * @private
1566
- */
1567
- function transformLiteralValue(ast: ValueNode, context: ASTNode): mixed {
1568
- switch (ast.kind) {
1569
- case 'IntValue':
1570
- return parseInt(ast.value, 10);
1571
- case 'FloatValue':
1572
- return parseFloat(ast.value);
1573
- case 'StringValue':
1574
- return ast.value;
1575
- case 'BooleanValue':
1576
- // Note: duplicated because Flow does not understand fall-through cases
1577
- return ast.value;
1578
- case 'EnumValue':
1579
- // Note: duplicated because Flow does not understand fall-through cases
1580
- return ast.value;
1581
- case 'ListValue':
1582
- return ast.values.map(item => transformLiteralValue(item, context));
1583
- case 'NullValue':
1584
- return null;
1585
- case 'ObjectValue': {
1586
- const objectValue = {};
1587
- ast.fields.forEach(field => {
1588
- const fieldName = getName(field);
1589
- const value = transformLiteralValue(field.value, context);
1590
- objectValue[fieldName] = value;
1591
- });
1592
- return objectValue;
1593
- }
1594
- case 'Variable':
1595
- throw createUserError(
1596
- 'Unexpected variable where a literal (static) value is required.',
1597
- null,
1598
- [ast, context],
1599
- );
1600
- default:
1601
- (ast.kind: empty);
1602
- throw createCompilerError(`Unknown ast kind '${ast.kind}'.`, [ast]);
1603
- }
1604
- }
1605
-
1606
- /**
1607
- * @private
1608
- */
1609
- function buildArgumentDefinitions(
1610
- variables: VariableDefinitions,
1611
- ): $ReadOnlyArray<LocalArgumentDefinition> {
1612
- return Array.from(variables.values(), ({ast, name, defaultValue, type}) => {
1613
- return {
1614
- kind: 'LocalArgumentDefinition',
1615
- loc: buildLocation(ast.loc),
1616
- name,
1617
- type,
1618
- defaultValue,
1619
- };
1620
- });
1621
- }
1622
-
1623
- /**
1624
- * @private
1625
- */
1626
- function buildLocation(loc: ?ASTLocation): Location {
1627
- if (loc == null) {
1628
- return {kind: 'Unknown'};
1629
- }
1630
- return {
1631
- kind: 'Source',
1632
- start: loc.start,
1633
- end: loc.end,
1634
- source: loc.source,
1635
- };
1636
- }
1637
-
1638
- /**
1639
- * @private
1640
- */
1641
- function applyConditions(
1642
- conditions: $ReadOnlyArray<Condition>,
1643
- selections: $ReadOnlyArray<Selection>,
1644
- ): $ReadOnlyArray<Condition | Selection> {
1645
- let nextSelections = selections;
1646
- conditions.forEach(condition => {
1647
- nextSelections = [
1648
- {
1649
- ...condition,
1650
- selections: nextSelections,
1651
- },
1652
- ];
1653
- });
1654
- return nextSelections;
1655
- }
1656
-
1657
- /**
1658
- * @private
1659
- */
1660
- function getName(ast): string {
1661
- const name = ast.name?.value;
1662
- if (typeof name !== 'string') {
1663
- throw createCompilerError("Expected ast node to have a 'name'.", null, [
1664
- ast,
1665
- ]);
1666
- }
1667
- return name;
1668
- }
1669
-
1670
- function getTypeName(ast: ?TypeNode): string {
1671
- return ast ? print(ast) : 'Undefined Type Name';
1672
- }
1673
-
1674
- /**
1675
- * @private
1676
- */
1677
- function getFragmentType(ast: ASTDefinitionNode): TypeNode {
1678
- if (ast.kind === 'FragmentDefinition') {
1679
- return ast.typeCondition;
1680
- }
1681
- throw createCompilerError(
1682
- 'Expected ast node to be a FragmentDefinition node.',
1683
- null,
1684
- [ast],
1685
- );
1686
- }
1687
-
1688
- function checkFragmentSpreadTypeCompatibility(
1689
- schema: Schema,
1690
- fragmentType: CompositeTypeID,
1691
- parentType: TypeID,
1692
- fragmentName: ?string,
1693
- fragmentTypeAST: ?TypeNode | ?FragmentSpreadNode,
1694
- parentTypeAST: ?TypeNode,
1695
- ) {
1696
- if (
1697
- !schema.doTypesOverlap(fragmentType, schema.assertCompositeType(parentType))
1698
- ) {
1699
- const nodes = [];
1700
- if (parentTypeAST) {
1701
- nodes.push(parentTypeAST);
1702
- }
1703
- if (fragmentTypeAST) {
1704
- nodes.push(fragmentTypeAST);
1705
- }
1706
-
1707
- const possibleConcreteTypes = schema.isAbstractType(parentType)
1708
- ? Array.from(
1709
- schema.getPossibleTypes(schema.assertAbstractType(parentType)),
1710
- )
1711
- : [];
1712
- let suggestedTypesMessage = '';
1713
- if (possibleConcreteTypes.length !== 0) {
1714
- suggestedTypesMessage = ` Possible concrete types include ${possibleConcreteTypes
1715
- .sort()
1716
- .slice(0, 3)
1717
- .map(type => `'${schema.getTypeString(type)}'`)
1718
- .join(', ')}, etc.`;
1719
- }
1720
-
1721
- throw createUserError(
1722
- (fragmentName != null
1723
- ? `Fragment '${fragmentName}' cannot be spread here as objects of `
1724
- : 'Fragment cannot be spread here as objects of ') +
1725
- `type '${schema.getTypeString(parentType)}' ` +
1726
- `can never be of type '${schema.getTypeString(fragmentType)}'.` +
1727
- suggestedTypesMessage,
1728
- null,
1729
- nodes,
1730
- );
1731
- }
1732
- }
1733
-
1734
- module.exports = {parse, transform};