relay-compiler 9.0.0 → 10.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (217) 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 +3862 -2505
  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 +571 -0
  10. package/codegen/ReaderCodeGenerator.js.flow +512 -0
  11. package/codegen/RelayCodeGenerator.js.flow +85 -0
  12. package/codegen/RelayFileWriter.js.flow +367 -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 +74 -0
  19. package/core/ASTConvert.js.flow +233 -0
  20. package/core/CompilerContext.js.flow +191 -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 +326 -0
  27. package/core/IRPrinter.js.flow +477 -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 +138 -0
  36. package/core/RelayParser.js.flow +1731 -0
  37. package/core/RelaySourceModuleParser.js.flow +135 -0
  38. package/core/Schema.js.flow +2037 -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 +137 -0
  51. package/language/javascript/RelayFlowBabelFactories.js.flow +176 -0
  52. package/language/javascript/RelayFlowGenerator.js.flow +1099 -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 +10 -0
  57. package/lib/bin/RelayCompilerMain.js +127 -130
  58. package/lib/codegen/CodegenDirectory.js +2 -6
  59. package/lib/codegen/CodegenRunner.js +37 -76
  60. package/lib/codegen/CodegenWatcher.js +13 -21
  61. package/lib/codegen/NormalizationCodeGenerator.js +131 -50
  62. package/lib/codegen/ReaderCodeGenerator.js +116 -49
  63. package/lib/codegen/RelayCodeGenerator.js +17 -6
  64. package/lib/codegen/RelayFileWriter.js +15 -37
  65. package/lib/codegen/compileRelayArtifacts.js +16 -30
  66. package/lib/codegen/sortObjectByKey.js +43 -0
  67. package/lib/codegen/writeRelayGeneratedFile.js +86 -96
  68. package/lib/core/ASTCache.js +3 -4
  69. package/lib/core/CompilerContext.js +3 -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 +16 -21
  75. package/lib/core/IRTransformer.js +8 -6
  76. package/lib/core/IRValidator.js +1 -3
  77. package/lib/core/RelayCompilerScope.js +4 -4
  78. package/lib/core/RelayGraphQLEnumsGenerator.js +12 -15
  79. package/lib/core/RelayIRTransforms.js +23 -13
  80. package/lib/core/RelayParser.js +53 -89
  81. package/lib/core/RelaySourceModuleParser.js +1 -3
  82. package/lib/core/Schema.js +106 -77
  83. package/lib/core/SchemaUtils.js +15 -1
  84. package/lib/core/getFieldDefinition.js +12 -15
  85. package/lib/core/getIdentifierForSelection.js +1 -1
  86. package/lib/core/inferRootArgumentDefinitions.js +27 -36
  87. package/lib/index.js +1 -3
  88. package/lib/language/javascript/FindGraphQLTags.js +7 -72
  89. package/lib/language/javascript/RelayFlowBabelFactories.js +5 -5
  90. package/lib/language/javascript/RelayFlowGenerator.js +131 -108
  91. package/lib/language/javascript/RelayFlowTypeTransformers.js +1 -3
  92. package/lib/reporters/ConsoleReporter.js +1 -3
  93. package/lib/reporters/MultiReporter.js +1 -3
  94. package/lib/runner/Artifacts.js +69 -170
  95. package/lib/runner/BufferedFilesystem.js +32 -66
  96. package/lib/runner/GraphQLASTNodeGroup.js +54 -120
  97. package/lib/runner/GraphQLNodeMap.js +14 -19
  98. package/lib/runner/Sources.js +70 -85
  99. package/lib/runner/StrictMap.js +21 -37
  100. package/lib/runner/getChangedNodeNames.js +30 -62
  101. package/lib/transforms/ApplyFragmentArgumentTransform.js +71 -31
  102. package/lib/transforms/ClientExtensionsTransform.js +15 -15
  103. package/lib/transforms/ConnectionTransform.js +26 -38
  104. package/lib/transforms/DeclarativeConnectionMutationTransform.js +225 -0
  105. package/lib/transforms/DeferStreamTransform.js +27 -17
  106. package/lib/transforms/DisallowTypenameOnRoot.js +55 -0
  107. package/lib/transforms/FieldHandleTransform.js +7 -3
  108. package/lib/transforms/FilterCompilerDirectivesTransform.js +29 -0
  109. package/lib/transforms/FlattenTransform.js +23 -19
  110. package/lib/transforms/GenerateIDFieldTransform.js +56 -35
  111. package/lib/transforms/GenerateTypeNameTransform.js +84 -10
  112. package/lib/transforms/InlineDataFragmentTransform.js +9 -4
  113. package/lib/transforms/MaskTransform.js +17 -17
  114. package/lib/transforms/MatchTransform.js +114 -32
  115. package/lib/transforms/ReactFlightComponentTransform.js +162 -0
  116. package/lib/transforms/RefetchableFragmentTransform.js +21 -17
  117. package/lib/transforms/RelayDirectiveTransform.js +8 -3
  118. package/lib/transforms/RequiredFieldTransform.js +380 -0
  119. package/lib/transforms/SkipClientExtensionsTransform.js +8 -0
  120. package/lib/transforms/SkipHandleFieldTransform.js +6 -2
  121. package/lib/transforms/SkipRedundantNodesTransform.js +9 -2
  122. package/lib/transforms/SkipSplitOperationTransform.js +32 -0
  123. package/lib/transforms/SkipUnreachableNodeTransform.js +9 -2
  124. package/lib/transforms/SkipUnusedVariablesTransform.js +18 -17
  125. package/lib/transforms/SplitModuleImportTransform.js +2 -2
  126. package/lib/transforms/TestOperationTransform.js +26 -20
  127. package/lib/transforms/ValidateGlobalVariablesTransform.js +18 -30
  128. package/lib/transforms/ValidateRequiredArgumentsTransform.js +12 -15
  129. package/lib/transforms/ValidateServerOnlyDirectivesTransform.js +16 -30
  130. package/lib/transforms/ValidateUnusedVariablesTransform.js +18 -30
  131. package/lib/transforms/query-generators/FetchableQueryGenerator.js +161 -0
  132. package/lib/transforms/query-generators/NodeQueryGenerator.js +22 -3
  133. package/lib/transforms/query-generators/QueryQueryGenerator.js +2 -1
  134. package/lib/transforms/query-generators/ViewerQueryGenerator.js +1 -0
  135. package/lib/transforms/query-generators/index.js +23 -6
  136. package/lib/transforms/query-generators/utils.js +17 -16
  137. package/lib/util/RelayCompilerCache.js +2 -4
  138. package/lib/util/argumentContainsVariables.js +37 -0
  139. package/lib/util/dedupeJSONStringify.js +15 -12
  140. package/lib/util/generateAbstractTypeRefinementKey.js +24 -0
  141. package/lib/util/getModuleName.js +1 -1
  142. package/lib/util/joinArgumentDefinitions.js +3 -1
  143. package/package.json +7 -7
  144. package/relay-compiler.js +4 -4
  145. package/relay-compiler.min.js +4 -4
  146. package/reporters/ConsoleReporter.js.flow +81 -0
  147. package/reporters/MultiReporter.js.flow +43 -0
  148. package/reporters/Reporter.js.flow +19 -0
  149. package/runner/Artifacts.js.flow +219 -0
  150. package/runner/BufferedFilesystem.js.flow +194 -0
  151. package/runner/GraphQLASTNodeGroup.js.flow +176 -0
  152. package/runner/GraphQLASTUtils.js.flow +26 -0
  153. package/runner/GraphQLNodeMap.js.flow +55 -0
  154. package/runner/Sources.js.flow +228 -0
  155. package/runner/StrictMap.js.flow +96 -0
  156. package/runner/compileArtifacts.js.flow +76 -0
  157. package/runner/extractAST.js.flow +100 -0
  158. package/runner/getChangedNodeNames.js.flow +48 -0
  159. package/runner/getSchemaInstance.js.flow +36 -0
  160. package/runner/types.js.flow +37 -0
  161. package/transforms/ApplyFragmentArgumentTransform.js.flow +526 -0
  162. package/transforms/ClientExtensionsTransform.js.flow +224 -0
  163. package/transforms/ConnectionTransform.js.flow +855 -0
  164. package/transforms/DeclarativeConnectionMutationTransform.js.flow +246 -0
  165. package/transforms/DeferStreamTransform.js.flow +265 -0
  166. package/transforms/DisallowIdAsAlias.js.flow +47 -0
  167. package/transforms/DisallowTypenameOnRoot.js.flow +45 -0
  168. package/transforms/FieldHandleTransform.js.flow +79 -0
  169. package/transforms/FilterCompilerDirectivesTransform.js.flow +33 -0
  170. package/transforms/FilterDirectivesTransform.js.flow +45 -0
  171. package/transforms/FlattenTransform.js.flow +454 -0
  172. package/transforms/GenerateIDFieldTransform.js.flow +152 -0
  173. package/transforms/GenerateTypeNameTransform.js.flow +161 -0
  174. package/transforms/InlineDataFragmentTransform.js.flow +125 -0
  175. package/transforms/InlineFragmentsTransform.js.flow +71 -0
  176. package/transforms/MaskTransform.js.flow +126 -0
  177. package/transforms/MatchTransform.js.flow +589 -0
  178. package/transforms/ReactFlightComponentTransform.js.flow +195 -0
  179. package/transforms/RefetchableFragmentTransform.js.flow +272 -0
  180. package/transforms/RelayDirectiveTransform.js.flow +97 -0
  181. package/transforms/RequiredFieldTransform.js.flow +415 -0
  182. package/transforms/SkipClientExtensionsTransform.js.flow +54 -0
  183. package/transforms/SkipHandleFieldTransform.js.flow +44 -0
  184. package/transforms/SkipRedundantNodesTransform.js.flow +257 -0
  185. package/transforms/SkipSplitOperationTransform.js.flow +37 -0
  186. package/transforms/SkipUnreachableNodeTransform.js.flow +149 -0
  187. package/transforms/SkipUnusedVariablesTransform.js.flow +59 -0
  188. package/transforms/SplitModuleImportTransform.js.flow +98 -0
  189. package/transforms/TestOperationTransform.js.flow +142 -0
  190. package/transforms/TransformUtils.js.flow +26 -0
  191. package/transforms/ValidateGlobalVariablesTransform.js.flow +81 -0
  192. package/transforms/ValidateRequiredArgumentsTransform.js.flow +127 -0
  193. package/transforms/ValidateServerOnlyDirectivesTransform.js.flow +112 -0
  194. package/transforms/ValidateUnusedVariablesTransform.js.flow +89 -0
  195. package/transforms/query-generators/FetchableQueryGenerator.js.flow +189 -0
  196. package/transforms/query-generators/NodeQueryGenerator.js.flow +219 -0
  197. package/transforms/query-generators/QueryQueryGenerator.js.flow +57 -0
  198. package/transforms/query-generators/ViewerQueryGenerator.js.flow +97 -0
  199. package/transforms/query-generators/index.js.flow +90 -0
  200. package/transforms/query-generators/utils.js.flow +76 -0
  201. package/util/CodeMarker.js.flow +79 -0
  202. package/util/DefaultHandleKey.js.flow +17 -0
  203. package/util/RelayCompilerCache.js.flow +88 -0
  204. package/util/Rollout.js.flow +39 -0
  205. package/util/TimeReporter.js.flow +79 -0
  206. package/util/areEqualOSS.js.flow +123 -0
  207. package/util/argumentContainsVariables.js.flow +38 -0
  208. package/util/dedupeJSONStringify.js.flow +152 -0
  209. package/util/generateAbstractTypeRefinementKey.js.flow +29 -0
  210. package/util/getDefinitionNodeHash.js.flow +25 -0
  211. package/util/getModuleName.js.flow +39 -0
  212. package/util/joinArgumentDefinitions.js.flow +105 -0
  213. package/util/md5.js.flow +22 -0
  214. package/util/murmurHash.js.flow +94 -0
  215. package/util/nullthrowsOSS.js.flow +25 -0
  216. package/util/orList.js.flow +37 -0
  217. package/util/partitionArray.js.flow +37 -0
