Skip to content

Latest commit

 

History

History
203 lines (141 loc) · 6.24 KB

README.md

File metadata and controls

203 lines (141 loc) · 6.24 KB

Houston

🚨 We have an application/problem+json!

npm npm bundle size npm install size maintainability code coverage vulnerabilities dependencies

🚀 Quick Start

Install

# npm
npm i @moducate/houston

# or yarn
yarn add @moducate/houston

Import

// ESM / TypeScript
import { withError } from "@moducate/houston";

// or CommonJS
const { withError } = require("@moducate/houston");

📄 Templates

You can create error templates using the exported withTemplate function:

const { withTemplate } = require("@moducate/houston");
const app = require("express")();

const [withUserNotFound, rawUserNotFound] = withTemplate(({ userId }) => ({
  type: "https://example.com/user-not-found",
  status: 404,
  instance: `/users/${userId}`,
}));

app.get("/not-found", (_, res) => {
  return withUserNotFound(res, { userId: 1 });
});

const res = rawUserNotFound({ userId: 1 });
// => The second function returned by withTemplate transforms and returns an object (decoupled from http.ServerResponse)

console.log(JSON.stringify(res));
// => { "type": "https://example.com/user-not-found", "status": 404, "instance": "/users/1" }

If you are not needing to use both functions, you can use this handy shorthand to obtain one of them:

const { withTemplate } = require("@moducate/houston");

const [withNotFound] = withTemplate(() => ({ type: "https://example.com/not-found", status: 404 }));
// => Returns the function that transforms a http.ServerResponse

const [, withNotFound] = withTemplate(() => ({ type: "https://example.com/not-found", status: 404 }));
// => Returns the raw function for transforming an object

💪 TypeScript

withTemplate supports TypeScript generics so you can have type definitions for your template's parameters:

const [withUserNotFound] = withTemplate<{ userId: number }>(({ userId }) => ({
  type: "https://example.com/user-not-found",
  status: 404,
  instance: `/users/${userId}`,
}));
// => withUserNotFound's second parameter (`params`) now has the type `{ userId: number }`

🏷 MIME Type

The exported mime constant can be used to obtain the media/MIME type for RFC 7807 JSON errors.

const { mime } = require("@moducate/houston");

console.log(mime);
// => 'application/problem+json'

This is what the Content-Type header of the response supplied to withError is set to.

🛠 Options

You can supply options as an additional parameter to withError and withTemplate (and the subsequent withError function returned by the template) to configure Houston's behaviour:

...

withError(
  res,
  { type: "https://example.com/not-found", status: 404 },
  { /* options */ },
);

...

options.stringify

You can supply a custom function used to stringify the error response's JSON body.

By default, JSON.stringify is used.

💡 Examples

📁 Full source code for these examples can be found in the examples directory.

Express

const { withError } = require("@moducate/houston");
const app = require("express")();

app.get("/not-found", (_, res) => {
  return withError(res, { type: "https://example.com/not-found", status: 404 });
});

Next.js API Routes

import { withError } from "@moducate/houston/nextjs";

export default function handler(req, res) {
  return withError(req, res, { type: "https://example.com/not-found", status: 404 });
}

Cloudflare Workers

import { withError } from "@moducate/houston/cf-workers";

addEventListener("fetch", event => {
  return withError(event, { type: "https://example.com/not-found", status: 404 });
});

Netlify Functions

import { withError } from "@moducate/houston/netlify";
import type { Handler } from "@netlify/functions";

const handler: Handler = async (event, context) => {
  return withError(event, { type: "https://example.com/not-found", status: 404 });
};

export { handler };

Fastify

⚠ Fastify uses a custom Reply class, rather than http.ServerResponse.

This means you need to supply reply.raw (instead of reply) to withError().

const { withError } = require("@moducate/houston");
const app = require("fastify")();

app.get("/not-found", (_, reply) => {
  return withError(reply.raw, { type: "https://example.com/not-found", status: 404 });
});

fast-json-stringify

See the examples/fast-json-stringify directory for an example project using Houston with Fastify and fast-json-stringify.

Templates

See the examples/templates directory for an example project using Houston's templating functionality with Express.

⚖ License

Houston is licensed under the MIT License.