UNPKG

@cran/lib.gql.core

Version:

GQL Core Functionality

93 lines (73 loc) 2.51 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import type { GraphQLSchema } from "graphql"; import type { IResolvers, TypeSource } from "@graphql-tools/utils"; import { makeExecutableSchema } from "@graphql-tools/schema"; export namespace Plugin { export enum Phase { PREPARE = 0, DEFAULT = 1, FINALIZE = 2, } export type Transformer = ( schema: GraphQLSchema ) => GraphQLSchema; export type Transformers = { [Key in `${Phase}`]?: Transformer; }; export function apply<Context = any> ( plugin: Plugin<Context> ) { let schema = makeExecutableSchema<Context>({ typeDefs : plugin.typeDefs ?? [ ], resolvers: plugin.resolvers ?? { }, }); for (const phase of [ Phase.PREPARE, Phase.DEFAULT, Phase.FINALIZE, ]) { schema = getTransformerByPhase(plugin, phase)?.(schema) ?? schema; } return schema; } export function compose<Context = any> ( plugins: Array<Plugin<Context>> ) { return { typeDefs: plugins.map(function mapTypeDefs ( plugin ) { return plugin.typeDefs; }), resolvers: plugins.reduce<IResolvers<any, Context>>( function reduceResolvers ( acc, plugin ) { return Object.assign(acc, plugin.resolvers); }, { } ), transformer: { [Phase.PREPARE] : composeTransformerByPhase(plugins, Phase.PREPARE), [Phase.DEFAULT] : composeTransformerByPhase(plugins, Phase.DEFAULT), [Phase.FINALIZE]: composeTransformerByPhase(plugins, Phase.FINALIZE), }, } as const as Plugin<Context>; } export function composeTransformerByPhase<Context> ( plugins: Array<Plugin<Context>>, phase: Phase ) { return function wrappedTransformerPhase ( schema: GraphQLSchema ) { let current = schema; for (const plugin of plugins) { const transformer = getTransformerByPhase(plugin, phase); if (transformer) { current = transformer(current); } } return current; }; } export function getTransformerByPhase<Context> ( plugin: Plugin<Context>, phase: Phase ) { if ("object" === typeof plugin.transformer) { return plugin.transformer[phase]; } if (phase === Phase.DEFAULT && "function" === typeof plugin.transformer) { return plugin.transformer; } return undefined; } } export interface Plugin<Context = any> { typeDefs? : TypeSource; resolvers? : IResolvers<any, Context>; transformer?: Plugin.Transformer | Plugin.Transformers; }