relay-compiler 0.0.0-main-8ff54d69 → 0.0.0-main-38f1c96e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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};