Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mcollina/mercurius-auto-schema
https://github.com/mcollina/mercurius-auto-schema
Last synced: 12 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/mcollina/mercurius-auto-schema
- Owner: mcollina
- License: mit
- Created: 2021-06-15T13:06:12.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-03-06T18:03:36.000Z (almost 2 years ago)
- Last Synced: 2024-12-12T01:35:22.696Z (28 days ago)
- Language: JavaScript
- Size: 42 KB
- Stars: 43
- Watchers: 4
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-list - mercurius-auto-schema
README
# mercurius-auto-schema
`mercurius-auto-schema` allows you to create a GraphQL schema and endpoint from
Fastify own route definitions. By using this module, you would get a dynamic OpenAPI
specification of your API that will be used as the basis for the GraphQL implementation.The main difference with other similar approaches is that `mercurius-auto-schema` does not
perform any HTTP requests but leverages the high-throughput `fastify.inject()` utility for
in-process request processing.Built upon:
* [fastify-swagger](https://github.com/fastify/fastify-swagger)
* [mercurius](https://github.com/mercurius-js/mercurius)
* [openapi-graphql](https://github.com/mcollina/openapi-graphql)
* [`fastify.inject()`](https://www.fastify.io/docs/latest/Testing/#benefits-of-using-fastifyinject)This module is high level and it exposes all the behavior of its constituent parts.
See the individual modules for various docs and explanations.## Install
```sh
npm i mercurius-auto-schema
```## Example
```js
'use strict'const fastify = require('fastify')()
const { printSchema } = require('graphql')fastify.register(require('mercurius-auto-schema'), {
definitions: {
openapi: {
info: {
title: 'Test OpenAPI',
description: 'testing the fastify openapi',
version: '0.1.0'
}
},
exposeRoute: true
},
graphql: {
graphiql: true
}
})fastify.put('/some-route/:id', {
schema: {
description: 'post some data',
tags: ['user', 'code'],
summary: 'qwerty',
params: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'user id'
}
}
},
body: {
type: 'object',
properties: {
hello: { type: 'string' },
obj: {
type: 'object',
properties: {
some: { type: 'string' }
}
}
}
},
response: {
201: {
description: 'Succesful response',
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
}
}, (req, reply) => { reply.send({ hello: `Hello ${req.body.hello}` }) })fastify.get('/user/:id', {
schema: {
description: 'get a user',
params: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'user id'
}
}
},
response: {
201: {
description: 'Succesful response',
type: 'object',
properties: {
name: { type: 'string' },
companyId: { type: 'string' }
}
}
}
},
links: {
201: {
company: {
operationId: 'getCompany',
parameters: {
id: '$request.path.id'
}
}
}
}
}, () => 'hello world')fastify.get('/company/:id', {
schema: {
operationId: 'getCompany',
description: 'get a company',
params: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'company id'
}
}
},
response: {
201: {
description: 'Succesful response',
type: 'object',
properties: {
name: { type: 'string' }
}
}
}
}
}, () => 'hello world')fastify.listen(3000, err => {
if (err) throw err
console.log(printSchema(fastify.graphql.schema))
})
```This will print:
```
type Query {
"""
get a companyEquivalent to GET /company/{id}
"""
company(
"""company id"""
id: String!
): Company"""
get a userEquivalent to GET /user/{id}
"""
user(
"""user id"""
id: String!
): User
}"""Succesful response"""
type Company {
name: String
}"""Succesful response"""
type User {
company: Company
companyId: String
name: String
}type Mutation {
"""
post some dataEquivalent to PUT /some-route/{id}
"""
putSomeRouteId(
"""user id"""
id: String!
someRouteInput: SomeRouteInput
): SomeRoute2
}"""Succesful response"""
type SomeRoute2 {
hello: String
}input SomeRouteInput {
hello: String
obj: ObjInput
}input ObjInput {
some: String
}
```### Authorization headers & JWT support
If your application requires authenticating with JWT using a bearer token scheme,
you could specify a few options to create a smoother transformation.
(If you are curious to what happens without these options, take a look at https://github.com/mcollina/openapi-graphql#authentication).```js
'use strict'const fastify = require('fastify')
const auto = require('mercurius-auto-schema')
const JWT = require('fastify-jwt')async function run () {
const app = fastify({ logger: { level: 'error' } })app.register(JWT, {
secret: 'CHANGEME!!'
})app.register(auto, {
definitions: {
openapi: {
info: {
title: 'Test swagger',
description: 'testing the fastify swagger api',
version: '0.1.0'
},
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
format: 'JWT'
}
}
}
}
},// Disable the auth-wrapping objects
viewer: false,// You can use customizeHttpRequest to add other headers as well, e.g. OpenTelemetry.
customizeHttpRequest (opts, context) {
opts.headers.authorization = context.reply.request.headers.authorization
return opts
}
})app.get('/user/:id', {
schema: {
operationId: 'user',
description: 'get a user',
params: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'user id'
}
}
},
response: {
200: {
description: 'Succesful response',
type: 'object',
properties: {
name: { type: 'string' },
companyId: { type: 'string' }
}
}
},
security: [
{ bearerAuth: [] }
]
}
}, async (req) => {
await req.jwtVerify()
equal(req.user.name, 'foobar', 'jwt parsed correctly')
equal(req.params.id, 'foo42', 'user id matches')return {
companyId: 42,
name: 'foo'
}
})await app.ready()
{
const query = 'query { user (id: "foo42") { name, companyId } }'const res = await app.inject({
method: 'POST',
url: '/graphql',
headers: {
Authorization: `Bearer ${app.jwt.sign({ name: 'foobar' })}`
},
body: {
query
}
})console.log(res.json())
// {
// data: {
// user: {
// name: 'foo',
// companyId: 42
// }
// }
// }
}
})
```## License
MIT