/
index.ts
72 lines (64 loc) 路 2.73 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import type { WithRequired } from '@apollo/utils.withrequired';
import bodyParser from 'body-parser'; // note that importing 'json' directly doesn't work in ESM
import cors from 'cors';
import express from 'express';
import http, { IncomingMessage, ServerResponse } from 'http';
import type { ListenOptions } from 'net';
import type { ApolloServer } from '../ApolloServer.js';
import { expressMiddleware } from '../express4/index.js';
import type { BaseContext, ContextFunction } from '../externalTypes/index.js';
import { ApolloServerPluginDrainHttpServer } from '../plugin/drainHttpServer/index.js';
import { urlForHttpServer } from '../utils/urlForHttpServer.js';
// Note that while we do use express and expressMiddleware to implement the
// standalone server, this is an internal implementation detail. We could
// rewrite this to have no dependencies other than the core http package.
// Because of this, our TypeScript types encourage users to only use
// functionality of `req` and `res` that are part of the core http
// implementations rather than the Express-specific subclasses; if you need
// typesafe access to Express-specific properties, just use expressMiddleware
// directly.
export interface StandaloneServerContextFunctionArgument {
req: IncomingMessage;
res: ServerResponse;
}
export interface StartStandaloneServerOptions<TContext extends BaseContext> {
context?: ContextFunction<
[StandaloneServerContextFunctionArgument],
TContext
>;
}
export async function startStandaloneServer(
server: ApolloServer<BaseContext>,
options?: StartStandaloneServerOptions<BaseContext> & {
listen?: ListenOptions;
},
): Promise<{ url: string }>;
export async function startStandaloneServer<TContext extends BaseContext>(
server: ApolloServer<TContext>,
options: WithRequired<StartStandaloneServerOptions<TContext>, 'context'> & {
listen?: ListenOptions;
},
): Promise<{ url: string }>;
export async function startStandaloneServer<TContext extends BaseContext>(
server: ApolloServer<TContext>,
options?: StartStandaloneServerOptions<TContext> & { listen?: ListenOptions },
): Promise<{ url: string }> {
const app: express.Express = express();
const httpServer: http.Server = http.createServer(app);
server.addPlugin(
ApolloServerPluginDrainHttpServer({ httpServer: httpServer }),
);
await server.start();
const context = options?.context ?? (async () => ({} as TContext));
app.use(
cors(),
bodyParser.json({ limit: '50mb' }),
expressMiddleware(server, { context }),
);
const listenOptions = options?.listen ?? { port: 4000 };
// Wait for server to start listening
await new Promise<void>((resolve) => {
httpServer.listen(listenOptions, resolve);
});
return { url: urlForHttpServer(httpServer) };
}