API Declr provides a declarative way to to implement schema-enforced API endpoints in Node.js projects. Written in TypeScript. Supports multiple web frameworks.
API Declr is opinionated; it aims to help backend developers implement overlooked REST API best practices such as HATEOAS (Hypermedia as the Engine of Application State).
Other than error handling (throwing instance of the ApiRequestError class), API Declr is designed to be used as a functional library, the two functions you will use are:
-
xApiEndpoint(...), wherexis your choice of (supported) web framework. This is the function you will use to implement the endpoint that will deal with a particular kind of API request (i.e. HTTP request method on a given path). -
apiResponseGenerator(...)is used to declare a function that produces a particular kind of response associated with a HTTP response status (e.g.200 OK). Response generator functions declared usingapiResponseGenerator(...)are called inside the request handler function (argument ofxApiEndpoint(...)) to produce a response. Another way to produce a response is to throw an instance of theApiRequestErrorclass.
More to come...
<root>/
├─ _/
│ ├─ endpoint/
│ │ ├─ tx-adapters/
│ │ │ ├─ next-response-adapter.ts
│ │ │ ├─ ...
│ ├─ error/
│ ├─ request/
│ ├─ response/
├─ next-api-endpoint.ts
├─ ...
-
The root folder contains source files that export API endpoint declarator functions for different web frameworks, e.g.
next-api-endpoint.tsexports a function by the same name that is used to declare an endpoint in Next.js projects (i.e. usesNextRequestclass to produce instance ofNextResponse).-
Folders named
_represent underlying source dependency of the module represented by the current folder. -
The
_/endpoint/tx-adaptersfolder contains source files that export transmission adapters used by the*-ap-endpoint.tssource files. Transmission adapters (TxAdapter) are functions that transform the response object (ApiResponseSpec) produced by the handler function (ApiRequestHandlerFn, an argument to the declarator function) to a format suitable for the specific web framework. E.g.next-response-adapter.tsexports a function callednextResponseAdapter(as typeTxAdapterFn) which converts a response object to an instance ofNextResponse.
-
-
The
errorfolder provisions the Error classApiRequestErrorwhich is thrown inside the handler function to produce an error response. Errors are enumerated in_/error/_/errors-map.ts.
Create an API endpoint GET /api/hello using the App Router by creating the file <root>/src/app/api/hello/route.ts:
import {
apiResponseGeneratorFn,
nextApiEndpoint,
} from "@/libs/utils/api-endpoint/next-api-endpoint";
import { z } from "zod";
export const GET = nextApiEndpoint({
method: "GET",
path: "/hello",
requestSchema: {
body: z.null(),
headers: z.object({}),
pathParams: z.object({}),
queryParams: z.object({
name: z.string().optional(),
}),
},
responseGenerators: {
OK: apiResponseGeneratorFn("OK", {
body: z.object({
message: z.string(),
}),
headers: z.object({}),
})(async (name?: string) => ({
status: "OK",
body: {
message: name ? `Hello, ${name}!` : `Hello, you!`,
},
headers: {},
})),
},
})(
async ({ generators, params }) =>
await generators.OK(params.queryParams.name)
);The endpoint will respond with the following response, where "Hello, you!" will be replaced by "Hello, <name>!" if name is passed as a query argument on the request URL:
{
"status": "OK",
"statusCode": 200,
"statusType": "SUCCESS",
"data": {
"message": "Hello, you!"
}
}-
Internal: Not applicable
-
External: