/ src / server / app.js
app.js
  1  const log = require('loglevel')
  2  const Koa = require('koa')
  3  const mount = require('koa-mount')
  4  const serve = require('koa-static')
  5  const GraphQL = require('koa-graphql')
  6  const JSON = require('koa-json')
  7  const Logger = require('koa-logger')
  8  const JsonError = require('koa-json-error')
  9  const JoiRouter = require('koa-joi-router')
 10  const BodyParser = require('koa-bodyparser')
 11  
 12  const DB = require('./db')
 13  const conf = require('./config')
 14  const Schema = require('./schema')
 15  
 16  const App = (diffmgr, gQLschema) => {
 17    const app = new Koa()
 18    const router = new JoiRouter()
 19    
 20    app.on('error', (err, ctx) => {
 21      console.error('server error', err, ctx)
 22    })
 23  
 24    app.use(Logger((str, args) => log.info(str)))
 25       .use(JSON({pretty: true}))
 26       .use(JsonError())
 27       .use(BodyParser({onerror:console.error}))
 28       .use(router.middleware())
 29  
 30    /* host the public folder */
 31    app.use(serve('public'))
 32    /* Host location of the diffs */
 33    app.use(mount('/view', serve(conf.DIFFS_PATH)))
 34  
 35    /* Declare the GraphQL endpoint */
 36    app.use(mount('/graphql', GraphQL({schema: gQLschema, graphiql: true})))
 37  
 38    /* Prefix for all paths defined below */
 39    router.prefix('/api')
 40  
 41    /* Static healthcheck response */
 42    router.get('/health', (ctx) => { ctx.body = 'OK' })
 43  
 44    /* Diffs */
 45    router.get('/diffs', async (ctx) => {
 46      const diffs = await DB.Diff.query().eager('builds')
 47      ctx.body = { count: diffs.length, data: diffs }
 48    })
 49  
 50    router.get('/diffs/:name', async (ctx) => {
 51      ctx.body = await DB.Diff.query().eager('builds')
 52        .where('name', ctx.request.params.name)
 53    })
 54  
 55    /* Builds */
 56    router.get('/builds', async (ctx) => {
 57      builds = await DB.Build.query().eager('diffs')
 58      ctx.body = { count: builds.length, data: builds }
 59    })
 60  
 61    router.get('/builds/:name', async (ctx) => {
 62      ctx.body = await DB.Build.query().eager('diffs.builds')
 63        .where('name', ctx.request.params.name)
 64    })
 65  
 66    router.post('/builds', async (ctx) => {
 67      let diff
 68      const build = await DB.Build.query().insert(ctx.request.body)
 69      const older = await diffmgr.findLastDiffableBuild(build)
 70      if (older) {
 71         diff = await diffmgr.build(build, older)
 72      }
 73      ctx.body = {
 74        status: 'ok',
 75        diff: {
 76          build: older.name,
 77          file: older.filename,
 78          url: diff ? `${conf.PUBLIC_DOMAIN}/view/${diff}` : null,
 79        }
 80      }
 81    })
 82  
 83    /* Manual */
 84    router.route({
 85      method: 'post',
 86      path: '/diffs/manual',
 87      validate: { type: 'json', body: Schema.manual },
 88      handler: async (ctx) => {
 89        const rval = await diffmgr.manual(ctx.request.body)
 90        ctx.status = 201
 91        ctx.body = {
 92          status:'ok',
 93          url: `${conf.PUBLIC_DOMAIN}/view/${rval.name}`
 94        }
 95      },
 96    })
 97  
 98    return app
 99  }
100  
101  module.exports = App