This repository has been archived by the owner on Apr 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathGraphbackServer.ts
128 lines (105 loc) · 3.15 KB
/
GraphbackServer.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { ApolloServer, PubSub } from "apollo-server-express";
import newExpress from "express";
import {
GraphbackDataProvider,
GraphbackCRUDService,
CRUDService,
LayeredRuntimeResolverGenerator
} from "@graphback/runtime";
import { InputModelTypeContext } from "@graphback/core";
import { SchemaGenerator } from "@graphback/codegen-schema";
import { Server, createServer } from "http";
import getPort from "get-port";
const ENDPOINT = "/graphql";
export interface ServiceBuilder {
(data: GraphbackDataProvider, sub: PubSub):
| Promise<GraphbackCRUDService>
| GraphbackCRUDService;
}
export class GraphbackServer {
protected readonly graphqlSchema: string;
protected readonly httpServer: Server;
protected serverPort?: number;
constructor(httpServer: Server, graphqlSchema: string) {
this.httpServer = httpServer;
this.graphqlSchema = graphqlSchema;
}
public async start(port?: number): Promise<void> {
if (this.httpServer.listening) {
// the server is already running
return;
}
if (port === undefined) {
// if no port is passed, use the previous port
// or get a new available port
if (this.serverPort !== undefined) {
port = this.serverPort;
} else {
port = await getPort();
}
}
this.httpServer.listen({ port });
this.serverPort = port;
}
public async stop(): Promise<void> {
const server = this.httpServer;
if (!server.listening) {
return;
}
// convert server close to a promise
await new Promise((resolve, reject) => {
server.close(e => {
if (e) {
reject(e);
} else {
resolve();
}
});
});
}
public getHttpUrl(): string {
if (this.serverPort === undefined) {
throw new Error(
`can not retrieve the httpUrl because the server has not been started yet`
);
}
return `http://localhost:${this.serverPort}${ENDPOINT}`;
}
public getWsUrl(): string {
if (this.serverPort === undefined) {
throw new Error(
`can not retrieve the subscriptions url because the server has not been started yet`
);
}
return `ws://localhost:${this.serverPort}${ENDPOINT}`;
}
public getSchema(): string {
return this.graphqlSchema;
}
}
export async function buildGraphbackServer(
context: InputModelTypeContext[],
data: GraphbackDataProvider,
serviceBuilder?: ServiceBuilder
): Promise<GraphbackServer> {
const schemaGenerator = new SchemaGenerator(context);
const schema = schemaGenerator.generate();
const sub = new PubSub();
const service: GraphbackCRUDService = serviceBuilder
? await serviceBuilder(data, sub)
: new CRUDService(data, sub);
const resolverGenerator = new LayeredRuntimeResolverGenerator(
context,
service
);
const resolvers = resolverGenerator.generate();
const express = newExpress();
const apollo = new ApolloServer({
typeDefs: schema,
resolvers: resolvers
});
apollo.applyMiddleware({ app: express, path: ENDPOINT });
const httpServer = createServer(express);
apollo.installSubscriptionHandlers(httpServer);
return new GraphbackServer(httpServer, schema);
}