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
97import cors from '@koa/cors'
import { ApolloServer } from 'apollo-server-koa'
import { Server } from 'http'
import jsonwebtoken from 'jsonwebtoken'
import Knex from 'knex'
import Koa, { Context } from 'koa'
import bodyParser from 'koa-bodyparser'
import jwt from 'koa-jwt'
import { Model } from 'objection'
import knexFile from '../knexfile'
import { config } from './config'
import { RequestContext } from './globalTypes'
import { schema } from './middlewares/graphql'
import { DataLoaderService } from './utils/DataLoaderService'
const HTTP_PORT = config.get('port')
const JWT_SECRET = config.get('jwtSecret')
export class App {
private readonly koa: Koa
private readonly apollo: ApolloServer
private server: Server
private corsOptions: cors.Options = {
origin: (ctx) =>
new RegExp('http://localhost:.*').test(ctx.header.origin)
? ctx.header.origin
: '',
credentials: true,
}
constructor() {
this.apollo = new ApolloServer({
schema,
tracing: config.get('apollo.tracing'),
debug: config.get('apollo.debug'),
introspection: true,
playground: {
settings: {
'editor.cursorShape': 'line',
'request.credentials': 'same-origin',
},
endpoint: '/graphql',
},
context: ({ ctx }: { ctx: Context }) => {
const c: RequestContext = {
setJWT: async (user) => {
const token = await jsonwebtoken.sign(
{
id: user.id,
isAdmin: user.isAdmin,
},
JWT_SECRET,
{ expiresIn: '7d' }
)
ctx.cookies.set('token', token, { httpOnly: true })
},
removeJWT: async () => ctx.cookies.set('token', undefined),
user: ctx.state.user ?? null,
}
c.loaders = Object.freeze(new DataLoaderService(c))
return c
},
})
this.koa = new Koa()
this.koa.use(cors(this.corsOptions))
this.koa.use(bodyParser())
this.koa.use(
jwt({
secret: JWT_SECRET,
passthrough: true,
getToken: (req) => req.cookies.get('token'),
})
)
const knex = Knex(knexFile)
Model.knex(knex)
this.apollo.applyMiddleware({ app: this.koa })
this.server = this.koa.listen({ port: HTTP_PORT }, () => {
// eslint-disable-next-line
console.log('GraphQL Server ready')
})
}
}