relay-compiler 8.0.0 → 10.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. package/bin/RelayCompilerBin.js.flow +169 -0
  2. package/bin/RelayCompilerMain.js.flow +515 -0
  3. package/bin/__fixtures__/plugin-module.js.flow +17 -0
  4. package/bin/relay-compiler +8930 -8967
  5. package/codegen/CodegenDirectory.js.flow +375 -0
  6. package/codegen/CodegenRunner.js.flow +432 -0
  7. package/codegen/CodegenTypes.js.flow +28 -0
  8. package/codegen/CodegenWatcher.js.flow +254 -0
  9. package/codegen/NormalizationCodeGenerator.js.flow +563 -0
  10. package/codegen/ReaderCodeGenerator.js.flow +477 -0
  11. package/codegen/RelayCodeGenerator.js.flow +85 -0
  12. package/codegen/RelayFileWriter.js.flow +365 -0
  13. package/codegen/SourceControl.js.flow +58 -0
  14. package/codegen/compileRelayArtifacts.js.flow +182 -0
  15. package/codegen/createPrintRequireModuleDependency.js.flow +21 -0
  16. package/codegen/sortObjectByKey.js.flow +25 -0
  17. package/codegen/writeRelayGeneratedFile.js.flow +223 -0
  18. package/core/ASTCache.js.flow +73 -0
  19. package/core/ASTConvert.js.flow +233 -0
  20. package/core/CompilerContext.js.flow +190 -0
  21. package/core/CompilerError.js.flow +250 -0
  22. package/core/DotGraphQLParser.js.flow +39 -0
  23. package/core/GraphQLCompilerProfiler.js.flow +341 -0
  24. package/core/GraphQLDerivedFromMetadata.js.flow +36 -0
  25. package/core/GraphQLWatchmanClient.js.flow +111 -0
  26. package/core/IR.js.flow +327 -0
  27. package/core/IRPrinter.js.flow +482 -0
  28. package/core/IRTransformer.js.flow +377 -0
  29. package/core/IRValidator.js.flow +260 -0
  30. package/core/IRVisitor.js.flow +150 -0
  31. package/core/JSModuleParser.js.flow +24 -0
  32. package/core/RelayCompilerScope.js.flow +199 -0
  33. package/core/RelayFindGraphQLTags.js.flow +119 -0
  34. package/core/RelayGraphQLEnumsGenerator.js.flow +55 -0
  35. package/core/RelayIRTransforms.js.flow +131 -0
  36. package/core/RelayParser.js.flow +1731 -0
  37. package/core/RelaySourceModuleParser.js.flow +135 -0
  38. package/core/Schema.js.flow +1983 -0
  39. package/core/SchemaUtils.js.flow +120 -0
  40. package/core/filterContextForNode.js.flow +50 -0
  41. package/core/getFieldDefinition.js.flow +156 -0
  42. package/core/getIdentifierForArgumentValue.js.flow +49 -0
  43. package/core/getIdentifierForSelection.js.flow +69 -0
  44. package/core/getLiteralArgumentValues.js.flow +32 -0
  45. package/core/getNormalizationOperationName.js.flow +19 -0
  46. package/core/inferRootArgumentDefinitions.js.flow +323 -0
  47. package/index.js +1 -1
  48. package/index.js.flow +200 -0
  49. package/language/RelayLanguagePluginInterface.js.flow +283 -0
  50. package/language/javascript/FindGraphQLTags.js.flow +232 -0
  51. package/language/javascript/RelayFlowBabelFactories.js.flow +180 -0
  52. package/language/javascript/RelayFlowGenerator.js.flow +1042 -0
  53. package/language/javascript/RelayFlowTypeTransformers.js.flow +184 -0
  54. package/language/javascript/RelayLanguagePluginJavaScript.js.flow +34 -0
  55. package/language/javascript/formatGeneratedModule.js.flow +65 -0
  56. package/lib/bin/RelayCompilerBin.js +24 -7
  57. package/lib/bin/RelayCompilerMain.js +141 -136
  58. package/lib/codegen/CodegenDirectory.js +13 -8
  59. package/lib/codegen/CodegenRunner.js +37 -76
  60. package/lib/codegen/CodegenWatcher.js +13 -21
  61. package/lib/codegen/NormalizationCodeGenerator.js +117 -140
  62. package/lib/codegen/ReaderCodeGenerator.js +76 -117
  63. package/lib/codegen/RelayCodeGenerator.js +17 -6
  64. package/lib/codegen/RelayFileWriter.js +19 -40
  65. package/lib/codegen/compileRelayArtifacts.js +16 -30
  66. package/lib/codegen/sortObjectByKey.js +43 -0
  67. package/lib/codegen/writeRelayGeneratedFile.js +86 -95
  68. package/lib/core/ASTCache.js +2 -4
  69. package/lib/core/CompilerContext.js +2 -4
  70. package/lib/core/CompilerError.js +27 -54
  71. package/lib/core/GraphQLCompilerProfiler.js +8 -12
  72. package/lib/core/GraphQLDerivedFromMetadata.js +1 -10
  73. package/lib/core/GraphQLWatchmanClient.js +4 -12
  74. package/lib/core/IRPrinter.js +23 -21
  75. package/lib/core/IRTransformer.js +8 -16
  76. package/lib/core/IRValidator.js +1 -9
  77. package/lib/core/IRVisitor.js +0 -2
  78. package/lib/core/RelayCompilerScope.js +4 -4
  79. package/lib/core/RelayGraphQLEnumsGenerator.js +12 -15
  80. package/lib/core/RelayIRTransforms.js +16 -14
  81. package/lib/core/RelayParser.js +53 -89
  82. package/lib/core/RelaySourceModuleParser.js +3 -3
  83. package/lib/core/Schema.js +61 -73
  84. package/lib/core/SchemaUtils.js +15 -1
  85. package/lib/core/getFieldDefinition.js +12 -15
  86. package/lib/core/getIdentifierForSelection.js +2 -4
  87. package/lib/core/inferRootArgumentDefinitions.js +33 -73
  88. package/lib/index.js +4 -5
  89. package/lib/language/javascript/FindGraphQLTags.js +4 -3
  90. package/lib/language/javascript/RelayFlowGenerator.js +82 -171
  91. package/lib/language/javascript/RelayFlowTypeTransformers.js +1 -3
  92. package/lib/language/javascript/RelayLanguagePluginJavaScript.js +6 -4
  93. package/lib/language/javascript/formatGeneratedModule.js +11 -2
  94. package/lib/reporters/ConsoleReporter.js +1 -3
  95. package/lib/reporters/MultiReporter.js +1 -3
  96. package/lib/runner/Artifacts.js +69 -170
  97. package/lib/runner/BufferedFilesystem.js +32 -66
  98. package/lib/runner/GraphQLASTNodeGroup.js +54 -120
  99. package/lib/runner/GraphQLNodeMap.js +14 -19
  100. package/lib/runner/Sources.js +51 -85
  101. package/lib/runner/StrictMap.js +21 -37
  102. package/lib/runner/getChangedNodeNames.js +30 -62
  103. package/lib/transforms/ApplyFragmentArgumentTransform.js +73 -59
  104. package/lib/transforms/ClientExtensionsTransform.js +12 -16
  105. package/lib/transforms/ConnectionTransform.js +30 -37
  106. package/lib/transforms/DeclarativeConnectionMutationTransform.js +167 -0
  107. package/lib/transforms/DeferStreamTransform.js +30 -73
  108. package/lib/transforms/DisallowTypenameOnRoot.js +55 -0
  109. package/lib/transforms/FieldHandleTransform.js +6 -2
  110. package/lib/transforms/FlattenTransform.js +18 -45
  111. package/lib/transforms/GenerateIDFieldTransform.js +56 -35
  112. package/lib/transforms/GenerateTypeNameTransform.js +84 -10
  113. package/lib/transforms/InlineDataFragmentTransform.js +9 -4
  114. package/lib/transforms/MaskTransform.js +17 -17
  115. package/lib/transforms/MatchTransform.js +110 -32
  116. package/lib/transforms/RefetchableFragmentTransform.js +21 -38
  117. package/lib/transforms/RelayDirectiveTransform.js +8 -3
  118. package/lib/transforms/SkipClientExtensionsTransform.js +8 -0
  119. package/lib/transforms/SkipHandleFieldTransform.js +6 -2
  120. package/lib/transforms/SkipRedundantNodesTransform.js +7 -4
  121. package/lib/transforms/SkipSplitOperationTransform.js +32 -0
  122. package/lib/transforms/SkipUnreachableNodeTransform.js +9 -10
  123. package/lib/transforms/SkipUnusedVariablesTransform.js +18 -17
  124. package/lib/transforms/SplitModuleImportTransform.js +2 -2
  125. package/lib/transforms/TestOperationTransform.js +26 -22
  126. package/lib/transforms/ValidateGlobalVariablesTransform.js +18 -30
  127. package/lib/transforms/ValidateRequiredArgumentsTransform.js +12 -16
  128. package/lib/transforms/ValidateServerOnlyDirectivesTransform.js +16 -30
  129. package/lib/transforms/ValidateUnusedVariablesTransform.js +18 -30
  130. package/lib/transforms/query-generators/FetchableQueryGenerator.js +161 -0
  131. package/lib/transforms/query-generators/NodeQueryGenerator.js +22 -3
  132. package/lib/transforms/query-generators/QueryQueryGenerator.js +2 -1
  133. package/lib/transforms/query-generators/ViewerQueryGenerator.js +1 -0
  134. package/lib/transforms/query-generators/index.js +23 -6
  135. package/lib/transforms/query-generators/utils.js +17 -16
  136. package/lib/util/RelayCompilerCache.js +2 -4
  137. package/lib/util/argumentContainsVariables.js +37 -0
  138. package/lib/util/dedupeJSONStringify.js +15 -12
  139. package/lib/util/generateAbstractTypeRefinementKey.js +24 -0
  140. package/lib/util/getModuleName.js +3 -5
  141. package/lib/util/joinArgumentDefinitions.js +3 -1
  142. package/package.json +6 -6
  143. package/relay-compiler.js +4 -4
  144. package/relay-compiler.min.js +4 -4
  145. package/reporters/ConsoleReporter.js.flow +81 -0
  146. package/reporters/MultiReporter.js.flow +43 -0
  147. package/reporters/Reporter.js.flow +19 -0
  148. package/runner/Artifacts.js.flow +219 -0
  149. package/runner/BufferedFilesystem.js.flow +194 -0
  150. package/runner/GraphQLASTNodeGroup.js.flow +176 -0
  151. package/runner/GraphQLASTUtils.js.flow +26 -0
  152. package/runner/GraphQLNodeMap.js.flow +55 -0
  153. package/runner/Sources.js.flow +214 -0
  154. package/runner/StrictMap.js.flow +96 -0
  155. package/runner/compileArtifacts.js.flow +76 -0
  156. package/runner/extractAST.js.flow +100 -0
  157. package/runner/getChangedNodeNames.js.flow +48 -0
  158. package/runner/getSchemaInstance.js.flow +36 -0
  159. package/runner/types.js.flow +37 -0
  160. package/transforms/ApplyFragmentArgumentTransform.js.flow +526 -0
  161. package/transforms/ClientExtensionsTransform.js.flow +222 -0
  162. package/transforms/ConnectionTransform.js.flow +856 -0
  163. package/transforms/DeclarativeConnectionMutationTransform.js.flow +157 -0
  164. package/transforms/DeferStreamTransform.js.flow +265 -0
  165. package/transforms/DisallowIdAsAlias.js.flow +47 -0
  166. package/transforms/DisallowTypenameOnRoot.js.flow +45 -0
  167. package/transforms/FieldHandleTransform.js.flow +80 -0
  168. package/transforms/FilterDirectivesTransform.js.flow +45 -0
  169. package/transforms/FlattenTransform.js.flow +453 -0
  170. package/transforms/GenerateIDFieldTransform.js.flow +152 -0
  171. package/transforms/GenerateTypeNameTransform.js.flow +161 -0
  172. package/transforms/InlineDataFragmentTransform.js.flow +125 -0
  173. package/transforms/InlineFragmentsTransform.js.flow +71 -0
  174. package/transforms/MaskTransform.js.flow +126 -0
  175. package/transforms/MatchTransform.js.flow +583 -0
  176. package/transforms/RefetchableFragmentTransform.js.flow +272 -0
  177. package/transforms/RelayDirectiveTransform.js.flow +97 -0
  178. package/transforms/SkipClientExtensionsTransform.js.flow +54 -0
  179. package/transforms/SkipHandleFieldTransform.js.flow +44 -0
  180. package/transforms/SkipRedundantNodesTransform.js.flow +254 -0
  181. package/transforms/SkipSplitOperationTransform.js.flow +37 -0
  182. package/transforms/SkipUnreachableNodeTransform.js.flow +149 -0
  183. package/transforms/SkipUnusedVariablesTransform.js.flow +59 -0
  184. package/transforms/SplitModuleImportTransform.js.flow +98 -0
  185. package/transforms/TestOperationTransform.js.flow +142 -0
  186. package/transforms/TransformUtils.js.flow +26 -0
  187. package/transforms/ValidateGlobalVariablesTransform.js.flow +81 -0
  188. package/transforms/ValidateRequiredArgumentsTransform.js.flow +127 -0
  189. package/transforms/ValidateServerOnlyDirectivesTransform.js.flow +112 -0
  190. package/transforms/ValidateUnusedVariablesTransform.js.flow +89 -0
  191. package/transforms/query-generators/FetchableQueryGenerator.js.flow +189 -0
  192. package/transforms/query-generators/NodeQueryGenerator.js.flow +219 -0
  193. package/transforms/query-generators/QueryQueryGenerator.js.flow +57 -0
  194. package/transforms/query-generators/ViewerQueryGenerator.js.flow +97 -0
  195. package/transforms/query-generators/index.js.flow +90 -0
  196. package/transforms/query-generators/utils.js.flow +76 -0
  197. package/util/CodeMarker.js.flow +79 -0
  198. package/{lib/core/GraphQLIR.js → util/DefaultHandleKey.js.flow} +9 -2
  199. package/util/RelayCompilerCache.js.flow +88 -0
  200. package/util/Rollout.js.flow +39 -0
  201. package/util/TimeReporter.js.flow +79 -0
  202. package/util/areEqualOSS.js.flow +123 -0
  203. package/util/argumentContainsVariables.js.flow +38 -0
  204. package/util/dedupeJSONStringify.js.flow +152 -0
  205. package/util/generateAbstractTypeRefinementKey.js.flow +29 -0
  206. package/util/getDefinitionNodeHash.js.flow +25 -0
  207. package/util/getModuleName.js.flow +39 -0
  208. package/util/joinArgumentDefinitions.js.flow +105 -0
  209. package/util/md5.js.flow +22 -0
  210. package/util/murmurHash.js.flow +94 -0
  211. package/util/nullthrowsOSS.js.flow +25 -0
  212. package/util/orList.js.flow +37 -0
  213. package/util/partitionArray.js.flow +37 -0
  214. package/lib/core/GraphQLCompilerContext.js +0 -165
  215. package/lib/core/GraphQLIRPrinter.js +0 -371
  216. package/lib/core/GraphQLIRTransformer.js +0 -344
  217. package/lib/core/GraphQLIRValidator.js +0 -218
  218. package/lib/core/GraphQLIRVisitor.js +0 -46
  219. package/lib/core/RelayCompilerError.js +0 -277
  220. package/lib/transforms/ConnectionFieldTransform.js +0 -276
