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

モデルは、サーバーの 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。null 許容にするには ? を使用します。

必須フィールド

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

データベーステーブル

データベーステーブルと ORM を使用するには、table を追加します。

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

デフォルト値

  • default= は、Dart モデルとデータベースの列の両方に値を設定します。
  • defaultModel= は、Dart モデルのみに値を設定します(Dart でオブジェクトを作成するときに使用されます)。
  • defaultPersist= は、データベースの列のみに値を設定します(id でない限り、Dart ではフィールドを null 許容にする必要があります)。
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 フィールドはデフォルト値が serial の int です。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 がわかります。
  • id: int?, defaultPersist=serial — デフォルトの動作を明示した形式です。

カスタム ID 型を持つモデルとのリレーションでは、外部キーのフィールドにも同じ型を使用します。

スコープ

  • サーバー専用クラス: serverOnly: true
  • フィールド単位: scope=serverOnly、scope=none(デフォルトは all)
  • 永続化しないフィールド: !persist(DB に保存されません)
  • JSON キーの別名: jsonKey=display_name

イミュータブルクラス

immutable: true — フィールドが final になり、==、hashCode、copyWith が利用できます。

継承

  • extends: ParentClass — 子クラスは親クラスのフィールドを継承します。階層内で table を持つクラスは 1 つだけにします。
  • sealed: true — すべてのサブタイプを網羅する抽象 sealed 階層を定義します。sealed クラスには table を指定しません。

親が serverOnly の場合、子も serverOnly にする必要があります。子クラスで親のフィールドを再定義することはできません。

列挙型

enum: Status
values:
  - pending
  - active
  - completed

デフォルトのシリアライズ方式は byName です。インデックスを使用するには、serialized: byIndex を設定します。

例外

シリアライズ可能な例外を定義するには、class: の代わりに exception: を使用します。フィールドの型はクラスと同じで、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])

リレーション

1対1(一意インデックス付きの外部キー):

  • ID フィールド:addressId: int, relation(parent=address) + addressId の一意インデックス
  • オブジェクトフィールド:address: Address?, relation(addressId を生成します)
  • オプション:NULL 許容の外部キーには relation(optional)、外部キー名をカスタムするには relation(field=customId) を使います
  • 双方向:両側に同じ relation(name=...) を指定し、外部キー側に fk を指定します(外部キー名をカスタムする場合は field= を指定します)

1対多:

  • 「1」側:employees: List<Employee>?, relation
  • 「多」側:companyId: int, relation(parent=company)(一意インデックスはありません)
  • 双方向:両側に relation(name=company_employees) を指定します

多対多:2つのリレーションフィールドを持つ結合テーブルモデルを使用します。

参照アクション: relation(onDelete=Cascade) と relation(onUpdate=...) は、SQL の外部キーアクション(Cascade、SetNull、SetDefault、Restrict、NoAction)に対応します。SetNull には、NULL 許容の外部キー(NULL 許容のオブジェクトリレーションフィールド、または relation(optional))が必要です。制約チェックを明示的に遅延できるようにするには deferrable を追加し、デフォルトでコミットまで遅延させるには deferred を追加します。Restrict アクションは、制約が遅延可能な場合でも常に即時にチェックされます。チェックを遅延可能にする必要がある場合は、NoAction を使用してください。

クエリ:先読みには include を、リストリレーションには where/orderBy/limit/offset を指定した includeList を使用します。リレーションの管理には attach/detach を使用します。

後方互換性

後方互換性を維持するため、クライアントが使用するシリアライズ済みクラスのフィールドを変更または削除しないでください。新しいフィールドを追加する場合は、NULL 許容にするかデフォルト値を設定してください。そうすることで、フィールドを送信しない古いクライアントも引き続き動作します。

リファレンスファイル

コメント