Docs

GraphQL EZ

Get Started

How EZ Plugins work?#

Diagram#

Dependencies#

Every EZ Plugin should add as Peer Dependency the common package graphql-ez

{ "devDependencies": { "graphql-ez": "*" }, "peerDependencies": { "graphql-ez": "*" } }

Lifecycle#

EZ Plugins execute around the lifecycle of the app creation:

register#

This step happens right away when CreateApp is called, and plugins hook into this step with the callback onRegister.

Usually, in this step, the InternalAppBuildContext is populated with the required configuration or modules

import type { EZPlugin } from 'graphql-ez'; declare module 'graphql-ez' { interface InternalAppBuildContext { fooBar?: FooBarOptions; } } export const ezFooBar = (options?: FooBarOptions): EZPlugin => { return { name: 'Foo Bar', onRegister(ctx) { ctx.fooBar = options; }, }; };

You also can add helpers in the App Builder

import type { EZPlugin } from 'graphql-ez'; declare module 'graphql-ez' { interface BaseAppBuilder { registerFooBar: RegisterFooBar; } } export const ezFooBar = (options?: FooBarOptions): EZPlugin => { return { name: 'Foo Bar', onRegister(ctx) { ctx.appBuilder.fooBar = args => { // ... }; }, }; };

preBuild#

This step happens right before .buildApp is called, and plugins hook into this step with the callback onPreBuild.

Usually, in this step, the Envelop Plugins are populated with whatever the plugin does

import type { EZPlugin } from 'graphql-ez'; export const ezFooBar = (options?: FooBarOptions): EZPlugin => { return { name: 'Foo Bar', onPreBuild(ctx) { // ... const { fooBar, envelop: { plugins }, } = ctx.options; plugins.push(useFooBar(fooBar)); }, }; };

afterBuild#

This step happens right after .buildApp is called, and plugins hook into this step with the callback onAfterBuild.

This plugin receives not only the InternalAppBuildContext, but also the created Envelop instance.

Usually, the plugins use this to add logic depending on the resulting schema or adding logic that depends on the Envelop instance

Keep in mind that you can also add a custom Envelop plugin in previous steps and use the onSchemaChange lifecycle for a more robust plugin.

import type { EZPlugin } from 'graphql-ez'; export const ezFooBar = (options?: FooBarOptions): EZPlugin => { return { name: 'Foo Bar', onAfterBuild(getEnveloped, ctx) { // ... const { schema } = getEnveloped(); // ... }, }; };

integrationRegister#

This step happens right at the beginning of the web-server integration register, having access to the integration-specific context.

Here the plugin gives a callback for every relevant integration supported.

The plugin also has to mention the supported integrations explicitly with the compatibilityList property.

import type { EZPlugin } from 'graphql-ez'; export const ezFooBar = (options?: FooBarOptions): EZPlugin => { return { name: 'Foo Bar', compatibilityList: { fastify: true, express: true, }, async onIntegrationRegister(ctx) { // ... return { async fastify({ integration }) { // This function is going to be called only when this plugin is used with Fastify // ... }, async express({ integration }) { // This function is going to be called only when this plugin is used with Express // ... }, }; }, }; };