relay-compiler 0.0.0-main-f0b65f0b → 0.0.0-main-e0026a71

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