teeny-express-server

0.1.1 • Public • Published

Teeny Static Server

npm version Dependency Status devDependency Status

Teeny Express Server is a simple configurable static server, powered by Express.

It provides some default out of the box:

  • Authentication via Passport
    • Registration
    • Registration verification
    • Session expiration
    • Login
    • Logout
    • Password recovery
  • Database persistence
  • Routes configuration
    • Static caching
    • GZIP compression
    • Automatic HTTPS redirection
    • Custom favicon
    • Authentication
    • Token verification (useful for registration)
    • Access to internal database API (proxied to either MongoDB or Lowdb)
      • findUser()
      • updateUser()
      • addUser()

Installation

> cd your-project
> npm install --save teeny-express-server

Starting

Assuming you created a configuration file under your-project/config.js, you can start your new server with the following command line:

> cd your-project
> npx teeny-express-server --config config.js

Configuration

The configuration file is a JavaScript module.

// my-project/config.js
const path = require("path");

module.exports = {
  /**
   * Port the server will listen to.
   */
  port: 3000,
  /**
   * Database configuration.
   */
  database: (DB_TYPE) => ({
    /**
     * The type of database to use for this project.
     * One of DB_TYPE.MONGODB or DB_TYPE.LOWDB.
     */
    type: DB_TYPE.MONGODB,
    /**
     * The location of the DB.
     * For LowDB, it needs to be the full path to a JSON file.
     * For MongoDB, it is only used in dev mode, and needs to be a folder.
     * In production, MongoDB with rely on the environment variable
     * ATLAS_DB_URI.
     */
    location: path.join(process.cwd(), "tmp/DB"),
  }),
  /**
   * Authentication redirects.
   * This object list all potential redirects for the following actions:
   * login, register, activate, forgot and update.
   */
  auth: {
    login: {
      /**
       * Where to redirect when login is successful.
       */
      successRedirectTo: "/",
      /**
       * Where to redirect when access requires authentication
       * and the user is not authenticated.
       */
      notAuthenticatedRedirectTo: "/login",
      /**
       * Where to redirect when login is not successful.
       * This can be for multiple reasons: user does not exist or password
       * is invalid. The parameter used here (auth=401) is simply an
       * example, but anything can be used instead.
       */
      failureRedirectTo: "/login?auth=401",
    },
    register: {
      /**
       * Where to redirect when a user has successfully registered a
       * new account (but not yet activated).
       */
      successRedirectTo: "/login?auth=201",
      /**
       * Where to redirect when a user has failed to registered a
       * new account. The reason is unknown (internal serve error).
       */
      failureRedirectTo: "/login?auth=500",
      /**
       * Where to redirect when a user has failed to registered a
       * new account. The reason is because the account already exists.
       */
      alreadyExistsRedirectTo: "/login?auth=403",
      /**
       * How to confirm the registration.
       * 2 choices:
       * - none: once someone registers, it's done!
       * - json: this adds one step to the registration process: activation.
       * By choosing json, the response from the registration will be a JSON
       * object with one key: "url" with an activation URL.
       * It's up to the implementer to use that URL and provide it to the
       * person who is registering. One way is to send an email with it.
       * Once this URL is hit, the account is activated and the user can
       * login. As long as this URL is not used, the account remains dormant.
       */
      confirmation: "json",
    },
    activate: {
      /**
       * Where to redirect to when a user is hitting the "activate" URL provided
       * during registration if the confirmation choice was "json" (see above).
       */
      successRedirectTo: "/",
      /**
       * Where to redirect to when a user is hitting an "activate " URL that is
       * invalid (invalid token, or it's been used before).
       */
      failureRedirectTo: "/login?auth=406",
    },
    forgot: {
      /**
       * Where to redirect to when a user ask for their password to be reset, but
       * the request failed.
       */
      failureRedirectTo: "/login?auth=500",
    },
    update: {
      /**
       * What is the corresponding static route where password reset activation
       * requests should be routed to. Please see the special "token" key provided
       * in the static route.
       */
      updatePassword: "/update",
      /**
       * Where to redirect to when password reset has been successful.
       */
      successRedirectTo: "/login?auth=202",
      /**
       * Where to redirect to when password reset has not been successful.
       */
      failureRedirectTo: "/login?auth=500",
    },
  },
  /**
   * What favicon to use for this application.
   */
  favicon: path.join(process.cwd(), "public/favicon.ico"),
  /**
   * List of static path that needs special caching. For example,
   * JavaScript, CSS or images files. Each routes can use the "utils" helper
   * that provides a few constants, such as times in milliseconds that can
   * be used for caching expiration (but you can use your own if needed):
   *  - utils.TWENTY_FOUR_HOURS
   *  - utils.TWO_WEEKS
   *  - utils.ONE_YEAR
   */
  static: ({ utils }) => [
    {
      /**
       * Use this option to create a virtual path prefix (where the path does
       * not actually exist in the file system) for files that are served.
       */
      virtual: "",
      /**
       * This specifies the root directory from which to serve static assets.
       */
      root: path.join(process.cwd(), "public/js"),
      /**
       * Set the max-age property of the Cache-Control header in milliseconds or
       * a string in ms format (see https://www.npmjs.com/package/ms).
       */
      maxAge: utils.isProd() ? utils.ONE_YEAR : 0,
    },
  ],
  /**
   * List of middleware and HTTP method routes (such as get, put, post, and so on).
   * Based on the keys provided, Teeny Static Server will interpret them as either
   * pure redirect to a static file or pure API request. If the special key "token"
   * is used and a token is available in the server (for example during activation),
   * it will be passed as a parameter to the corresponding URL, as in url?token=xxx.
   */
  routes: ({ utils }) => [
    /**
     * Example for a login page.
     * - route is the path to listen to
     * - method is the HTTP method (get, put, post, etc.)
     * - auth is a boolean indicating this route should not be protected by authentication
     * - file is the actual file to render when the route is resolved
     * - root is root directory from which to serve the file.
     */
    {
      route: "/login",
      method: "GET",
      auth: false,
      file: "login.html",
      root: path.join(process.cwd(), "public"),
    },
    /**
     * Example for a main page.
     * - route is the path to listen to
     * - method is the HTTP method (get, put, post, etc.)
     * - auth is a boolean indicating this route should be protected by authentication
     * - file is the actual file to render when the route is resolved
     * - root is root directory from which to serve the file.
     */
    {
      route: "/",
      method: "GET",
      auth: true,
      file: "index.html",
      root: path.join(process.cwd(), "public"),
    },
    /**
     * Example for a reset password page.
     * - route is the path to listen to
     * - method is the HTTP method (get, put, post, etc.)
     * - auth is a boolean indicating this route should not be protected by authentication
     * - token is a boolean indicating that any activation token should be passed as a param
     * - file is the actual file to render when the route is resolved
     * - root is root directory from which to serve the file.
     */
    {
      route: "/update",
      method: "GET",
      auth: false,
      token: true,
      file: "update.html",
      root: path.join(process.cwd(), "public"),
    },
    /**
     * Example for an API.
     * - route is the REST path
     * - method is the HTTP method (post)
     * - auth is a boolean indicating this route should be protected by authentication
     * - action is accepting a method to run, receiving req, res and next
     */
    {
      route: "/api/users",
      method: "POST",
      auth: true,
      action: (req, res, next) => {
        utils.db.findUser({ username: "testing" }, (err, user) => {
          res.send(err ? { status: "error" } : user);
        });
      },
    },
    /**
     * The last route should often be a catch all (*) and renders a 404 page.
     */
    {
      route: "*",
      method: "all",
      auth: false,
      file: "404.html",
      status: utils.constants.HTTP_NOT_FOUND,
      root: path.join(process.cwd(), "public"),
    },
  ],
};

Appendix

Mongo Shell

List all users

> mongo mongodb://localhost/teeny-server-s
MongoDB shell version v4.2.1
connecting to: mongodb://localhost:27017/teeny-server-s

db.users.find()

Readme

Keywords

none

Package Sidebar

Install

npm i teeny-express-server

Weekly Downloads

1

Version

0.1.1

License

MIT

Unpacked Size

35.1 kB

Total Files

15

Last publish

Collaborators

  • aversini