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,477 @@
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
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const CodeMarker = require('../util/CodeMarker');
16
+
17
+ const argumentContainsVariables = require('../util/argumentContainsVariables');
18
+ const generateAbstractTypeRefinementKey = require('../util/generateAbstractTypeRefinementKey');
19
+
20
+ const {createCompilerError, createUserError} = require('../core/CompilerError');
21
+ const {getStorageKey, stableCopy} = require('relay-runtime');
22
+
23
+ import type {
24
+ Argument,
25
+ ArgumentValue,
26
+ ArgumentDefinition,
27
+ ClientExtension,
28
+ Defer,
29
+ Stream,
30
+ Metadata,
31
+ Fragment,
32
+ Selection,
33
+ Condition,
34
+ LinkedField,
35
+ ScalarField,
36
+ FragmentSpread,
37
+ InlineFragment,
38
+ ModuleImport,
39
+ InlineDataFragmentSpread,
40
+ } from '../core/IR';
41
+ import type {Schema, TypeID} from '../core/Schema';
42
+ import type {
43
+ ReaderArgument,
44
+ ReaderArgumentDefinition,
45
+ ReaderField,
46
+ ReaderFragment,
47
+ ReaderInlineDataFragmentSpread,
48
+ ReaderLinkedField,
49
+ ReaderModuleImport,
50
+ ReaderScalarField,
51
+ ReaderSelection,
52
+ } from 'relay-runtime';
53
+
54
+ /**
55
+ * @public
56
+ *
57
+ * Converts an IR node into a plain JS object representation that can be
58
+ * used at runtime.
59
+ */
60
+ function generate(schema: Schema, node: Fragment): ReaderFragment {
61
+ if (node == null) {
62
+ return node;
63
+ }
64
+
65
+ let metadata = null;
66
+ if (node.metadata != null) {
67
+ const {mask, plural, connection, refetch} = node.metadata;
68
+ if (Array.isArray(connection)) {
69
+ metadata = metadata ?? {};
70
+ metadata.connection = (connection: any);
71
+ }
72
+ if (typeof mask === 'boolean') {
73
+ metadata = metadata ?? {};
74
+ metadata.mask = mask;
75
+ }
76
+ if (plural === true) {
77
+ metadata = metadata ?? {};
78
+ metadata.plural = true;
79
+ }
80
+ if (refetch != null && typeof refetch === 'object') {
81
+ metadata = metadata ?? {};
82
+ metadata.refetch = {
83
+ connection: refetch.connection,
84
+ fragmentPathInResult: refetch.fragmentPathInResult,
85
+ operation: CodeMarker.moduleDependency(
86
+ // $FlowFixMe[unclear-addition]
87
+ refetch.operation + '.graphql',
88
+ ),
89
+ };
90
+ if (typeof refetch.identifierField === 'string') {
91
+ metadata.refetch = {
92
+ ...metadata.refetch,
93
+ identifierField: refetch.identifierField,
94
+ };
95
+ }
96
+ }
97
+ }
98
+ const rawType = schema.getRawType(node.type);
99
+ return {
100
+ argumentDefinitions: generateArgumentDefinitions(
101
+ schema,
102
+ node.argumentDefinitions,
103
+ ),
104
+ kind: 'Fragment',
105
+ // $FlowFixMe[incompatible-return]
106
+ metadata,
107
+ name: node.name,
108
+ selections: generateSelections(schema, node.selections),
109
+ type: schema.getTypeString(rawType),
110
+ abstractKey: schema.isAbstractType(rawType)
111
+ ? generateAbstractTypeRefinementKey(schema, rawType)
112
+ : null,
113
+ };
114
+ }
115
+
116
+ function generateSelections(
117
+ schema: Schema,
118
+ selections: $ReadOnlyArray<Selection>,
119
+ ): $ReadOnlyArray<ReaderSelection> {
120
+ return selections
121
+ .map(selection => {
122
+ switch (selection.kind) {
123
+ case 'ClientExtension':
124
+ return generateClientExtension(schema, selection);
125
+ case 'FragmentSpread':
126
+ return generateFragmentSpread(schema, selection);
127
+ case 'Condition':
128
+ return generateCondition(schema, selection);
129
+ case 'ScalarField':
130
+ // NOTE: The type discriminator is used only for the
131
+ // normalization ast.
132
+ const isTypeDiscriminator = selection.metadata?.abstractKey != null;
133
+ if (isTypeDiscriminator) {
134
+ return null;
135
+ }
136
+ return generateScalarField(schema, selection);
137
+ case 'ModuleImport':
138
+ return generateModuleImport(schema, selection);
139
+ case 'InlineDataFragmentSpread':
140
+ return generateInlineDataFragmentSpread(schema, selection);
141
+ case 'InlineFragment':
142
+ return generateInlineFragment(schema, selection);
143
+ case 'LinkedField':
144
+ return generateLinkedField(schema, selection);
145
+ case 'Defer':
146
+ return generateDefer(schema, selection);
147
+ case 'Stream':
148
+ return generateStream(schema, selection);
149
+ default:
150
+ (selection: empty);
151
+ throw new Error();
152
+ }
153
+ })
154
+ .filter(Boolean);
155
+ }
156
+
157
+ function generateArgumentDefinitions(
158
+ schema: Schema,
159
+ nodes: $ReadOnlyArray<ArgumentDefinition>,
160
+ ): $ReadOnlyArray<ReaderArgumentDefinition> {
161
+ return nodes
162
+ .map(node => {
163
+ switch (node.kind) {
164
+ case 'LocalArgumentDefinition':
165
+ return {
166
+ defaultValue: stableCopy(node.defaultValue),
167
+ kind: 'LocalArgument',
168
+ name: node.name,
169
+ };
170
+ case 'RootArgumentDefinition':
171
+ return {
172
+ kind: 'RootArgument',
173
+ name: node.name,
174
+ };
175
+ default:
176
+ throw new Error();
177
+ }
178
+ })
179
+ .sort((nodeA, nodeB) => {
180
+ if (nodeA.name > nodeB.name) {
181
+ return 1;
182
+ }
183
+ if (nodeA.name < nodeB.name) {
184
+ return -1;
185
+ }
186
+ return 0;
187
+ });
188
+ }
189
+
190
+ function generateClientExtension(
191
+ schema: Schema,
192
+ node: ClientExtension,
193
+ ): ReaderSelection {
194
+ return {
195
+ kind: 'ClientExtension',
196
+ selections: generateSelections(schema, node.selections),
197
+ };
198
+ }
199
+
200
+ function generateDefer(schema: Schema, node: Defer): ReaderSelection {
201
+ return {
202
+ kind: 'Defer',
203
+ selections: generateSelections(schema, node.selections),
204
+ };
205
+ }
206
+
207
+ function generateStream(schema: Schema, node: Stream): ReaderSelection {
208
+ return {
209
+ kind: 'Stream',
210
+ selections: generateSelections(schema, node.selections),
211
+ };
212
+ }
213
+
214
+ function generateCondition(schema: Schema, node: Condition): ReaderSelection {
215
+ if (node.condition.kind !== 'Variable') {
216
+ throw createCompilerError(
217
+ "ReaderCodeGenerator: Expected 'Condition' with static value to be " +
218
+ 'pruned or inlined',
219
+ [node.condition.loc],
220
+ );
221
+ }
222
+ return {
223
+ condition: node.condition.variableName,
224
+ kind: 'Condition',
225
+ passingValue: node.passingValue,
226
+ selections: generateSelections(schema, node.selections),
227
+ };
228
+ }
229
+
230
+ function generateFragmentSpread(
231
+ schema: Schema,
232
+ node: FragmentSpread,
233
+ ): ReaderSelection {
234
+ return {
235
+ args: generateArgs(node.args),
236
+ kind: 'FragmentSpread',
237
+ name: node.name,
238
+ };
239
+ }
240
+
241
+ function generateInlineFragment(
242
+ schema: Schema,
243
+ node: InlineFragment,
244
+ ): ReaderSelection {
245
+ const rawType = schema.getRawType(node.typeCondition);
246
+ return {
247
+ kind: 'InlineFragment',
248
+ selections: generateSelections(schema, node.selections),
249
+ type: schema.getTypeString(rawType),
250
+ abstractKey: schema.isAbstractType(rawType)
251
+ ? generateAbstractTypeRefinementKey(schema, rawType)
252
+ : null,
253
+ };
254
+ }
255
+
256
+ function generateInlineDataFragmentSpread(
257
+ schema: Schema,
258
+ node: InlineDataFragmentSpread,
259
+ ): ReaderInlineDataFragmentSpread {
260
+ return {
261
+ kind: 'InlineDataFragmentSpread',
262
+ name: node.name,
263
+ selections: generateSelections(schema, node.selections),
264
+ };
265
+ }
266
+
267
+ function generateLinkedField(
268
+ schema: Schema,
269
+ node: LinkedField,
270
+ ): ReaderLinkedField {
271
+ // Note: it is important that the arguments of this field be sorted to
272
+ // ensure stable generation of storage keys for equivalent arguments
273
+ // which may have originally appeared in different orders across an app.
274
+
275
+ // TODO(T37646905) enable this invariant after splitting the
276
+ // RelayCodeGenerator-test and running the FieldHandleTransform on
277
+ // Reader ASTs.
278
+ //
279
+ // invariant(
280
+ // node.handles == null,
281
+ // 'ReaderCodeGenerator: unexpected handles',
282
+ // );
283
+ const rawType = schema.getRawType(node.type);
284
+ let field: ReaderLinkedField = {
285
+ alias: node.alias === node.name ? null : node.alias,
286
+ args: generateArgs(node.args),
287
+ concreteType: !schema.isAbstractType(rawType)
288
+ ? schema.getTypeString(rawType)
289
+ : null,
290
+ kind: 'LinkedField',
291
+ name: node.name,
292
+ plural: isPlural(schema, node.type),
293
+ selections: generateSelections(schema, node.selections),
294
+ storageKey: null,
295
+ };
296
+ // Precompute storageKey if possible
297
+ const storageKey = getStaticStorageKey(field, node.metadata);
298
+ if (storageKey) {
299
+ field = {...field, storageKey};
300
+ }
301
+ return field;
302
+ }
303
+
304
+ function generateModuleImport(
305
+ schema: Schema,
306
+ node: ModuleImport,
307
+ ): ReaderModuleImport {
308
+ const fragmentName = node.name;
309
+ const regExpMatch = fragmentName.match(
310
+ /^([a-zA-Z][a-zA-Z0-9]*)(?:_([a-zA-Z][_a-zA-Z0-9]*))?$/,
311
+ );
312
+ if (!regExpMatch) {
313
+ throw createCompilerError(
314
+ 'ReaderCodeGenerator: @match fragments should be named ' +
315
+ `'FragmentName_propName', got '${fragmentName}'.`,
316
+ [node.loc],
317
+ );
318
+ }
319
+ const fragmentPropName = regExpMatch[2];
320
+ if (typeof fragmentPropName !== 'string') {
321
+ throw createCompilerError(
322
+ 'ReaderCodeGenerator: @module fragments should be named ' +
323
+ `'FragmentName_propName', got '${fragmentName}'.`,
324
+ [node.loc],
325
+ );
326
+ }
327
+ return {
328
+ documentName: node.key,
329
+ fragmentName,
330
+ fragmentPropName,
331
+ kind: 'ModuleImport',
332
+ };
333
+ }
334
+
335
+ function generateScalarField(
336
+ schema: Schema,
337
+ node: ScalarField,
338
+ ): ReaderScalarField {
339
+ // Note: it is important that the arguments of this field be sorted to
340
+ // ensure stable generation of storage keys for equivalent arguments
341
+ // which may have originally appeared in different orders across an app.
342
+
343
+ // TODO(T37646905) enable this invariant after splitting the
344
+ // RelayCodeGenerator-test and running the FieldHandleTransform on
345
+ // Reader ASTs.
346
+ //
347
+ // invariant(
348
+ // node.handles == null,
349
+ // 'ReaderCodeGenerator: unexpected handles',
350
+ // );
351
+
352
+ let field: ReaderScalarField = {
353
+ alias: node.alias === node.name ? null : node.alias,
354
+ args: generateArgs(node.args),
355
+ kind: 'ScalarField',
356
+ name: node.name,
357
+ storageKey: null,
358
+ };
359
+ // Precompute storageKey if possible
360
+ const storageKey = getStaticStorageKey(field, node.metadata);
361
+ if (storageKey) {
362
+ field = {...field, storageKey};
363
+ }
364
+ return field;
365
+ }
366
+
367
+ function generateArgument(
368
+ name: string,
369
+ value: ArgumentValue,
370
+ ): ReaderArgument | null {
371
+ switch (value.kind) {
372
+ case 'Variable':
373
+ return {
374
+ kind: 'Variable',
375
+ name: name,
376
+ variableName: value.variableName,
377
+ };
378
+ case 'Literal':
379
+ return value.value === null
380
+ ? null
381
+ : {
382
+ kind: 'Literal',
383
+ name: name,
384
+ value: stableCopy(value.value),
385
+ };
386
+ case 'ObjectValue': {
387
+ const objectKeys = value.fields.map(field => field.name).sort();
388
+ const objectValues = new Map(
389
+ value.fields.map(field => {
390
+ return [field.name, field.value];
391
+ }),
392
+ );
393
+ return {
394
+ fields: objectKeys.map(fieldName => {
395
+ const fieldValue = objectValues.get(fieldName);
396
+ if (fieldValue == null) {
397
+ throw createCompilerError('Expected to have object field value');
398
+ }
399
+ return (
400
+ generateArgument(fieldName, fieldValue) ?? {
401
+ kind: 'Literal',
402
+ name: fieldName,
403
+ value: null,
404
+ }
405
+ );
406
+ }),
407
+ kind: 'ObjectValue',
408
+ name: name,
409
+ };
410
+ }
411
+ case 'ListValue': {
412
+ return {
413
+ items: value.items.map((item, index) => {
414
+ return generateArgument(`${name}.${index}`, item);
415
+ }),
416
+ kind: 'ListValue',
417
+ name: name,
418
+ };
419
+ }
420
+ default:
421
+ throw createUserError(
422
+ 'ReaderCodeGenerator: Complex argument values (Lists or ' +
423
+ 'InputObjects with nested variables) are not supported.',
424
+ [value.loc],
425
+ );
426
+ }
427
+ }
428
+
429
+ function generateArgs(
430
+ args: $ReadOnlyArray<Argument>,
431
+ ): ?$ReadOnlyArray<ReaderArgument> {
432
+ const concreteArguments = [];
433
+ args.forEach(arg => {
434
+ const concreteArgument = generateArgument(arg.name, arg.value);
435
+ if (concreteArgument !== null) {
436
+ concreteArguments.push(concreteArgument);
437
+ }
438
+ });
439
+ return concreteArguments.length === 0
440
+ ? null
441
+ : concreteArguments.sort(nameComparator);
442
+ }
443
+
444
+ function nameComparator(
445
+ a: {+name: string, ...},
446
+ b: {+name: string, ...},
447
+ ): number {
448
+ return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
449
+ }
450
+
451
+ /**
452
+ * Pre-computes storage key if possible and advantageous. Storage keys are
453
+ * generated for fields with supplied arguments that are all statically known
454
+ * (ie. literals, no variables) at build time.
455
+ */
456
+ function getStaticStorageKey(field: ReaderField, metadata: Metadata): ?string {
457
+ const metadataStorageKey = metadata?.storageKey;
458
+ if (typeof metadataStorageKey === 'string') {
459
+ return metadataStorageKey;
460
+ }
461
+ if (
462
+ !field.args ||
463
+ field.args.length === 0 ||
464
+ field.args.some(argumentContainsVariables)
465
+ ) {
466
+ return null;
467
+ }
468
+ return getStorageKey(field, {});
469
+ }
470
+
471
+ function isPlural(schema: Schema, type: TypeID): boolean {
472
+ return schema.isList(schema.getNullableType(type));
473
+ }
474
+
475
+ module.exports = {
476
+ generate,
477
+ };
@@ -0,0 +1,85 @@
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 NormalizationCodeGenerator = require('./NormalizationCodeGenerator');
16
+ const ReaderCodeGenerator = require('./ReaderCodeGenerator');
17
+ const sortObjectByKey = require('./sortObjectByKey');
18
+ const md5 = require('../util/md5');
19
+ const nullthrows = require('nullthrows');
20
+ const {createCompilerError} = require('../core/CompilerError');
21
+
22
+ import type {Fragment, Request, SplitOperation} from '../core/IR';
23
+ import type {Schema} from '../core/Schema';
24
+ import type {
25
+ ConcreteRequest,
26
+ NormalizationSplitOperation,
27
+ ReaderFragment,
28
+ } from 'relay-runtime';
29
+
30
+ /**
31
+ * @public
32
+ *
33
+ * Converts an IR node into a plain JS object representation that can be
34
+ * used at runtime.
35
+ */
36
+ declare function generate(schema: Schema, node: Fragment): ReaderFragment;
37
+ declare function generate(schema: Schema, node: Request): ConcreteRequest;
38
+ declare function generate(
39
+ schema: Schema,
40
+ node: SplitOperation,
41
+ ): NormalizationSplitOperation;
42
+ function generate(
43
+ schema: Schema,
44
+ node: Fragment | Request | SplitOperation,
45
+ ): $FlowFixMe {
46
+ switch (node.kind) {
47
+ case 'Fragment':
48
+ if (node.metadata?.inlineData === true) {
49
+ return {
50
+ kind: 'InlineDataFragment',
51
+ name: node.name,
52
+ };
53
+ }
54
+ return ReaderCodeGenerator.generate(schema, node);
55
+ case 'Request':
56
+ return {
57
+ fragment: ReaderCodeGenerator.generate(schema, node.fragment),
58
+ kind: 'Request',
59
+ operation: NormalizationCodeGenerator.generate(schema, node.root),
60
+ params:
61
+ node.id != null
62
+ ? {
63
+ id: node.id,
64
+ metadata: sortObjectByKey(node.metadata),
65
+ name: node.name,
66
+ operationKind: node.root.operation,
67
+ }
68
+ : {
69
+ cacheID: md5(nullthrows(node.text)),
70
+ metadata: sortObjectByKey(node.metadata),
71
+ name: node.name,
72
+ operationKind: node.root.operation,
73
+ text: node.text,
74
+ },
75
+ };
76
+ case 'SplitOperation':
77
+ return NormalizationCodeGenerator.generate(schema, node);
78
+ }
79
+ throw createCompilerError(
80
+ `RelayCodeGenerator: Unknown AST kind '${node.kind}'.`,
81
+ [node.loc],
82
+ );
83
+ }
84
+
85
+ module.exports = {generate};