seagull-js/seagull

View on GitHub
packages/routes/src/RouteContext.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { PageType, render } from '@seagull/pages'
import { Request, Response } from 'express'
import * as fs from 'fs'
import { Container } from 'inversify'
import { isString } from 'lodash'
import * as rfs from 'require-from-string'

/*
 * Class wrapping a express request and response.
 * Provides functionality to everything you might want to do in context of a request.
 */
export class RouteContext {
  request: Request
  response: Response
  injector = new Container()

  constructor(request: Request, response: Response) {
    this.request = request
    this.response = response
  }

  // returns plain text
  text(this: RouteContext, data: string) {
    this.response.type('txt')
    this.response.send(data)
  }

  // returns an error message
  error(message: string = 'internal server error') {
    this.response.status(500)
    this.response.send(message)
  }

  // send response as HTML
  html(data: string) {
    this.response.type('html')
    this.response.send(data)
  }

  // return data as JSON response
  json(data: any) {
    this.response.json(data)
  }

  // send notFound error
  missing(message: string = 'not found') {
    this.response.status(404)
    this.response.send(message)
  }

  // redirect to other path with 301 (permanent) or 302
  redirect(path: string, permanent: boolean = true) {
    const code = permanent ? 301 : 302
    this.response.redirect(code, path)
  }

  // render a Page with data
  render(src: string | PageType, data: any) {
    const renderer: any = isString(src) ? this.renderUMD : this.renderPage
    data = Object.assign(data, { path: this.request.url })
    const html = renderer(src, data)
    this.response.type('html')
    this.response.send(html)
  }

  private renderUMD(pageSource: string, data: any) {
    const pagePath = `${process.cwd()}/dist/assets/pages/${pageSource}.js`
    const pagePathServer = pagePath.replace('.js', '-server.js')
    const pageBlob = fs.readFileSync(pagePath, 'utf-8')
    const pageBlobServer = fs.readFileSync(pagePathServer, 'utf-8')
    const renderPageBundle = rfs(pageBlobServer).__renderPage as any
    return renderPageBundle(pageBlob, data)
  }

  private renderPage(pageSource: PageType, data: any) {
    return render('', pageSource, data)
  }
}