UNPKG

@mercuriusjs/gateway

Version:
203 lines (180 loc) 7.67 kB
import { FastifyInstance, FastifyReply } from 'fastify' import { MercuriusContext, MercuriusPlugin, MercuriusOptions, PreExecutionHookResponse } from 'mercurius' import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http" import { DocumentNode, GraphQLSchema, ExecutionResult, } from "graphql"; interface ServiceConfig { setSchema: (schema: string) => ServiceConfig; } interface Gateway { refresh: (isRetry?: boolean) => Promise<GraphQLSchema | null>; serviceMap: Record<string, ServiceConfig>; /** * `preGatewayExecution` is the hook to be executed in the GraphQL gateway request lifecycle. * The previous hook was `preExecution`, the next hook will be `onResolution`. * Notice: in the `preGatewayExecution` hook, you can modify the following items by returning them in the hook definition: * - `document` * - `errors` * Each hook definition will trigger multiple times in a single request just before executing remote GraphQL queries on the federated services. */ addHook<TContext = MercuriusContext, TError extends Error = Error>(name: 'preGatewayExecution', hook: preGatewayExecutionHookHandler<TContext, TError>): void; /** * `preGatewaySubscriptionExecution` is the hook to be executed in the GraphQL gateway subscription lifecycle. * The previous hook was `preSubscriptionExecution`, the next hook will be `onSubscriptionResolution`. */ addHook<TContext = MercuriusContext>(name: 'preGatewaySubscriptionExecution', hook: preGatewaySubscriptionExecutionHookHandler<TContext>): void; /** * `onGatewayReplaceSchema` is an application lifecycle hook. When the Gateway service obtains new versions of federated schemas within a defined polling interval, the `onGatewayReplaceSchema` hook will be triggered every time a new schema is built. It is called just before the old schema is replaced with the new one. * This hook will only be triggered in gateway mode. It has the following parameters: * - `instance` - The gateway server `FastifyInstance` (this contains the old schema). * - `schema` - The new schema that has been built from the gateway refresh. */ addHook(name: 'onGatewayReplaceSchema', hook: onGatewayReplaceSchemaHookHandler): void; } declare module "fastify" { interface FastifyInstance { /** * GraphQL plugin */ graphqlGateway: Gateway } interface FastifyReply { /** * @param source GraphQL query string * @param context request context * @param variables request variables which will get passed to the executor * @param operationName specify which operation will be run */ graphql< TData extends Record<string, any> = Record<string, any>, TVariables extends Record<string, any> = Record<string, any> >( source: string, context?: Record<string, any>, variables?: TVariables, operationName?: string ): Promise<ExecutionResult<TData>>; } } /** * Federated GraphQL Service metadata */ export interface MercuriusServiceMetadata { name: string; } export interface Collectors { collectHeaders?: boolean; collectStatutsCodes?: boolean; collectExtensions?: boolean; } interface WsConnectionParams { connectionInitPayload?: | (() => Record<string, any> | Promise<Record<string, any>>) | Record<string, any>; reconnect?: boolean; maxReconnectAttempts?: number; connectionCallback?: () => void; failedConnectionCallback?: (err: { message: string }) => void | Promise<void>; failedReconnectCallback?: () => void; rewriteConnectionInitPayload?: <TContext extends MercuriusContext = MercuriusContext>(payload: Record<string, any> | undefined, context: TContext) => Record<string, any>; } export interface MercuriusGatewayService { name: string; url: string | string[]; schema?: string; wsUrl?: string; mandatory?: boolean; initHeaders?: | (() => OutgoingHttpHeaders | Promise<OutgoingHttpHeaders>) | OutgoingHttpHeaders; rewriteHeaders?: <TContext extends MercuriusContext = MercuriusContext>( headers: IncomingHttpHeaders, context: TContext ) => OutgoingHttpHeaders | Promise<OutgoingHttpHeaders>; connections?: number; bodyTimeout?: number; headersTimeout?: number; maxHeaderSize?: number; keepAlive?: number; keepAliveMaxTimeout?: number; rejectUnauthorized?: boolean; wsConnectionParams?: | (() => WsConnectionParams | Promise<WsConnectionParams>) | WsConnectionParams; setResponseHeaders?: (reply: FastifyReply) => void; collectors?: Collectors; allowBatchedQueries?: boolean; } export interface MercuriusGatewayOptions { gateway: { services: Array<MercuriusGatewayService> | (() => Promise<Array<MercuriusGatewayService>>); pollingInterval?: number; errorHandler?(error: Error, service: MercuriusGatewayService): void; retryServicesCount?: number; retryServicesInterval?: number; }; } type MercuriusFederationOptions = MercuriusOptions & MercuriusGatewayOptions declare const mercuriusGatewayPlugin: ( instance: FastifyInstance, opts: MercuriusFederationOptions ) => void export default mercuriusGatewayPlugin; // ------------------------ // Request Lifecycle hooks // ------------------------ /** * `preGatewayExecution` is the hook to be executed in the GraphQL gateway request lifecycle. * The previous hook was `preExecution`, the next hook will be `onResolution`. * Notice: in the `preGatewayExecution` hook, you can modify the following items by returning them in the hook definition: * - `document` * - `errors` * Each hook definition will trigger multiple times in a single request just before executing remote GraphQL queries on the federated services. * * Because it is a gateway hook, this hook contains service metadata in the `service` parameter: * - `name`: service name */ export interface preGatewayExecutionHookHandler<TContext = MercuriusContext, TError extends Error = Error> { ( schema: GraphQLSchema, source: DocumentNode, context: TContext, service: MercuriusServiceMetadata ): Promise<PreExecutionHookResponse<TError> | void> | PreExecutionHookResponse<TError> | void; } // ----------------------------- // Subscription Lifecycle hooks // ----------------------------- /** * `preGatewaySubscriptionExecution` is the hook to be executed in the GraphQL gateway subscription lifecycle. * The previous hook was `preSubscriptionExecution`, the next hook will be `onSubscriptionResolution`. * * Because it is a gateway hook, this hook contains service metadata in the `service` parameter: * - `name`: service name */ export interface preGatewaySubscriptionExecutionHookHandler<TContext = MercuriusContext> { ( schema: GraphQLSchema, source: DocumentNode, context: TContext, service: MercuriusServiceMetadata ): Promise<void> | void; } // ---------------------------- // Application Lifecycle hooks // ---------------------------- /** * `onGatewayReplaceSchema` is an application lifecycle hook. When the Gateway service obtains new versions of federated schemas within a defined polling interval, the `onGatewayReplaceSchema` hook will be triggered every time a new schema is built. It is called just before the old schema is replaced with the new one. * This hook will only be triggered in gateway mode. It has the following parameters: * - `instance` - The gateway server `FastifyInstance` (this contains the old schema). * - `schema` - The new schema that has been built from the gateway refresh. */ export interface onGatewayReplaceSchemaHookHandler { ( instance: FastifyInstance, schema: GraphQLSchema ): Promise<void> | void; }