๐Ÿ“ฆ flaviendelangle / expense-manager

๐Ÿ“„ App.ts ยท 97 lines
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')
    })
  }
}