UNPKG

zenstack

Version:

FullStack enhancement for Prisma ORM: seamless integration from database to UI

278 lines (205 loc) 11.6 kB
<div align="center"> <a href="https://zenstack.dev"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/zenstackhq/zenstack-docs/main/static/img/logo-dark.png"> <img src="https://raw.githubusercontent.com/zenstackhq/zenstack-docs/main/static/img/logo.png" height="128"> </picture> </a> <h1>ZenStack</h1> <a href="https://www.npmjs.com/package/zenstack"> <img src="https://img.shields.io/npm/v/zenstack"> </a> <a href="https://www.npmjs.com/package/zenstack"> <img src="https://img.shields.io/npm/dm/zenstack"> </a> <img src="https://github.com/zenstackhq/zenstack/actions/workflows/build-test.yml/badge.svg"> <a href="https://twitter.com/zenstackhq"> <img src="https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2Fzenstackhq%2Fzenstack"> </a> <a href="https://discord.gg/Ykhr738dUe"> <img src="https://img.shields.io/discord/1035538056146595961"> </a> <a href="https://github.com/zenstackhq/zenstack/blob/main/LICENSE"> <img src="https://img.shields.io/badge/license-MIT-green"> </a> </div> ## What it is ZenStack is a Node.js/TypeScript toolkit that simplifies the development of web applications. It enhances [Prisma ORM](https://prisma.io) with a flexible Authorization layer and auto-generated, type-safe APIs/hooks, unlocking its full potential for full-stack development. Our goal is to let you save time writing boilerplate code and focus on building real features! ## How it works > Read full documentation at 👉🏻 [zenstack.dev](https://zenstack.dev). Join [Discord](https://discord.gg/Ykhr738dUe) for feedback and questions. ZenStack incrementally extends Prisma's power with the following four layers: ### 1. ZModel - an extended Prisma schema language ZenStack introduces a data modeling language called "ZModel" - a superset of Prisma schema language. It extended Prisma schema with custom attributes and functions and, based on that, implemented a flexible access control layer around Prisma. ```ts // base.zmodel abstract model Base { id String @id author User @relation(fields: [authorId], references: [id]) authorId String // 🔐 allow full CRUD by author @@allow('all', author == auth()) } ``` ```ts // schema.zmodel import "base" model Post extends Base { title String published Boolean @default(false) // 🔐 allow logged-in users to read published posts @@allow('read', auth() != null && published) } ``` The `zenstack` CLI transpiles the ZModel into a standard Prisma schema, which you can use with the regular Prisma workflows. ### 2. Runtime enhancements to Prisma client At runtime, transparent proxies are created around Prisma clients for intercepting queries and mutations to enforce access policies. ```ts import { enhance } from '@zenstackhq/runtime'; // a regular Prisma client const prisma = new PrismaClient(); async function getPosts(userId: string) { // create an enhanced Prisma client that has access control enabled const enhanced = enhance(prisma, { user: userId }); // only posts that're visible to the user will be returned return enhanced.post.findMany(); } ``` ### 3. Automatic RESTful APIs through server adapters Server adapter packages help you wrap an access-control-enabled Prisma client into backend CRUD APIs that can be safely called from the frontend. Here's an example for Next.js: ```ts // pages/api/model/[...path].ts import { requestHandler } from '@zenstackhq/next'; import { enhance } from '@zenstackhq/runtime'; import { getSessionUser } from '@lib/auth'; import { prisma } from '@lib/db'; // Mount Prisma-style APIs: "/api/model/post/findMany", "/api/model/post/create", etc. // Can be configured to provide standard RESTful APIs (using JSON:API) instead. export default requestHandler({ getPrisma: (req, res) => enhance(prisma, { user: getSessionUser(req, res) }), }); ``` ### 4. Generated client libraries (hooks) for data access Plugins can generate strong-typed client libraries that talk to the aforementioned APIs. Here's an example for React: ```tsx // components/MyPosts.tsx import { useFindManyPost } from '@lib/hooks'; const MyPosts = () => { // list all posts that're visible to the current user, together with their authors const { data: posts } = useFindManyPost({ include: { author: true }, orderBy: { createdAt: 'desc' }, }); return ( <ul> {posts?.map((post) => ( <li key={post.id}> {post.title} by {post.author.name} </li> ))} </ul> ); }; ``` ## Architecture The following diagram gives a high-level architecture overview of ZenStack. ![Architecture](https://zenstack.dev/img/architecture-light.png) ## Links - [Home](https://zenstack.dev) - [Documentation](https://zenstack.dev/docs) - [Community chat](https://discord.gg/Ykhr738dUe) - [Twitter](https://twitter.com/zenstackhq) - [Blog](https://zenstack.dev/blog) ## Features - 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 ### Plugins - Prisma schema generator - [Zod](https://zod.dev/) schema generator - [SWR](https://github.com/vercel/swr) and [TanStack Query](https://github.com/TanStack/query) hooks generator - OpenAPI specification generator - [tRPC](https://trpc.io) router generator - 🙋🏻 [Request for a plugin](https://discord.gg/Ykhr738dUe) ### Framework adapters - [Next.js](https://zenstack.dev/docs/reference/server-adapters/next) - [Nuxt](https://zenstack.dev/docs/reference/server-adapters/nuxt) - [SvelteKit](https://zenstack.dev/docs/reference/server-adapters/sveltekit) - [Fastify](https://zenstack.dev/docs/reference/server-adapters/fastify) - [ExpressJS](https://zenstack.dev/docs/reference/server-adapters/express) - [NestJS](https://zenstack.dev/docs/reference/server-adapters/nestjs) - [Hono](https://zenstack.dev/docs/reference/server-adapters/hono) - 🙋🏻 [Request for an adapter](https://discord.gg/Ykhr738dUe) ### Prisma schema extensions - [Custom attributes and functions](https://zenstack.dev/docs/reference/zmodel-language#custom-attributes-and-functions) - [Multi-file schema and model inheritance](https://zenstack.dev/docs/guides/multiple-schema) - [Polymorphic Relations](https://zenstack.dev/docs/guides/polymorphism) - [Strongly typed JSON field](https://zenstack.dev/docs/guides/typing-json) - [Field encryption](https://zenstack.dev/docs/guides/field-encryption) - 🙋🏻 [Request for an extension](https://discord.gg/Ykhr738dUe) ## Examples ### Schema Samples The [sample repo](https://github.com/zenstackhq/authz-modeling-samples) includes the following patterns: - ACL - RBAC - ABAC - Multi-Tenancy You can use [this blog post](https://zenstack.dev/blog/model-authz) as an introduction. ### Multi-Tenant Todo App Check out the [Multi-tenant Todo App](https://zenstack-todo.vercel.app/) for a running example. You can find different implementations below: - [Next.js + NextAuth + TanStack Query](https://github.com/zenstackhq/sample-todo-nextjs-tanstack) - [Next.js + NextAuth + SWR](https://github.com/zenstackhq/sample-todo-nextjs) - [Next.js + NextAuth + tRPC](https://github.com/zenstackhq/sample-todo-trpc) - [Nuxt + TanStack Query](https://github.com/zenstackhq/sample-todo-nuxt) - [SvelteKit + TanStack Query](https://github.com/zenstackhq/sample-todo-sveltekit) - [RedwoodJS](https://github.com/zenstackhq/sample-todo-redwood) ### Blog App - [Next.js + App Route + TanStack Query](https://github.com/zenstackhq/docs-tutorial-nextjs-app-dir) - [Next.js + Pages Route + SWR](https://github.com/zenstackhq/docs-tutorial-nextjs) - [Next.js + App Route + tRPC](https://github.com/zenstackhq/sample-blog-nextjs-app-trpc) - [Nuxt + TanStack Query](https://github.com/zenstackhq/docs-tutorial-nuxt) - [SvelteKit](https://github.com/zenstackhq/docs-tutorial-sveltekit) - [Remix](https://github.com/zenstackhq/docs-tutorial-remix) - [NestJS Backend API](https://github.com/zenstackhq/docs-tutorial-nestjs) - [Express Backend API](https://github.com/zenstackhq/docs-tutorial-express) - [Clerk Integration](https://github.com/zenstackhq/docs-tutorial-clerk) ## Community Join our [discord server](https://discord.gg/Ykhr738dUe) for chat and updates! ## Contributing If you like ZenStack, join us to make it a better tool! Please use the [Contributing Guide](CONTRIBUTING.md) for details on how to get started, and don't hesitate to join [Discord](https://discord.gg/Ykhr738dUe) to share your thoughts. Documentations reside in a separate repo: [zenstack-docs](https://github.com/zenstackhq/zenstack-docs). Please also consider [sponsoring our work](https://github.com/sponsors/zenstackhq) to speed up the development. Your contribution will be 100% used as a bounty reward to encourage community members to help fix bugs, add features, and improve documentation. ## Sponsors Thank you for your generous support! ### Current Sponsors <table> <tr> <td align="center"><a href="https://suhyl.com/"><img src="https://avatars.githubusercontent.com/u/124434734?s=200&v=4" width="100" style="border-radius:50%" alt="Suhyl"/><br />Suhyl</a></td> <td align="center"><a href="https://www.marblism.com/"><img src="https://avatars.githubusercontent.com/u/143199531?s=200&v=4" width="100" style="border-radius:50%" alt="Marblism"/><br />Marblism</a></td> <td align="center"><a href="https://www.mermaidchart.com/"><img src="https://avatars.githubusercontent.com/u/117662492?s=200&v=4" width="100" style="border-radius:50%" alt="Mermaid Chart"/><br />Mermaid Chart</a></td> <td align="center"><a href="https://coderabbit.ai/"><img src="https://avatars.githubusercontent.com/u/132028505?v=4" width="100" style="border-radius:50%" alt="CodeRabbit"/><br />CodeRabbit</a></td> <td align="center"><a href="https://github.com/j0hannr"><img src="https://avatars.githubusercontent.com/u/52762073?v=4" width="100" style="border-radius:50%" alt="Johann Rohn"/><br />Johann Rohn</a></td> </tr> </table> ### Previous Sponsors <table> <tr> <td align="center"><a href="https://github.com/baenie"><img src="https://avatars.githubusercontent.com/u/58309104?v=4" width="100" style="border-radius:50%" alt="Benjamin Zecirovic"/><br />Benjamin Zecirovic</a></td> <td align="center"><a href="https://github.com/umussetu"><img src="https://avatars.githubusercontent.com/u/152648499?v=4" width="100" style="border-radius:50%" alt="Ulric"/><br />Ulric</a></td> <td align="center"><a href="https://github.com/iamfj"><img src="https://avatars.githubusercontent.com/u/24557998?v=4" width="100" style="border-radius:50%" alt="Fabian Jocks"/><br />Fabian Jocks</a></td> </tr> </table> ## Contributors Thanks to all the contributors who have helped make ZenStack better! #### Source <a href="https://github.com/zenstackhq/zenstack/graphs/contributors"> <img src="https://contrib.rocks/image?repo=zenstackhq/zenstack" /> </a> #### Docs <a href="https://github.com/zenstackhq/zenstack-docs/graphs/contributors"> <img src="https://contrib.rocks/image?repo=zenstackhq/zenstack-docs" /> </a> ## License [MIT](LICENSE)