UNPKG

jok

Version:

Bundle of utility functions for code generation related to nodejs and graphql

147 lines (127 loc) 4.16 kB
// Note: express is only used if you use the ApolloServer.listen API to create // an express app for you instead of applyMiddleware (which you might not even // use with express). The dependency is unused otherwise, so don't worry if // you're not using express or your version doesn't quite match up. import { ApolloServer as ApolloServerBase, Config, CorsOptions, } from 'apollo-server-express' import express from 'express' import http from 'http' import net from 'net' export interface ServerInfo { address: string family: string url: string subscriptionsUrl: string port: number | string subscriptionsPath: string server: http.Server } export class ApolloServer extends ApolloServerBase { public express: express.Express private httpServer?: http.Server private cors?: CorsOptions | boolean private path?: string constructor( config: Config & { cors?: CorsOptions | boolean express?: express.Express path?: string }, ) { super(config) this.cors = config && config.cors this.path = config && config.path this.express = (config && config.express) || (express && express()) } private createServerInfo( server: http.Server, subscriptionsPath?: string, ): ServerInfo { const serverInfo: any = { ...(server.address() as net.AddressInfo), server, subscriptionsPath, } // Convert IPs which mean "any address" (IPv4 or IPv6) into localhost // corresponding loopback ip. Note that the url field we're setting is // primarily for consumption by our test suite. If this heuristic is // wrong for your use case, explicitly specify a frontend host (in the // `frontends.host` field in your engine config, or in the `host` // option to ApolloServer.listen). let hostForUrl = serverInfo.address if (serverInfo.address === '' || serverInfo.address === '::') { hostForUrl = 'localhost' } serverInfo.url = require('url').format({ protocol: 'http', hostname: hostForUrl, port: serverInfo.port, pathname: this.graphqlPath, }) serverInfo.subscriptionsUrl = require('url').format({ protocol: 'ws', hostname: hostForUrl, port: serverInfo.port, slashes: true, pathname: subscriptionsPath, }) return serverInfo } public applyMiddleware() { throw new Error( 'To use Apollo Server with an existing express application, please use apollo-server-express', ) } // Listen takes the same arguments as http.Server.listen. public async prepare() { await this.willStart() // This class is the easy mode for people who don't create their own express // object, so we have to create it. const app = this.express // provide generous values for the getting started experience super.applyMiddleware({ app, path: this.path || '/', bodyParserConfig: { limit: '50mb' }, cors: typeof this.cors !== 'undefined' ? this.cors : { origin: '*', }, }) const httpServer = http.createServer(app) this.httpServer = httpServer if (this.subscriptionServerOptions) { this.installSubscriptionHandlers(httpServer) } const listen = async (...opts: Array<any>) => { await new Promise(resolve => { httpServer.once('listening', resolve) // If the user passed a callback to listen, it'll get called in addition // to our resolver. They won't have the ability to get the ServerInfo // object unless they use our Promise, though. httpServer.listen(...(opts.length ? opts : [{ port: 4000 }])) }) return this.createServerInfo(httpServer, this.subscriptionsPath) } return listen } listen(...opts: Array<any>): Promise<ServerInfo> { return this.prepare().then(startListening => startListening(...opts), ) } public async stop() { if (this.httpServer) { const httpServer = this.httpServer await new Promise(resolve => httpServer.close(resolve)) this.httpServer = undefined } await super.stop() } }