
Wasp 数据模型实战用 Entity 与 Prisma Schema 构建应用的数据库基石【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp导读Entity实体是 Wasp 应用数据模型的根基——它定义了数据库中的表结构与关系。Wasp 基于 Prisma ORM 实现全部数据库能力你在项目根目录的schema.prisma文件中以 Prisma Schema Language 声明模型Wasp 会将其识别为 Entity 并自动生成类型安全的数据库访问代码。读完本文你将掌握在 Wasp 项目中定义 Entity、通过wasp db migrate-dev同步数据库、在 Operations 与自定义服务端代码中使用 Entity 的完整流程并能读懂仓库中真实示例如 kitchen-sink、TodoAppTs的数据模型设计。Entity 是什么数据模型的最小单元在 Wasp 中一个 Entity 就对应数据库中的一张表。官方文档对它的定义非常直白In short, an Entity defines a model in your database.Wasp 没有自研一套数据库 ORM而是直接采用业界成熟的 Prisma ORM 作为底层实现并在其之上做了一层轻薄的抽象。这意味着你不需要学习任何新的建模语法——用 Prisma 的schema.prisma文件定义模型和关系即可Wasp 会理解并接管这个 Prisma schema 文件自动读取你定义的所有模型每个 Prismamodel声明就是一个 Wasp Entity。关于 Prisma Schema File 与 Wasp 的协作方式可进一步阅读 Prisma Schema File 文档。Entity 与 Prisma Model 的概念区分虽然现阶段定义一个 Prisma model是创建 Entity 的唯一途径但两者在概念层级上并不等同Entity 是 Wasp 的概念属于更高层的抽象Model 是 Prisma 的概念指 Prisma Schema 中的model块声明。官方文档明确说明Wasp 未来计划扩展 Entity 的定义方式和能力范围。因此可以这样理解目前所有 Prisma model 都是 Entity所有 Entity 都是 Prisma model但这种一一对应关系会随着 Wasp 的演进而变化。在阅读 Wasp 文档和源码时注意区分这两个术语的语境。schema.prismaEntity 的定义场所在你的 Wasp 项目中schema.prisma文件位于项目根目录与main.wasp或新版本中的main.wasp.ts、src/、tsconfig.json平级. ├── main.wasp ... ├── schema.prisma ├── src ├── tsconfig.json └── vite.config.ts以仓库中的真实项目 examples/tutorials/TodoAppTs 为例其schema.prisma位于examples/tutorials/TodoAppTs/schema.prisma内容如下datasource db { provider sqlite // Wasp requires that the url is set to the DATABASE_URL environment variable. url env(DATABASE_URL) } // Wasp requires the prisma-client-js generator to be present. generator client { provider prisma-client-js } model User { id Int id default(autoincrement()) tasks Task[] } model Task { id Int id default(autoincrement()) description String isDone Boolean default(false) user User? relation(fields: [userId], references: [id]) userId Int? }这个文件清楚地展示了 Wasp 项目 schema 的三个组成部分datasource块声明数据库类型此处为 SQLite与连接 URLgenerator块声明生成 Prisma Client 的方式prisma-client-jsmodel块声明数据模型即 Wasp Entity。Prisma 使用的Prisma Schema Language是一种声明式的、专门为定义模型而设计的简洁语言。本文后面会给出完整示例你也可以直接参考 Prisma 官方的 schema 概览与语言规范来深入学习相关内容在文档中均有指引但本文以下内容已足以支撑你完成 Wasp 项目的数据建模。定义你的第一个 EntityTask 模型全解析在schema.prisma中声明一个model即可创建一个 Entity。以官方文档的 Task 为例model Task { id String id default(uuid()) description String isDone Boolean default(false) }这段声明告诉 Wasp为 Task 创建一张表表中包含三列含义如下字段类型约束/默认值说明idStringid default(uuid())主键数据库自动生成随机唯一 UUIDdescriptionString无存储任务描述isDoneBooleandefault(false)任务完成状态创建时若未显式赋值数据库默认写入false值得留意的是字段类型可以按需扩展。对照仓库中 examples/kitchen-sink/schema.prisma你可以看到更丰富的建模手法enum TaskVisibility { PRIVATE LINK_ONLY PUBLIC } model Task { id Int id default(autoincrement()) description String isDone Boolean default(false) user User relation(fields: [userId], references: [id]) userId Int votes TaskVote[] visibility TaskVisibility default(PRIVATE) }这里演示了三个进阶能力autoincrement()自增整数主键、通过relation(fields: [userId], references: [id])建立多对一关联、以及用enum定义枚举字段并为visibility设置默认值。这些都属于标准 Prisma schema 语法只要写法合法Wasp 都能直接支持。Entity 的 TypeScript 类型从数据库到代码的类型安全在 TypeScript 项目中Wasp 会为每个 Entity 自动暴露对应的类型你可以直接从wasp/entities模块导入import { Task } from wasp/entities const task: Task { ... } // 你也可以定义专门处理 Entity 的函数 function getInfoMessage(task: Task): string { const isDoneText task.isDone ? is done : is not done return Task ${task.description} is ${isDoneText}. }把Task类型用在函数签名里就相当于把参数类型与数据库实体绑定在一起。这种绑定带来两个好处消除重复不必手写与 schema 重复的接口定义变更即报错当你修改schema.prisma中的模型时导入的Task类型随之改变任何仍按旧结构编码的代码都会抛出类型错误从而在编译期就暴露过期的数据定义。Entity 类型在客户端代码中同样可用import { Task } from wasp/entities export function ExamplePage() { const task: Task { id: some-id, description: Some random task, isDone: false, } return div{task.description}/div }在仓库的官方 starters 模板中也能看到这种用法例如waspc/data/Cli/starters/basic/src/tasks/queries.ts与waspc/data/Cli/starters/basic/src/tasks/actions.ts都从wasp/entities导入实体类型并配合 Operations 使用——这正是文档所说在 Operations 中使用 Entity 类型的典型场景。让 Entity 生效wasp db migrate-dev 工作流定义好 Entity 之后需要让数据库与模型定义保持同步。Wasp 的标准工作流分四步在schema.prisma中创建或更新 Entity运行wasp db migrate-dev该命令会对比数据库与schema.prisma中的 Entity 定义生成迁移脚本并应用到数据库提交migrations/目录迁移脚本会自动放入项目的migrations/文件夹务必将其纳入版本控制这样团队成员与 CI 环境才能按相同顺序回放数据库结构变更在代码中使用 Entity实现 OperationsQueries 与 Actions时通过 Wasp 的 JavaScript API 访问数据库。以仓库中的迁移记录为例examples/kitchen-sink/migrations 下按时间戳命名的目录如20240110132515_add_session/、20240516082146_add_votes/、20250321140734_add_visibility_enum/正是wasp db migrate-dev持续产出迁移脚本的痕迹——每个目录对应一次数据模型演进。在 Operations 中使用 Entity绝大多数业务场景下你会通过 Wasp 的 Operations 机制Query 读、Action 写与 Entity 交互。在main.wasp旧版 Wasp 文件中需要把 Entity 显式声明给对应的操作。参见 Prisma Schema File 文档 中的示例query getTasks { fn: import { getTasks } from src/queries, entities: [Task] } job myJob { executor: PgBoss, perform: { fn: import { foo } from src/workers/bar }, entities: [Task], } api fooBar { fn: import { fooBar } from src/apis, entities: [Task], httpRoute: (GET, /foo/bar/:email) }这里getTasks查询、myJob后台任务、fooBarAPI 都声明依赖TaskEntityWasp 会据此注入对应的数据库访问权限与类型。在新版 TypeScript Spec 语法main.wasp.ts中写法略有不同但语义一致见 examples/tutorials/TodoAppTs/main.wasp.tsquery(getTasks, { entities: [Task] }), action(createTask, { entities: [Task] }), action(updateTask, { entities: [Task] }),Operations 的完整说明见 Operations 总览文档包含 Queries 与 Actions。直接使用 Prisma Client当标准 Operations 无法满足需求时你可以在 Wasp 服务端代码中直接使用 Prisma Client与 Entity 交互。官方文档明确限定Prisma Client 只能在服务端使用导入方式如下import { prisma } from wasp/server prisma.task.create({ description: Read the Entities doc, isDone: true // almost :) })注意这里的细节prisma.task.create中的task是 Entity 名称的小写形式这正是 Prisma Client 按模型自动生成的 CRUD 方法命名规则更多 CRUD 用法可参考 Prisma Client 官方文档。这一导入路径在 Wasp 源码中可以得到印证生成器模板 waspc/data/Generator/templates/server/src/actions/_action.ts 第 2 行正是import { prisma } from wasp/server说明每个 Action 的生成代码都会依赖该模块。另外waspc/data/Generator/templates/sdk/wasp/client/vite/plugins/detectServerImports.ts 中通过检查模块名是否以wasp/server开头来识别服务端导入从源码层面确认了wasp/server是服务端专属模块。推荐策略优先使用 Wasp 提供的标准机制Operations只有在需要 Wasp 未覆盖的 Prisma 特性时才直接操作 Prisma Client。Wasp 对 schema.prisma 的特殊要求Wasp 允许你像在普通 JS/TS 项目中一样使用 Prisma schema 文件但有三条 Wasp 特有的规则必须遵守详见 Prisma Schema File 文档datasource 块datasource db { provider postgresql url env(DATABASE_URL) }provider只能是postgresql或sqlite因为 Wasp 目前只支持这两种数据库url必须设置为env(DATABASE_URL)Wasp 依赖该环境变量完成数据库连接。仓库中两种 provider 都有真实用例examples/kitchen-sink/schema.prisma 使用 PostgreSQLexamples/tutorials/TodoAppTs/schema.prisma 使用 SQLite。generator 块generator client { provider prisma-client-js }Wasp 要求 schema 中必须存在provider prisma-client-js的 generator 块否则无法生成客户端代码。如果你需要其他 Prisma 生成器如生成文档或自定义代码可以额外添加。model 块只要符合 Prisma Schema 语法你可以按任意方式定义模型。目前 Wasp 尚未完全支持 schema 文件中的///三斜杠注释语法如需该功能可关注上游进展。Prisma preview featuresPrisma 的某些新特性仍处于预览阶段需要在 generator 块中通过previewFeatures显式启用。一个典型场景是 PostgreSQL 扩展支持例如启用pgvector进行向量检索datasource db { provider postgresql url env(DATABASE_URL) extensions [pgvector(map: vector)] } generator client { provider prisma-client-js previewFeatures [postgresqlExtensions] }仓库中的 examples/ask-the-documents/schema.prisma 就是这一配置的完整落地示例——它用Unsupported(vector(1536))类型声明了 AI 文档问答场景中的向量字段model Document { id String id default(uuid()) title String url String unique content String embedding Unsupported(vector(1536)) createdAt DateTime default(now()) updatedAt DateTime updatedAt }这展示了 Wasp Entity 并不局限于基础数据类型借助 Prisma 的 preview features 与Unsupported类型你可以建模向量、JSON 等高级字段满足 AI 时代应用的存储需求。实战要点回顾Entity 数据库表在根目录schema.prisma中用 Prisma model 声明Wasp 自动识别为 Entity类型安全贯穿前后端wasp/entities导出的实体类型在客户端与服务端一致可用schema 变更会即时反映为类型错误迁移流程是刚需每次改动模型都要执行wasp db migrate-dev并把生成的migrations/目录提交到版本控制两条数据访问路径常规业务走 Operationsentities: [Task]声明高级需求在服务端import { prisma } from wasp/server直连数据库三条 schema 红线provider仅限 PostgreSQL/SQLite、url必须是env(DATABASE_URL)、必须存在prisma-client-jsgenerator。掌握 Entity 之后下一步就是学习如何围绕它构建完整的读写逻辑——即 Wasp 的 OperationsQueries 与 Actions相关文档见 Operations 总览。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考