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,365 @@
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
+ baseDocuments: ImmutableMap<string, DocumentNode>,
150
+ documents: ImmutableMap<string, DocumentNode>,
151
+ schema: Schema,
152
+ reporter: Reporter,
153
+ sourceControl: ?SourceControl,
154
+ languagePlugin?: ?PluginInterface,
155
+ |}): Promise<Map<string, CodegenDirectory>> {
156
+ return Profiler.asyncContext('RelayFileWriter.writeAll', async () => {
157
+ const {
158
+ artifacts: artifactsWithBase,
159
+ transformedTypeContext,
160
+ transformedQueryContext,
161
+ } = compileAll({
162
+ schema,
163
+ baseDir: writerConfig.baseDir,
164
+ baseDocuments: baseDocuments.valueSeq().toArray(),
165
+ compilerTransforms: writerConfig.compilerTransforms,
166
+ documents: documents.valueSeq().toArray(),
167
+ reporter,
168
+ typeGenerator: writerConfig.typeGenerator,
169
+ });
170
+ // Build a context from all the documents
171
+ const baseDefinitionNames = new Set();
172
+ baseDocuments.forEach(doc => {
173
+ doc.definitions.forEach(def => {
174
+ if (isExecutableDefinitionAST(def) && def.name) {
175
+ baseDefinitionNames.add(def.name.value);
176
+ }
177
+ });
178
+ });
179
+
180
+ // remove nodes that are present in the base or that derive from nodes
181
+ // in the base
182
+ const artifacts = artifactsWithBase.filter(([_definition, node]) => {
183
+ const sourceName = getReaderSourceDefinitionName(node);
184
+ return !baseDefinitionNames.has(sourceName);
185
+ });
186
+
187
+ const artifactMap = new Map(
188
+ artifacts.map(([_definition, node]) => [
189
+ node.kind === 'Request' ? node.params.name : node.name,
190
+ node,
191
+ ]),
192
+ );
193
+
194
+ const definitionsMeta = new Map();
195
+ const getDefinitionMeta = (definitionName: string) => {
196
+ const artifact = nullthrows(artifactMap.get(definitionName));
197
+ const sourceName = getReaderSourceDefinitionName(artifact);
198
+ const definitionMeta = definitionsMeta.get(sourceName);
199
+ invariant(
200
+ definitionMeta,
201
+ 'RelayFileWriter: Could not determine source for definition: `%s`.',
202
+ definitionName,
203
+ );
204
+ return definitionMeta;
205
+ };
206
+ documents.forEach((doc, filePath) => {
207
+ doc.definitions.forEach(def => {
208
+ if (def.name) {
209
+ definitionsMeta.set(def.name.value, {
210
+ dir: path.join(writerConfig.baseDir, path.dirname(filePath)),
211
+ ast: def,
212
+ });
213
+ }
214
+ });
215
+ });
216
+
217
+ const allOutputDirectories: Map<string, CodegenDirectory> = new Map();
218
+ const addCodegenDir = dirPath => {
219
+ const codegenDir = new CodegenDirectory(dirPath, {
220
+ onlyValidate: onlyValidate,
221
+ filesystem: writerConfig.filesystem,
222
+ });
223
+ allOutputDirectories.set(dirPath, codegenDir);
224
+ return codegenDir;
225
+ };
226
+
227
+ for (const existingDirectory of writerConfig.generatedDirectories || []) {
228
+ addCodegenDir(existingDirectory);
229
+ }
230
+
231
+ let configOutputDirectory;
232
+ if (writerConfig.outputDir) {
233
+ configOutputDirectory = addCodegenDir(writerConfig.outputDir);
234
+ }
235
+
236
+ const getGeneratedDirectory = definitionName => {
237
+ if (configOutputDirectory) {
238
+ return configOutputDirectory;
239
+ }
240
+ const generatedPath = path.join(
241
+ getDefinitionMeta(definitionName).dir,
242
+ '__generated__',
243
+ );
244
+ let cachedDir = allOutputDirectories.get(generatedPath);
245
+ if (!cachedDir) {
246
+ cachedDir = addCodegenDir(generatedPath);
247
+ }
248
+ return cachedDir;
249
+ };
250
+
251
+ const formatModule = Profiler.instrument(
252
+ writerConfig.formatModule,
253
+ 'RelayFileWriter:formatModule',
254
+ );
255
+
256
+ const persistQuery = writerConfig.persistQuery
257
+ ? Profiler.instrumentWait(
258
+ writerConfig.persistQuery,
259
+ 'RelayFileWriter:persistQuery',
260
+ )
261
+ : null;
262
+
263
+ try {
264
+ await Promise.all(
265
+ artifacts.map(async ([definition, node]) => {
266
+ const nodeName =
267
+ node.kind === 'Request' ? node.params.name : node.name;
268
+ if (baseDefinitionNames.has(nodeName)) {
269
+ // don't add definitions that were part of base context
270
+ return;
271
+ }
272
+
273
+ const typeNode = transformedTypeContext.get(nodeName);
274
+ const typeText = typeNode
275
+ ? writerConfig.typeGenerator.generate(
276
+ schema,
277
+ (typeNode: $FlowFixMe),
278
+ {
279
+ customScalars: writerConfig.customScalars,
280
+ enumsHasteModule: writerConfig.enumsHasteModule,
281
+ optionalInputFields: writerConfig.optionalInputFieldsForFlow,
282
+ useHaste: writerConfig.useHaste,
283
+ useSingleArtifactDirectory: !!writerConfig.outputDir,
284
+ noFutureProofEnums: writerConfig.noFutureProofEnums,
285
+ normalizationIR:
286
+ definition.kind === 'Request' ? definition.root : undefined,
287
+ },
288
+ )
289
+ : '';
290
+
291
+ const sourceHash = Profiler.run('hashGraphQL', () =>
292
+ md5(graphql.print(getDefinitionMeta(nodeName).ast)),
293
+ );
294
+
295
+ await writeRelayGeneratedFile(
296
+ schema,
297
+ getGeneratedDirectory(nodeName),
298
+ definition,
299
+ node,
300
+ formatModule,
301
+ typeText,
302
+ persistQuery,
303
+ sourceHash,
304
+ writerConfig.extension,
305
+ writerConfig.printModuleDependency,
306
+ writerConfig.repersist ?? false,
307
+ writerConfig.writeQueryParameters ?? function noop() {},
308
+ languagePlugin,
309
+ );
310
+ }),
311
+ );
312
+
313
+ const generateExtraFiles = writerConfig.generateExtraFiles;
314
+ if (generateExtraFiles) {
315
+ Profiler.run('RelayFileWriter:generateExtraFiles', () => {
316
+ const configDirectory = writerConfig.outputDir;
317
+ generateExtraFiles(
318
+ dir => {
319
+ const outputDirectory = dir || configDirectory;
320
+ invariant(
321
+ outputDirectory,
322
+ 'RelayFileWriter: cannot generate extra files without specifying ' +
323
+ 'an outputDir in the config or passing it in.',
324
+ );
325
+ let outputDir = allOutputDirectories.get(outputDirectory);
326
+ if (!outputDir) {
327
+ outputDir = addCodegenDir(outputDirectory);
328
+ }
329
+ return outputDir;
330
+ },
331
+ transformedQueryContext,
332
+ getGeneratedDirectory,
333
+ );
334
+ });
335
+ }
336
+
337
+ allOutputDirectories.forEach(dir => {
338
+ dir.deleteExtraFiles(languagePlugin?.keepExtraFile);
339
+ });
340
+ if (sourceControl && !onlyValidate) {
341
+ await CodegenDirectory.sourceControlAddRemove(
342
+ sourceControl,
343
+ Array.from(allOutputDirectories.values()),
344
+ );
345
+ }
346
+ } catch (error) {
347
+ let details;
348
+ try {
349
+ details = JSON.parse(error.message);
350
+ } catch (_) {} // eslint-disable-line lint/no-unused-catch-bindings
351
+ if (details && details.name === 'GraphQL2Exception' && details.message) {
352
+ throw new Error('GraphQL error writing modules:\n' + details.message);
353
+ }
354
+ throw new Error(
355
+ 'Error writing modules:\n' + String(error.stack || error),
356
+ );
357
+ }
358
+
359
+ return allOutputDirectories;
360
+ });
361
+ }
362
+
363
+ module.exports = {
364
+ writeAll,
365
+ };
@@ -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;