UNPKG

@harmonyjs/controller-apollo-gateway

Version:

Apollo Gateway controller for Harmony

94 lines (93 loc) 4.14 kB
import { ApolloGateway, RemoteGraphQLDataSource, } from '@apollo/gateway'; import { ApolloServer } from '@harmonyjs/apollo-fastify'; let gatewayReference = null; let firstComposition = true; function didUpdateComposition(callback, serviceNumber) { return function (services) { if (services.serviceDefinitions.length === serviceNumber && !firstComposition) { callback(); } firstComposition = false; }; } /* * The Apollo Controller exposes a GraphQL endpoint through an Apollo Server */ const ControllerApolloGateway = function (config) { return ({ name: 'ControllerApolloGateway', async initialize({ server, logger }) { const { path, enablePlayground, services, authentication, gatewayConfig, apolloConfig, routeConfig, } = config; logger.info('Registering GraphQL Federation endpoint...'); const gateway = gatewayReference || new ApolloGateway({ ...(gatewayConfig || {}), serviceList: services, buildService({ url }) { return new RemoteGraphQLDataSource({ url, willSendRequest({ request, context }) { if (context.headers) { Object.keys(context.headers).forEach((header) => { request.http.headers.set(header, context.headers[header]); }); } }, }); }, }); if (config.servicePoller) { if (!gatewayReference) { logger.warn('Service polling enabled'); logger.warn('This is a development feature only. Do not use in production!'); } firstComposition = true; gatewayReference = gateway; gatewayReference.experimental_pollInterval = 1000; gatewayReference.logger.disableAll(true); gatewayReference.startPollingServices(); gatewayReference.experimental_didUpdateComposition = didUpdateComposition(config.servicePoller, config.services.length); } const apolloServer = new ApolloServer({ ...(apolloConfig || {}), gateway, playground: !!enablePlayground, introspection: !!enablePlayground, context: ({ request }) => ({ headers: request.headers, }), subscriptions: false, }); const routeOptions = { ...(routeConfig || {}) }; if (authentication) { // @ts-ignore if (!server[authentication.validator]) { logger.error('The provided authentication controller was not initialized'); logger.error(`Make sure the authentication controller ${authentication().name} is present in your controllers array and is before ${this.name}`); throw new Error('Missing controller'); } const preValidation = []; if (routeOptions.preValidation) { if (Array.isArray(routeOptions.preValidation)) { preValidation.push(...routeOptions.preValidation); } else { preValidation.push(routeOptions.preValidation); } } // @ts-ignore preValidation.push(server[authentication.validator].try); routeOptions.preValidation = preValidation; } await server.register(apolloServer.createHandler({ path, cors: true, routeOptions, })); logger.info(`GraphQL endpoint at ${path}`); if (enablePlayground) { logger.info(`GraphQL playground at ${path}`); } }, }); }; export default ControllerApolloGateway;