@omakei/adonisjs-apollo
v1.1.0
Published
GraphQL apollo server integration for adonisjs v6
Downloads
4
Readme
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-apollo
Then 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 DateTime
Uploads
To enable support for inline multipart/form-data uploads using graphql-upload:
- Set
enableUploads: true
inconfig/apollo.ts
. - Update the config of the body parser in
config/bodyparser.ts
by adding your GraphQL route (by default:/graphql
) to themultipart.processManually
array. - 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.