Home Reference Source

terrier-repo/mod.ts

import { ServerRequest, Response } from "./package.ts";

/**
 * Web framework for Deno
 * @example
 * const app = new Terrier();
 */
export class Terrier {
  /**
   * Middleware stack
   * @protected
   */
  protected stack: Function[];
  /**
   * Error handler
   */
  errHandler: Function;

  /**
   * Initiate Terrier with an optional error handler
   * @param errHandler An optional error handler when something goes wrong.
   */
  constructor(errHandler: Function = null) {
    this.stack = [];
    this.errHandler = errHandler || this.defaultErrHandler;
  }

  /**
   * Push to the middleware stack
   * @param middleware The piece of middleware you are wanting to push
   */
  public use = (middleware: Function) => {
    this.stack.push(middleware);
  };

  /**
   * Callback to be used when starting the HTTP server
   * @param req Request object sent by HTTP server
   * @example
   * http.listenAndServe(":8080", app.callback);
   */
  public callback = (req: ServerRequest) => {
    let res: Response = {
      status: 200,
      headers: new Headers(),
      body: null
    };
    let idx: number = 0;

    const next = (err: Error = null) => {
      if (err != null) {
        return this.errHandler(req, res, err);
      }
      if (idx >= this.stack.length) {
        return;
      }

      const layer = this.stack[idx++];
      try {
        layer(req, res, next);
      } catch (error) {
        next(error);
      }
    };

    next();
  };

  /**
   * Default error handler if nothing is specified in constructor
   * @protected
   * @param req Request object sent by HTTP server
   * @param res Response object sent by middleware
   */
  protected defaultErrHandler = (req: ServerRequest, res: Response) => {
    const enc = new TextEncoder();
    res.status = 500;
    res.body = enc.encode("500 Internal Server Error");
    req.respond(res);
  };
}