RESTful API Handler
Introduction
The RESTful-style API handler exposes CRUD APIs as RESTful endpoints using JSON:API as transportation format. The API handler is not meant to be used directly; instead, you should use it together with a server adapter which handles the request and response API for a specific framework.
It can be created as the following:
- Next.js
- SvelteKit
- Nuxt
import { NextRequestHandler } from '@zenstackhq/server/next';
import { RestApiHandler } from '@zenstackhq/server/api';
import { getPrisma } from '~/lib/db';
const handler = NextRequestHandler({
getPrisma,
useAppDir: true,
handler: RestApiHandler({ endpoint: 'http://myhost/api' })
});
export {
handler as GET,
handler as POST,
handler as PUT,
handler as PATCH,
handler as DELETE,
};
import { SvelteKitHandler } from '@zenstackhq/server/sveltekit';
import { RestApiHandler } from '@zenstackhq/server/api';
import { getPrisma } from './lib/db';
export const handle = SvelteKitHandler({
prefix: '/api/model',
getPrisma,
handler: RestApiHandler({ endpoint: 'http://myhost/api/model' })
});
import { createEventHandler } from '@zenstackhq/server/nuxt';
import { RestApiHandler } from '@zenstackhq/server/api';
import { getPrisma } from './lib/db';
export default createEventHandler({
handler: RestApiHandler({ endpoint: 'http://myhost/api/model' })
getPrisma
});
The factory function accepts an options object with the following fields:
-
endpoint
Required. A
string
field representing the base URL of the RESTful API, used for generating resource links. -
pageSize
Optional. A
number
field representing the default page size for listing resources and relationships. Defaults to 100. Set to Infinity to disable pagination.
Endpoints and Features
The RESTful API handler conforms to the the JSON:API v1.1 specification for its URL design and input/output format. The following sections list the endpoints and features are implemented. The examples refer to the following schema modeling a blogging app:
model User {
id Int @id @default(autoincrement())
email String
posts Post[]
}
model Profile {
id Int @id @default(autoincrement())
gender String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(false)
viewCount Int @default(0)
author User @relation(fields: [authorId], references: [id])
authorId Int
comments Comment[]
}
model Comment {
id Int @id @default(autoincrement())
content String
post Post @relation(fields: [postId], references: [id])
postId Int
}
Listing resources
A specific type of resource can be listed using the following endpoint:
GET /:type
Status codes
- 200: The request was successful and the response body contains the requested resources.
- 400: The request was malformed.
- 403: The request was forbidden.
- 404: The requested resource type does not exist.
- 422: The request violated data validation rules.
Examples
GET /post
{
"meta": {
"total": 1
},
"data": [
{
"attributes": {
"authorId": 1,
"published": true,
"title": "My Awesome Post",
"viewCount": 0
},
"id": 1,
"links": {
"self": "http://myhost/api/post/1"
},
"relationships": {
"author": {
"data": { "id": 1, "type": "user" },
"links": {
"related": "http://myhost/api/post/1/author/1",
"self": "http://myhost/api/post/1/relationships/author/1"
}
}
},
"type": "post"
}
],
"jsonapi": {
"version": "1.1"
},
"links": {
"first": "http://myhost/api/post?page%5Blimit%5D=100",
"last": "http://myhost/api/post?page%5Boffset%5D=0",
"next": null,
"prev": null,
"self": "http://myhost/api/post"
}
}
Fetching a resource
A unique resource can be fetched using the following endpoint:
GET /:type/:id