Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mercurius

Package Overview
Dependencies
Maintainers
2
Versions
116
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mercurius - npm Package Compare versions

Comparing version 12.2.0 to 13.0.0

examples/schema-by-http-header.js

122

docs/faq.md

@@ -32,1 +32,123 @@ # FAQ

```
## Execute against different schemas based on request headers
Sometimes we may face the need to present a scheme that varies depending on specific situations.
To accomplish this need we can use one powerful fastify/find-my-way feature called **Custom Constraints**.
https://www.fastify.io/docs/latest/Reference/Routes/#asynchronous-custom-constraints
> Fastify supports constraining routes to match only certain requests based on some property of the request, like the Host header, or any other value via find-my-way constraints.
We can then create two mercurius instances that expose the two different schemas and use the constraint on the header to drive the request to one or other mercurius instance.
### 1. Create the constraint and initialize the fastify instance
```js
const Fastify = require('fastify')
const mercurius = require('..')
// Define the constraint custom strategy
const schemaStrategy = {
name: 'schema',
storage: function () {
const handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
deriveConstraint: (req, ctx) => {
return req.headers.schema
},
validate: () => true,
mustMatchWhenDerived: true
}
// Initialize fastify
const app = Fastify({ constraints: { schema: schemaStrategy } })
```
### 2. Initialize the first mercurius instance and bind it to the `/` route only if the `schema` header value is equal to `A`
```js
const schema = `
type Query {
add(x: Int, y: Int): Int
}
`
const resolvers = {
Query: {
add: async (_, obj) => {
const { x, y } = obj
return x + y
}
}
}
// Schema A registration with A constraint
app.register(async childServer => {
childServer.register(mercurius, {
schema,
resolvers,
graphiql: false,
routes: false
})
childServer.route({
path: '/',
method: 'POST',
constraints: { schema: 'A' },
handler: (req, reply) => {
const query = req.body
return reply.graphql(query)
}
})
})
```
### 3. Initialize the second mercurius instance and bind it to the `/` route only if the `schema` header value is equal to `B`
```js
const schema2 = `
type Query {
subtract(x: Int, y: Int): Int
}
`
const resolvers2 = {
Query: {
subtract: async (_, obj) => {
const { x, y } = obj
return x - y
}
}
}
app.register(async childServer => {
childServer.register(mercurius, {
schema: schema2,
resolvers: resolvers2,
graphiql: false,
routes: false
})
childServer.route({
path: '/',
method: 'POST',
constraints: { schema: 'B' },
handler: (req, reply) => {
const query = req.body
return reply.graphql(query)
}
})
})
```
4. Start the fastify server
```js
app.listen({ port: 3000 })
```
### Important notes:
In order to use graphql in constrained routes we need to set mercurius `routes` parameter to `false` in order to avoid that both the mercurius instances try to expose themself at `/graphql`.

3

docs/lifecycle.md

@@ -31,3 +31,2 @@ # Lifecycle

```

@@ -60,2 +59,2 @@ ## Subscription lifecycle

└─▶ onSubscriptionEnd Hook
```
```

@@ -474,3 +474,3 @@ 'use strict'

if (reply && reply.request.raw.method === 'GET') {
if (reply && reply.request.raw.method === 'GET' && !reply.request.ws) {
// let's validate we cannot do mutations here

@@ -477,0 +477,0 @@ const operationAST = getOperationAST(document, operationName)

{
"name": "mercurius",
"version": "12.2.0",
"version": "13.0.0",
"description": "Fastify GraphQL adapter with subscription support",

@@ -43,8 +43,9 @@ "main": "index.js",

"autocannon": "^7.3.0",
"concurrently": "^7.0.0",
"concurrently": "^8.0.1",
"docsify-cli": "^4.4.3",
"fastify": "^4.0.0",
"fastify": "^4.17.0",
"graphql-ws": "^5.11.2",
"pre-commit": "^1.2.2",
"proxyquire": "^2.1.3",
"semver": "^7.5.0",
"sinon": "^15.0.0",

@@ -55,4 +56,4 @@ "snazzy": "^9.0.0",

"tap": "^16.3.0",
"tsd": "^0.25.0",
"typescript": "^4.3.5",
"tsd": "^0.28.0",
"typescript": "^5.0.2",
"wait-on": "^7.0.1"

@@ -63,3 +64,3 @@ },

"@fastify/static": "^6.0.0",
"@fastify/websocket": "^7.0.0",
"@fastify/websocket": "^8.0.0",
"fastify-plugin": "^4.2.0",

@@ -74,3 +75,3 @@ "graphql": "^16.0.0",

"single-user-cache": "^0.6.0",
"tiny-lru": "^10.0.0",
"tiny-lru": "^11.0.0",
"undici": "^5.0.0",

@@ -77,0 +78,0 @@ "ws": "^8.2.2"

@@ -12,2 +12,3 @@ 'use strict'

const { GraphQLError } = require('graphql-jit/dist/error')
const semver = require('semver')

@@ -892,5 +893,11 @@ test('ErrorWithProps - support status code in the constructor', async (t) => {

t.equal(res.statusCode, 400)
t.same(res.json(),
{ data: null, errors: [{ message: 'Unexpected token h in JSON at position 1' }] }
)
if (semver.gte(process.version, '20.0.0')) {
t.same(res.json(),
{ data: null, errors: [{ message: 'Unexpected token \'h\', "this is not a json" is not valid JSON' }] }
)
} else {
t.same(res.json(),
{ data: null, errors: [{ message: 'Unexpected token h in JSON at position 1' }] }
)
}
})

@@ -897,0 +904,0 @@

@@ -9,2 +9,3 @@ 'use strict'

const { GraphQLError } = require('graphql')
const semver = require('semver')
const GQL = require('..')

@@ -389,6 +390,11 @@

t.equal(res.statusCode, 400)
t.strictSame(JSON.parse(res.body), {
data: null,
errors: [{ message: 'Unexpected token o in JSON at position 1' }]
})
if (semver.gte(process.version, '20.0.0')) {
t.same(res.json(),
{ data: null, errors: [{ message: 'Unexpected token \'o\', "notajson" is not valid JSON' }] }
)
} else {
t.same(res.json(),
{ data: null, errors: [{ message: 'Unexpected token o in JSON at position 1' }] }
)
}
})

@@ -761,3 +767,3 @@

test('mutation with GET errors', async (t) => {
test('HTTP mutation with GET errors', async (t) => {
const app = Fastify()

@@ -795,2 +801,57 @@ const schema = `

test('websocket mutation with GET allowed', async (t) => {
const app = Fastify()
// Simulate fastify-websocket logic
app.addHook('onRequest', (request, reply, done) => {
request.ws = true
done()
})
const schema = `
type Mutation {
setMessage(message: String): String
}
type Query {
getMessage: String
}
`
let msg = 'hello'
const resolvers = {
setMessage: async ({ message }) => {
msg = message
return message
},
async getMessage () {
return msg
}
}
app.register(GQL, {
schema,
resolvers
})
const query = querystring.stringify({
query: 'mutation { setMessage(message: "hello world") }'
})
const res = await app.inject({
headers: {
connection: 'upgrade',
upgrade: 'websocket'
},
method: 'GET',
url: '/graphql?' + query
})
t.same(JSON.parse(res.body), {
data: {
setMessage: 'hello world'
}
})
t.equal(msg, 'hello world')
})
test('POST should support null variables', async (t) => {

@@ -797,0 +858,0 @@ const app = Fastify()

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc