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