Skip to content

Minimalist serverless middleware and utilities.

Notifications You must be signed in to change notification settings

front-of-house/hypr

Repository files navigation

hypr

npm version test coverage npm bundle size

Minimalist serverless middleware and utilities. Get started instantly with Presta.

npm i hypr

Usage

Define a stack of serverless handlers. Middleware handlers should mutate event and context. All returned responses are deeply merged and returned to the client.

import * as hypr from 'hypr'
import { helmet } from 'hypr/helmet'

export const route = '*'

export const handler = hypr.stack([
  (event, context) => {
    const user = getLoggedInUser(event) // your code here
    context.user = user
  },
  (event, context) => {
    return {
      json: { message: `Hello, ${context.user.firstName}!` }
    }
  }
  helmet(),
])

To define specific HTTP methods, use hypr.main.

export const handler = hypr.stack([
  hypr.main({
    get(event, context) {
      return {
        json: { message: 'GET request' }
      }
    },
    post(event, context) {
      return {
        json: { message: 'POST request' }
      }
    }
  }),
  ...
])

For errors, throw a HttpError.

const authMiddleware = (event, context) => {
  const user = getLoggedInUser(event) // your code here
  context.user = user
}

const authGuard = (event, context) => {
  if (!context.user) {
    throw new hypr.HttpError(401, 'You are not authorized to view this page')
  }
}

export const handler = hypr.stack([
  authMiddleware,
  authGuard,
  (event, context) => {
    return {
      json: { message: `You are authenticated.` },
    }
  },
])

You can also pass JSON to HttpError.

throw new hypr.HttpError(400, {
  code: `auth`,
  error: `You are not authorized to view this page`,
})

Available middlewares

Hypr bundles a few useful middlewares.

hypr/helmet

Protect your APIs with common security headers. Inspired by helmet.

import { stack, main } from 'hypr'
import { helmet } from 'hypr/helmet'

export const handler = stack([
  main(...),
  helmet(),
])

hypr/cookies

Parse and serialize cookies using sugarcookie. thaw and bake are just aliases for parse and serialize exports.

import { stack, main } from 'hypr'
import { thaw, bake } from 'hypr/cookies'

export const handler = stack([
  thaw(), // reads from `event.headers.cookie`
  main((event) => {
    const { session_id } = event.cookies
    const { id, expiresAt } = refreshSession(session_id)

    return {
      statusCode: 204,
      cookies: {
        // shorthand, no options
        cookie_name: 'value',
        // with options
        session_id: [
          id,
          {
            expires: expiresAt,
            secure: true,
            httpOnly: true,
          },
        ],
      },
    }
  }),
  bake(), // serializes to response.headers['set-cookie']
])

Creating middleware

Middleware run before and/or after any main handlers. Anything running before should attach props to event or context. Anything running after should read values from the response and merge in new values.

For this reason, middlewares are passed a third, non-standard, parameter response. See the available cookie middleware for examples.

import { createHandler } from 'hypr'

export const set204IfNoBodyMiddleware = createHandler((options) => {
  return (event, context, response) => {
    if (!response.body) {
      return { statusCode: 204 }
      // or mutate with response.statusCode = 204
    }
  }
})

License

MIT License © Sure Thing