Skip to content

Commit 40cdd29

Browse files
authored
feat: Support schema directives
2 parents 85f11c3 + 7b99b9e commit 40cdd29

File tree

7 files changed

+258
-109
lines changed

7 files changed

+258
-109
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Fully-featured GraphQL Server with focus on easy setup, performance & great deve
2727
* TypeScript typings
2828
* GraphQL Playground
2929
* Extensible via Express middlewares
30+
* Schema directives
3031
* Apollo Tracing
3132
* Accepts both `application/json` and `application/graphql` content-type
3233
* Runs everywhere: Can be deployed via `now`, `up`, AWS Lambda, Heroku etc
@@ -78,6 +79,7 @@ The `props` argument accepts the following fields:
7879
| `resolvers` | Object | `null` | Contains resolvers for the fields specified in `typeDefs` (required if `schema` is not provided \*) |
7980
| `schema` | Object | `null` | An instance of [`GraphQLSchema`](http://graphql.org/graphql-js/type/#graphqlschema) (required if `typeDefs` and `resolvers` are not provided \*) |
8081
| `context` | Object or Function | `{}` | Contains custom data being passed through your resolver chain. This can be passed in as an object, or as a Function with the signature `(req: ContextParameters) => any` \*\* |
82+
| `schemaDirectives` | Object | `null` | [`Apollo Server schema directives`](https://www.apollographql.com/docs/graphql-tools/schema-directives.html) that allow for transforming schema types, fields, and arguments |
8183

8284
> (*) There are two major ways of providing the [schema](https://blog.graph.cool/graphql-server-basics-the-schema-ac5e2950214e) information to the `constructor`:
8385
>

package.json

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,36 +26,39 @@
2626
"scripts": {
2727
"prepublish": "npm run build",
2828
"build": "rm -rf dist && tsc -d",
29-
"lint": "tslint --project tsconfig.json {src,test}/**/*.ts",
29+
"lint": "tslint --project tsconfig.json {src,test}/**/*.ts && prettier-check --ignore-path .gitignore {src,.}/{*.ts,*.js}",
30+
"format": "prettier --write --ignore-path .gitignore {src,.}/{*.ts,*.js}",
3031
"test": "npm run lint && npm run build"
3132
},
3233
"release": {
3334
"branch": "master"
3435
},
3536
"dependencies": {
3637
"@types/cors": "^2.8.3",
37-
"@types/express": "^4.0.39",
38-
"@types/graphql": "^0.12.0",
38+
"@types/express": "^4.11.1",
39+
"@types/graphql": "^0.12.5",
3940
"@types/zen-observable": "^0.5.3",
4041
"apollo-server-express": "^1.3.2",
4142
"apollo-server-lambda": "1.3.2",
4243
"apollo-upload-server": "^5.0.0",
4344
"aws-lambda": "^0.1.2",
4445
"body-parser-graphql": "1.0.0",
4546
"cors": "^2.8.4",
46-
"express": "^4.16.2",
47+
"express": "^4.16.3",
4748
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0",
48-
"graphql-import": "^0.4.4",
49+
"graphql-import": "^0.4.5",
4950
"graphql-playground-middleware-express": "1.5.7",
5051
"graphql-playground-middleware-lambda": "1.4.3",
5152
"graphql-subscriptions": "^0.5.8",
52-
"graphql-tools": "^2.18.0",
53+
"graphql-tools": "^2.23.1",
5354
"subscriptions-transport-ws": "^0.9.6"
5455
},
5556
"devDependencies": {
5657
"@types/aws-lambda": "0.0.33",
58+
"prettier": "^1.11.1",
59+
"prettier-check": "^2.0.0",
5760
"tslint": "5.9.1",
58-
"tslint-config-prettier": "1.9.0",
61+
"tslint-config-prettier": "^1.10.0",
5962
"tslint-config-standard": "7.0.0",
6063
"typescript": "2.7.2"
6164
}

prettier.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
semi: false,
3+
singleQuote: true,
4+
trailingComma: 'all',
5+
}

src/index.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { importSchema } from 'graphql-import'
1414
import expressPlayground from 'graphql-playground-middleware-express'
1515
import { makeExecutableSchema } from 'graphql-tools'
1616
import { createServer, Server } from 'http'
17-
import { createServer as createHttpsServer, Server as HttpsServer} from 'https';
17+
import { createServer as createHttpsServer, Server as HttpsServer } from 'https'
1818
import * as path from 'path'
1919
import { SubscriptionServer } from 'subscriptions-transport-ws'
2020

@@ -55,7 +55,12 @@ export class GraphQLServer {
5555
if (props.schema) {
5656
this.executableSchema = props.schema
5757
} else if (props.typeDefs && props.resolvers) {
58-
const { directiveResolvers, resolvers, typeDefs } = props
58+
const {
59+
directiveResolvers,
60+
schemaDirectives,
61+
resolvers,
62+
typeDefs,
63+
} = props
5964

6065
const typeDefsString = buildTypeDefsString(typeDefs)
6166

@@ -65,6 +70,7 @@ export class GraphQLServer {
6570

6671
this.executableSchema = makeExecutableSchema({
6772
directiveResolvers,
73+
schemaDirectives,
6874
typeDefs: typeDefsString,
6975
resolvers: {
7076
...uploadMixin,
@@ -97,12 +103,12 @@ export class GraphQLServer {
97103
start(
98104
options: Options,
99105
callback?: ((options: Options) => void),
100-
): Promise<Server|HttpsServer>
101-
start(callback?: ((options: Options) => void)): Promise<Server|HttpsServer>
106+
): Promise<Server | HttpsServer>
107+
start(callback?: ((options: Options) => void)): Promise<Server | HttpsServer>
102108
start(
103109
optionsOrCallback?: Options | ((options: Options) => void),
104110
callback?: ((options: Options) => void),
105-
): Promise<Server|HttpsServer> {
111+
): Promise<Server | HttpsServer> {
106112
const options =
107113
optionsOrCallback && typeof optionsOrCallback === 'function'
108114
? {}
@@ -224,16 +230,17 @@ export class GraphQLServer {
224230
}
225231

226232
return new Promise((resolve, reject) => {
227-
const server: Server|HttpsServer = this.options.https ?
228-
createHttpsServer(this.options.https, app) : createServer(app);
233+
const server: Server | HttpsServer = this.options.https
234+
? createHttpsServer(this.options.https, app)
235+
: createServer(app)
229236

230237
if (!subscriptionServerOptions) {
231238
server.listen(this.options.port, () => {
232239
callbackFunc(this.options)
233240
resolve(server)
234241
})
235242
} else {
236-
const combinedServer = server;
243+
const combinedServer = server
237244
combinedServer.listen(this.options.port, () => {
238245
callbackFunc(this.options)
239246
resolve(combinedServer)
@@ -246,15 +253,21 @@ export class GraphQLServer {
246253
subscribe,
247254
onConnect: subscriptionServerOptions.onConnect
248255
? subscriptionServerOptions.onConnect
249-
: async (connectionParams, webSocket) => ({ ...connectionParams }),
256+
: async (connectionParams, webSocket) => ({
257+
...connectionParams,
258+
}),
250259
onDisconnect: subscriptionServerOptions.onDisconnect,
251260
onOperation: async (message, connection, webSocket) => {
252261
// The following should be replaced when SubscriptionServer accepts a formatError
253262
// parameter for custom error formatting.
254263
// See https://github.com/apollographql/subscriptions-transport-ws/issues/182
255264
connection.formatResponse = value => ({
256-
...value,
257-
errors: value.errors && value.errors.map(this.options.formatError || defaultErrorFormatter),
265+
...value,
266+
errors:
267+
value.errors &&
268+
value.errors.map(
269+
this.options.formatError || defaultErrorFormatter,
270+
),
258271
})
259272

260273
let context

src/lambda.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class GraphQLServerLambda {
2626
if (props.schema) {
2727
this.executableSchema = props.schema
2828
} else if (props.typeDefs && props.resolvers) {
29-
let { directiveResolvers, typeDefs, resolvers } = props
29+
let { directiveResolvers, schemaDirectives, typeDefs, resolvers } = props
3030

3131
// read from .graphql file if path provided
3232
if (typeDefs.endsWith('graphql')) {
@@ -43,6 +43,7 @@ export class GraphQLServerLambda {
4343

4444
this.executableSchema = makeExecutableSchema({
4545
directiveResolvers,
46+
schemaDirectives,
4647
typeDefs,
4748
resolvers,
4849
})

src/types.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import {
88
GraphQLTypeResolver,
99
ValidationContext,
1010
} from 'graphql'
11-
import { IDirectiveResolvers, ITypeDefinitions } from 'graphql-tools/dist/Interfaces'
11+
import {
12+
IDirectiveResolvers,
13+
ITypeDefinitions,
14+
} from 'graphql-tools/dist/Interfaces'
15+
import { SchemaDirectiveVisitor } from 'graphql-tools/dist/schemaVisitor'
1216
import { ExecutionParams } from 'subscriptions-transport-ws'
1317
import { LogFunction } from 'apollo-server-core'
1418

@@ -17,7 +21,7 @@ export interface IResolvers {
1721
}
1822

1923
export type IResolverObject = {
20-
[key: string]: GraphQLFieldResolver<any, any> | IResolverOptions,
24+
[key: string]: GraphQLFieldResolver<any, any> | IResolverOptions
2125
}
2226

2327
export interface IResolverOptions {
@@ -83,6 +87,9 @@ export interface SubscriptionServerOptions {
8387

8488
export interface Props {
8589
directiveResolvers?: IDirectiveResolvers<any, any>
90+
schemaDirectives?: {
91+
[name: string]: typeof SchemaDirectiveVisitor
92+
}
8693
typeDefs?: ITypeDefinitions
8794
resolvers?: IResolvers
8895
schema?: GraphQLSchema
@@ -91,6 +98,9 @@ export interface Props {
9198

9299
export interface LambdaProps {
93100
directiveResolvers?: IDirectiveResolvers<any, any>
101+
schemaDirectives?: {
102+
[name: string]: typeof SchemaDirectiveVisitor
103+
}
94104
typeDefs?: string
95105
resolvers?: IResolvers
96106
schema?: GraphQLSchema

0 commit comments

Comments
 (0)