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

Abstraction for reusable schema @directive implementations. #640

Merged
merged 80 commits into from
Mar 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
6344500
Simplify directiveResolvers wrapping with an async function.
benjamn Feb 14, 2018
a805fdd
Initial implementation of @directive visitor logic.
benjamn Feb 14, 2018
38818fa
Add a test that @directives are preserved in the schema AST.
benjamn Feb 14, 2018
25a5ab0
Stick to object union types to fix tests with GraphQL v0.11 (old).
benjamn Feb 14, 2018
5b41872
Add a basic test of GraphQLSchemaDirective.visitSchema.
benjamn Feb 14, 2018
eb7dc73
Prevent re-visiting object types by not visiting union members.
benjamn Feb 14, 2018
892eb73
Expose this.schema to GraphQLSchemaDirective visitor methods.
benjamn Feb 14, 2018
0449de5
Make the static description string optional.
benjamn Feb 14, 2018
18b3af0
Add an additional details parameter to some visitor methods.
benjamn Feb 14, 2018
73c30b8
Use -Type suffix for GraphQLType details property names.
benjamn Feb 14, 2018
866a7a5
Declare declaredDirectives values as GraphQLDirective, not any.
benjamn Feb 14, 2018
af91add
Rename GraphQLSchemaDirective to SchemaDirectiveVisitor.
benjamn Feb 14, 2018
a7aa136
Stop inheriting from GraphQLDirective.
benjamn Feb 14, 2018
3d235b3
Add a top-level SchemaDirectiveVisitor comment.
benjamn Feb 14, 2018
b3bb685
Reorder constructor and improve comment about protected modifier.
benjamn Feb 14, 2018
f8a8dcc
Remove overzealous test requiring directives to be declared in schema.
benjamn Feb 14, 2018
99ad072
Reimplement attachDirectiveResolvers using SchemaDirectiveVisitor.vis…
benjamn Feb 14, 2018
0128a10
Fix an argument typo in @rest example.
benjamn Feb 14, 2018
72d1cd5
Add a test of undeclared @directive argument values.
benjamn Feb 14, 2018
00786cb
Test that SchemaDirectiveVisitor can be used as a no-op visitor.
benjamn Feb 14, 2018
2b9401c
Test that SchemaDirectiveVisitor.getLocations works.
benjamn Feb 14, 2018
37ebc31
Test that visitors can visit the schema object itself.
benjamn Feb 14, 2018
be78d68
Make makeExecutableSchema accept a directiveVisitors option.
benjamn Feb 14, 2018
6c24668
Add a test of declared directive parameters with default values.
benjamn Feb 15, 2018
7c2dc88
Final pass over SchemaDirectiveVisitor implementation comments.
benjamn Feb 15, 2018
f951c81
Expose this.visitedType on SchemaDirectiveVisitor instances.
benjamn Feb 15, 2018
547f5d6
Return useful information from SchemaDirectiveVisitor.visitSchema.
benjamn Feb 15, 2018
f57036e
Skip visitors if visitorClass.shouldCall(method) returns false.
benjamn Feb 15, 2018
5f385f6
Radically refactor SchemaVisitor, visitSchema, and SchemaDirectiveVis…
benjamn Feb 15, 2018
3d32448
Rename VisitableType to VisitableSchemaType.
benjamn Feb 15, 2018
9f22c87
Re-export schemaVisitor.ts exports from graphql-tools package.
benjamn Feb 15, 2018
9838718
Move public schema member declaration to SchemaVisitor base class.
benjamn Feb 16, 2018
0a9aa8b
Provide a shared context object to all visitor instances.
benjamn Feb 16, 2018
2a44bb3
Improve coverage by testing implementsVisitorMethod more carefully.
benjamn Feb 16, 2018
5870196
Add a test of a simple visitor that always selects itself.
benjamn Feb 16, 2018
a51f68b
Improve the no-op visitor test by actually verifying what happened.
benjamn Feb 16, 2018
3ef5c35
Fix visitSchema visitorSelector comment to refer to VisitableSchemaType.
benjamn Feb 16, 2018
bfb837e
Add missing public access modifier to visitVieldDefinition in comment.
benjamn Feb 16, 2018
b5e347f
Introductory documentation for schema @directives.
benjamn Feb 16, 2018
0d659c9
Fixing some typos.
benjamn Feb 20, 2018
d57c68d
Add section about implementing schema directives to docs.
benjamn Feb 21, 2018
3ff3e25
Fix typo.
benjamn Feb 26, 2018
67c625d
Add comment about omitted resolver argument.
benjamn Feb 26, 2018
99fd3b7
Allow SchemaDirectiveVisitors to provide GraphQLDirective declarations.
benjamn Feb 26, 2018
7a9139e
Throw if visitor does not implement methods for all declared locations.
benjamn Feb 26, 2018
2a75280
Add documentation about directive declarations.
benjamn Feb 26, 2018
43790f6
Add a number of examples to the SchemaDirectiveVisitor documentation.
benjamn Feb 26, 2018
4c19400
Add tests for all directive examples, and convert examples to JS.
benjamn Feb 27, 2018
f8b4440
Tolerate GraphQL.js versions that do not return data from mutations.
benjamn Feb 27, 2018
094b0e9
Flatten example classes a bit for readability.
benjamn Feb 27, 2018
043ee0d
Conform LimitedLengthType name to older graphql-js requirements.
benjamn Feb 27, 2018
fc3670b
Pass GraphQLSchema instead of GraphQLDirective to getDirectiveDeclara…
benjamn Feb 27, 2018
cbfc21a
Remove directiveResolvers from directive docs, with note.
benjamn Feb 27, 2018
69e1ede
Properly handle errors from faulty LimitedLengthType.
benjamn Feb 27, 2018
6776473
Rename directiveVisitors option to just directives.
benjamn Feb 27, 2018
d3bdc29
Rename directiveResolvers and some subclasses in docs.
benjamn Feb 27, 2018
83e23dc
Improve the @length example tests.
benjamn Feb 27, 2018
8b4a2d0
Simplify intro documentation, plus many other improvements.
benjamn Feb 27, 2018
552ad53
More uniform ```js Markdown language identifiers.
benjamn Feb 27, 2018
9c9e7cf
Reorder LengthDirective and LimitedLengthType classes.
benjamn Feb 27, 2018
193510f
Further simplify introduction, and add brief usage section.
benjamn Feb 28, 2018
fe33c44
Link to DirectiveLocation enum implementation.
benjamn Feb 28, 2018
02d4f5a
Avoid editorial words like 'very'.
benjamn Feb 28, 2018
a01ce05
More tweaks to address review feedback from @stubailo.
benjamn Feb 28, 2018
236ed46
Use .html in links rather than .md.
benjamn Feb 28, 2018
5260e18
Tweak to title of schema directives documentation.
benjamn Mar 6, 2018
34ca07a
Automatically update references to schema types that have changed.
benjamn Mar 7, 2018
0439bf5
Allow each to be used for arrays as well as objects.
benjamn Mar 8, 2018
fb91771
Add a more powerful iteration utility called updateEachKey.
benjamn Mar 8, 2018
c90eb0d
Add missing GraphQLInputObjectType to VisitableSchemaType union.
benjamn Mar 8, 2018
a10d924
Allow visitor methods to return replacement objects, null, or undefined.
benjamn Mar 8, 2018
cdf2ccc
Annotate visitor method stubs with return type options.
benjamn Mar 8, 2018
a07ca3f
Prevent visitSchema from replacing the original GraphQLSchema object.
benjamn Mar 8, 2018
01f10a7
Reconcile GraphQLObjectType .name properties with schema.getTypeMap().
benjamn Mar 9, 2018
0dd82be
Add Query type to enum value removal test to make graphql@0.11 happy.
benjamn Mar 9, 2018
31b8fb2
Fix bug in healSchema that sometimes removed '__'-prefixed types.
benjamn Mar 10, 2018
63cec8e
Call healSchema in visitSchemaDirectives rather than in visitSchema.
benjamn Mar 10, 2018
9b29251
Improve @auth example and corresponding tests.
benjamn Mar 14, 2018
2c8c50d
Improve @uniqueID example.
benjamn Mar 14, 2018
86666cd
Rename makeExecutableSchema({ directives }) option to schemaDirectives.
benjamn Mar 14, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions docs/source/directive-resolvers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@

## Directive example
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the old documentation, just to be clear. The new docs are in schema-directives.md.


Let's take a look at how we can create `@upper` Directive to upper-case a string returned from resolve on Field
[See a complete runnable example on Launchpad.](https://launchpad.graphql.com/p00rw37qx0)

To start, let's grab the schema definition string from the `makeExecutableSchema` example [in the "Generating a schema" article](/tools/graphql-tools/generate-schema.html#example).

```js
import { makeExecutableSchema } from 'graphql-tools';
import { graphql } from 'graphql';

// Construct a schema, using GraphQL schema language
const typeDefs = `
directive @upper on FIELD_DEFINITION

type Query {
hello: String @upper
}
`;

// Implement resolvers for out custom Directive
const directiveResolvers = {
upper(
next,
src,
args,
context,
) {
return next().then((str) => {
if (typeof(str) === 'string') {
return str.toUpperCase();
}
return str;
});
},
}

// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: (root, args, context) => {
return 'Hello world!';
},
},
};

export const schema = makeExecutableSchema({
typeDefs,
resolvers,
directiveResolvers,
});

const query = `
query UPPER_HELLO {
hello
}
`;

graphql(schema, query).then((result) => console.log('Got result', result));
```

> Note: next() always return a Promise for consistency, resolved with original resolver value or rejected with an error.

## Multi-Directives example

Multi-Directives on a field will be apply with LTR order.
[See a complete runnable example on Launchpad.](https://launchpad.graphql.com/nx945rq1x7)

```js
// graphql-tools combines a schema string with resolvers.
import { makeExecutableSchema } from 'graphql-tools';

// Construct a schema, using GraphQL schema language
const typeDefs = `
directive @upper on FIELD_DEFINITION
directive @concat(value: String!) on FIELD_DEFINITION

type Query {
foo: String @concat(value: "@gmail.com") @upper
}
`;

