Exemplo n.º 1
0
  async writeAll(): Promise<Map<string, CodegenDirectory>> {
    const tStart = Date.now();

    // Can't convert to IR unless the schema already has Relay-local extensions
    const transformedSchema = ASTConvert.transformASTSchema(
      this._baseSchema,
      this._config.schemaExtensions,
    );
    const extendedSchema = ASTConvert.extendASTSchema(
      transformedSchema,
      this._baseDocuments.merge(this._documents).valueSeq().toArray(),
    );

    // Build a context from all the documents
    const baseDefinitionNames = new Set();
    this._baseDocuments.forEach(doc => {
      doc.definitions.forEach(def => {
        if (isOperationDefinitionAST(def) && def.name) {
          baseDefinitionNames.add(def.name.value);
        }
      });
    });
    const definitionDirectories = new Map();
    const allOutputDirectories: Map<string, CodegenDirectory> = new Map();
    const addCodegenDir = dirPath => {
      const codegenDir = new CodegenDirectory(dirPath, {
        onlyValidate: this._onlyValidate,
      });
      allOutputDirectories.set(dirPath, codegenDir);
      return codegenDir;
    };

    let configOutputDirectory;
    if (this._config.outputDir) {
      configOutputDirectory = addCodegenDir(this._config.outputDir);
    } else {
      this._documents.forEach((doc, filePath) => {
        doc.definitions.forEach(def => {
          if (isOperationDefinitionAST(def) && def.name) {
            definitionDirectories.set(
              def.name.value,
              path.join(this._config.baseDir, path.dirname(filePath)),
            );
          }
        });
      });
    }

    const definitions = ASTConvert.convertASTDocumentsWithBase(
      extendedSchema,
      this._baseDocuments.valueSeq().toArray(),
      this._documents.valueSeq().toArray(),
      // Verify using local and global rules, can run global verifications here
      // because all files are processed together
      [...RelayValidator.LOCAL_RULES, ...RelayValidator.GLOBAL_RULES],
    );

    const compilerContext = new RelayCompilerContext(extendedSchema);
    const compiler = new RelayCompiler(
      this._baseSchema,
      compilerContext,
      this._config.compilerTransforms,
    );

    const getGeneratedDirectory = definitionName => {
      if (configOutputDirectory) {
        return configOutputDirectory;
      }
      const definitionDir = definitionDirectories.get(definitionName);
      invariant(
        definitionDir,
        'RelayFileWriter: Could not determine source directory for definition: %s',
        definitionName,
      );
      const generatedPath = path.join(definitionDir, '__generated__');
      let cachedDir = allOutputDirectories.get(generatedPath);
      if (!cachedDir) {
        cachedDir = addCodegenDir(generatedPath);
      }
      return cachedDir;
    };

    const nodes = compiler.addDefinitions(definitions);

    const transformedQueryContext = compiler.transformedQueryContext();
    const compiledDocumentMap = compiler.compile();

    const tCompiled = Date.now();

    let tGenerated;
    try {
      await Promise.all(
        nodes.map(async node => {
          if (baseDefinitionNames.has(node.name)) {
            // don't add definitions that were part of base context
            return;
          }
          if (
            this._config.fragmentsWithLegacyFlowTypes &&
            this._config.fragmentsWithLegacyFlowTypes.has(node.name)
          ) {
            const legacyFlowTypes = printFlowTypes(node);
            if (legacyFlowTypes) {
              writeLegacyFlowFile(
                getGeneratedDirectory(node.name),
                node.name,
                legacyFlowTypes,
                this._config.platform,
              );
            }
          }

          const flowTypes = RelayFlowGenerator.generate(
            node,
            this._config.inputFieldWhiteListForFlow,
          );
          const compiledNode = compiledDocumentMap.get(node.name);
          invariant(
            compiledNode,
            'RelayCompiler: did not compile definition: %s',
            node.name,
          );
          await writeRelayGeneratedFile(
            getGeneratedDirectory(compiledNode.name),
            compiledNode,
            this._config.formatModule,
            flowTypes,
            this.skipPersist ? null : this._config.persistQuery,
            this._config.platform,
            this._config.relayRuntimeModule || 'relay-runtime',
          );
        }),
      );
      tGenerated = Date.now();

      if (this._config.generateExtraFiles) {
        const configDirectory = this._config.outputDir;
        invariant(
          configDirectory,
          'RelayFileWriter: cannot generate extra files without specifying ' +
            ' an outputDir in the config.',
        );

        this._config.generateExtraFiles(dir => {
          const outputDirectory = dir || configDirectory;
          let outputDir = allOutputDirectories.get(outputDirectory);
          if (!outputDir) {
            outputDir = addCodegenDir(outputDirectory);
          }
          return outputDir;
        }, transformedQueryContext);
      }

      // clean output directories
      allOutputDirectories.forEach(dir => {
        dir.deleteExtraFiles();
      });
    } catch (error) {
      tGenerated = Date.now();
      let details;
      try {
        details = JSON.parse(error.message);
      } catch (_) {}
      if (details && details.name === 'GraphQL2Exception' && details.message) {
        console.log('ERROR writing modules:\n' + details.message);
      } else {
        console.log('Error writing modules:\n' + error.toString());
      }
      return allOutputDirectories;
    }

    const tExtra = Date.now();
    console.log(
      'Writer time: %s [%s compiling, %s generating, %s extra]',
      toSeconds(tStart, tExtra),
      toSeconds(tStart, tCompiled),
      toSeconds(tCompiled, tGenerated),
      toSeconds(tGenerated, tExtra),
    );
    return allOutputDirectories;
  }
Exemplo n.º 2
0
    schema?: ?GraphQLSchema,
  ): {[key: string]: ConcreteBatch | ConcreteFragment} {
    const {transformASTSchema} = require('ASTConvert');
    const RelayCompiler = require('RelayCompiler');
    const RelayCompilerContext = require('RelayCompilerContext');
    const RelayIRTransforms = require('RelayIRTransforms');
    const RelayTestSchema = require('RelayTestSchema');
    const parseGraphQLText = require('parseGraphQLText');

    schema = schema || RelayTestSchema;
    const relaySchema = transformASTSchema(
      schema,
      RelayIRTransforms.schemaExtensions,
    );
    const compiler = new RelayCompiler(
      schema,
      new RelayCompilerContext(relaySchema),
      RelayIRTransforms,
    );

    compiler.addDefinitions(parseGraphQLText(relaySchema, text).definitions);
    const documentMap = {};
    compiler.compile().forEach(node => {
      documentMap[node.name] = node;
    });
    return documentMap;
  },
};

module.exports = RelayModernTestUtils;