Skip to content

Commit

Permalink
Feat: add the ability to add in additional route properties (#1080)
Browse files Browse the repository at this point in the history
* feat: add in route properties

* tests(route): add tests for additionalRouteProp

* fix(routes): normalize additionalProps before injection

* docs: add type information for options

* tests(routes): add more description for the ts linter

* docs(api): add `additionalRouteProps` to options api

* docs(typedocs): fix grammatical error

* fix: change name to `additionalRouteOptions`

* fix: type tests for `additionalRouteOptions`

also relevant changes to the types for the same
  • Loading branch information
barelyhuman committed Feb 16, 2024
1 parent 70b2d88 commit 7525759
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/api/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
- `allowBatchedQueries`: Boolean. Flag to control whether to allow batched queries. When `true`, the server supports recieving an array of queries and returns an array of results.

- `compilerOptions`: Object. Configurable options for the graphql-jit compiler. For more details check https://github.com/zalando-incubator/graphql-jit
- `additionalRouteOptions`: Object. Takes similar configuration to the Route Options of Fastify. Use cases include being able to add constraints, modify validation schema, increase the `bodyLimit`, etc. You can read more about the possible values on [fastify.dev's Routes Options](https://fastify.dev/docs/latest/Reference/Routes/#options)

#### queryDepth example

Expand Down
13 changes: 13 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
FastifyReply,
FastifyRequest,
FastifyInstance,
RouteOptions
} from "fastify";
import {
DocumentNode,
Expand Down Expand Up @@ -487,6 +488,18 @@ declare namespace mercurius {
* receive an array of responses within a single request.
*/
allowBatchedQueries?: boolean;

/**
* Customize the graphql routers initialized by mercurius with
* more fastify route options.
*
* Usecases:
* - Add more validation
* - change the schema structure
* - Hook on the request's life cycle
* - Increase body size limit for larger queries
*/
additionalRouteOptions?:Omit<RouteOptions,"handler"|"wsHandler"|"method"|"url">
}

export type MercuriusOptions = MercuriusCommonOptions & (MercuriusSchemaOptions)
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ const mercurius = fp(async function (app, opts) {
entityResolversFactory: undefined,
subscriptionContextFn,
keepAlive,
fullWsTransport
fullWsTransport,
additionalRouteOptions: opts.additionalRouteOptions
})
}

Expand Down
13 changes: 11 additions & 2 deletions lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ module.exports = async function (app, opts) {
persistedQueryProvider,
allowBatchedQueries,
keepAlive,
fullWsTransport
fullWsTransport,
additionalRouteOptions
} = opts

// Load the persisted query settings
Expand All @@ -214,6 +215,12 @@ module.exports = async function (app, opts) {
notSupportedError
} = persistedQueryProvider || {}

const normalizedRouteOptions = { ...additionalRouteOptions }
if (normalizedRouteOptions.handler || normalizedRouteOptions.wsHandler) {
normalizedRouteOptions.handler = undefined
normalizedRouteOptions.wsHandler = undefined
}

async function executeQuery (query, variables, operationName, request, reply) {
// Validate a query is present
if (!query) {
Expand Down Expand Up @@ -293,6 +300,7 @@ module.exports = async function (app, opts) {
method: 'GET',
schema: getSchema,
attachValidation: true,
...normalizedRouteOptions,
handler: async function (request, reply) {
// Generate the context for this request
if (contextFn) {
Expand Down Expand Up @@ -338,7 +346,8 @@ module.exports = async function (app, opts) {

app.post(graphqlPath, {
schema: postSchema(allowBatchedQueries),
attachValidation: true
attachValidation: true,
...normalizedRouteOptions
}, async function (request, reply) {
// Generate the context for this request
if (contextFn) {
Expand Down
97 changes: 97 additions & 0 deletions test/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2187,3 +2187,100 @@ test('if ide has plugin set, serve config.js with the correct endpoint', async (
t.equal(res.body.toString(), 'window.GRAPHQL_ENDPOINT = \'/something/app/graphql\';\n' +
'window.GRAPHIQL_PLUGIN_LIST = []')
})

test('GET graphql endpoint with invalid additionalRouteProp constraint', async (t) => {
const app = Fastify()
const schema = `
type Query {
add(x: Int, y: Int): Int
}
`
app.register(GQL, {
schema,
additionalRouteOptions: {
constraints: {
host: 'auth.fastify.dev'
}
}
})

const res = await app.inject({
method: 'GET',
url: '/graphiql',
headers: {
Host: 'fail.fastify.dev'
}
})

t.equal(res.statusCode, 404)
})

test('GET graphql endpoint with valid additionalRouteProp constraint', async (t) => {
const app = Fastify()
const schema = `
type Query {
add(x: Int, y: Int): Int
}
`
app.register(GQL, {
schema,
additionalRouteOptions: {
constraints: {
host: 'auth.fastify.dev'
}
}
})

const query = '{ add(x: 2, y: 2) }'

const res = await app.inject({
method: 'GET',
url: '/graphql',
headers: {
Host: 'auth.fastify.dev',
'Content-Type': 'text/plain'
},
query: {
query
}
})

t.equal(res.statusCode, 200)
})

test('GET graphql endpoint, additionalRouteOptions should ignore custom handler', async (t) => {
const app = Fastify()
const schema = `
type Query {
add(x: Int, y: Int): Int
}
`

let executed = false

app.register(GQL, {
schema,
additionalRouteOptions: {
// @ts-expect-error `handler` property is ignored in props
handler (req, reply) {
executed = true
}
}
})

const query = '{ add(x: 2, y: 2) }'

const res = await app.inject({
method: 'GET',
url: '/graphql',
headers: {
'Content-Type': 'text/plain'
},
query: {
query
}
})

t.equal(res.statusCode, 200)
t.notOk(executed)
})
7 changes: 7 additions & 0 deletions test/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ makeGraphqlServer({
})
makeGraphqlServer({ schema, errorFormatter: mercurius.defaultErrorFormatter })
makeGraphqlServer({ schema: [schema, 'extend type Query { foo: String }'] })
makeGraphqlServer({
additionalRouteOptions: {
constraints: {
version: '1.2'
}
}
})

// Subscriptions

Expand Down

0 comments on commit 7525759

Please sign in to comment.