# mercurius-auto-schema

> Automatically generate a GraphQL endpoint from routes

Latest version **0.2.0** (published 2022-01-28) · MIT license · 0 weekly downloads

## Install

```sh
npm install mercurius-auto-schema
pnpm add mercurius-auto-schema
yarn add mercurius-auto-schema
bun add mercurius-auto-schema
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2022-01-28 |
| First published | 2021-06-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 5 |
| Unpacked size | 20.3 KB |
| Known vulnerabilities | 0 (+3 in 1 direct dependencies) |
| Install scripts | no |
| GitHub stars | 44 |
| Author | Matteo Collina |
| Maintainers | matteo.collina |
| Keywords | fastify, mercurius, schema, openapi, graphql, routes, route |

## Links

- npm: https://www.npmjs.com/package/mercurius-auto-schema
- Repository: https://github.com/mcollina/mercurius-auto-schema
- Homepage: https://github.com/mcollina/mercurius-auto-schema#readme
- Issues: https://github.com/mcollina/mercurius-auto-schema/issues
- npm.io page: https://npm.io/package/mercurius-auto-schema

## Dependencies (5)

- [qs](https://npm.io/package/qs.md) ^6.10.1
- [mercurius](https://npm.io/package/mercurius.md) ^9.0.0
- [fastify-plugin](https://npm.io/package/fastify-plugin.md) ^3.0.0
- [fastify-swagger](https://npm.io/package/fastify-swagger.md) ^4.7.0
- [openapi-graphql](https://npm.io/package/openapi-graphql.md) ^2.0.0

## Alternatives

- [express-promise-router](https://npm.io/package/express-promise-router.md) — 736.1K weekly downloads
- [next-usequerystate](https://npm.io/package/next-usequerystate.md) — 29.8K weekly downloads
- [@bitkyc08/opencodex](https://npm.io/package/@bitkyc08/opencodex.md) — 4.6K weekly downloads
- [lynkr](https://npm.io/package/lynkr.md) — 575 weekly downloads
- [baremetal.js](https://npm.io/package/baremetal.js.md) — 42 weekly downloads

## Recent versions

- 0.2.0 (latest) — 2022-01-28
- 0.1.0 — 2021-06-25

## 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 company

  Equivalent to GET /company/{id}
  """
  company(
    """company id"""
    id: String!
  ): Company

  """
  get a user

  Equivalent 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 data

  Equivalent 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

---
_Source: https://npm.io/package/mercurius-auto-schema · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