@@ -0,0 +1,367 @@
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 ASTConvert = require('../core/ASTConvert');
16
+ const CodegenDirectory = require('./CodegenDirectory');
17
+ const CompilerContext = require('../core/CompilerContext');
18
+ const Profiler = require('../core/GraphQLCompilerProfiler');
19
+ const RelayParser = require('../core/RelayParser');
20
+
21
+ const compileRelayArtifacts = require('./compileRelayArtifacts');
22
+ const graphql = require('graphql');
23
+ const invariant = require('invariant');
24
+ const md5 = require('../util/md5');
25
+ const nullthrows = require('nullthrows');
26
+ const path = require('path');
27
+ const writeRelayGeneratedFile = require('./writeRelayGeneratedFile');
28
+
29
+ const {
30
+ getReaderSourceDefinitionName,
31
+ } = require('../core/GraphQLDerivedFromMetadata');
32
+ const {isExecutableDefinitionAST} = require('../core/SchemaUtils');
33
+ const {Map: ImmutableMap} = require('immutable');
34
+
35
+ import type {Schema} from '../core/Schema';
36
+ import type {
37
+ FormatModule,
38
+ PluginInterface,
39
+ TypeGenerator,
40
+ } from '../language/RelayLanguagePluginInterface';
41
+ import type {ScalarTypeMapping} from '../language/javascript/RelayFlowTypeTransformers';
42
+ import type {Reporter} from '../reporters/Reporter';
43
+ import type {Filesystem} from './CodegenDirectory';
44
+ import type {SourceControl} from './SourceControl';
45
+ import type {RelayCompilerTransforms} from './compileRelayArtifacts';
46
+ import type {DocumentNode, ValidationContext} from 'graphql';
47
+ import type {RequestParameters} from 'relay-runtime';
48
+
49
+ export type GenerateExtraFiles = (
50
+ getOutputDirectory: (path?: string) => CodegenDirectory,
51
+ compilerContext: CompilerContext,
52
+ getGeneratedDirectory: (definitionName: string) => CodegenDirectory,
53
+ ) => void;
54
+
55
+ export type ValidationRule = (context: ValidationContext) => any;
56
+
57
+ export type WriterConfig = {
58
+ baseDir: string,
59
+ compilerTransforms: RelayCompilerTransforms,
60
+ customScalars: ScalarTypeMapping,
61
+ formatModule: FormatModule,
62
+ generateExtraFiles?: GenerateExtraFiles,
63
+ optionalInputFieldsForFlow: $ReadOnlyArray<string>,
64
+ outputDir?: ?string,
65
+ generatedDirectories?: $ReadOnlyArray<string>,
66
+ persistQuery?: ?(text: string) => Promise<string>,
67
+ schemaExtensions: $ReadOnlyArray<string>,
68
+ noFutureProofEnums: boolean,
69
+ useHaste: boolean,
70
+ extension: string,
71
+ typeGenerator: TypeGenerator,
72
+ // Haste style module that exports flow types for GraphQL enums.
73
+ // TODO(T22422153) support non-haste environments
74
+ enumsHasteModule?: string,
75
+ printModuleDependency?: string => string,
76
+ filesystem?: Filesystem,
77
+ repersist?: boolean,
78
+ writeQueryParameters?: (
79
+ outputDirectory: CodegenDirectory,
80
+ filename: string,
81
+ moduleName: string,
82
+ requestParams: RequestParameters,
83
+ ) => void,
84
+ ...
85
+ };
86
+
87
+ function compileAll({
88
+ baseDir,
89
+ baseDocuments,
90
+ schema,
91
+ compilerTransforms,
92
+ documents,
93
+ reporter,
94
+ typeGenerator,
95
+ }: {|
96
+ baseDir: string,
97
+ baseDocuments: $ReadOnlyArray<DocumentNode>,
98
+ schema: Schema,
99
+ compilerTransforms: RelayCompilerTransforms,
100
+ documents: $ReadOnlyArray<DocumentNode>,
101
+ reporter: Reporter,
102
+ typeGenerator: TypeGenerator,
103
+ |}) {
104
+ const definitions = ASTConvert.convertASTDocumentsWithBase(
105
+ schema,
106
+ baseDocuments,
107
+ documents,
108
+ RelayParser.transform,
109
+ );
110
+ const compilerContext = new CompilerContext(schema).addAll(definitions);
111
+
112
+ const transformedTypeContext = compilerContext.applyTransforms(
113
+ typeGenerator.transforms,
114
+ reporter,
115
+ );
116
+ const transformedQueryContext = compilerContext.applyTransforms(
117
+ [
118
+ ...compilerTransforms.commonTransforms,
119
+ ...compilerTransforms.queryTransforms,
120
+ ],
121
+ reporter,
122
+ );
123
+ const artifacts = compileRelayArtifacts(
124
+ compilerContext,
125
+ compilerTransforms,
126
+ reporter,
127
+ );
128
+
129
+ return {
130
+ artifacts,
131
+ definitions,
132
+ transformedQueryContext,
133
+ transformedTypeContext,
134
+ };
135
+ }
136
+
137
+ function writeAll({
138
+ config: writerConfig,
139
+ onlyValidate,
140
+ baseDocuments,
141
+ documents,
142
+ schema,
143
+ reporter,
144
+ sourceControl,
145
+ languagePlugin,
146
+ }: {|
147
+ config: WriterConfig,
148
+ onlyValidate: boolean,
149
+ // $FlowFixMe[value-as-type]
150
+ baseDocuments: ImmutableMap<string, DocumentNode>,
151
+ // $FlowFixMe[value-as-type]
152
+ documents: ImmutableMap<string, DocumentNode>,
153
+ schema: Schema,
154
+ reporter: Reporter,
155
+ sourceControl: ?SourceControl,
156
+ languagePlugin?: ?PluginInterface,
157
+ |}): Promise<Map<string, CodegenDirectory>> {
158
+ return Profiler.asyncContext('RelayFileWriter.writeAll', async () => {
159
+ const {
160
+ artifacts: artifactsWithBase,
161
+ transformedTypeContext,
162
+ transformedQueryContext,
163
+ } = compileAll({
164
+ schema,
165
+ baseDir: writerConfig.baseDir,
166
+ baseDocuments: baseDocuments.valueSeq().toArray(),
167
+ compilerTransforms: writerConfig.compilerTransforms,
168
+ documents: documents.valueSeq().toArray(),
169
+ reporter,
170
+ typeGenerator: writerConfig.typeGenerator,
171
+ });
172
+ // Build a context from all the documents
173
+ const baseDefinitionNames = new Set();
174
+ baseDocuments.forEach(doc => {
175
+ doc.definitions.forEach(def => {
176
+ if (isExecutableDefinitionAST(def) && def.name) {
177
+ baseDefinitionNames.add(def.name.value);
178
+ }
179
+ });
180
+ });
181
+
182
+ // remove nodes that are present in the base or that derive from nodes
183
+ // in the base
184
+ const artifacts = artifactsWithBase.filter(([_definition, node]) => {
185
+ const sourceName = getReaderSourceDefinitionName(node);
186
+ return !baseDefinitionNames.has(sourceName);
187
+ });
188
+
189
+ const artifactMap = new Map(
190
+ artifacts.map(([_definition, node]) => [
191
+ node.kind === 'Request' ? node.params.name : node.name,
192
+ node,
193
+ ]),
194
+ );
195
+
196
+ const definitionsMeta = new Map();
197
+ const getDefinitionMeta = (definitionName: string) => {
198
+ const artifact = nullthrows(artifactMap.get(definitionName));
199
+ const sourceName = getReaderSourceDefinitionName(artifact);
200
+ const definitionMeta = definitionsMeta.get(sourceName);
201
+ invariant(
202
+ definitionMeta,
203
+ 'RelayFileWriter: Could not determine source for definition: `%s`.',
204
+ definitionName,
205
+ );
206
+ return definitionMeta;
207
+ };
208
+ documents.forEach((doc, filePath) => {
209
+ doc.definitions.forEach(def => {
210
+ if (def.name) {
211
+ definitionsMeta.set(def.name.value, {
212
+ dir: path.join(writerConfig.baseDir, path.dirname(filePath)),
213
+ ast: def,
214
+ });
215
+ }
216
+ });
217
+ });
218
+
219
+ const allOutputDirectories: Map<string, CodegenDirectory> = new Map();
220
+ const addCodegenDir = dirPath => {
221
+ const codegenDir = new CodegenDirectory(dirPath, {
222
+ onlyValidate: onlyValidate,
223
+ filesystem: writerConfig.filesystem,
224
+ });
225
+ allOutputDirectories.set(dirPath, codegenDir);
226
+ return codegenDir;
227
+ };
228
+
229
+ for (const existingDirectory of writerConfig.generatedDirectories || []) {
230
+ addCodegenDir(existingDirectory);
231
+ }
232
+
233
+ let configOutputDirectory;
234
+ if (writerConfig.outputDir) {
235
+ configOutputDirectory = addCodegenDir(writerConfig.outputDir);
236
+ }
237
+
238
+ const getGeneratedDirectory = definitionName => {
239
+ if (configOutputDirectory) {
240
+ return configOutputDirectory;
241
+ }
242
+ const generatedPath = path.join(
243
+ getDefinitionMeta(definitionName).dir,
244
+ '__generated__',
245
+ );
246
+ let cachedDir = allOutputDirectories.get(generatedPath);
247
+ if (!cachedDir) {
248
+ cachedDir = addCodegenDir(generatedPath);
249
+ }
250
+ return cachedDir;
251
+ };
252
+
253
+ const formatModule = Profiler.instrument(
254
+ writerConfig.formatModule,
255
+ 'RelayFileWriter:formatModule',
256
+ );
257
+
258
+ const persistQuery = writerConfig.persistQuery
259
+ ? Profiler.instrumentWait(
260
+ writerConfig.persistQuery,
261
+ 'RelayFileWriter:persistQuery',
262
+ )
263
+ : null;
264
+
265
+ try {
266
+ await Promise.all(
267
+ artifacts.map(async ([definition, node]) => {
268
+ const nodeName =
269
+ node.kind === 'Request' ? node.params.name : node.name;
270
+ if (baseDefinitionNames.has(nodeName)) {
271
+ // don't add definitions that were part of base context
272
+ return;
273
+ }
274
+
275
+ const typeNode = transformedTypeContext.get(nodeName);
276
+ const typeText = typeNode
277
+ ? writerConfig.typeGenerator.generate(
278
+ schema,
279
+ (typeNode: $FlowFixMe),
280
+ {
281
+ customScalars: writerConfig.customScalars,
282
+ enumsHasteModule: writerConfig.enumsHasteModule,
283
+ optionalInputFields: writerConfig.optionalInputFieldsForFlow,
284
+ useHaste: writerConfig.useHaste,
285
+ useSingleArtifactDirectory: !!writerConfig.outputDir,
286
+ noFutureProofEnums: writerConfig.noFutureProofEnums,
287
+ normalizationIR:
288
+ definition.kind === 'Request' ? definition.root : undefined,
289
+ },
290
+ )
291
+ : '';
292
+
293
+ const sourceHash = Profiler.run('hashGraphQL', () =>
294
+ md5(graphql.print(getDefinitionMeta(nodeName).ast)),
295
+ );
296
+
297
+ await writeRelayGeneratedFile(
298
+ schema,
299
+ getGeneratedDirectory(nodeName),
300
+ definition,
301
+ node,
302
+ formatModule,
303
+ typeText,
304
+ persistQuery,
305
+ sourceHash,
306
+ writerConfig.extension,
307
+ writerConfig.printModuleDependency,
308
+ writerConfig.repersist ?? false,
309
+ writerConfig.writeQueryParameters ?? function noop() {},
310
+ languagePlugin,
311
+ );
312
+ }),
313
+ );
314
+
315
+ const generateExtraFiles = writerConfig.generateExtraFiles;
316
+ if (generateExtraFiles) {
317
+ Profiler.run('RelayFileWriter:generateExtraFiles', () => {
318
+ const configDirectory = writerConfig.outputDir;
319
+ generateExtraFiles(
320
+ dir => {
321
+ const outputDirectory = dir || configDirectory;
322
+ invariant(
323
+ outputDirectory,
324
+ 'RelayFileWriter: cannot generate extra files without specifying ' +
325
+ 'an outputDir in the config or passing it in.',
326
+ );
327
+ let outputDir = allOutputDirectories.get(outputDirectory);
328
+ if (!outputDir) {
329
+ outputDir = addCodegenDir(outputDirectory);
330
+ }
331
+ return outputDir;
332
+ },
333
+ transformedQueryContext,
334
+ getGeneratedDirectory,
335
+ );
336
+ });
337
+ }
338
+
339
+ allOutputDirectories.forEach(dir => {
340
+ dir.deleteExtraFiles(languagePlugin?.keepExtraFile);
341
+ });
342
+ if (sourceControl && !onlyValidate) {
343
+ await CodegenDirectory.sourceControlAddRemove(
344
+ sourceControl,
345
+ Array.from(allOutputDirectories.values()),
346
+ );
347
+ }
348
+ } catch (error) {
349
+ let details;
350
+ try {
351
+ details = JSON.parse(error.message);
352
+ } catch (_) {} // eslint-disable-line lint/no-unused-catch-bindings
353
+ if (details && details.name === 'GraphQL2Exception' && details.message) {
354
+ throw new Error('GraphQL error writing modules:\n' + details.message);
355
+ }
356
+ throw new Error(
357
+ 'Error writing modules:\n' + String(error.stack || error),
358
+ );
359
+ }
360
+
361
+ return allOutputDirectories;
362
+ });
363
+ }
364
+
365
+ module.exports = {
366
+ writeAll,
367
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const childProcess = require('child_process');
16
+
17
+ function execFile(cmd: string, args: Array<string>): Promise<void> {
18
+ return new Promise((resolve, reject) => {
19
+ childProcess.execFile(cmd, args, err => {
20
+ if (err) {
21
+ reject(err);
22
+ } else {
23
+ resolve();
24
+ }
25
+ });
26
+ });
27
+ }
28
+
29
+ /**
30
+ * An abstraction over the source control system to make it injectable.
31
+ */
32
+ export type SourceControl = {
33
+ addRemove(
34
+ added: $ReadOnlyArray<string>,
35
+ removed: $ReadOnlyArray<string>,
36
+ ): Promise<void>,
37
+ ...
38
+ };
39
+
40
+ const SourceControlMercurial: SourceControl = {
41
+ async addRemove(
42
+ added: $ReadOnlyArray<string>,
43
+ removed: $ReadOnlyArray<string>,
44
+ ): Promise<void> {
45
+ // NOTE: Not using `hg addremove` as that has a bug when deleting a file
46
+ // that was just added, but not yet committed: T10711513
47
+ if (added.length > 0) {
48
+ await execFile('hg', ['add', ...added]);
49
+ }
50
+ if (removed.length > 0) {
51
+ await execFile('hg', ['forget', ...removed]);
52
+ }
53
+ },
54
+ };
55
+
56
+ module.exports = {
57
+ SourceControlMercurial,
58
+ };
@@ -0,0 +1,182 @@
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 Printer = require('../core/IRPrinter');
16
+ const Profiler = require('../core/GraphQLCompilerProfiler');
17
+ const RelayCodeGenerator = require('./RelayCodeGenerator');
18
+
19
+ const filterContextForNode = require('../core/filterContextForNode');
20
+
21
+ import type CompilerContext from '../core/CompilerContext';
22
+ import type {IRTransform} from '../core/CompilerContext';
23
+ import type {GeneratedDefinition} from '../core/IR';
24
+ import type {Reporter} from '../reporters/Reporter';
25
+ import type {GeneratedNode} from 'relay-runtime';
26
+
27
+ export type RelayCompilerTransforms = {
28
+ commonTransforms: $ReadOnlyArray<IRTransform>,
29
+ codegenTransforms: $ReadOnlyArray<IRTransform>,
30
+ fragmentTransforms: $ReadOnlyArray<IRTransform>,
31
+ printTransforms: $ReadOnlyArray<IRTransform>,
32
+ queryTransforms: $ReadOnlyArray<IRTransform>,
33
+ ...
34
+ };
35
+
36
+ function createFragmentContext(
37
+ context: CompilerContext,
38
+ transforms: RelayCompilerTransforms,
39
+ reporter?: Reporter,
40
+ ): CompilerContext {
41
+ // The fragment is used for reading data from the normalized store.
42
+ return context.applyTransforms(
43
+ [...transforms.commonTransforms, ...transforms.fragmentTransforms],
44
+ reporter,
45
+ );
46
+ }
47
+
48
+ function createPrintContext(
49
+ context: CompilerContext,
50
+ transforms: RelayCompilerTransforms,
51
+ reporter?: Reporter,
52
+ ): CompilerContext {
53
+ // The unflattened query is used for printing, since flattening creates an
54
+ // invalid query.
55
+ return context.applyTransforms(
56
+ [
57
+ ...transforms.commonTransforms,
58
+ ...transforms.queryTransforms,
59
+ ...transforms.printTransforms,
60
+ ],
61
+ reporter,
62
+ );
63
+ }
64
+
65
+ function createCodeGenContext(
66
+ context: CompilerContext,
67
+ transforms: RelayCompilerTransforms,
68
+ reporter?: Reporter,
69
+ ): CompilerContext {
70
+ // The flattened query is used for codegen in order to reduce the number of
71
+ // duplicate fields that must be processed during response normalization.
72
+ return context.applyTransforms(
73
+ [
74
+ ...transforms.commonTransforms,
75
+ ...transforms.queryTransforms,
76
+ ...transforms.codegenTransforms,
77
+ ],
78
+ reporter,
79
+ );
80
+ }
81
+
82
+ function compile(
83
+ context: CompilerContext,
84
+ fragmentContext: CompilerContext,
85
+ printContext: CompilerContext,
86
+ codeGenContext: CompilerContext,
87
+ ): $ReadOnlyArray<[GeneratedDefinition, GeneratedNode]> {
88
+ const results = [];
89
+ const schema = context.getSchema();
90
+
91
+ // Add everything from codeGenContext, these are the operations as well as
92
+ // SplitOperations from @match.
93
+ for (const node of codeGenContext.documents()) {
94
+ if (node.kind === 'Root') {
95
+ const fragment = fragmentContext.getRoot(node.name);
96
+ const request = {
97
+ kind: 'Request',
98
+ fragment: {
99
+ kind: 'Fragment',
100
+ argumentDefinitions: fragment.argumentDefinitions,
101
+ directives: fragment.directives,
102
+ loc: {kind: 'Derived', source: node.loc},
103
+ metadata: null,
104
+ name: fragment.name,
105
+ selections: fragment.selections,
106
+ type: fragment.type,
107
+ },
108
+ id: null,
109
+ loc: node.loc,
110
+ metadata: node.metadata || {},
111
+ name: fragment.name,
112
+ root: node,
113
+ text: printOperation(printContext, fragment.name),
114
+ };
115
+ results.push([request, RelayCodeGenerator.generate(schema, request)]);
116
+ } else {
117
+ results.push([node, RelayCodeGenerator.generate(schema, node)]);
118
+ }
119
+ }
120
+
121
+ // Add all the Fragments from the fragmentContext for the reader ASTs.
122
+ for (const node of fragmentContext.documents()) {
123
+ if (node.kind === 'Fragment') {
124
+ results.push([node, RelayCodeGenerator.generate(schema, node)]);
125
+ }
126
+ }
127
+ return results;
128
+ }
129
+
130
+ const OPERATION_ORDER = {
131
+ Root: 0,
132
+ SplitOperation: 1,
133
+ Fragment: 2,
134
+ };
135
+ function printOperation(printContext: CompilerContext, name: string): string {
136
+ const printableRoot = printContext.getRoot(name);
137
+ return filterContextForNode(printableRoot, printContext)
138
+ .documents()
139
+ .sort((a, b) => {
140
+ if (a.kind !== b.kind) {
141
+ return OPERATION_ORDER[a.kind] - OPERATION_ORDER[b.kind];
142
+ }
143
+ return a.name < b.name ? -1 : 1;
144
+ })
145
+ .map(doc => Printer.print(printContext.getSchema(), doc))
146
+ .join('\n');
147
+ }
148
+
149
+ /**
150
+ * Transforms the provided compiler context
151
+ *
152
+ * compileRelayArtifacts generates artifacts for Relay's runtime as a result of
153
+ * applying a series of transforms. Each kind of artifact is dependent on
154
+ * transforms being applied in the following order:
155
+ *
156
+ * - Fragment Readers: commonTransforms, fragmentTransforms
157
+ * - Operation Writers: commonTransforms, queryTransforms, codegenTransforms
158
+ * - GraphQL Text: commonTransforms, queryTransforms, printTransforms
159
+ *
160
+ * The order of the transforms applied for each artifact below is important.
161
+ * CompilerContext will memoize applying each transform, so while
162
+ * `commonTransforms` appears in each artifacts' application, it will not result
163
+ * in repeated work as long as the order remains consistent across each context.
164
+ */
165
+ function compileRelayArtifacts(
166
+ context: CompilerContext,
167
+ transforms: RelayCompilerTransforms,
168
+ reporter?: Reporter,
169
+ ): $ReadOnlyArray<[GeneratedDefinition, GeneratedNode]> {
170
+ return Profiler.run('GraphQLCompiler.compile', () => {
171
+ const fragmentContext = createFragmentContext(
172
+ context,
173
+ transforms,
174
+ reporter,
175
+ );
176
+ const printContext = createPrintContext(context, transforms, reporter);
177
+ const codeGenContext = createCodeGenContext(context, transforms, reporter);
178
+ return compile(context, fragmentContext, printContext, codeGenContext);
179
+ });
180
+ }
181
+
182
+ module.exports = compileRelayArtifacts;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ function createPrintRequireModuleDependency(
16
+ extension: string,
17
+ ): string => string {
18
+ return moduleName => `require('./${moduleName}.${extension}')`;
19
+ }
20
+
21
+ module.exports = createPrintRequireModuleDependency;
@@ -0,0 +1,25 @@
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
+ 'use strict';
12
+
13
+ function sortObjectByKey<T: ?{[key: string]: mixed}>(obj: T): T {
14
+ if (obj == null) {
15
+ return obj;
16
+ }
17
+ const result = {};
18
+ for (const key of Object.keys(obj).sort()) {
19
+ result[key] = obj[key];
20
+ }
21
+ // $FlowFixMe[incompatible-return]
22
+ return result;
23
+ }
24
+
25
+ module.exports = sortObjectByKey;