@omakei/adonisjs-apollo
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

adonisjs-apollo

Apollo GraphQL server for AdonisJS 6.

NPM version build status Test coverage npm download

[!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 in config/apollo.ts.
  • Update the config of the body parser in config/bodyparser.ts by adding your GraphQL route (by default: /graphql) to the multipart.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.

License

MIT

Package Sidebar

Install

npm i @omakei/adonisjs-apollo

Weekly Downloads

1

Version

1.1.0

License

MIT

Unpacked Size

30.6 kB

Total Files

26

Last publish

Collaborators

  • omakei