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,272 @@
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 IRVisitor = require('../core/IRVisitor');
16
+
17
+ const getLiteralArgumentValues = require('../core/getLiteralArgumentValues');
18
+ const inferRootArgumentDefinitions = require('../core/inferRootArgumentDefinitions');
19
+
20
+ const {
21
+ createUserError,
22
+ eachWithCombinedError,
23
+ } = require('../core/CompilerError');
24
+ const {buildRefetchOperation} = require('./query-generators');
25
+
26
+ import type CompilerContext from '../core/CompilerContext';
27
+ import type {Argument, Field, Fragment} from '../core/IR';
28
+ import type {Schema} from '../core/Schema';
29
+ import type {ReaderPaginationMetadata} from 'relay-runtime';
30
+
31
+ const SCHEMA_EXTENSION = `
32
+ directive @refetchable(
33
+ queryName: String!
34
+ ) on FRAGMENT_DEFINITION
35
+ `;
36
+
37
+ /**
38
+ * This transform synthesizes "refetch" queries for fragments that
39
+ * are trivially refetchable. This is comprised of three main stages:
40
+ *
41
+ * 1. Validating that fragments marked with @refetchable qualify for
42
+ * refetch query generation; mainly this means that the fragment
43
+ * type is able to be refetched in some canonical way.
44
+ * 2. Determining the variable definitions to use for each generated
45
+ * query. GraphQL does not have a notion of fragment-local variables
46
+ * at all, and although Relay adds this concept developers are still
47
+ * allowed to reference global variables. This necessitates a
48
+ * visiting all reachable fragments for each @refetchable fragment,
49
+ * and finding the union of all global variables expceted to be defined.
50
+ * 3. Building the refetch queries, a straightforward copying transform from
51
+ * Fragment to Root IR nodes.
52
+ */
53
+ function refetchableFragmentTransform(
54
+ context: CompilerContext,
55
+ ): CompilerContext {
56
+ const schema = context.getSchema();
57
+
58
+ const refetchOperations = buildRefetchMap(context);
59
+ let nextContext = context;
60
+ eachWithCombinedError(refetchOperations, ([refetchName, fragment]) => {
61
+ const {
62
+ identifierField,
63
+ path,
64
+ node,
65
+ transformedFragment,
66
+ } = buildRefetchOperation(schema, fragment, refetchName);
67
+ const connectionMetadata = extractConnectionMetadata(
68
+ context.getSchema(),
69
+ transformedFragment,
70
+ );
71
+ nextContext = nextContext.replace({
72
+ ...transformedFragment,
73
+ metadata: {
74
+ ...(transformedFragment.metadata || {}),
75
+ refetch: {
76
+ connection: connectionMetadata ?? null,
77
+ operation: refetchName,
78
+ fragmentPathInResult: path,
79
+ identifierField,
80
+ },
81
+ },
82
+ });
83
+ nextContext = nextContext.add({
84
+ ...node,
85
+ metadata: {
86
+ ...(node.metadata || {}),
87
+ derivedFrom: transformedFragment.name,
88
+ isRefetchableQuery: true,
89
+ },
90
+ });
91
+ });
92
+ return nextContext;
93
+ }
94
+
95
+ /**
96
+ * Walk the documents of a compiler context and create a mapping of
97
+ * refetch operation names to the source fragment from which the refetch
98
+ * operation should be derived.
99
+ */
100
+ function buildRefetchMap(context: CompilerContext): Map<string, Fragment> {
101
+ const refetchOperations = new Map();
102
+ eachWithCombinedError(context.documents(), node => {
103
+ if (node.kind !== 'Fragment') {
104
+ return;
105
+ }
106
+ const refetchName = getRefetchQueryName(node);
107
+ if (refetchName === null) {
108
+ return;
109
+ }
110
+ const previousOperation = refetchOperations.get(refetchName);
111
+ if (previousOperation != null) {
112
+ throw createUserError(
113
+ `Duplicate definition for @refetchable operation '${refetchName}' from fragments '${node.name}' and '${previousOperation.name}'`,
114
+ [node.loc, previousOperation.loc],
115
+ );
116
+ }
117
+ refetchOperations.set(refetchName, node);
118
+ });
119
+ const transformed = inferRootArgumentDefinitions(context);
120
+ return new Map(
121
+ Array.from(refetchOperations.entries(), ([name, fragment]) => {
122
+ return [name, transformed.getFragment(fragment.name)];
123
+ }),
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Validate that any @connection usage is valid for refetching:
129
+ * - Variables are used for both the "count" and "cursor" arguments
130
+ * (after/first or before/last)
131
+ * - Exactly one connection
132
+ * - Has a stable path to the connection data
133
+ *
134
+ * Returns connection metadata to add to the transformed fragment or undefined
135
+ * if there is no connection.
136
+ */
137
+ function extractConnectionMetadata(
138
+ schema: Schema,
139
+ fragment: Fragment,
140
+ ): ReaderPaginationMetadata | void {
141
+ const fields = [];
142
+ let connectionField = null;
143
+ let path = null;
144
+ IRVisitor.visit(fragment, {
145
+ LinkedField: {
146
+ enter(field) {
147
+ fields.push(field);
148
+ if (
149
+ field.connection === true ||
150
+ (field.handles &&
151
+ field.handles.some(handle => handle.name === 'connection'))
152
+ ) {
153
+ // Disallow multiple @connections
154
+ if (connectionField != null) {
155
+ throw createUserError(
156
+ `Invalid use of @refetchable with @connection in fragment '${fragment.name}', at most once @connection can appear in a refetchable fragment.`,
157
+ [field.loc],
158
+ );
159
+ }
160
+ // Disallow connections within plurals
161
+ const pluralOnPath = fields.find(pathField =>
162
+ schema.isList(schema.getNullableType(pathField.type)),
163
+ );
164
+ if (pluralOnPath) {
165
+ throw createUserError(
166
+ `Invalid use of @refetchable with @connection in fragment '${fragment.name}', refetchable connections cannot appear inside plural fields.`,
167
+ [field.loc, pluralOnPath.loc],
168
+ );
169
+ }
170
+ connectionField = field;
171
+ path = fields.map(pathField => pathField.alias);
172
+ }
173
+ },
174
+ leave() {
175
+ fields.pop();
176
+ },
177
+ },
178
+ });
179
+ if (connectionField == null || path == null) {
180
+ return;
181
+ }
182
+ // Validate arguments: if either of before/last appear they must both appear
183
+ // and use variables (not scalar values)
184
+ let backward = null;
185
+ const before = findArgument(connectionField, 'before');
186
+ const last = findArgument(connectionField, 'last');
187
+ if (before || last) {
188
+ if (
189
+ !before ||
190
+ !last ||
191
+ before.value.kind !== 'Variable' ||
192
+ last.value.kind !== 'Variable'
193
+ ) {
194
+ throw createUserError(
195
+ `Invalid use of @refetchable with @connection in fragment '${fragment.name}', refetchable connections must use variables for the before and last arguments.`,
196
+ [
197
+ connectionField.loc,
198
+ before && before.value.kind !== 'Variable' ? before.value.loc : null,
199
+ last && last.value.kind !== 'Variable' ? last.value.loc : null,
200
+ ].filter(Boolean),
201
+ );
202
+ }
203
+ backward = {
204
+ count: last.value.variableName,
205
+ cursor: before.value.variableName,
206
+ };
207
+ }
208
+ // Validate arguments: if either of after/first appear they must both appear
209
+ // and use variables (not scalar values)
210
+ let forward = null;
211
+ const after = findArgument(connectionField, 'after');
212
+ const first = findArgument(connectionField, 'first');
213
+ if (after || first) {
214
+ if (
215
+ !after ||
216
+ !first ||
217
+ after.value.kind !== 'Variable' ||
218
+ first.value.kind !== 'Variable'
219
+ ) {
220
+ throw createUserError(
221
+ `Invalid use of @refetchable with @connection in fragment '${fragment.name}', refetchable connections must use variables for the after and first arguments.`,
222
+ [
223
+ connectionField.loc,
224
+ after && after.value.kind !== 'Variable' ? after.value.loc : null,
225
+ first && first.value.kind !== 'Variable' ? first.value.loc : null,
226
+ ].filter(Boolean),
227
+ );
228
+ }
229
+ forward = {
230
+ count: first.value.variableName,
231
+ cursor: after.value.variableName,
232
+ };
233
+ }
234
+ return {forward, backward, path};
235
+ }
236
+
237
+ function getRefetchQueryName(fragment: Fragment): string | null {
238
+ const refetchableDirective = fragment.directives.find(
239
+ directive => directive.name === 'refetchable',
240
+ );
241
+ if (refetchableDirective == null) {
242
+ return null;
243
+ }
244
+ const refetchArguments = getLiteralArgumentValues(refetchableDirective.args);
245
+ const queryName = refetchArguments.queryName;
246
+ if (queryName == null) {
247
+ throw createUserError(
248
+ "Expected the 'queryName' argument of @refetchable to be provided",
249
+ [refetchableDirective.loc],
250
+ );
251
+ } else if (typeof queryName !== 'string') {
252
+ const queryNameArg = refetchableDirective.args.find(
253
+ arg => arg.name === 'queryName',
254
+ );
255
+ throw createUserError(
256
+ `Expected the 'queryName' argument of @refetchable to be a string, got '${String(
257
+ queryName,
258
+ )}'.`,
259
+ [queryNameArg?.loc ?? refetchableDirective.loc],
260
+ );
261
+ }
262
+ return queryName;
263
+ }
264
+
265
+ function findArgument(field: Field, argumentName: string): Argument | null {
266
+ return field.args.find(arg => arg.name === argumentName) ?? null;
267
+ }
268
+
269
+ module.exports = {
270
+ SCHEMA_EXTENSION,
271
+ transform: refetchableFragmentTransform,
272
+ };
@@ -0,0 +1,97 @@
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 IRTransformer = require('../core/IRTransformer');
16
+
17
+ const getLiteralArgumentValues = require('../core/getLiteralArgumentValues');
18
+ const invariant = require('invariant');
19
+
20
+ import type CompilerContext from '../core/CompilerContext';
21
+ import type {Fragment, FragmentSpread} from '../core/IR';
22
+
23
+ const RELAY = 'relay';
24
+ const SCHEMA_EXTENSION = `
25
+ directive @relay(
26
+ # Marks a fragment as being backed by a GraphQLList.
27
+ plural: Boolean,
28
+
29
+ # Marks a fragment spread which should be unmasked if provided false
30
+ mask: Boolean = true,
31
+ ) on FRAGMENT_DEFINITION | FRAGMENT_SPREAD
32
+ `;
33
+
34
+ /**
35
+ * A transform that extracts `@relay(plural: Boolean)` directives and converts
36
+ * them to metadata that can be accessed at runtime.
37
+ */
38
+ function relayDirectiveTransform(context: CompilerContext): CompilerContext {
39
+ return IRTransformer.transform(context, {
40
+ Fragment: visitRelayMetadata(fragmentMetadata),
41
+ FragmentSpread: visitRelayMetadata(fragmentSpreadMetadata),
42
+ });
43
+ }
44
+
45
+ type MixedObj = {[key: string]: mixed, ...};
46
+ function visitRelayMetadata<T: Fragment | FragmentSpread>(
47
+ metadataFn: MixedObj => MixedObj,
48
+ ): T => T {
49
+ return function(node) {
50
+ const relayDirective = node.directives.find(({name}) => name === RELAY);
51
+ if (!relayDirective) {
52
+ return this.traverse(node);
53
+ }
54
+ const argValues = getLiteralArgumentValues(relayDirective.args);
55
+ const metadata = metadataFn(argValues);
56
+ return this.traverse({
57
+ ...node,
58
+ directives: node.directives.filter(
59
+ directive => directive !== relayDirective,
60
+ ),
61
+ // $FlowFixMe[cannot-spread-indexer]
62
+ metadata: {
63
+ ...(node.metadata || {}),
64
+ ...metadata,
65
+ },
66
+ });
67
+ };
68
+ }
69
+
70
+ function fragmentMetadata({mask, plural}): MixedObj {
71
+ invariant(
72
+ plural === undefined || typeof plural === 'boolean',
73
+ 'RelayDirectiveTransform: Expected the "plural" argument to @relay ' +
74
+ 'to be a boolean literal if specified.',
75
+ );
76
+ invariant(
77
+ mask === undefined || typeof mask === 'boolean',
78
+ 'RelayDirectiveTransform: Expected the "mask" argument to @relay ' +
79
+ 'to be a boolean literal if specified.',
80
+ );
81
+ return {mask, plural};
82
+ }
83
+
84
+ function fragmentSpreadMetadata({mask}): MixedObj {
85
+ invariant(
86
+ mask === undefined || typeof mask === 'boolean',
87
+ 'RelayDirectiveTransform: Expected the "mask" argument to @relay ' +
88
+ 'to be a boolean literal if specified.',
89
+ );
90
+ return {mask};
91
+ }
92
+
93
+ module.exports = {
94
+ RELAY,
95
+ SCHEMA_EXTENSION,
96
+ transform: relayDirectiveTransform,
97
+ };
@@ -0,0 +1,54 @@
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 IRTransformer = require('../core/IRTransformer');
16
+
17
+ import type CompilerContext from '../core/CompilerContext';
18
+ import type {ClientExtension, Fragment, FragmentSpread} from '../core/IR';
19
+
20
+ function skipClientExtensionTransform(
21
+ context: CompilerContext,
22
+ ): CompilerContext {
23
+ return IRTransformer.transform(context, {
24
+ Fragment: visitFragment,
25
+ FragmentSpread: vistFragmentSpread,
26
+ ClientExtension: visitClientExtension,
27
+ });
28
+ }
29
+
30
+ function visitFragment(node: Fragment): ?Fragment {
31
+ const context: CompilerContext = this.getContext();
32
+ if (context.getSchema().isServerType(node.type)) {
33
+ return this.traverse(node);
34
+ }
35
+ return null;
36
+ }
37
+
38
+ function vistFragmentSpread(node: FragmentSpread): ?FragmentSpread {
39
+ const context: CompilerContext = this.getContext();
40
+ const fragment = context.getFragment(node.name, node.loc);
41
+ const isServer = context.getSchema().isServerType(fragment.type);
42
+ return isServer ? node : null;
43
+ }
44
+
45
+ function visitClientExtension(
46
+ node: ClientExtension,
47
+ state: void,
48
+ ): ?ClientExtension {
49
+ return null;
50
+ }
51
+
52
+ module.exports = {
53
+ transform: skipClientExtensionTransform,
54
+ };
@@ -0,0 +1,44 @@
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 IRTransformer = require('../core/IRTransformer');
16
+
17
+ import type CompilerContext from '../core/CompilerContext';
18
+ import type {Field} from '../core/IR';
19
+
20
+ /**
21
+ * A transform that removes field `handles`. Intended for use when e.g.
22
+ * printing queries to send to a GraphQL server.
23
+ */
24
+ function skipHandleFieldTransform(context: CompilerContext): CompilerContext {
25
+ return IRTransformer.transform(context, {
26
+ LinkedField: visitField,
27
+ ScalarField: visitField,
28
+ });
29
+ }
30
+
31
+ function visitField<F: Field>(field: F): ?F {
32
+ const transformedNode = this.traverse(field);
33
+ if (transformedNode.handles) {
34
+ return {
35
+ ...transformedNode,
36
+ handles: null,
37
+ };
38
+ }
39
+ return transformedNode;
40
+ }
41
+
42
+ module.exports = {
43
+ transform: skipHandleFieldTransform,
44
+ };