@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,189 @@
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 SchemaUtils = require('../../core/SchemaUtils');
16
+
17
+ const {createUserError} = require('../../core/CompilerError');
18
+ const {
19
+ buildFragmentSpread,
20
+ buildOperationArgumentDefinitions,
21
+ } = require('./utils');
22
+
23
+ import type {Fragment} from '../../core/IR';
24
+ import type {Schema} from '../../core/Schema';
25
+ import type {QueryGenerator, RefetchRoot} from '.';
26
+
27
+ function buildRefetchOperation(
28
+ schema: Schema,
29
+ fragment: Fragment,
30
+ queryName: string,
31
+ ): ?RefetchRoot {
32
+ let fetchableIdentifierField = null;
33
+ if (schema.isObject(fragment.type)) {
34
+ const objectType = schema.assertObjectType(fragment.type);
35
+ fetchableIdentifierField = schema.getFetchableFieldName(objectType);
36
+ }
37
+ if (fetchableIdentifierField == null) {
38
+ return null;
39
+ }
40
+ const identifierField = schema.getFieldConfig(
41
+ schema.expectField(fragment.type, fetchableIdentifierField),
42
+ );
43
+ if (!schema.isId(schema.getRawType(identifierField.type))) {
44
+ const typeName = schema.getTypeString(fragment.type);
45
+ throw createUserError(
46
+ `Invalid use of @refetchable on fragment '${fragment.name}', the type ` +
47
+ `'${typeName}' is @fetchable but the identifying field '${fetchableIdentifierField}' ` +
48
+ "does not have type 'ID'.",
49
+ [fragment.loc],
50
+ );
51
+ }
52
+
53
+ const queryType = schema.expectQueryType();
54
+ const fetchFieldName = `fetch__${schema.getTypeString(fragment.type)}`;
55
+ const fetchField = schema.getFieldConfig(
56
+ schema.expectField(queryType, fetchFieldName),
57
+ );
58
+ if (
59
+ !(
60
+ fetchField != null &&
61
+ schema.isObject(fetchField.type) &&
62
+ schema.areEqualTypes(fetchField.type, fragment.type) &&
63
+ schema.areEqualTypes(
64
+ schema.getNullableType(fetchField.args[0].type),
65
+ schema.expectIdType(),
66
+ )
67
+ )
68
+ ) {
69
+ const typeName = schema.getTypeString(fragment.type);
70
+ throw createUserError(
71
+ `Invalid use of @refetchable on fragment '${fragment.name}', the type ` +
72
+ `'${typeName}' is @fetchable but there is no corresponding '${fetchFieldName}'` +
73
+ `field or it is invalid (expected '${fetchFieldName}(id: ID!): ${typeName}').`,
74
+ [fragment.loc],
75
+ );
76
+ }
77
+
78
+ // name and type of the node(_: ID) field parameter
79
+ const idArgName = fetchField.args[0].name;
80
+ const idArgType = fetchField.args[0].type;
81
+ // name and type of the query variable
82
+ const idVariableType = SchemaUtils.getNonNullIdInput(schema);
83
+ const idVariableName = 'id';
84
+
85
+ const argumentDefinitions = buildOperationArgumentDefinitions(
86
+ fragment.argumentDefinitions,
87
+ );
88
+ const idArgument = argumentDefinitions.find(
89
+ argDef => argDef.name === idVariableName,
90
+ );
91
+ if (idArgument != null) {
92
+ throw createUserError(
93
+ `Invalid use of @refetchable on fragment \`${fragment.name}\`, this ` +
94
+ 'fragment already has an `$id` variable in scope.',
95
+ [idArgument.loc],
96
+ );
97
+ }
98
+ const argumentDefinitionsWithId = [
99
+ ...argumentDefinitions,
100
+ {
101
+ defaultValue: null,
102
+ kind: 'LocalArgumentDefinition',
103
+ loc: {kind: 'Derived', source: fragment.loc},
104
+ name: idVariableName,
105
+ type: idVariableType,
106
+ },
107
+ ];
108
+ return {
109
+ identifierField: fetchableIdentifierField,
110
+ path: [fetchFieldName],
111
+ node: {
112
+ argumentDefinitions: argumentDefinitionsWithId,
113
+ directives: [],
114
+ kind: 'Root',
115
+ loc: {kind: 'Derived', source: fragment.loc},
116
+ metadata: null,
117
+ name: queryName,
118
+ operation: 'query',
119
+ selections: [
120
+ {
121
+ alias: fetchFieldName,
122
+ args: [
123
+ {
124
+ kind: 'Argument',
125
+ loc: {kind: 'Derived', source: fragment.loc},
126
+ name: idArgName,
127
+ type: schema.assertInputType(idArgType),
128
+ value: {
129
+ kind: 'Variable',
130
+ loc: {kind: 'Derived', source: fragment.loc},
131
+ variableName: idVariableName,
132
+ type: idVariableType,
133
+ },
134
+ },
135
+ ],
136
+ connection: false,
137
+ directives: [],
138
+ handles: null,
139
+ kind: 'LinkedField',
140
+ loc: {kind: 'Derived', source: fragment.loc},
141
+ metadata: null,
142
+ name: fetchFieldName,
143
+ selections: [buildFragmentSpread(fragment)],
144
+ type: fragment.type,
145
+ },
146
+ ],
147
+ type: queryType,
148
+ },
149
+ transformedFragment: enforceIDField(
150
+ schema,
151
+ fragment,
152
+ fetchableIdentifierField,
153
+ ),
154
+ };
155
+ }
156
+
157
+ function enforceIDField(
158
+ schema: Schema,
159
+ fragment: Fragment,
160
+ fetchableIdentifierField: string,
161
+ ): Fragment {
162
+ const idSelection = fragment.selections.find(
163
+ selection =>
164
+ selection.kind === 'ScalarField' &&
165
+ selection.name === fetchableIdentifierField &&
166
+ selection.alias === fetchableIdentifierField &&
167
+ schema.areEqualTypes(
168
+ schema.getNullableType(selection.type),
169
+ schema.expectIdType(),
170
+ ),
171
+ );
172
+ if (idSelection) {
173
+ return fragment;
174
+ }
175
+ const idField = SchemaUtils.generateIDField(schema, fragment.type);
176
+ // idField is uniquely owned here, safe to mutate
177
+ (idField: $FlowFixMe).alias = fetchableIdentifierField;
178
+ // idField is uniquely owned here, safe to mutate
179
+ (idField: $FlowFixMe).name = fetchableIdentifierField;
180
+ return {
181
+ ...fragment,
182
+ selections: [...fragment.selections, idField],
183
+ };
184
+ }
185
+
186
+ module.exports = ({
187
+ description: '@fetchable types',
188
+ buildRefetchOperation,
189
+ }: QueryGenerator);
@@ -0,0 +1,219 @@
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 SchemaUtils = require('../../core/SchemaUtils');
16
+
17
+ const nullthrows = require('nullthrows');
18
+
19
+ const {createUserError} = require('../../core/CompilerError');
20
+ const {
21
+ buildFragmentSpread,
22
+ buildOperationArgumentDefinitions,
23
+ } = require('./utils');
24
+
25
+ import type {Fragment} from '../../core/IR';
26
+ import type {Schema} from '../../core/Schema';
27
+ import type {QueryGenerator, RefetchRoot} from '.';
28
+
29
+ const NODE_TYPE_NAME = 'Node';
30
+ const NODE_FIELD_NAME = 'node';
31
+
32
+ function buildRefetchOperation(
33
+ schema: Schema,
34
+ fragment: Fragment,
35
+ queryName: string,
36
+ ): ?RefetchRoot {
37
+ const eligible =
38
+ schema.getTypeString(fragment.type) === NODE_TYPE_NAME ||
39
+ (schema.isObject(fragment.type) &&
40
+ schema
41
+ .getInterfaces(schema.assertCompositeType(fragment.type))
42
+ .some(interfaceType =>
43
+ schema.areEqualTypes(
44
+ interfaceType,
45
+ schema.expectTypeFromString(NODE_TYPE_NAME),
46
+ ),
47
+ )) ||
48
+ (schema.isAbstractType(fragment.type) &&
49
+ Array.from(
50
+ schema.getPossibleTypes(schema.assertAbstractType(fragment.type)),
51
+ ).every(possibleType =>
52
+ schema.implementsInterface(
53
+ schema.assertCompositeType(possibleType),
54
+ schema.assertInterfaceType(
55
+ schema.expectTypeFromString(NODE_TYPE_NAME),
56
+ ),
57
+ ),
58
+ ));
59
+ if (!eligible) {
60
+ return null;
61
+ }
62
+
63
+ const queryType = schema.expectQueryType();
64
+ const nodeType = schema.getTypeFromString(NODE_TYPE_NAME);
65
+ const nodeField = schema.getFieldConfig(
66
+ schema.expectField(queryType, NODE_FIELD_NAME),
67
+ );
68
+ if (
69
+ !(
70
+ nodeType &&
71
+ schema.isInterface(nodeType) &&
72
+ schema.isInterface(nodeField.type) &&
73
+ schema.areEqualTypes(nodeField.type, nodeType) &&
74
+ nodeField.args.length === 1 &&
75
+ schema.areEqualTypes(
76
+ schema.getNullableType(nodeField.args[0].type),
77
+ schema.expectIdType(),
78
+ ) &&
79
+ // the fragment must be on Node or on a type that implements Node
80
+ ((schema.isObject(fragment.type) &&
81
+ schema
82
+ .getInterfaces(schema.assertCompositeType(fragment.type))
83
+ .some(interfaceType =>
84
+ schema.areEqualTypes(interfaceType, nodeType),
85
+ )) ||
86
+ (schema.isAbstractType(fragment.type) &&
87
+ Array.from(
88
+ schema.getPossibleTypes(schema.assertAbstractType(fragment.type)),
89
+ ).every(possibleType =>
90
+ schema
91
+ .getInterfaces(schema.assertCompositeType(possibleType))
92
+ .some(interfaceType =>
93
+ schema.areEqualTypes(interfaceType, nodeType),
94
+ ),
95
+ )))
96
+ )
97
+ ) {
98
+ throw createUserError(
99
+ `Invalid use of @refetchable on fragment '${fragment.name}', check ` +
100
+ 'that your schema defines a `Node { id: ID }` interface and has a ' +
101
+ '`node(id: ID): Node` field on the query type (the id argument may ' +
102
+ 'also be non-null).',
103
+ [fragment.loc],
104
+ );
105
+ }
106
+
107
+ // name and type of the node(_: ID) field parameter
108
+ const idArgName = nodeField.args[0].name;
109
+ const idArgType = nodeField.args[0].type;
110
+ // name and type of the query variable
111
+ const idVariableType = SchemaUtils.getNonNullIdInput(schema);
112
+ const idVariableName = 'id';
113
+
114
+ const argumentDefinitions = buildOperationArgumentDefinitions(
115
+ fragment.argumentDefinitions,
116
+ );
117
+ const idArgument = argumentDefinitions.find(
118
+ argDef => argDef.name === idVariableName,
119
+ );
120
+ if (idArgument != null) {
121
+ throw createUserError(
122
+ `Invalid use of @refetchable on fragment \`${fragment.name}\`, this ` +
123
+ 'fragment already has an `$id` variable in scope.',
124
+ [idArgument.loc],
125
+ );
126
+ }
127
+ const argumentDefinitionsWithId = [
128
+ ...argumentDefinitions,
129
+ {
130
+ defaultValue: null,
131
+ kind: 'LocalArgumentDefinition',
132
+ loc: {kind: 'Derived', source: fragment.loc},
133
+ name: idVariableName,
134
+ type: idVariableType,
135
+ },
136
+ ];
137
+ return {
138
+ identifierField: 'id',
139
+ path: [NODE_FIELD_NAME],
140
+ node: {
141
+ argumentDefinitions: argumentDefinitionsWithId,
142
+ directives: [],
143
+ kind: 'Root',
144
+ loc: {kind: 'Derived', source: fragment.loc},
145
+ metadata: null,
146
+ name: queryName,
147
+ operation: 'query',
148
+ selections: [
149
+ {
150
+ alias: NODE_FIELD_NAME,
151
+ args: [
152
+ {
153
+ kind: 'Argument',
154
+ loc: {kind: 'Derived', source: fragment.loc},
155
+ name: idArgName,
156
+ type: schema.assertInputType(idArgType),
157
+ value: {
158
+ kind: 'Variable',
159
+ loc: {kind: 'Derived', source: fragment.loc},
160
+ variableName: idVariableName,
161
+ type: idVariableType,
162
+ },
163
+ },
164
+ ],
165
+ connection: false,
166
+ directives: [],
167
+ handles: null,
168
+ kind: 'LinkedField',
169
+ loc: {kind: 'Derived', source: fragment.loc},
170
+ metadata: null,
171
+ name: NODE_FIELD_NAME,
172
+ selections: [buildFragmentSpread(fragment)],
173
+ type: schema.assertLinkedFieldType(nodeType),
174
+ },
175
+ ],
176
+ type: queryType,
177
+ },
178
+ transformedFragment: enforceIDField(schema, fragment),
179
+ };
180
+ }
181
+
182
+ function enforceIDField(schema: Schema, fragment: Fragment): Fragment {
183
+ const idSelection = fragment.selections.find(
184
+ selection =>
185
+ selection.kind === 'ScalarField' &&
186
+ selection.name === 'id' &&
187
+ selection.alias === 'id' &&
188
+ schema.areEqualTypes(
189
+ schema.getNullableType(selection.type),
190
+ schema.expectIdType(),
191
+ ),
192
+ );
193
+ if (idSelection) {
194
+ return fragment;
195
+ }
196
+ const idField = schema.getFieldByName(fragment.type, 'id');
197
+ const nodeType = schema.assertCompositeType(
198
+ nullthrows(schema.getTypeFromString(NODE_TYPE_NAME)),
199
+ );
200
+ const generatedIDSelection = idField
201
+ ? SchemaUtils.generateIDField(schema, fragment.type)
202
+ : {
203
+ kind: 'InlineFragment',
204
+ directives: [],
205
+ loc: {kind: 'Generated'},
206
+ metadata: null,
207
+ selections: [SchemaUtils.generateIDField(schema, nodeType)],
208
+ typeCondition: nodeType,
209
+ };
210
+ return {
211
+ ...fragment,
212
+ selections: [...fragment.selections, generatedIDSelection],
213
+ };
214
+ }
215
+
216
+ module.exports = ({
217
+ description: 'the Node interface or types implementing the Node interface',
218
+ buildRefetchOperation,
219
+ }: QueryGenerator);
@@ -0,0 +1,57 @@
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 {
16
+ buildFragmentSpread,
17
+ buildOperationArgumentDefinitions,
18
+ } = require('./utils');
19
+
20
+ import type {Fragment} from '../../core/IR';
21
+ import type {Schema} from '../../core/Schema';
22
+ import type {QueryGenerator, RefetchRoot} from '.';
23
+
24
+ function buildRefetchOperation(
25
+ schema: Schema,
26
+ fragment: Fragment,
27
+ queryName: string,
28
+ ): ?RefetchRoot {
29
+ const queryType = schema.expectQueryType();
30
+ if (!schema.areEqualTypes(fragment.type, queryType)) {
31
+ return null;
32
+ }
33
+
34
+ return {
35
+ identifierField: null,
36
+ path: [],
37
+ node: {
38
+ argumentDefinitions: buildOperationArgumentDefinitions(
39
+ fragment.argumentDefinitions,
40
+ ),
41
+ directives: [],
42
+ kind: 'Root',
43
+ loc: {kind: 'Derived', source: fragment.loc},
44
+ metadata: null,
45
+ name: queryName,
46
+ operation: 'query',
47
+ selections: [buildFragmentSpread(fragment)],
48
+ type: queryType,
49
+ },
50
+ transformedFragment: fragment,
51
+ };
52
+ }
53
+
54
+ module.exports = ({
55
+ description: 'the Query type',
56
+ buildRefetchOperation,
57
+ }: QueryGenerator);
@@ -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 {createUserError} = require('../../core/CompilerError');
16
+ const {
17
+ buildFragmentSpread,
18
+ buildOperationArgumentDefinitions,
19
+ } = require('./utils');
20
+
21
+ import type {Fragment} from '../../core/IR';
22
+ import type {Schema} from '../../core/Schema';
23
+ import type {QueryGenerator, RefetchRoot} from '.';
24
+
25
+ const VIEWER_TYPE_NAME = 'Viewer';
26
+ const VIEWER_FIELD_NAME = 'viewer';
27
+
28
+ function buildRefetchOperation(
29
+ schema: Schema,
30
+ fragment: Fragment,
31
+ queryName: string,
32
+ ): ?RefetchRoot {
33
+ if (schema.getTypeString(fragment.type) !== VIEWER_TYPE_NAME) {
34
+ return null;
35
+ }
36
+ // Handle fragments on viewer
37
+ const queryType = schema.expectQueryType();
38
+ const viewerType = schema.getTypeFromString(VIEWER_TYPE_NAME);
39
+ const viewerField = schema.getFieldConfig(
40
+ schema.expectField(queryType, VIEWER_FIELD_NAME),
41
+ );
42
+ const viewerFieldType = schema.getNullableType(viewerField.type);
43
+ if (
44
+ !(
45
+ viewerType &&
46
+ schema.isObject(viewerType) &&
47
+ schema.isObject(viewerFieldType) &&
48
+ schema.areEqualTypes(viewerFieldType, viewerType) &&
49
+ viewerField.args.length === 0 &&
50
+ schema.areEqualTypes(fragment.type, viewerType)
51
+ )
52
+ ) {
53
+ throw createUserError(
54
+ `Invalid use of @refetchable on fragment '${fragment.name}', check ` +
55
+ "that your schema defines a 'Viewer' object type and has a " +
56
+ "'viewer: Viewer' field on the query type.",
57
+ [fragment.loc],
58
+ );
59
+ }
60
+ return {
61
+ identifierField: null,
62
+ path: [VIEWER_FIELD_NAME],
63
+ node: {
64
+ argumentDefinitions: buildOperationArgumentDefinitions(
65
+ fragment.argumentDefinitions,
66
+ ),
67
+ directives: [],
68
+ kind: 'Root',
69
+ loc: {kind: 'Derived', source: fragment.loc},
70
+ metadata: null,
71
+ name: queryName,
72
+ operation: 'query',
73
+ selections: [
74
+ {
75
+ alias: VIEWER_FIELD_NAME,
76
+ args: [],
77
+ connection: false,
78
+ directives: [],
79
+ handles: null,
80
+ kind: 'LinkedField',
81
+ loc: {kind: 'Derived', source: fragment.loc},
82
+ metadata: null,
83
+ name: VIEWER_FIELD_NAME,
84
+ selections: [buildFragmentSpread(fragment)],
85
+ type: schema.assertLinkedFieldType(viewerField.type),
86
+ },
87
+ ],
88
+ type: queryType,
89
+ },
90
+ transformedFragment: fragment,
91
+ };
92
+ }
93
+
94
+ module.exports = ({
95
+ description: 'the Viewer type',
96
+ buildRefetchOperation,
97
+ }: QueryGenerator);
@@ -0,0 +1,90 @@
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 FetchableQueryGenerator = require('./FetchableQueryGenerator');
16
+ const NodeQueryGenerator = require('./NodeQueryGenerator');
17
+ const QueryQueryGenerator = require('./QueryQueryGenerator');
18
+ const ViewerQueryGenerator = require('./ViewerQueryGenerator');
19
+
20
+ const {createUserError} = require('../../core/CompilerError');
21
+
22
+ import type {Fragment, Root} from '../../core/IR';
23
+ import type {Schema} from '../../core/Schema';
24
+
25
+ export type RefetchRoot = {|
26
+ identifierField: ?string,
27
+ path: $ReadOnlyArray<string>,
28
+ node: Root,
29
+ transformedFragment: Fragment,
30
+ |};
31
+
32
+ /**
33
+ * A strategy to generate queries for a given fragment. Multiple stategies
34
+ * can be tried, such as generating a `node(id: ID)` query or a query directly
35
+ * on the root query type.
36
+ */
37
+ export type QueryGenerator = {|
38
+ /**
39
+ * Used to describe what fragments this QueryGenerator applies to, used in
40
+ * error messages.
41
+ */
42
+ +description: string,
43
+ /**
44
+ * Returns RefetchRoot or null if not applicable. Might throw a user error
45
+ * for an invalid schema or other problems.
46
+ */
47
+ +buildRefetchOperation: (
48
+ schema: Schema,
49
+ fragment: Fragment,
50
+ queryName: string,
51
+ ) => ?RefetchRoot,
52
+ |};
53
+
54
+ const GENERATORS = [
55
+ ViewerQueryGenerator,
56
+ QueryQueryGenerator,
57
+ NodeQueryGenerator,
58
+ FetchableQueryGenerator,
59
+ ];
60
+
61
+ /**
62
+ * Builds a query to refetch the given fragment or throws if we have not way to
63
+ * generate one.
64
+ */
65
+ function buildRefetchOperation(
66
+ schema: Schema,
67
+ fragment: Fragment,
68
+ queryName: string,
69
+ ): RefetchRoot {
70
+ for (const generator of GENERATORS) {
71
+ const refetchRoot = generator.buildRefetchOperation(
72
+ schema,
73
+ fragment,
74
+ queryName,
75
+ );
76
+ if (refetchRoot != null) {
77
+ return refetchRoot;
78
+ }
79
+ }
80
+ throw createUserError(
81
+ `Invalid use of @refetchable on fragment '${fragment.name}', only ` +
82
+ 'supported are fragments on:\n' +
83
+ GENERATORS.map(generator => ` - ${generator.description}`).join('\n'),
84
+ [fragment.loc],
85
+ );
86
+ }
87
+
88
+ module.exports = {
89
+ buildRefetchOperation,
90
+ };