@@ -0,0 +1,377 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const invariant = require('invariant');
16
+
17
+ const {eachWithCombinedError} = require('./CompilerError');
18
+
19
+ import type CompilerContext, {CompilerContextDocument} from './CompilerContext';
20
+ import type {
21
+ Argument,
22
+ ClientExtension,
23
+ Condition,
24
+ Defer,
25
+ Directive,
26
+ Fragment,
27
+ FragmentSpread,
28
+ IR,
29
+ InlineDataFragmentSpread,
30
+ InlineFragment,
31
+ LinkedField,
32
+ ListValue,
33
+ Literal,
34
+ LocalArgumentDefinition,
35
+ ModuleImport,
36
+ ObjectFieldValue,
37
+ ObjectValue,
38
+ Request,
39
+ Root,
40
+ RootArgumentDefinition,
41
+ ScalarField,
42
+ SplitOperation,
43
+ Stream,
44
+ Variable,
45
+ } from './IR';
46
+
47
+ type NodeVisitor<S> = {|
48
+ Argument?: NodeVisitorFunction<Argument, S>,
49
+ ClientExtension?: NodeVisitorFunction<ClientExtension, S>,
50
+ Condition?: NodeVisitorFunction<Condition, S>,
51
+ Defer?: NodeVisitorFunction<Defer, S>,
52
+ Directive?: NodeVisitorFunction<Directive, S>,
53
+ Fragment?: NodeVisitorFunction<Fragment, S>,
54
+ FragmentSpread?: NodeVisitorFunction<FragmentSpread, S>,
55
+ InlineFragment?: NodeVisitorFunction<InlineFragment, S>,
56
+ LinkedField?: NodeVisitorFunction<LinkedField, S>,
57
+ ListValue?: NodeVisitorFunction<ListValue, S>,
58
+ Literal?: NodeVisitorFunction<Literal, S>,
59
+ LocalArgumentDefinition?: NodeVisitorFunction<LocalArgumentDefinition, S>,
60
+ ModuleImport?: NodeVisitorFunction<ModuleImport, S>,
61
+ ObjectFieldValue?: NodeVisitorFunction<ObjectFieldValue, S>,
62
+ ObjectValue?: NodeVisitorFunction<ObjectValue, S>,
63
+ Request?: NodeVisitorFunction<Request, S>,
64
+ Root?: NodeVisitorFunction<Root, S>,
65
+ InlineDataFragmentSpread?: NodeVisitorFunction<InlineDataFragmentSpread, S>,
66
+ RootArgumentDefinition?: NodeVisitorFunction<RootArgumentDefinition, S>,
67
+ ScalarField?: NodeVisitorFunction<ScalarField, S>,
68
+ SplitOperation?: NodeVisitorFunction<SplitOperation, S>,
69
+ Stream?: NodeVisitorFunction<Stream, S>,
70
+ Variable?: NodeVisitorFunction<Variable, S>,
71
+ |};
72
+ type NodeVisitorFunction<N: IR, S> = (node: N, state: S) => ?N;
73
+
74
+ /**
75
+ * @public
76
+ *
77
+ * Helper for writing compiler transforms that apply "map" and/or "filter"-style
78
+ * operations to compiler contexts. The `visitor` argument accepts a map of IR
79
+ * kinds to user-defined functions that can map nodes of that kind to new values
80
+ * (of the same kind).
81
+ *
82
+ * If a visitor function is defined for a kind, the visitor function is
83
+ * responsible for traversing its children (by calling `this.traverse(node)`)
84
+ * and returning either the input (to indicate no changes), a new node (to
85
+ * indicate changes), or null/undefined (to indicate the removal of that node
86
+ * from the output).
87
+ *
88
+ * If a visitor function is *not* defined for a kind, a default traversal is
89
+ * used to evaluate its children.
90
+ *
91
+ * The `stateInitializer` argument accepts an optional function to construct the
92
+ * state for each document (fragment or root) in the context. Any documents for
93
+ * which the initializer returns null/undefined is deleted from the context
94
+ * without being traversed.
95
+ *
96
+ * Example: Alias all scalar fields with the reverse of their name:
97
+ *
98
+ * ```
99
+ * transform(context, {
100
+ * ScalarField: visitScalarField,
101
+ * });
102
+ *
103
+ * function visitScalarField(field: ScalarField, state: State): ?ScalarField {
104
+ * // Traverse child nodes - for a scalar field these are the arguments &
105
+ * // directives.
106
+ * const nextField = this.traverse(field, state);
107
+ * // Return a new node with a different alias.
108
+ * return {
109
+ * ...nextField,
110
+ * alias: nextField.name.split('').reverse().join(''),
111
+ * };
112
+ * }
113
+ * ```
114
+ */
115
+ function transform<S>(
116
+ context: CompilerContext,
117
+ visitor: NodeVisitor<S>,
118
+ stateInitializer: void | (CompilerContextDocument => ?S),
119
+ ): CompilerContext {
120
+ const transformer = new Transformer(context, visitor);
121
+ return context.withMutations(ctx => {
122
+ let nextContext = ctx;
123
+ eachWithCombinedError(context.documents(), prevNode => {
124
+ let nextNode;
125
+ if (stateInitializer === undefined) {
126
+ nextNode = transformer.visit(prevNode, (undefined: $FlowFixMe));
127
+ } else {
128
+ const state = stateInitializer(prevNode);
129
+ if (state != null) {
130
+ nextNode = transformer.visit(prevNode, state);
131
+ }
132
+ }
133
+ if (!nextNode) {
134
+ nextContext = nextContext.remove(prevNode.name);
135
+ } else if (nextNode !== prevNode) {
136
+ nextContext = nextContext.replace(nextNode);
137
+ }
138
+ });
139
+ return nextContext;
140
+ });
141
+ }
142
+
143
+ /**
144
+ * @internal
145
+ */
146
+ class Transformer<S> {
147
+ _context: CompilerContext;
148
+ _states: Array<S>;
149
+ _visitor: NodeVisitor<S>;
150
+
151
+ constructor(context: CompilerContext, visitor: NodeVisitor<S>) {
152
+ this._context = context;
153
+ this._states = [];
154
+ this._visitor = visitor;
155
+ }
156
+
157
+ /**
158
+ * @public
159
+ *
160
+ * Returns the original compiler context that is being transformed. This can
161
+ * be used to look up fragments by name, for example.
162
+ */
163
+ getContext(): CompilerContext {
164
+ return this._context;
165
+ }
166
+
167
+ /**
168
+ * @public
169
+ *
170
+ * Transforms the node, calling a user-defined visitor function if defined for
171
+ * the node's kind. Uses the given state for this portion of the traversal.
172
+ *
173
+ * Note: This differs from `traverse` in that it calls a visitor function for
174
+ * the node itself.
175
+ */
176
+ visit<N: IR>(node: N, state: S): ?N {
177
+ this._states.push(state);
178
+ const nextNode = this._visit(node);
179
+ this._states.pop();
180
+ return nextNode;
181
+ }
182
+
183
+ /**
184
+ * @public
185
+ *
186
+ * Transforms the children of the given node, skipping the user-defined
187
+ * visitor function for the node itself. Uses the given state for this portion
188
+ * of the traversal.
189
+ *
190
+ * Note: This differs from `visit` in that it does not call a visitor function
191
+ * for the node itself.
192
+ */
193
+ traverse<N: IR>(node: N, state: S): ?N {
194
+ this._states.push(state);
195
+ const nextNode = this._traverse(node);
196
+ this._states.pop();
197
+ return nextNode;
198
+ }
199
+
200
+ _visit<N: IR>(node: N): ?N {
201
+ const nodeVisitor = this._visitor[node.kind];
202
+ if (nodeVisitor) {
203
+ // If a handler for the kind is defined, it is responsible for calling
204
+ // `traverse` to transform children as necessary.
205
+ const state = this._getState();
206
+ const nextNode = nodeVisitor.call(this, (node: $FlowIssue), state);
207
+ return (nextNode: $FlowIssue);
208
+ }
209
+ // Otherwise traverse is called automatically.
210
+ return this._traverse(node);
211
+ }
212
+
213
+ _traverse<N: IR>(prevNode: N): ?N {
214
+ let nextNode;
215
+ switch (prevNode.kind) {
216
+ case 'Argument':
217
+ nextNode = this._traverseChildren(prevNode, null, ['value']);
218
+ break;
219
+ case 'Literal':
220
+ case 'LocalArgumentDefinition':
221
+ case 'RootArgumentDefinition':
222
+ case 'Variable':
223
+ nextNode = prevNode;
224
+ break;
225
+ case 'Defer':
226
+ nextNode = this._traverseChildren(prevNode, ['selections'], ['if']);
227
+ break;
228
+ case 'Stream':
229
+ nextNode = this._traverseChildren(
230
+ prevNode,
231
+ ['selections'],
232
+ ['if', 'initialCount'],
233
+ );
234
+ break;
235
+ case 'ClientExtension':
236
+ nextNode = this._traverseChildren(prevNode, ['selections']);
237
+ break;
238
+ case 'Directive':
239
+ nextNode = this._traverseChildren(prevNode, ['args']);
240
+ break;
241
+ case 'ModuleImport':
242
+ nextNode = this._traverseChildren(prevNode, ['selections']);
243
+ if (!nextNode.selections.length) {
244
+ nextNode = null;
245
+ }
246
+ break;
247
+ case 'FragmentSpread':
248
+ case 'ScalarField':
249
+ nextNode = this._traverseChildren(prevNode, ['args', 'directives']);
250
+ break;
251
+ case 'InlineDataFragmentSpread':
252
+ nextNode = this._traverseChildren(prevNode, ['selections']);
253
+ break;
254
+ case 'LinkedField':
255
+ nextNode = this._traverseChildren(prevNode, [
256
+ 'args',
257
+ 'directives',
258
+ 'selections',
259
+ ]);
260
+ if (!nextNode.selections.length) {
261
+ nextNode = null;
262
+ }
263
+ break;
264
+ case 'ListValue':
265
+ nextNode = this._traverseChildren(prevNode, ['items']);
266
+ break;
267
+ case 'ObjectFieldValue':
268
+ nextNode = this._traverseChildren(prevNode, null, ['value']);
269
+ break;
270
+ case 'ObjectValue':
271
+ nextNode = this._traverseChildren(prevNode, ['fields']);
272
+ break;
273
+ case 'Condition':
274
+ nextNode = this._traverseChildren(
275
+ prevNode,
276
+ ['directives', 'selections'],
277
+ ['condition'],
278
+ );
279
+ if (!nextNode.selections.length) {
280
+ nextNode = null;
281
+ }
282
+ break;
283
+ case 'InlineFragment':
284
+ nextNode = this._traverseChildren(prevNode, [
285
+ 'directives',
286
+ 'selections',
287
+ ]);
288
+ if (!nextNode.selections.length) {
289
+ nextNode = null;
290
+ }
291
+ break;
292
+ case 'Fragment':
293
+ case 'Root':
294
+ nextNode = this._traverseChildren(prevNode, [
295
+ 'argumentDefinitions',
296
+ 'directives',
297
+ 'selections',
298
+ ]);
299
+ break;
300
+ case 'Request':
301
+ nextNode = this._traverseChildren(prevNode, null, ['fragment', 'root']);
302
+ break;
303
+ case 'SplitOperation':
304
+ nextNode = this._traverseChildren(prevNode, ['selections']);
305
+ break;
306
+ default:
307
+ (prevNode: empty);
308
+ invariant(false, 'IRTransformer: Unknown kind `%s`.', prevNode.kind);
309
+ }
310
+ return nextNode;
311
+ }
312
+
313
+ _traverseChildren<N: IR>(
314
+ prevNode: N,
315
+ pluralKeys: ?Array<string>,
316
+ singularKeys?: Array<string>,
317
+ ): N {
318
+ let nextNode;
319
+ pluralKeys &&
320
+ pluralKeys.forEach(key => {
321
+ const prevItems = prevNode[key];
322
+ if (!prevItems) {
323
+ return;
324
+ }
325
+ invariant(
326
+ Array.isArray(prevItems),
327
+ 'IRTransformer: Expected data for `%s` to be an array, got `%s`.',
328
+ key,
329
+ prevItems,
330
+ );
331
+ const nextItems = this._map(prevItems);
332
+ if (nextNode || nextItems !== prevItems) {
333
+ nextNode = nextNode || {...prevNode};
334
+ nextNode[key] = nextItems;
335
+ }
336
+ });
337
+ singularKeys &&
338
+ singularKeys.forEach(key => {
339
+ const prevItem = prevNode[key];
340
+ if (!prevItem) {
341
+ return;
342
+ }
343
+ const nextItem = this._visit(prevItem);
344
+ if (nextNode || nextItem !== prevItem) {
345
+ nextNode = nextNode || {...prevNode};
346
+ nextNode[key] = nextItem;
347
+ }
348
+ });
349
+ return nextNode || prevNode;
350
+ }
351
+
352
+ _map<N: IR>(prevItems: Array<N>): Array<N> {
353
+ let nextItems;
354
+ prevItems.forEach((prevItem, index) => {
355
+ const nextItem = this._visit(prevItem);
356
+ if (nextItems || nextItem !== prevItem) {
357
+ nextItems = nextItems || prevItems.slice(0, index);
358
+ if (nextItem) {
359
+ nextItems.push(nextItem);
360
+ }
361
+ }
362
+ });
363
+ return nextItems || prevItems;
364
+ }
365
+
366
+ _getState(): S {
367
+ invariant(
368
+ this._states.length,
369
+ 'IRTransformer: Expected a current state to be set but found none. ' +
370
+ 'This is usually the result of mismatched number of pushState()/popState() ' +
371
+ 'calls.',
372
+ );
373
+ return this._states[this._states.length - 1];
374
+ }
375
+ }
376
+
377
+ module.exports = {transform};
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const invariant = require('invariant');
16
+
17
+ const {eachWithCombinedError} = require('./CompilerError');
18
+
19
+ import type CompilerContext, {CompilerContextDocument} from './CompilerContext';
20
+ import type {
21
+ Argument,
22
+ ClientExtension,
23
+ Condition,
24
+ Defer,
25
+ Directive,
26
+ Fragment,
27
+ FragmentSpread,
28
+ InlineDataFragmentSpread,
29
+ InlineFragment,
30
+ IR,
31
+ LinkedField,
32
+ ListValue,
33
+ Literal,
34
+ LocalArgumentDefinition,
35
+ ModuleImport,
36
+ ObjectFieldValue,
37
+ ObjectValue,
38
+ Request,
39
+ Root,
40
+ RootArgumentDefinition,
41
+ ScalarField,
42
+ SplitOperation,
43
+ Stream,
44
+ Variable,
45
+ } from './IR';
46
+
47
+ type NodeVisitor<S> = {|
48
+ Argument?: NodeVisitorFunction<Argument, S>,
49
+ ClientExtension?: NodeVisitorFunction<ClientExtension, S>,
50
+ Condition?: NodeVisitorFunction<Condition, S>,
51
+ Defer?: NodeVisitorFunction<Defer, S>,
52
+ Directive?: NodeVisitorFunction<Directive, S>,
53
+ Fragment?: NodeVisitorFunction<Fragment, S>,
54
+ FragmentSpread?: NodeVisitorFunction<FragmentSpread, S>,
55
+ InlineFragment?: NodeVisitorFunction<InlineFragment, S>,
56
+ LinkedField?: NodeVisitorFunction<LinkedField, S>,
57
+ ListValue?: NodeVisitorFunction<ListValue, S>,
58
+ Literal?: NodeVisitorFunction<Literal, S>,
59
+ LocalArgumentDefinition?: NodeVisitorFunction<LocalArgumentDefinition, S>,
60
+ ModuleImport?: NodeVisitorFunction<ModuleImport, S>,
61
+ ObjectFieldValue?: NodeVisitorFunction<ObjectFieldValue, S>,
62
+ ObjectValue?: NodeVisitorFunction<ObjectValue, S>,
63
+ Request?: NodeVisitorFunction<Request, S>,
64
+ Root?: NodeVisitorFunction<Root, S>,
65
+ InlineDataFragmentSpread?: NodeVisitorFunction<InlineDataFragmentSpread, S>,
66
+ RootArgumentDefinition?: NodeVisitorFunction<RootArgumentDefinition, S>,
67
+ ScalarField?: NodeVisitorFunction<ScalarField, S>,
68
+ SplitOperation?: NodeVisitorFunction<SplitOperation, S>,
69
+ Stream?: NodeVisitorFunction<Stream, S>,
70
+ Variable?: NodeVisitorFunction<Variable, S>,
71
+ |};
72
+ type NodeVisitorFunction<N: IR, S> = (node: N, state: S) => void;
73
+
74
+ /**
75
+ * @public
76
+ *
77
+ * Helper for writing AST validators that shares the same logic with
78
+ * the transfomer
79
+ *
80
+ */
81
+ function validate<S>(
82
+ context: CompilerContext,
83
+ visitor: NodeVisitor<S>,
84
+ stateInitializer: void | (CompilerContextDocument => ?S),
85
+ ): void {
86
+ const validator = new Validator(context, visitor);
87
+ eachWithCombinedError(context.documents(), prevNode => {
88
+ if (stateInitializer === undefined) {
89
+ validator.visit(prevNode, (undefined: $FlowFixMe));
90
+ } else {
91
+ const state = stateInitializer(prevNode);
92
+ if (state != null) {
93
+ validator.visit(prevNode, state);
94
+ }
95
+ }
96
+ });
97
+ }
98
+
99
+ /**
100
+ * @internal
101
+ */
102
+ class Validator<S> {
103
+ _context: CompilerContext;
104
+ _states: Array<S>;
105
+ _visitor: NodeVisitor<S>;
106
+
107
+ constructor(context: CompilerContext, visitor: NodeVisitor<S>) {
108
+ this._context = context;
109
+ this._states = [];
110
+ this._visitor = visitor;
111
+ }
112
+
113
+ getContext(): CompilerContext {
114
+ return this._context;
115
+ }
116
+
117
+ visit<N: IR>(node: N, state: S): void {
118
+ this._states.push(state);
119
+ this._visit(node);
120
+ this._states.pop();
121
+ }
122
+
123
+ traverse<N: IR>(node: N, state: S): void {
124
+ this._states.push(state);
125
+ this._traverse(node);
126
+ this._states.pop();
127
+ }
128
+
129
+ _visit<N: IR>(node: N): void {
130
+ const nodeVisitor = this._visitor[node.kind];
131
+ if (nodeVisitor) {
132
+ // If a handler for the kind is defined, it is responsible for calling
133
+ // `traverse` to transform children as necessary.
134
+ const state = this._getState();
135
+ nodeVisitor.call(this, (node: $FlowIssue), state);
136
+ return;
137
+ }
138
+ // Otherwise traverse is called automatically.
139
+ this._traverse(node);
140
+ }
141
+
142
+ _traverse<N: IR>(prevNode: N): void {
143
+ switch (prevNode.kind) {
144
+ case 'Argument':
145
+ this._traverseChildren(prevNode, null, ['value']);
146
+ break;
147
+ case 'Literal':
148
+ case 'LocalArgumentDefinition':
149
+ case 'RootArgumentDefinition':
150
+ case 'Variable':
151
+ break;
152
+ case 'Defer':
153
+ this._traverseChildren(prevNode, ['selections'], ['if']);
154
+ break;
155
+ case 'Stream':
156
+ this._traverseChildren(
157
+ prevNode,
158
+ ['selections'],
159
+ ['if', 'initialCount'],
160
+ );
161
+ break;
162
+ case 'ClientExtension':
163
+ this._traverseChildren(prevNode, ['selections']);
164
+ break;
165
+ case 'Directive':
166
+ this._traverseChildren(prevNode, ['args']);
167
+ break;
168
+ case 'ModuleImport':
169
+ this._traverseChildren(prevNode, ['selections']);
170
+ break;
171
+ case 'FragmentSpread':
172
+ case 'ScalarField':
173
+ this._traverseChildren(prevNode, ['args', 'directives']);
174
+ break;
175
+ case 'InlineDataFragmentSpread':
176
+ this._traverseChildren(prevNode, ['selections']);
177
+ break;
178
+ case 'LinkedField':
179
+ this._traverseChildren(prevNode, ['args', 'directives', 'selections']);
180
+ break;
181
+ case 'ListValue':
182
+ this._traverseChildren(prevNode, ['items']);
183
+ break;
184
+ case 'ObjectFieldValue':
185
+ this._traverseChildren(prevNode, null, ['value']);
186
+ break;
187
+ case 'ObjectValue':
188
+ this._traverseChildren(prevNode, ['fields']);
189
+ break;
190
+ case 'Condition':
191
+ this._traverseChildren(
192
+ prevNode,
193
+ ['directives', 'selections'],
194
+ ['condition'],
195
+ );
196
+ break;
197
+ case 'InlineFragment':
198
+ this._traverseChildren(prevNode, ['directives', 'selections']);
199
+ break;
200
+ case 'Fragment':
201
+ case 'Root':
202
+ this._traverseChildren(prevNode, [
203
+ 'argumentDefinitions',
204
+ 'directives',
205
+ 'selections',
206
+ ]);
207
+ break;
208
+ case 'Request':
209
+ this._traverseChildren(prevNode, null, ['fragment', 'root']);
210
+ break;
211
+ case 'SplitOperation':
212
+ this._traverseChildren(prevNode, ['selections']);
213
+ break;
214
+ default:
215
+ (prevNode: empty);
216
+ invariant(false, 'IRValidator: Unknown kind `%s`.', prevNode.kind);
217
+ }
218
+ }
219
+
220
+ _traverseChildren<N: IR>(
221
+ prevNode: N,
222
+ pluralKeys: ?Array<string>,
223
+ singularKeys?: Array<string>,
224
+ ): void {
225
+ pluralKeys &&
226
+ pluralKeys.forEach(key => {
227
+ const prevItems = prevNode[key];
228
+ if (!prevItems) {
229
+ return;
230
+ }
231
+ invariant(
232
+ Array.isArray(prevItems),
233
+ 'IRValidator: Expected data for `%s` to be an array, got `%s`.',
234
+ key,
235
+ prevItems,
236
+ );
237
+ prevItems.forEach(prevItem => this._visit(prevItem));
238
+ });
239
+ singularKeys &&
240
+ singularKeys.forEach(key => {
241
+ const prevItem = prevNode[key];
242
+ if (!prevItem) {
243
+ return;
244
+ }
245
+ this._visit(prevItem);
246
+ });
247
+ }
248
+
249
+ _getState(): S {
250
+ invariant(
251
+ this._states.length,
252
+ 'IRValidator: Expected a current state to be set but found none. ' +
253
+ 'This is usually the result of mismatched number of pushState()/popState() ' +
254
+ 'calls.',
255
+ );
256
+ return this._states[this._states.length - 1];
257
+ }
258
+ }
259
+
260
+ module.exports = {validate};