Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make graphql-tools more composable and extensible #82

Closed
sheerun opened this issue Jul 8, 2016 · 2 comments
Closed

Make graphql-tools more composable and extensible #82

sheerun opened this issue Jul 8, 2016 · 2 comments

Comments

@sheerun
Copy link

sheerun commented Jul 8, 2016

I'd like to leave few comments and possible improvements on graphql-tools API.

Everything boils down to: improve composability and extensibility.

The main painpoint seems to be makeExecutableSchema. Currently it has 6 parameters, and soon it'll have 20. I think Apollo-Server could follow UNIX philosophy and instead of exposing single function responsible for multiple things, let it expose basic blocks for building schemas (aka commands), and way to connect them (aka pipes). makeExecutableSchema encourages the opposite.

So the first proposal is: Please make graphql-tools what they sound to be, and deprecate omnipotent makeExecutableSchema, instead documenting building blocks like buildFromTypeDefinitions or addResolveFunctions, and provide a standard way to compose them.

How to make these functions better composable? I think you could take route http://ramdajs.com/ or lodash/fp or redux took: instead of exposing functions operating directly on schema, let expose functions that return schema/type decorators.

This means changing current "interface" of graphql-tools functions (GraphQLSchema, Options) => GraphQLSchema to decorator-style Options => GraphQLSchema => GraphQLSchema, and making type GraphQLDecorator: GraphQLSchema => GraphQLSchema a base building block.

const baseDecorator = combineDecorators(
  addTypeDefinitions(definitions),
  addErrorLogging(logger)
)

const developmentDecorator = combineDecorators(
  baseDecorator,
  addMockResolvers(mocks),
  assertResolveFunctionsPresent(resolverValidationOptions)
)

const productionDecorator = combineDecorators(
  baseDecorator,
  addResolveFunctions(resolvers)
)

const baseSchema = new GraphQLSchema();
const developmentSchema = applyDecorator(developmentDecorator, baseSchema);
const productionSchema = applyDecorator(productionDecorator, baseSchema);

Here are all the types used in above example:

interface GraphQLDecorator {
  <T>(type: T): T;
} 

interface GraphQLSchemaDecorator extends GraphQLDecorator<GraphQLSchema> {
  (schema: GraphQLSchema): GraphQLSchema;
}

// Decorator constructors
function addTypeDefinitions(definitions: AddTypeDefinitionsOptions): GraphQLSchemaDecorator;
function addErrorLogging(logger: AddErrorLoggingOptions): GraphQLSchemaDecorator;
function addMockResolvers(mocks: AddMocksResolverOptions): GraphQLSchemaDecorator;
function assertResolveFunctions(options?: AssertResolveFunctionsOptions): GraphQLSchemaDecorator;

// Composing function
function <T>combineDecorators(...decorators: GraphQLDecorator<T>[]): GraphQLDecorator<T>

// Applying function
function <T>applyDecorator(decorator: GraphQLDecorator<T>, type: T): T

// Resulting types
function baseDecorator: GraphQLSchemaDecorator
function productionDecorator: GraphQLSchemaDecorator
function baseSchema: GraphQLSchema
function developmentSchema: GraphQLSchema
function productionSchema: GraphQLSchema

While decorator constructors as well as composing function could be allowed to mutate GraphQLSchema for performance, but the applyDecorator can be used copy input type first, and only then apply provided decorator, it someone doesn't want to mutate original type / schema.

I hope you'll appreciate how regular graphql-tools API could be :)

The changes would be exhaustive, so maybe it would be better to deprecate this part of graphql-tools and instead move these functions to graphql-decorators package.

@helfer
Copy link
Contributor

helfer commented Aug 1, 2016

@sheerun I think you're right, makeExecutableSchema has a bit too many arguments. I'd be supportive of a PR that makes sure that all of its functionality can be reproduced with simpler functions in graphql-tools (most of it already can). A large part of that would also be to update the documentation.

PS: I was on vacation recently, thus my slower than usual reply.

@helfer
Copy link
Contributor

helfer commented Aug 28, 2016

I'd still be open to a PR, but I'll close this for now, since there hasn't been any more discussion.

@helfer helfer closed this as completed Aug 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants