@omakei/adonisjs-apollo v1.1.0
adonisjs-apollo
Apollo GraphQL server for AdonisJS 6.
!WARNING This module is unstable and in active development. Use at your own risk.
Disclaimer
This repository its a fork from zakodium/adonis-apollo and its for the purpose of supporting AdonisJs v6 while waiting v6 on the original repository.
Installation
npm i @omakei/adonisjs-apollo
node ace configure @omakei/adonisjs-apolloThen add the following to the "metaFiles" array in .adonisrc.json:
{
"pattern": "app/schemas/*",
"reloadServer": true
}Usage
Bind the apollo server to your AdonisJs application.
In start/routes.ts:
import ApolloServer from '@omakei/adonisjs-apollo/apollo_server'
import app from '@adonisjs/core/services/app'
const apollo = await app.container.make(ApolloServer)
apollo.applyMiddleware()Schema
The GraphQL schema should be defined in .graphql files (by default located in app/schemas).
The schema folders are scanned recursively.
type Query {
hello: String!
rectangle: Rectangle!
}
type Rectangle {
width: Int!
height: Int!
area: Int!
}Resolvers
Resolvers should be exported from .ts files (by default located in app/resolvers).
Only the first level of resolver folders is scanned, so you can use sub-folders put additional code.
All resolvers are merged into a single object, so you can define them in multiple files.
There are two supported ways of defining resolvers:
Exporting classes
Multiple classes can be exported from a single file. The name of the exported binding will be used as the name of the GraphQL type.
export class Query {
hello() {
return 'world';
}
rectangle() {
return { width: 10, height: 20 };
}
}
export class Rectangle {
area(rectangle) {
return rectangle.width * rectangle.height;
}
}It is also possible to add the suffix Resolvers to the exported name to avoid potential conflicts:
interface Rectangle {
width: number;
height: number;
}
export class RectangleResolvers {
area(rectangle: Rectangle) {
return rectangle.width * rectangle.height;
}
}Exporting a single object
When a single object is exported as default, it is assumed to be a map of resolvers.
interface Rectangle {
width: number;
height: number;
}
export default {
Query: {
hello: () => 'world',
rectangle() {
return { width: 10, height: 20 };
},
},
Rectangle: {
area: (rectangle: Rectangle) => rectangle.width * rectangle.height,
},
};Troubleshooting
Error: Query root type must be provided
Apollo requires a query root type to be defined in your schema.
To fix this error, create a file app/schemas/some_schema.graphql with at least
a Query type.
For example:
type Query {
hello: String!
}BadRequestError: This operation has been blocked as a potential Cross-Site Request Forgery (CSRF)
This error may happen if you try to access the GraphQL endpoint from a browser.
Make sure forceContentNegotiationTo is not unconditionally set to 'application/json' in config/app.ts.
You can either disable this option or set it to a function that ignores the GraphQL route.
You can also disable the csrf token feature in config/apollo.ts using csrfPrevention: false.
Configuration
import env from '#start/env'
import { HttpContext } from '@adonisjs/core/http'
import { defineConfig } from '@omakei/adonisjs-apollo'
import app from '@adonisjs/core/services/app'
export default defineConfig(
{
schemas: 'app/schemas',
resolvers: 'app/resolvers',
path: '/graphql',
async context({ ctx }) {
return ctx
},
executableSchema: {
inheritResolversFromInterfaces: true,
},
apolloServer: {
csrfPrevention: false,
},
},
{ fallbackUrl: env.get('APP_URL'), ioc: app.container }
)Landing page
To configure the default landing page, you can pass apolloProductionLandingPageOptions
or apolloLocalLandingPageOptions to the config. Another possibility is to
override the plugins config in config/apollo.ts.
The default configuration is:
import {
ApolloServerPluginLandingPageLocalDefault,
ApolloServerPluginLandingPageProductionDefault,
} from '@apollo/server/plugin/landingPage/default';
const plugins = [
Env.get('NODE_ENV') === 'production'
? ApolloServerPluginLandingPageProductionDefault({
footer: false,
...apolloProductionLandingPageOptions,
})
: ApolloServerPluginLandingPageLocalDefault({
footer: false,
...apolloLocalLandingPageOptions,
}),
];See the Apollo Graphql documentation to learn how to customize or disable the landing page.
Scalars
All the resolvers from graphql-scalars are installed automatically.
To enable any of the scalar types documented in graphql-scalars,
for example DateTime, just add a scalar line to your schema:
scalar DateTimeUploads
To enable support for inline multipart/form-data uploads using graphql-upload:
- Set
enableUploads: trueinconfig/apollo.ts. - Update the config of the body parser in
config/bodyparser.tsby adding your GraphQL route (by default:/graphql) to themultipart.processManuallyarray. - Add the Upload scalar to your schema:
scalar Upload. - Make sure your GraphQL upload client sends the
'Apollo-Require-Preflight'header, otherwise Apollo will reject multipart requests to prevent CSRF attacks.
License
2 years ago