-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.ts
81 lines (73 loc) · 2.89 KB
/
router.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
import { identity } from 'lodash'
import Router = require('koa-router')
import * as path from 'path'
import send = require('koa-send')
import { readdirSync } from 'fs'
import { parse, ParsedPath } from 'path'
import passport from './auth/passport'
import * as handlers from './handlers'
declare module 'koa-router' {
export interface IRouterContext {
render(view: string, data?: any): any
}
}
type MappedHandlers = {
[key in keyof typeof handlers]: (ctx: Router.IRouterContext) => Promise<any>
}
const mappedHandlers: MappedHandlers = Object.keys(handlers).reduce((mh: MappedHandlers, key: keyof typeof handlers) => {
const handler = handlers[key]
return {
[key]: async (ctx: Router.IRouterContext) => Object.assign(ctx.response, await handler(ctx)),
...mh,
}
}, {} as MappedHandlers)
// Sychronously yield all files in the given directory, searching recursively
// tslint:disable-next-line:readonly-array
function* files(...dirs: string[]): IterableIterator<ParsedPath & { full: string }> {
for (const dir of dirs) {
for (const name of readdirSync(path.join(__dirname, '..', dir))) {
const parsed = parse(name)
// Yield all files in subdirectories
if (!parsed.ext) {
yield* files(`${dir}/${name}`)
} else {
yield { ...parsed, full: `${dir}/${parsed.base}` }
}
}
}
}
export function createRouter(withRouter: (router: Router) => Router = identity): Router {
const v1Router = withRouter(new Router())
.get('/website', mappedHandlers.getWebsite)
// Redirect the user to Twitter for authentication. When complete, Twitter
// will redirect the user back to the application at
// /auth/twitter/callback
.get('/auth/twitter', passport.authenticate('twitter'))
// Twitter will redirect the user to this URL after approval. Finish the
// authentication process by attempting to obtain an access token. If
// access was granted, the user will be logged in. Otherwise,
// authentication has failed.
.get(
'/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/auth-success',
failureRedirect: '/welcome',
})
)
.get('/me', mappedHandlers.getMe)
.post('/feedback', mappedHandlers.postFeedback)
.post('/logout', mappedHandlers.logout)
.post('/subscribe', mappedHandlers.subscribe)
.get('/leads', mappedHandlers.leads)
.get('/fail', () => {
throw new Error('Failure!')
})
const router = new Router()
.get(`/health-check`, ({ response }) => Object.assign(response, { status: 200, body: 'OK' }))
.use('/v1', v1Router.routes(), v1Router.allowedMethods())
for (const file of files('/public', '/css', '/html')) {
const route = file.base === 'index.html' ? '' : file.ext === '.html' ? file.name : file.base
router.get('/' + route, ctx => send(ctx, file.full)) // tslint:disable-line:no-expression-statement
}
return router
}