Web开发的景观在不断变化。我们从提供静态HTML页面的裸金属机开始,到灯堆的上升,然后是平均堆栈,现在是果酱堆栈。
在不同级别的情况下,有两个趋势正在发展:
-
结构的合并
开发人员对在应用程序中将许多不同的作品结合在一起感到厌倦。他们已经开始更少的支持:统一的编程语言,单声波,元框架(例如next.js),甚至没有明确编码后端的构建Web应用程序。
-
SQL数据库的复兴
SQL数据库可能从来没有真正失去NOSQL的任何基础;从时尚的角度来看,使用一段时间就变得不那么酷了。现在,随着越来越多的人意识到,很少有网络应用程序确实是“ Web量表”,而关系数据库仍然是大多数用例的最佳选择,SQL数据库正在卷土重来。
在这篇文章中,我将分享Prisma和ZenStack的组合与上述两个趋势相对应,以及它们如何帮助您以更少的精力来建立安全的后端。
什么是Prisma
Prisma是JavaScript/Tyspript的ORM工具包。 ORM是一种库,可让您无需编写SQL即可访问数据库。相反,您以与应用程序的其余部分相同的语言编写代码来操纵数据库,ORM库将其转换为SQL查询。
更具体地说,Prisma是模式优先的ORM,这意味着您首先在模式文件中定义数据模型,然后Prisma为您生成数据库架构和相应的CRUD操作。相反,另一个ORM类别是代码优先:您在编程语言(例如Typescript)中定义数据模型,而ORM则侵入数据库架构。
选择模式优先或代码优先是一个优先问题,尽管模式优先的ORM具有更连贯,简洁且易于阅读的好处。
什么是Zenstack
ZenStack是Prisma的扩展,增加了一层安全性。它允许您在架构文件中定义访问控制规则并在运行时注入Prisma查询。
此外,它提供了一个恢复的API来访问数据库并为您的前端代码生成客户端库。通过结合访问控制和API生成,Zenstack使得拥有完全安全的CRUD后端而不手动实施。
他们如何一起工作
Prisma和Zenstack非常适合使用关系数据库建立安全的后端。这是实现它的一般步骤:
1.定义数据模型
使用 zmodel 语言(Prisma架构的超集)来定义您的模型,关系和访问策略。可选,如果您将next.js用作全堆栈框架,请启用React插件来生成数据访问客户端挂钩。
// schema.zmodel
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String
// author has full access
@@allow('all', auth() == author)
// logged-in users can view published posts
@@allow('read', auth() != null && published)
}
// generate react hooks under ./src/lib/hook
plugin reactHooks {
provider = '@zenstackhq/react'
output = "./src/lib/hook
}
2.运行代码生成
使用zenstack
cli生成多个代码:
- 棱镜模式(schema.prism)
- Prisma客户
- 在运行时注入Prisma查询的访问策略
- 数据访问的钩子
您可以使用生成的schema.prisma
迁移数据库的架构和PRISMA客户端,以无需任何访问控制即可访问数据库。您将看到访问策略和反应挂钩接下来的帮助。
3.安装数据访问API
使用特定于框架的软件包安装数据访问API请求处理程序。通常,您通常会使用“增强” Prisma客户端来初始化请求处理程序以保护端点。 “增强”通过加载上一步中生成的访问策略,拦截Prisma客户的操作并注入额外的查询/突变条件来起作用。
这是Next.js:
的示例
// pages/api/model/[...path].ts
// the standard Prisma client
const prisma = new PrismaClient();
// create a Next.js API endpoint handler
export default requestHandler({
// set up a callback to get a database instance for handling the request
getPrisma: async (req, res) => {
// get current user in the session
const user = await getSessionUser(req, res);
// return an enhanced Prisma client that enforces access policies
return withPresets(prisma, { user });
},
});
4.使用生成的钩子访问数据
使用生成的钩子轻松构建UI零件。挂钩与上一步中安装的数据访问API对话。由于访问策略已经安全了API,因此挂钩将仅返回可读取的实体,并拒绝任何未经授权的突变。
// /src/components/posts.tsx
import { usePost } from '../lib/hooks';
const Posts: FC = () => {
// "usePost" is a generated hooks method
const { findMany } = usePost();
// list unpublished posts together with their author's data,
// the result "posts" only include entities that are readable
// to the current user
const posts = findMany({
where: { published: false },
include: { author: true },
orderBy: { updatedAt: 'desc' },
});
// entities are accurately typed based on the query structure
// posts: Array<Post & { author: user }>
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.title} by {post.author.e}
</li>
))}
</ul>
);
};
他们为什么提高您的生产力?
Prisma和Zenstack的组合以几种方式提高了您的发展生产率:
1.您的数据模型的清晰图片
使用DSL来建模您的实体,您始终对应用程序的数据模型进行了明确的描述。
2.靠近数据库的保障
安全性很难部分,因为必须在所有相关的API中始终应用规则。通过声明性地对安全性进行建模,您可以在数据库附近进行保护,并可以避免在添加或更新API时忘记添加必要检查的风险。当需求变化时,调整规则也更容易,因为模式是您的单一真实来源。
3.免费
Prisma客户端(后端)Typescript API提供了出色的类型安全性。感谢Zenstack的客户库一代,您现在可以在前端代码中享受相同的编程体验。
这对我来说是个好选择吗?
Prisma + Zenstack如果适用以下某些情况,可以非常适合您的项目:
- 您想要一个简单的体系结构,并希望完全使用元框架(例如Next.js或remix.run)构建全堆栈Web应用程序,而无需单独的后端。
- 您的应用程序具有非平凡的安全要求。
- 您不是SQL GURU,希望尽可能避免使用复杂的SQL任务。否则,Supabase或PostgREST可能是一个更好的选择。
- 您想避免被锁定在特定的数据库类型或霍斯特中。
包起来
Prisma和Zenstack是通过关系数据库建立安全后端的绝佳组合。希望您发现它对您的下一个项目有用。