Skip to content

Commit

Permalink
Refactor all graphql-js usages to use Relay Schema Interface
Browse files Browse the repository at this point in the history
Summary:
This diff is pretty straightforward.

The first major change is in `GraphQLIR.js` where all GraphQLTypes replaced with the opaque TypeID from the Schema module.

This change enforces, triggers a waterfall of updates (due to Flow errors) in Relay Transforms, Code Generators and RelayParsers (and other related helpers/modules).

Next change is in the `GraphQLCompilerContext` which no longer have references to the `server` and `client` schemas. Instead, it receives an instance of Schema, and expose it via `getSchema()` method.

To correctly handle this change, I have to update unit-tests in the compiler, so they are getting flow coverage.

Reviewed By: josephsavona

Differential Revision: D17433238

fbshipit-source-id: 582618875a6612f30deb51512c0421b9b373abfd
  • Loading branch information
alunyov authored and facebook-github-bot committed Sep 30, 2019
1 parent 9e6d919 commit 2606f32
Show file tree
Hide file tree
Showing 88 changed files with 1,674 additions and 1,691 deletions.
50 changes: 16 additions & 34 deletions packages/relay-compiler/bin/RelayCompilerMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,7 @@ const fs = require('fs');
const invariant = require('invariant');
const path = require('path');

const {
buildASTSchema,
buildClientSchema,
parse,
printSchema,
} = require('graphql');
const {buildClientSchema, Source, printSchema} = require('graphql');

