@ardatan/relay-compiler 12.0.0

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 (256) hide show
  1. package/LICENSE +21 -0
  2. package/bin/RelayCompilerBin.js.flow +169 -0
  3. package/bin/RelayCompilerMain.js.flow +515 -0
  4. package/bin/__fixtures__/plugin-module.js.flow +17 -0
  5. package/bin/relay-compiler +19066 -0
  6. package/codegen/CodegenDirectory.js.flow +375 -0
  7. package/codegen/CodegenRunner.js.flow +432 -0
  8. package/codegen/CodegenTypes.js.flow +28 -0
  9. package/codegen/CodegenWatcher.js.flow +254 -0
  10. package/codegen/NormalizationCodeGenerator.js.flow +566 -0
  11. package/codegen/ReaderCodeGenerator.js.flow +512 -0
  12. package/codegen/RelayCodeGenerator.js.flow +85 -0
  13. package/codegen/RelayFileWriter.js.flow +367 -0
  14. package/codegen/SourceControl.js.flow +58 -0
  15. package/codegen/compileRelayArtifacts.js.flow +182 -0
  16. package/codegen/createPrintRequireModuleDependency.js.flow +19 -0
  17. package/codegen/sortObjectByKey.js.flow +25 -0
  18. package/codegen/writeRelayGeneratedFile.js.flow +239 -0
  19. package/core/ASTCache.js.flow +74 -0
  20. package/core/ASTConvert.js.flow +233 -0
  21. package/core/CompilerContext.js.flow +191 -0
  22. package/core/CompilerError.js.flow +255 -0
  23. package/core/DotGraphQLParser.js.flow +39 -0
  24. package/core/GraphQLCompilerProfiler.js.flow +341 -0
  25. package/core/GraphQLDerivedFromMetadata.js.flow +36 -0
  26. package/core/GraphQLWatchmanClient.js.flow +111 -0
  27. package/core/IR.js.flow +326 -0
  28. package/core/IRPrinter.js.flow +478 -0
  29. package/core/IRTransformer.js.flow +377 -0
  30. package/core/IRValidator.js.flow +260 -0
  31. package/core/IRVisitor.js.flow +150 -0
  32. package/core/JSModuleParser.js.flow +24 -0
  33. package/core/RelayCompilerScope.js.flow +199 -0
  34. package/core/RelayFindGraphQLTags.js.flow +119 -0
  35. package/core/RelayGraphQLEnumsGenerator.js.flow +55 -0
  36. package/core/RelayIRTransforms.js.flow +138 -0
  37. package/core/RelayParser.js.flow +1734 -0
  38. package/core/RelaySourceModuleParser.js.flow +135 -0
  39. package/core/Schema.js.flow +2037 -0
  40. package/core/SchemaUtils.js.flow +120 -0
  41. package/core/filterContextForNode.js.flow +50 -0
  42. package/core/getFieldDefinition.js.flow +156 -0
  43. package/core/getIdentifierForArgumentValue.js.flow +49 -0
  44. package/core/getIdentifierForSelection.js.flow +69 -0
  45. package/core/getLiteralArgumentValues.js.flow +32 -0
  46. package/core/getNormalizationOperationName.js.flow +19 -0
  47. package/core/inferRootArgumentDefinitions.js.flow +323 -0
  48. package/index.js +10 -0
  49. package/index.js.flow +200 -0
  50. package/language/RelayLanguagePluginInterface.js.flow +283 -0
  51. package/language/javascript/FindGraphQLTags.js.flow +137 -0
  52. package/language/javascript/RelayFlowBabelFactories.js.flow +176 -0
  53. package/language/javascript/RelayFlowGenerator.js.flow +1100 -0
  54. package/language/javascript/RelayFlowTypeTransformers.js.flow +184 -0
  55. package/language/javascript/RelayLanguagePluginJavaScript.js.flow +34 -0
  56. package/language/javascript/formatGeneratedModule.js.flow +65 -0
  57. package/lib/bin/RelayCompilerBin.js +143 -0
  58. package/lib/bin/RelayCompilerMain.js +486 -0
  59. package/lib/bin/__fixtures__/plugin-module.js +16 -0
  60. package/lib/codegen/CodegenDirectory.js +336 -0
  61. package/lib/codegen/CodegenRunner.js +433 -0
  62. package/lib/codegen/CodegenTypes.js +11 -0
  63. package/lib/codegen/CodegenWatcher.js +271 -0
  64. package/lib/codegen/NormalizationCodeGenerator.js +480 -0
  65. package/lib/codegen/ReaderCodeGenerator.js +472 -0
  66. package/lib/codegen/RelayCodeGenerator.js +68 -0
  67. package/lib/codegen/RelayFileWriter.js +270 -0
  68. package/lib/codegen/SourceControl.js +60 -0
  69. package/lib/codegen/compileRelayArtifacts.js +157 -0
  70. package/lib/codegen/createPrintRequireModuleDependency.js +19 -0
  71. package/lib/codegen/sortObjectByKey.js +41 -0
  72. package/lib/codegen/writeRelayGeneratedFile.js +208 -0
  73. package/lib/core/ASTCache.js +70 -0
  74. package/lib/core/ASTConvert.js +198 -0
  75. package/lib/core/CompilerContext.js +165 -0
  76. package/lib/core/CompilerError.js +251 -0
  77. package/lib/core/DotGraphQLParser.js +40 -0
  78. package/lib/core/GraphQLCompilerProfiler.js +299 -0
  79. package/lib/core/GraphQLDerivedFromMetadata.js +31 -0
  80. package/lib/core/GraphQLWatchmanClient.js +150 -0
  81. package/lib/core/IR.js +11 -0
  82. package/lib/core/IRPrinter.js +389 -0
  83. package/lib/core/IRTransformer.js +345 -0
  84. package/lib/core/IRValidator.js +226 -0
  85. package/lib/core/IRVisitor.js +45 -0
  86. package/lib/core/JSModuleParser.js +18 -0
  87. package/lib/core/RelayCompilerScope.js +149 -0
  88. package/lib/core/RelayFindGraphQLTags.js +79 -0
  89. package/lib/core/RelayGraphQLEnumsGenerator.js +50 -0
  90. package/lib/core/RelayIRTransforms.js +109 -0
  91. package/lib/core/RelayParser.js +1382 -0
  92. package/lib/core/RelaySourceModuleParser.js +104 -0
  93. package/lib/core/Schema.js +1877 -0
  94. package/lib/core/SchemaUtils.js +98 -0
  95. package/lib/core/filterContextForNode.js +49 -0
  96. package/lib/core/getFieldDefinition.js +145 -0
  97. package/lib/core/getIdentifierForArgumentValue.js +53 -0
  98. package/lib/core/getIdentifierForSelection.js +48 -0
  99. package/lib/core/getLiteralArgumentValues.js +26 -0
  100. package/lib/core/getNormalizationOperationName.js +17 -0
  101. package/lib/core/inferRootArgumentDefinitions.js +351 -0
  102. package/lib/index.js +178 -0
  103. package/lib/language/RelayLanguagePluginInterface.js +14 -0
  104. package/lib/language/javascript/FindGraphQLTags.js +126 -0
  105. package/lib/language/javascript/RelayFlowBabelFactories.js +160 -0
  106. package/lib/language/javascript/RelayFlowGenerator.js +857 -0
  107. package/lib/language/javascript/RelayFlowTypeTransformers.js +119 -0
  108. package/lib/language/javascript/RelayLanguagePluginJavaScript.js +30 -0
  109. package/lib/language/javascript/formatGeneratedModule.js +36 -0
  110. package/lib/reporters/ConsoleReporter.js +61 -0
  111. package/lib/reporters/MultiReporter.js +45 -0
  112. package/lib/reporters/Reporter.js +11 -0
  113. package/lib/runner/Artifacts.js +323 -0
  114. package/lib/runner/BufferedFilesystem.js +261 -0
  115. package/lib/runner/GraphQLASTNodeGroup.js +256 -0
  116. package/lib/runner/GraphQLASTUtils.js +23 -0
  117. package/lib/runner/GraphQLNodeMap.js +81 -0
  118. package/lib/runner/Sources.js +271 -0
  119. package/lib/runner/StrictMap.js +134 -0
  120. package/lib/runner/compileArtifacts.js +39 -0
  121. package/lib/runner/extractAST.js +77 -0
  122. package/lib/runner/getChangedNodeNames.js +82 -0
  123. package/lib/runner/getSchemaInstance.js +30 -0
  124. package/lib/runner/types.js +12 -0
  125. package/lib/transforms/ApplyFragmentArgumentTransform.js +393 -0
  126. package/lib/transforms/ClientExtensionsTransform.js +222 -0
  127. package/lib/transforms/ConnectionTransform.js +643 -0
  128. package/lib/transforms/DeclarativeConnectionMutationTransform.js +221 -0
  129. package/lib/transforms/DeferStreamTransform.js +247 -0
  130. package/lib/transforms/DisallowIdAsAlias.js +41 -0
  131. package/lib/transforms/DisallowTypenameOnRoot.js +53 -0
  132. package/lib/transforms/FieldHandleTransform.js +81 -0
  133. package/lib/transforms/FilterCompilerDirectivesTransform.js +29 -0
  134. package/lib/transforms/FilterDirectivesTransform.js +41 -0
  135. package/lib/transforms/FlattenTransform.js +308 -0
  136. package/lib/transforms/GenerateIDFieldTransform.js +137 -0
  137. package/lib/transforms/GenerateTypeNameTransform.js +155 -0
  138. package/lib/transforms/InlineDataFragmentTransform.js +104 -0
  139. package/lib/transforms/InlineFragmentsTransform.js +63 -0
  140. package/lib/transforms/MaskTransform.js +121 -0
  141. package/lib/transforms/MatchTransform.js +438 -0
  142. package/lib/transforms/ReactFlightComponentTransform.js +161 -0
  143. package/lib/transforms/RefetchableFragmentTransform.js +249 -0
  144. package/lib/transforms/RelayDirectiveTransform.js +85 -0
  145. package/lib/transforms/RequiredFieldTransform.js +373 -0
  146. package/lib/transforms/SkipClientExtensionsTransform.js +49 -0
  147. package/lib/transforms/SkipHandleFieldTransform.js +45 -0
  148. package/lib/transforms/SkipRedundantNodesTransform.js +255 -0
  149. package/lib/transforms/SkipSplitOperationTransform.js +32 -0
  150. package/lib/transforms/SkipUnreachableNodeTransform.js +158 -0
  151. package/lib/transforms/SkipUnusedVariablesTransform.js +74 -0
  152. package/lib/transforms/SplitModuleImportTransform.js +85 -0
  153. package/lib/transforms/TestOperationTransform.js +145 -0
  154. package/lib/transforms/TransformUtils.js +21 -0
  155. package/lib/transforms/ValidateGlobalVariablesTransform.js +91 -0
  156. package/lib/transforms/ValidateRequiredArgumentsTransform.js +118 -0
  157. package/lib/transforms/ValidateServerOnlyDirectivesTransform.js +111 -0
  158. package/lib/transforms/ValidateUnusedVariablesTransform.js +96 -0
  159. package/lib/transforms/query-generators/FetchableQueryGenerator.js +157 -0
  160. package/lib/transforms/query-generators/NodeQueryGenerator.js +166 -0
  161. package/lib/transforms/query-generators/QueryQueryGenerator.js +48 -0
  162. package/lib/transforms/query-generators/ViewerQueryGenerator.js +77 -0
  163. package/lib/transforms/query-generators/index.js +60 -0
  164. package/lib/transforms/query-generators/utils.js +92 -0
  165. package/lib/util/CodeMarker.js +80 -0
  166. package/lib/util/DefaultHandleKey.js +15 -0
  167. package/lib/util/RelayCompilerCache.js +98 -0
  168. package/lib/util/Rollout.js +40 -0
  169. package/lib/util/TimeReporter.js +83 -0
  170. package/lib/util/areEqualArgValues.js +135 -0
  171. package/lib/util/argumentContainsVariables.js +37 -0
  172. package/lib/util/dedupeJSONStringify.js +160 -0
  173. package/lib/util/generateAbstractTypeRefinementKey.js +24 -0
  174. package/lib/util/getDefinitionNodeHash.js +22 -0
  175. package/lib/util/getModuleName.js +32 -0
  176. package/lib/util/joinArgumentDefinitions.js +66 -0
  177. package/lib/util/md5.js +17 -0
  178. package/lib/util/murmurHash.js +86 -0
  179. package/lib/util/nullthrowsOSS.js +23 -0
  180. package/lib/util/orList.js +36 -0
  181. package/lib/util/partitionArray.js +35 -0
  182. package/package.json +42 -0
  183. package/relay-compiler.js +17 -0
  184. package/relay-compiler.min.js +22 -0
  185. package/reporters/ConsoleReporter.js.flow +81 -0
  186. package/reporters/MultiReporter.js.flow +43 -0
  187. package/reporters/Reporter.js.flow +19 -0
  188. package/runner/Artifacts.js.flow +219 -0
  189. package/runner/BufferedFilesystem.js.flow +194 -0
  190. package/runner/GraphQLASTNodeGroup.js.flow +176 -0
  191. package/runner/GraphQLASTUtils.js.flow +26 -0
  192. package/runner/GraphQLNodeMap.js.flow +55 -0
  193. package/runner/Sources.js.flow +228 -0
  194. package/runner/StrictMap.js.flow +96 -0
  195. package/runner/compileArtifacts.js.flow +76 -0
  196. package/runner/extractAST.js.flow +100 -0
  197. package/runner/getChangedNodeNames.js.flow +48 -0
  198. package/runner/getSchemaInstance.js.flow +36 -0
  199. package/runner/types.js.flow +37 -0
  200. package/transforms/ApplyFragmentArgumentTransform.js.flow +526 -0
  201. package/transforms/ClientExtensionsTransform.js.flow +226 -0
  202. package/transforms/ConnectionTransform.js.flow +859 -0
  203. package/transforms/DeclarativeConnectionMutationTransform.js.flow +250 -0
  204. package/transforms/DeferStreamTransform.js.flow +266 -0
  205. package/transforms/DisallowIdAsAlias.js.flow +48 -0
  206. package/transforms/DisallowTypenameOnRoot.js.flow +45 -0
  207. package/transforms/FieldHandleTransform.js.flow +81 -0
  208. package/transforms/FilterCompilerDirectivesTransform.js.flow +33 -0
  209. package/transforms/FilterDirectivesTransform.js.flow +45 -0
  210. package/transforms/FlattenTransform.js.flow +462 -0
  211. package/transforms/GenerateIDFieldTransform.js.flow +154 -0
  212. package/transforms/GenerateTypeNameTransform.js.flow +167 -0
  213. package/transforms/InlineDataFragmentTransform.js.flow +129 -0
  214. package/transforms/InlineFragmentsTransform.js.flow +73 -0
  215. package/transforms/MaskTransform.js.flow +130 -0
  216. package/transforms/MatchTransform.js.flow +593 -0
  217. package/transforms/ReactFlightComponentTransform.js.flow +198 -0
  218. package/transforms/RefetchableFragmentTransform.js.flow +272 -0
  219. package/transforms/RelayDirectiveTransform.js.flow +99 -0
  220. package/transforms/RequiredFieldTransform.js.flow +419 -0
  221. package/transforms/SkipClientExtensionsTransform.js.flow +57 -0
  222. package/transforms/SkipHandleFieldTransform.js.flow +45 -0
  223. package/transforms/SkipRedundantNodesTransform.js.flow +259 -0
  224. package/transforms/SkipSplitOperationTransform.js.flow +37 -0
  225. package/transforms/SkipUnreachableNodeTransform.js.flow +149 -0
  226. package/transforms/SkipUnusedVariablesTransform.js.flow +59 -0
  227. package/transforms/SplitModuleImportTransform.js.flow +101 -0
  228. package/transforms/TestOperationTransform.js.flow +143 -0
  229. package/transforms/TransformUtils.js.flow +26 -0
  230. package/transforms/ValidateGlobalVariablesTransform.js.flow +81 -0
  231. package/transforms/ValidateRequiredArgumentsTransform.js.flow +131 -0
  232. package/transforms/ValidateServerOnlyDirectivesTransform.js.flow +115 -0
  233. package/transforms/ValidateUnusedVariablesTransform.js.flow +89 -0
  234. package/transforms/query-generators/FetchableQueryGenerator.js.flow +189 -0
  235. package/transforms/query-generators/NodeQueryGenerator.js.flow +219 -0
  236. package/transforms/query-generators/QueryQueryGenerator.js.flow +57 -0
  237. package/transforms/query-generators/ViewerQueryGenerator.js.flow +97 -0
  238. package/transforms/query-generators/index.js.flow +90 -0
  239. package/transforms/query-generators/utils.js.flow +76 -0
  240. package/util/CodeMarker.js.flow +79 -0
  241. package/util/DefaultHandleKey.js.flow +17 -0
  242. package/util/RelayCompilerCache.js.flow +88 -0
  243. package/util/Rollout.js.flow +39 -0
  244. package/util/TimeReporter.js.flow +79 -0
  245. package/util/areEqualArgValues.js.flow +126 -0
  246. package/util/argumentContainsVariables.js.flow +38 -0
  247. package/util/dedupeJSONStringify.js.flow +152 -0
  248. package/util/generateAbstractTypeRefinementKey.js.flow +29 -0
  249. package/util/getDefinitionNodeHash.js.flow +25 -0
  250. package/util/getModuleName.js.flow +39 -0
  251. package/util/joinArgumentDefinitions.js.flow +105 -0
  252. package/util/md5.js.flow +22 -0
  253. package/util/murmurHash.js.flow +94 -0
  254. package/util/nullthrowsOSS.js.flow +25 -0
  255. package/util/orList.js.flow +37 -0
  256. package/util/partitionArray.js.flow +37 -0
@@ -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};