ZenStack is a toolkit that simplifies the development of a web app's backend. It supercharges Prisma ORM with a powerful access control layer and unleashes its full potential for web development.
Our goal is to let you save time writing boilerplate code and focus on building real features!
ZenStack extended Prisma schema language for supporting custom attributes and functions and, based on that, implemented a flexible access control layer around Prisma.
// schema.zmodel
model Post {
id String @id
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String
// 🔐 allow logged-in users to read published posts
@@allow('read', auth() != null && published)
// 🔐 allow full CRUD by author
@@allow('all', author == auth())
}
At runtime, transparent proxies are created around Prisma clients for intercepting queries and mutations to enforce access policies. Moreover, framework integration packages help you wrap an access-control-enabled Prisma client into backend APIs that can be safely called from the frontend.
// Next.js example: pages/api/model/[...path].ts
import { requestHandler } from '@zenstackhq/next';
import { withPolicy } from '@zenstackhq/runtime';
import { getSessionUser } from '@lib/auth';
import { prisma } from '@lib/db';
export default requestHandler({
getPrisma: (req, res) => withPolicy(prisma, { user: getSessionUser(req, res) }),
});
Plugins can generate strong-typed client libraries that talk to the APIs:
// React example: components/MyPosts.tsx
import { usePost } from '@lib/hooks';
const MyPosts = () => {
// Post CRUD hooks
const { findMany } = usePost();
// list all posts that're visible to the current user, together with their authors
const { data: posts } = findMany({
include: { author: true },
orderBy: { createdAt: 'desc' },
});
return (
<ul>
{posts?.map((post) => (
<li key={post.id}>
{post.title} by {post.author.name}
</li>
))}
</ul>
);
};
The following diagram gives a high-level overview of how it works.
- Access control and data validation rules right inside your Prisma schema
- Auto-generated OpenAPI (RESTful) specifications, services, and client libraries
- End-to-end type safety
- Extensible: custom attributes, functions, and a plugin system
- A framework-agnostic core with framework-specific adapters
- Uncompromised performance
- Prisma schema generator
- Zod schema generator
- React hooks generator
- OpenAPI specification generator
- tRPC router generator
- 🙋🏻 Request for a plugin
- Next.js
- Fastify
- ExpressJS
- Nuxt.js (Future)
- SvelteKit (Future)
- 🙋🏻 Request for an adapter
- Custom attributes and functions
- Multi-file schema (coming soon)
- String-typed JSON field (coming soon)
- 🙋🏻 Request for an extension
Check out the Collaborative Todo App for a running example. You can find the source code below:
Join our discord server for chat and updates!