const {
commonTransforms,
Expand All @@ -42,7 +37,6 @@ const {

import type {ScalarTypeMapping} from '../language/javascript/RelayFlowTypeTransformers';
import type {WriteFilesOptions} from '../codegen/CodegenRunner';
import type {GraphQLSchema} from 'graphql';
import type {
PluginInitializer,
PluginInterface,
Expand Down Expand Up @@ -94,7 +88,6 @@ function getFilepathsFromGlob(
): Array<string> {
const {extensions, include, exclude} = config;
const patterns = include.map(inc => `${inc}/*.+(${extensions.join('|')})`);

const glob = require('fast-glob');
return glob.sync(patterns, {
cwd: baseDir,
Expand Down Expand Up @@ -143,7 +136,7 @@ function getLanguagePlugin(
} else {
languagePlugin = language;
}
if (languagePlugin.default) {
if (languagePlugin.default != null) {
// $FlowFixMe - Flow no longer considers statics of functions as any
languagePlugin = languagePlugin.default;
}
Expand Down Expand Up @@ -188,12 +181,12 @@ function getPersistQueryFunction(
}
}

async function main(config: Config) {
if (config.verbose && config.quiet) {
async function main(defaultConfig: Config) {
if (defaultConfig.verbose && defaultConfig.quiet) {
throw new Error("I can't be quiet and verbose at the same time");
}

config = getPathBasedConfig(config);
let config = getPathBasedConfig(defaultConfig);
config = await getWatchConfig(config);

// Use function from module.exports to be able to mock it for tests
Expand Down Expand Up @@ -268,7 +261,7 @@ function getCodegenRunner(config: Config): CodegenRunner {
verbose: config.verbose,
quiet: config.quiet,
});
const schema = getSchema(config.schema);
const schema = getSchemaSource(config.schema);
const languagePlugin = getLanguagePlugin(config.language);
const persistQueryFunction = getPersistQueryFunction(config);
const inputExtensions = config.extensions || languagePlugin.inputExtensions;
Expand All @@ -283,7 +276,7 @@ function getCodegenRunner(config: Config): CodegenRunner {
providedArtifactDirectory != null
? path.resolve(process.cwd(), providedArtifactDirectory)
: null;
const generatedDirectoryName = artifactDirectory || '__generated__';
const generatedDirectoryName = artifactDirectory ?? '__generated__';
const sourceSearchOptions = {
extensions: inputExtensions,
include: config.include,
Expand All @@ -299,7 +292,7 @@ function getCodegenRunner(config: Config): CodegenRunner {
baseDir: config.src,
getFileFilter: sourceModuleParser.getFileFilter,
getParser: sourceModuleParser.getParser,
getSchema: () => schema,
getSchemaSource: () => schema,
watchmanExpression: config.watchman
? buildWatchExpression(sourceSearchOptions)
: null,
Expand All @@ -310,7 +303,7 @@ function getCodegenRunner(config: Config): CodegenRunner {
graphql: {
baseDir: config.src,
getParser: DotGraphQLParser.getParser,
getSchema: () => schema,
getSchemaSource: () => schema,
watchmanExpression: config.watchman
? buildWatchExpression(graphqlSearchOptions)
: null,
Expand Down Expand Up @@ -443,29 +436,18 @@ function getRelayFileWriter(
};
}

function getSchema(schemaPath: string): GraphQLSchema {
try {
let source = fs.readFileSync(schemaPath, 'utf8');
if (path.extname(schemaPath) === '.json') {
source = printSchema(buildClientSchema(JSON.parse(source).data));
}
source = `
function getSchemaSource(schemaPath: string): Source {
let source = fs.readFileSync(schemaPath, 'utf8');
if (path.extname(schemaPath) === '.json') {
source = printSchema(buildClientSchema(JSON.parse(source).data));
}
source = `
directive @include(if: Boolean) on FRAGMENT_SPREAD | FIELD | INLINE_FRAGMENT
directive @skip(if: Boolean) on FRAGMENT_SPREAD | FIELD | INLINE_FRAGMENT
${source}
`;
return buildASTSchema(parse(source), {assumeValid: true});
} catch (error) {
throw new Error(
`
Error loading schema. Expected the schema to be a .graphql or a .json
file, describing your GraphQL server's API. Error detail:
${error.stack}
`.trim(),
);
}
return new Source(source, schemaPath);
}

// Ensure that a watchman "root" file exists in the given directory
Expand Down
18 changes: 12 additions & 6 deletions packages/relay-compiler/codegen/CodegenRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,23 @@ const Profiler = require('../core/GraphQLCompilerProfiler');
const invariant = require('invariant');
const path = require('path');

const {create: createSchema} = require('../core/Schema');
// $FlowFixMe - importing immutable, which is untyped (and flow is sad about it)
const {Map: ImmutableMap} = require('immutable');

import type ASTCache from '../core/ASTCache';
import type {Schema} from '../core/Schema';
import type {GraphQLReporter} from '../reporters/GraphQLReporter';
import type {CompileResult, File} from './CodegenTypes';
import type {FileFilter, WatchmanExpression} from './CodegenWatcher';
import type {SourceControl} from './SourceControl';
import type {DocumentNode, GraphQLSchema} from 'graphql';
import type {DocumentNode, Source} from 'graphql';

export type ParserConfig = {|
baseDir: string,
getFileFilter?: (baseDir: string) => FileFilter,
getParser: (baseDir: string) => ASTCache,
getSchema: () => GraphQLSchema,
getSchemaSource: () => Source,
generatedDirectoriesWatchmanExpression?: ?WatchmanExpression,
watchmanExpression?: ?WatchmanExpression,
filepaths?: ?Array<string>,
Expand All @@ -58,7 +60,7 @@ type WriterConfigs = {

export type WriteFilesOptions = {|
onlyValidate: boolean,
schema: GraphQLSchema,
schema: Schema,
documents: ImmutableMap<string, DocumentNode>,
baseDocuments: ImmutableMap<string, DocumentNode>,
sourceControl: ?SourceControl,
Expand Down Expand Up @@ -273,7 +275,7 @@ class CodegenRunner {
if (baseParsers) {
baseParsers.forEach(baseParserName => {
invariant(
this.parsers[baseParserName],
this.parsers[baseParserName] == null,
'Trying to access an uncompiled base parser config: %s',
baseParserName,
);
Expand All @@ -299,7 +301,11 @@ class CodegenRunner {
// always create a new writer: we have to write everything anyways
const documents = this.parsers[parser].documents();
const schema = Profiler.run('getSchema', () =>
this.parserConfigs[parser].getSchema(),
createSchema(
this.parserConfigs[parser].getSchemaSource(),
baseDocuments.toArray(),
[],
),
);

const outputDirectories = await writeFiles({
Expand Down Expand Up @@ -384,7 +390,7 @@ class CodegenRunner {
: anyFileFilter,
async files => {
invariant(
this.parsers[parserName],
this.parsers[parserName] == null,
'Trying to watch an uncompiled parser config: %s',
parserName,
);
Expand Down
Loading

0 comments on commit 2606f32

Please sign in to comment.