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
// ...
},
};
},
};
};