Plugins allow extending Stitch functionality. Plugin can modify the resource group, and add predefined globals to the Argument Injection mechanism. In the future, we plan to allow modifying Fastify and Apollo servers configurations, add and modify Graphql schema and more.
Stitch loads plugins from a specific location that can be configured by the environment variable PLUGINS_DIR
.
Each file or folder at the root level is loaded. It can be a single javascript file, a directory containing index.js
file, or a directory with a package.json
file that has the main
property.
Plugin should export one of the following:
- An object implementing the StitchPlugin interface (see below)
- A promise to the object as described in (1)
- A parameterless function returning an object, or a promise to the object as described in (1)
export interface StitchPlugin {
configure?(options?: unknown): ValueOrPromise<void>;
addArgumentInjectionGlobals?(): ValueOrPromise<Record<string, unknown>>;
transformResourceGroup?(resourceGroup: ResourceGroup): ValueOrPromise<ResourceGroup>;
transformBaseSchema?(baseSchema: BaseSchema): ValueOrPromise<BaseSchema>;
}
The plugin name is optional, and by default it is set to the file or folder name.
Optional method that's called on plugin initialization. Stitch will send it the configuration relevant for this plugin, based on the values defined in the PLUGINS_CONFIGURATION
environment variable.
For example, with this env var value:
PLUGINS_CONFIGURATION={ "awesome-plugin.js": { "arg1": "val1" } }
The options
param for the configure
function will be { arg: 'val1' }
Note: It's recommended to implement
configure
to get and validate plugin configuration rather than to use environment variables.
Returns an object or a promise to the object that will be available in Argument Injection clauses under the globals
constant.
Example:
Plugin:
{
addArgumentInjectionGlobals() {
return {
doublePad: (str, pad) => `${pad}${pad}${str}${pad}${pad}`,
};
},
}
GraphQL Schema:
type Query {
foo(str: String!): String! @localResolver(value: "{globals.doublePad(args.str, '_')}")
}
GraphQL Query:
query {
foo(str: "HELLO")
}
Result: { foo: "__HELLO__" }
.
Allows transforming the resource group. This transformation is done every time the resource group is changed by a mutation call to the Registry service.
For example this plugin adds a base policy if one does not exist:
{
transformResourceGroup(rg) {
if (rg.basePolicy) return rg;
return { ...rg, basePolicy: {
namespace: 'ns',
name: 'base',
args: {
user: '{jwt?.sub}',
},
}};
}
}
Also allows to export data the resource group's pluginsData
field, that will be available in Argument Injection clauses under the plugins
constant.
Allow to transform the base schema. This method can modify the scalars and directives definitions.
For example this plugin adds new directive and scalar:
const sdl = parse(`
directive @myDirective on FIELD_DEFINITION
scalar MyScalar
`);
class MyDirective extends SchemaDirectiveVisitor {
...
}
const MyScalar = new GraphQLScalarType({
...
});
const resolvers: IResolvers = {
MyScalar,
};
export function transformBaseSchema(baseSchema: BaseSchema): BaseSchema {
const result = {
typeDefs: concatAST([baseSchema.typeDefs, sdl]),
resolvers: { ...baseSchema.resolvers, ...resolvers }, // Important: consider to use deep merge. In some cases it's inevitable
directives: { ...baseSchema.directives, myDirective: MyDirective },
};
return result;
}
Allows to add or remove Apollo Server Plugins.
The function receives the default system plugin collection. It should return plugin collection as well.
For example:
export function transformApolloServerPlugins(plugins: PluginDefinition[]): PluginDefinition[] {
const plugin: ApolloServerPlugin = {
// Plugin code here
};
return [...plugins, plugin];
}
There are some more plugins examples here.
-
Currently running plugins can be queried from each service (Gateway and Registry) using the following query:
query { plugins { name version } }
-
On resource group update Registry stores the names and versions of plugins at that moment as a part of resource group metadata.
Resource group metadata is stored in separate files named
gateway-metadata.json
andregistry-metadata.json
.