// Customs directives, check https://github.com/apollographql/graphql-tools/pull/518
// for more examples
const directiveResolvers = {
upper(
next,
src,
args,
context,
) {
return next().then((str) => {
if (typeof(str) === 'string') {
return str.toUpperCase();
}
return str;
});
},
concat(
next,
src,
args,
context,
) {
return next().then((str) => {
if (typeof(str) !== 'undefined') {
return `${str}${args.value}`;
}
return str;
});
},
}

// Provide resolver functions for your schema fields
const resolvers = {
Query: {
foo: (root, args, context) => {
return 'foo';
},
},
};

// Required: Export the GraphQL.js schema object as "schema"
export const schema = makeExecutableSchema({
typeDefs,
resolvers,
directiveResolvers,
});
```

The result with query `{foo}` will be:
```json
{
"data": {
"foo": "FOO@GMAIL.COM"
}
}
```

## API

### directiveResolvers option

```js
import { makeExecutableSchema } from 'graphql-tools';

const directiveResolvers = {
// directive resolvers implement
};

const schema = makeExecutableSchema({
// ... other options
directiveResolvers,
})
```

`makeExecutableSchema` has new option field is `directiveResolvers`, a map object for custom Directive's resolvers.

### attachDirectiveResolvers

```js
import { attachDirectiveResolvers } from 'graphql-tools';

const directiveResolvers = {
// directive resolvers implement
};

attachDirectiveResolvers({
schema,
directiveResolvers,
});
```

Given an instance of GraphQLSchema and a `directiveResolvers` map object, `attachDirectiveResolvers` wrap all field's resolver with directive resolvers.
Loading