Koa Integration
This package provides middleware and helpers for integrating @jsonapi-serde/server
seamlessly with Koa. It simplifies handling JSON:API request parsing, response serialization, and error handling in your Koa apps.
Installation
$ npm add @jsonapi-serde/integration-koa
$ pnpm add @jsonapi-serde/integration-koa
$ yarn add @jsonapi-serde/integration-koa
$ bun add @jsonapi-serde/integration-koa
Middleware
jsonApiRequestMiddleware
Adds JSON:API content negotiation support by parsing the Accept
header and exposing acceptable media types on ctx.state.jsonApi.acceptableTypes
.
If the Accept
header is malformed or unsupported, it responds with a JSON:API error document (400 Bad Request
).
import Koa from "koa";
import { jsonApiRequestMiddleware } from "@jsonapi-serde/integration-koa";
const app = new Koa();
app.use(jsonApiRequestMiddleware());
jsonApiErrorMiddleware
Catches errors thrown during request handling and formats them as JSON:API error documents.
You can optionally provide a logger callback:
import { jsonApiErrorMiddleware } from "@jsonapi-serde/integration-koa";
app.use(jsonApiErrorMiddleware({
logError: (error, exposed) => {
if (!exposed) {
console.error(error);
}
}
}));
Request & Response Helpers
bodyContext(ctx: Koa.Context): BodyContext
Extracts the raw request body and Content-Type
header from the Koa context into a shape suitable for use with @jsonapi-serde/server
parsers.
import { bodyContext } from "@jsonapi-serde/integration-koa";
const parsed = parseResourceRequest(
bodyContext(ctx),
{ type: "article", attributesSchema: articleAttributesSchema }
);
NOTE
You must use Koa's bodyParser
before this helper.
sendJsonApiResponse(ctx: Koa.Context, document: JsonApiDocument)
Sends a JSON:API response document, sets status, body, and Content-Type
header accordingly.
Automatically validates the Accept
header media types set by jsonApiRequestMiddleware
.
NOTE
You must use jsonApiRequestMiddleware
before this helper.
Integration with koa-tree-router
The package provides treeRouterMethodNotAllowedHandler
to handle unsupported HTTP methods on routes, returning proper JSON:API errors.
import { treeRouterMethodNotAllowedHandler } from "@jsonapi-serde/integration-koa/tree-router";
import Router from "koa-tree-router";
const router = new Router({ onMethodNotAllowed: treeRouterMethodNotAllowedHandler });
Full Example
import Koa from "koa";
import Router from "koa-tree-router";
import { bodyParser } from "@koa/bodyparser";
import {
jsonApiRequestMiddleware,
jsonApiErrorMiddleware,
bodyContext,
sendJsonApiResponse,
treeRouterMethodNotAllowedHandler
} from "@jsonapi-serde/integration-koa";
import { parseResourceRequest, SerializeBuilder } from "@jsonapi-serde/server";
import { z } from "zod";
import { SerializeBuilder } from "./serializer";
const app = new Koa();
const router = new Router({onMethodNotAllowed: treeRouterMethodNotAllowedHandler});
// Populate your entity serializers
const serialize = SerializeBuilder.new().build();
const articleAttributesSchema = z.object({
title: z.string(),
content: z.string(),
});
app.use(jsonApiRequestMiddleware());
app.use(jsonApiErrorMiddleware());
app.use(bodyParser());
router.post("/articles", async (context) => {
const {attributes} = parseResourceRequest(bodyContext(context), {
type: "article",
attributesSchema: ArticleSchema,
});
const savedArticle = {
id: "1",
...attributes,
};
sendJsonApiResponse(context, serialize({
type: "article",
id: savedArticle.id,
attributes,
}));
});
app.use(router.routes());
app.listen(3000);