mcpField
S
serverpod-models

serverpod-models

github.com/serverpod开发3.3k45 次安装1 天前更新
代码仓库

关于 serverpod-models

serverpod-models 是 Serverpod 项目模型定义的技能,面向编写和维护数据模型的开发者。它说明如何用 .spy.yaml 配置生成 Dart 类、数据库表及序列化行为。

主要功能

  1. 01定义模型、枚举和异常
  2. 02配置字段类型与默认值
  3. 03生成数据库表和 ORM 关系
  4. 04设置索引与关联规则
  5. 05管理序列化兼容性

适用场景

  1. 01为服务端和客户端定义共享模型
  2. 02为模型配置数据库持久化
  3. 03设计关联、索引和主键
  4. 04维护客户端兼容的数据结构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/serverpod/serverpod --skill serverpod-models

安装后在 Claude Code 中输入/serverpod-models确认已加载。

附带文件references/client-side-database.mdreferences/custom-serialization.md

详细介绍

Serverpod Models

模型定义在 server 的 lib/ 下任意位置的 .spy.yaml 文件中。它们会为服务端和客户端生成 Dart 类,也可以选择生成数据库表。

每次更改模型后,都要确保代码已生成(Serverpod runner 运行时会自动生成,也可以手动运行 serverpod generate)。如果更改了带有 table 的模型,必须按照迁移工作流更新数据库架构。

基本类

class: Company
fields:
  name: String
  foundedDate: DateTime?
  employees: List<Employee>

字段类型:bool、int、double、String、Duration、DateTime、ByteData、UuidValue、Uri、BigInt、生成的类/枚举/异常、List<T>、Map<K,V>、Set<T>、Record。使用 ? 表示可空。

必填字段

class: Person
fields:
  name: String
  nickname: String?, required

数据库表

添加 table 以创建数据库表和 ORM:

class: Company
table: company
fields:
  name: String
  foundedDate: DateTime?

默认值

  • default= 会同时设置 Dart 模型和数据库列的值。
  • defaultModel= 仅在 Dart 模型中设置(在 Dart 中创建对象时使用)。
  • defaultPersist= 仅在数据库列中设置(除非字段为 id,否则该字段在 Dart 中必须可空)。
class: Post
table: post
fields:
  title: String, default='Untitled'
  createdAt: DateTime, default=now
  publishedAt: DateTime?, defaultPersist=now
  externalId: UuidValue, default=random_v7
  views: int, default=0
  isPublic: bool, default=false

支持 now(DateTime)、random/random_v7(UuidValue)和带引号的字面值。具有默认值的字段无需传入构造函数。

自定义 id 类型

除非显式声明,id 字段的类型为 int,默认值为 serial。显式声明即可使用 UUID 主键:

class: Company
table: company
fields:
  id: UuidValue?, defaultPersist=random_v7  # database generates the id
  name: String
  • defaultPersist=random_v7 — 数据库在插入时生成 id(v4 使用 random)。
  • defaultModel=random_v7 — Dart 在创建对象时生成 id,因此插入前即可获知。
  • id: int?, defaultPersist=serial — 默认行为的显式写法。

与自定义 id 类型模型的关系使用相同类型的外键字段。

作用范围

  • 仅限服务端的类: serverOnly: true
  • 单个字段: scope=serverOnly、scope=none(默认值为 all)
  • 不持久化的字段: !persist(不存储在数据库中)
  • JSON 键别名: jsonKey=display_name

不可变类

immutable: true — 字段为 final,并生成 ==、hashCode 和 copyWith。

继承

  • extends: ParentClass — 子类继承父类字段。继承层级中只能有一个类带有 table。
  • sealed: true — 用于穷尽子类型的抽象密封层级。密封类不能带有 table。

如果父类是 serverOnly,子类也必须是。子类不能重新定义父类字段。

枚举

enum: Status
values:
  - pending
  - active
  - completed

默认序列化方式:byName。设置 serialized: byIndex 可使用索引。

异常

使用 exception: 代替 class: 来声明可序列化异常。字段类型与类相同;支持 default 和 defaultModel。未捕获的异常会在客户端变成通用 500 错误;只有可序列化异常才会发送其数据。

exception: MyException
fields:
  message: String
  errorType: MyEnum

在服务端抛出,在客户端捕获:

// Server
throw MyException(message: 'Failed', errorType: MyEnum.thingyError);

// Client
try {
  await client.example.doThingy();
} on MyException catch (e) {
  print(e.message);
}

可序列化异常也可以通过流发送(支持双向发送;发送后流会关闭)。不要在异常字段中放入敏感数据,因为这些数据会发送给客户端。

索引

indexes:
  company_name_idx:
    fields: name
    unique: true
    nulls_distinct: false  # PostgreSQL only, treats NULLs as equal

字段级的 unique 会自动生成 btree 唯一索引:

fields:
  tenantId: int
  category: String
  # single-column unique index
  email: String, unique
  # composite unique index on (category, value)
  value: String, unique(per=category)
  # composite unique index on (category, tenantId, value)
  amount: int, unique(per=[category, tenantId])

关系

一对一(带唯一索引的外键):

  • ID 字段:addressId: int, relation(parent=address) + 在 addressId 上建立唯一索引
  • 对象字段:address: Address?, relation(会生成 addressId)
  • 可选:使用 relation(optional) 设置可空外键;使用 relation(field=customId) 自定义外键名
  • 双向关系:两侧使用相同的 relation(name=...);在外键侧使用 fk(自定义外键名时使用 field=)

一对多:

  • “一”侧:employees: List<Employee>?, relation
  • “多”侧:companyId: int, relation(parent=company)(无唯一索引)
  • 双向关系:两侧使用 relation(name=company_employees)

多对多: 使用包含两个关系字段的连接表模型。

引用操作: relation(onDelete=Cascade) 和 relation(onUpdate=...) 会映射到 SQL 外键操作(Cascade、SetNull、SetDefault、Restrict、NoAction)。SetNull 要求外键可空(使用可空对象关系字段或 relation(optional))。添加 deferrable 可显式延迟约束检查,添加 deferred 可默认将检查延迟到提交时。Restrict 操作始终会立即检查,即使约束已延迟;需要延迟检查时请使用 NoAction。

查询:使用 include 进行预加载;对于列表关系,使用带有 where/orderBy/limit/offset 的 includeList。使用 attach/detach 管理关系。

向后兼容性

为保持向后兼容,请勿更改或删除客户端使用的序列化类中的字段。只有在新字段可空或具有默认值时才添加,这样较旧客户端未发送该字段时也能正常工作。

参考文件

评论

支持 Markdown