mcpField
P
prisma-next-contract

prisma-next-contract

github.com/prismaデータ・データベース4112.0k 回インストール9 週間前に更新
リポジトリ

prisma-next-contract について

PSL または TypeScript builder で Prisma Next のデータ契約を作成・検証するスキルです。モデル、フィールド、リレーション、制約、拡張の変更を案内し、マイグレーションやクエリの作業と区別します。

主な機能

  1. 01PSL と TypeScript による契約作成
  2. 02契約の生成と検証
  3. 03モデル、フィールド、リレーションの編集
  4. 04インデックス、列挙型、値オブジェクト
  5. 05拡張の設定

活用シーン

  1. 01モデルやフィールドの追加・変更
  2. 02リレーションと制約の定義
  3. 03拡張型の設定
  4. 04契約生成時の診断への対応

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/prisma/prisma-next --skill prisma-next-contract

インストール後、Claude Code で/prisma-next-contractを入力して読み込まれたか確認します。

詳細

Prisma Next — コントラクトの作成

データコントラクトを編集するだけで、あとは Prisma が処理します。

データコントラクトは、データレイヤーにおける唯一の信頼できる情報源です。コントラクトのソースである contract.prisma(PSL、標準の記述形式)または contract.ts(TypeScript ビルダー)を編集すると、フレームワークがそこから型、マイグレーション、ランタイム設定を生成します。ユーザーの操作は次の 3 ステップです。

  1. データコントラクトを編集します。
  2. システムがマイグレーションを計画します。(prisma-next-migrations)
  3. データマイグレーションが必要な場合は、migration.ts を編集して実行します。(prisma-next-migrations)

ステップ 1 の裏側では、エージェントがコントラクトを編集するたびに prisma-next contract emit を実行します(または Vite プラグインをインストールすると、保存時にバンドラーが実行します。prisma-next-build を参照)。emit は、prisma-next.config.ts の contract: のファイル拡張子に基づいてファサードが選択するプロバイダーを通じてコントラクトのソースを読み込み、ソースと同じ場所に次の 2 つの成果物を書き出します。

  • contract.json — 正規のコンテンツハッシュ付き Contract IR です。プランナー、ランタイム、db verify によって読み込まれます。
  • contract.d.ts — Contract をインポートするときに、ランタイムとレーンが伝播する正確な TypeScript 型です。

どちらのファイルも生成された成果物です。ソースを編集し、JSON や .d.ts は編集しないでください。

使用する場面

  • モデル/フィールド/リレーションを追加、変更、削除したい場合。
  • インデックス、一意制約、列挙型、値オブジェクト(複合型)を追加したい場合。
  • 名前空間ブロック(Postgres スキーマ)またはコントラクトをまたぐ外部キーを追加したい場合。
  • モデルに @@control を設定するか、defaultControlPolicy を構成したい場合。
  • 拡張機能のカスタム型(pgvector.Vector(length: 1536)、cipherstash.EncryptedString({...}))を使いたい場合。
  • @prisma-next/extension-supabase を含め、prisma-next.config.ts の extensions: [...] で拡張機能をインストールまたは構成したい場合。
  • 作成ソースを(PSL ↔ TypeScript ビルダー間で)移行したい場合。
  • contract emit から PN-CLI-4002、PN-CLI-4003、または PN-CLI-4011 を受け取った場合。
  • 次の項目に言及している場合:スキーマ、フィールド、モデル、属性、prisma schema、PSL、contract.prisma、contract.ts、contract.json、contract.d.ts、contract emit、ファサードインポート、@prisma-next/postgres/config、@prisma-next/postgres/contract-builder、拡張機能、pgvector、cipherstash、postgis、paradedb、supabase、名前空間、スペースをまたぐ FK、@@control、列挙型、値オブジェクト、バリデーション、コールバック、ソフトデリート、パラノイド、スコープ。(最後の項目群は、以下の「Prisma Next がまだ対応していないこと」に該当します。)

使用しない場面

  • コントラクトの変更を DB に適用したい場合 → prisma-next-migrations。
  • コントラクトに対するクエリを書きたい場合 → prisma-next-queries。
  • db.ts(ランタイムのエントリーポイント、ミドルウェア、環境設定)を接続したい場合 → prisma-next-runtime。
  • Vite/バンドラーとの統合を行いたい場合 → prisma-next-build。
  • Prisma Next を初めてセットアップしたい場合 → prisma-next-quickstart。
  • 構造化された単一のエラーエンベロープを詳しく確認したい場合 → prisma-next-debug。
  • 未対応機能のリクエストを送信したい場合 → prisma-next-feedback。

主な概念

  • @prisma-next/<target> のファサードは、ユーザーが作成したコードからインポートする唯一のインターフェースです。 Postgres アプリの場合:@prisma-next/postgres/config、@prisma-next/postgres/contract-builder、@prisma-next/postgres/control、@prisma-next/postgres/runtime。Mongo も同じ構成です(@prisma-next/mongo/config、@prisma-next/mongo/contract-builder、@prisma-next/mongo/runtime)。各拡張機能は独自のファサードを公開します — @prisma-next/extension-pgvector/control、@prisma-next/extension-postgis/control、@prisma-next/extension-paradedb/control。ユーザーコードから @prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*、@prisma-next/sql-contract-* の内部に直接アクセスしないでください。 ファサードがファミリー/ターゲット/アダプター/ドライバーの配線を組み込んでいます。Common Pitfalls #4 を参照してください。
  • コントラクトソース。 フレームワークが読み込み、正規の Contract IR に変換するファイルです。どちらも正式にサポートされる、2 つの形式があります。
    • contract.prisma(PSL) — スキーマ形式の DSL です。一般的なアプリや、既存の Prisma ユーザーにとっての標準形式です。contract: './<path>/contract.prisma' で指定します — defineConfig ファサードが .prisma 拡張子を検出し、PSL プロバイダーに処理を振り分けます。
    • contract.ts(TypeScript ビルダー) — @prisma-next/postgres/contract-builder(または @prisma-next/mongo/contract-builder)の defineContract({...}, ({ field, model, rel, type }) => ({...})) を使ったプログラムによる作成形式です。contract: './<path>/contract.ts' で指定します — ファサードが .ts 拡張子を検出し、TS プロバイダーに処理を振り分けます。テナントごとのバリエーションや生成フィールドなど、プログラムによる合成が必要な場合や、PSL ではまだ表現できない構造(例:パラメーター付き拡張機能型の登録 — pgvector のコントラクトを参照してください)に使用します。
  • prisma-next.config.ts。 コントラクトソース、データベース接続、マイグレーションディレクトリ、およびインストール済みの拡張機能を設定します。@prisma-next/postgres/config(または @prisma-next/mongo/config)の defineConfig({...}) を使用します。ファサードが受け付けるフィールドは 4 つです:contract(パス文字列 — .prisma または .ts)、db({ connection?: string })、extensions(制御記述子の配列)、migrations({ dir?: string })。contract.json の出力先は contract から自動的に導出されます(例:./src/prisma/contract.prisma → ./src/prisma/contract.json)。
  • 生成パイプライン。 prisma-next contract emit --config <path>? は prisma-next.config.ts を読み込み、ファサードが選択したプロバイダーを呼び出し、生成された Contract を検証してから、ソースと同じ場所にある contract.json と contract.d.ts をアトミックに書き込みます。
  • 拡張機能の名前空間。 拡張機能は、名前空間付きコンストラクター(pgvector.Vector(length: 1536)、cipherstash.EncryptedString({equality: true}))とヘルパープリセットを提供します。記述子を 2 か所 に追加してインストールします — どちらもフィールド名は extensions ですが、2 つのインターフェースでは異なる型と形式の記述子を使用します。
    • 設定内(ファサードおよびコア): extensions: [pgvector] — @prisma-next/extension-<name>/control からインポートする 制御 記述子の配列です。
    • TS ビルダーの defineContract 内(contract.ts を作成する場合のみ): extensions: { pgvector } — @prisma-next/extension-<name>/pack からインポートする パック 記述子のレコードです。
  • コントラクトスペース。 コントラクトを生成する各パッケージは、独自の コントラクトスペース を所有します — パッケージルートの prisma-next.config.ts、コントラクトソース、ソースと同じ場所に生成される成果物、および migrations/ ディレクトリです。コントラクトスペースが利用側アプリケーションか、コントラクトスペースパッケージ(拡張機能、内部の集約ルートパッケージなど)かによって、意図的に使い分ける 2 つのディスク上のレイアウトがあります。
    • アプリケーションレイアウト(アプリ を構築する際に使用するもの)。リポジトリのルートに prisma-next.config.ts、src/prisma/contract.{prisma,ts}、同じ場所に src/prisma/contract.{json,d.ts}、同じ場所に src/prisma/db.ts、migrations/app/<timestamp>_<slug>/ の下にマイグレーションを配置します。app/ セグメントは利用側アプリケーションの space-id です。拡張機能の space-id は、拡張機能パッケージが管理する、兄弟ディレクトリの migrations/<extension-space-id>/ に配置されます。examples/prisma-next-demo ではこのレイアウトを使用しています。現状の prisma-next init は別の構成(リポジトリルートの prisma/...)を生成しますが、これは不具合です(TML-2532)。標準レイアウトは、すべてのコマンドが実際に想定しているものです。
    • コントラクトスペースパッケージレイアウト(拡張機能やモノレポ内のパッケージなど、コントラクトスペースパッケージを 公開 する際に使用するもの)。パッケージルートに prisma-next.config.ts、直下の src/contract.{prisma,ts}(prisma/ サブディレクトリなし)、同じ場所に src/contract.{json,d.ts}、migrations/ 直下に migrations/<timestamp>_<slug>/(<space-id> セグメントなし — パッケージ自体が 1 つのスペースです)を配置します。.cursor/rules/contract-space-package-layout.mdc と ADR 212 に記載されています。 どちらのレイアウトでも、defineConfig の contract: パスでソースを指定します。フレームワークはそこから、その他すべて(出力先、マイグレーションのルート)を導き出します。構築するものに合ったレイアウトを選び、それを使い続けてください。混在させないでください。

分岐に使用する診断コード

prisma-next contract emit は、安定したコードを含む構造化エラーを提示します。メッセージ本文ではなく、code に基づいて分岐してください。

コード意味次の手順
PN-CLI-4002 Contract configuration missingprisma-next.config.ts で contract が設定されていません。@prisma-next/postgres/config の defineConfig({...}) に、(アプリレイアウトの場合は)contract: './src/prisma/contract.prisma'、または(contract-space-package レイアウトの場合は)'./src/contract.prisma' を追加します。.ts ソースの場合も同様です。
PN-CLI-4003 Contract validation failedソースは読み込まれましたが、Contract IR の構造検証に失敗しました。問題のあるモデル/フィールドを示す meta.diagnostics / meta.issues を確認し、ソースを修正して再度出力します。
PN-CLI-4011 Missing extension packs in configコントラクトで名前空間付きコンストラクター(例:pgvector.Vector(...))が使用されていますが、設定の extensions に対応する記述子がありません。meta.missingExtensions にその名前が示されます。パッケージをインストールし、その制御記述子をインポートして(import pgvector from '@prisma-next/extension-pgvector/control')、prisma-next.config.ts の extensions: [...] に追加します。

ワークフロー — 信頼できるコントラクトソースを確認する

考え方:コントラクトを変更するときは、まずソースファイルの場所を確認します。設定が正式な情報源です。prisma-next.config.ts を読み、contract: フィールド(ファサード配下のパス文字列)を見つけて、指定されたファイルを開きます。同じフィールドから、インストール済みの extensions: [...] も確認できます。

cat prisma-next.config.ts

contract: が .prisma で終わる場合、ソースは PSL です。.ts で終わる場合、ソースは TS ビルダーです。prisma-next.config.ts がない場合は、prisma-next-quickstart に案内してください。

ワークフロー — モデル/フィールド/リレーションを編集する(PSL)

考え方:PSL のモデルはテーブル(Mongo ではコレクション)に、フィールドはカラムに変換されます。@relation(...) は外部キー側を宣言します。リレーションは所有側にのみ追加してください。フレームワークが逆参照を自動的に導出します。

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  authorId Int
  author   User   @relation(fields: [authorId], references: [id], onDelete: Cascade)

  @@unique([title, authorId])
  @@index([authorId])
}

次に、pnpm prisma-next contract emit を実行します(または Vite プラグインに任せます。prisma-next-build を参照)。カスケード動作は onDelete / onUpdate で明示してください。デフォルトは Restrict です。

@@index では、フィールドリストの代わりに expression:、部分インデックスの述語として where:、unique:、ターゲットに登録されたアクセスメソッドとして type:/options:、さらに name: と map: のいずれか一方も指定できます。

@@index(expression: "lower(email)", name: "users_email_lower")
@@index([authorId], where: "(archived_at IS NULL)", name: "posts_author_active")

name: は管理対象インデックスを宣言します(物理名は <name>_<8-hex hash> で、名前の変更は ALTER INDEX … RENAME として計画されます)。map: は正確な物理名をそのまま採用します(infer でキャプチャしたオブジェクト向けです。SQL 本文と併用すると警告が出ます。これはドリフト検出で、記述したテキストと Postgres の再出力結果がバイト単位で比較されるためです)。expression: には name: または map: が必要です。TS ビルダーでは、これに対応するものとして constraints.index([cols.x], {...}) / constraints.index({ expression, ... }) を使用できます。packages/2-sql/2-authoring/contract-ts/README.md を参照してください。

繰り返し使う型の PSL エイリアスは、トップレベルの types {} ブロックに記述します。

types {
  Email = String
}

model User {
  id    Int    @id @default(autoincrement())
  email Email  @unique
}

注:スカラーリスト(例:String[])と、暗黙的な Prisma-ORM の多対多リレーション(結合モデルなしで両側にリストナビゲーションがあるもの)は、SQL インタープリターで拒否されます。結合モデルを使用してください。複合型/埋め込み型(type Address { ... } を定義し、モデルに address Address を指定する形式)はサポートされています。インタープリターはこれらをドメイン内の valueObjects に変換し、jsonb カラムとして保存します。下記の「ワークフロー — 値オブジェクト」を参照してください。

ワークフロー — モデル/フィールド/リレーションを編集する(TS ビルダー)

コンセプト:同じモデルでも、記述方法は異なります。ファサードは、@prisma-next/postgres/family と @prisma-next/postgres/target のデフォルトエクスポートとして、defineContract、field、model、rel に加えて、family/target パックを再エクスポートします。コールバック形式のオーバーロード(defineContract({...}, ({ field, model, rel, type }) => ({...})))を使うと、より高水準のヘルパー(field.text()、field.id.uuidv7String()、field.temporal.createdAt()、type.sql.String(35))を利用できます。

import sqlFamily from '@prisma-next/postgres/family';
import { defineContract } from '@prisma-next/postgres/contract-builder';
import postgresPack from '@prisma-next/postgres/target';

export const contract = defineContract(
  {
    family: sqlFamily,
    target: postgresPack,
  },
  ({ field, model }) => ({
    models: {
      User: model('User', {
        fields: {
          id: field.id.uuidv7String(),
          email: field.text().unique(),
          createdAt: field.temporal.createdAt(),
        },
      }).sql({ table: 'app_user' }),
    },
  }),
);

次に、pnpm prisma-next contract emit を実行します。field.<scalar>() ヘルパーはコールバック形式のオーバーロード内でのみ利用できます。コールバックの外で利用できるのは、field.column(...)、field.generated(...)、field.namedType(...) だけです。

Mongo の場合は、すべての @prisma-next/postgres/* インポートを @prisma-next/mongo/* に置き換えます。Mongo ビルダーでは、index と valueObject も利用できます。

ワークフロー — 拡張機能で型付けされたスカラーを追加する(pgvector)

コンセプト:拡張機能は、名前空間(pgvector.*)と、2 種類の記述子(config ファサード用の control 記述子と、TS ビルダー用の pack 記述子)を提供します。defineConfig.extensions(配列形式)に control 記述子を登録します。TS ビルダーで記述する場合は、defineContract.extensions(レコード形式)にも pack 記述子を登録します。その後、コントラクトから名前空間付きのコンストラクターを参照します。

prisma-next.config.ts:

import pgvector from '@prisma-next/extension-pgvector/control';
import { defineConfig } from '@prisma-next/postgres/config';

export default defineConfig({
  contract: './src/prisma/contract.prisma',
  extensions: [pgvector],
});

src/prisma/contract.prisma:

model Document {
  id        Int                          @id @default(autoincrement())
  content   String
  embedding pgvector.Vector(length: 1536)
}

emit を実行します。名前付き型の変換により、カラムに vector(1536) が設定され、contract.d.ts の型マップには適切な TS 型が反映されます。

設定で pack を登録せずに pgvector.* を参照すると、emit は PN-CLI-4011 と meta.missingExtensions: ['pgvector'] を返して失敗します。エンベロープの fix テキストには、"Add the missing extension descriptors to extensions in prisma-next.config.ts" と記載されています。このフィールド名はファサードと一致しています。

単一拡張機能および複数拡張機能の構成を網羅した正式な実例については、examples/multi-extension-monorepo/app/prisma-next.config.ts と examples/prisma-next-postgis-demo/prisma-next.config.ts を参照してください。

ワークフロー — ポリモーフィズム(@@discriminator / @@base)

コンセプト(SQL ターゲット):1 つのベースモデルで識別子フィールドを宣言し、各バリアントモデルでベースと識別子の値を宣言します。バリアントで STI と MTI のどちらを使うかは、@@map(...) を設定するかどうかで決まります。@@map がない場合、バリアントはベースのテーブルを継承します(単一テーブル継承)。@@map("variant_table") がある場合、バリアントは独自のテーブルを持ち、主キーで 1 対 1 に結合されます(マルチテーブル継承)。

model Task {
  id    Int    @id @default(autoincrement())
  title String
  type  String

  @@discriminator(type)
  @@map("tasks")
}

// STI variant — shares the `tasks` table.
model Bug {
  severity String

  @@base(Task, "bug")
}

// MTI variant — joins to `tasks` via PK; carries its own `features` table.
model Feature {
  priority Int

  @@base(Task, "feature")
  @@map("features")
}

迷った場合は、インタープリターテストでポリモーフィズムの構文を確認してください:packages/2-sql/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts。

Mongo にはスキーマレイヤーがないため、Mongo のポリモーフィズムは TS ビルダーでモデルに discriminator フィールドを明示的に設定して表現します(@prisma-next/mongo/contract-builder を参照)。@@base/@@discriminator PSL 属性は SQL 専用です。

バリアントのクエリ処理はランタイムに関するものです。prisma-next-queries を参照してください。

ワークフロー — 値オブジェクト(複合型)

コンセプト:type Foo { ... } ブロックで値オブジェクトの形状を宣言します。インタープリターはこれらをコントラクトドメイン内の valueObjects に変換し、jsonb カラムとして保存します。値オブジェクトのネスト参照にも対応しています。

type Address {
  street  String
  city    String
  zip     String?
  country String
}

model User {
  id      String   @id @default(uuid())
  email   String
  address Address?
}

出力された contract.json には、フィールド記述子を含む domain.namespaces.<ns>.valueObjects.Address が記録されます。また、address カラムは storage 内で codecId: "pg/jsonb@1"/nativeType: "jsonb" として格納されます。

正式な実例:examples/prisma-next-demo/src/prisma/contract.prisma。

ワークフロー — Enum

コンセプト:PSL の enum ブロックでは、ドメインの enum を宣言します。宣言済みのコーデック(@@type("pg/text@1") → text 列)を通じて名前付きの値セットを保存し、プランナーが生成する CHECK 制約によって値を検証します。各メンバーは Name = "value" の形式でデータベースの値に対応付けます。同じコントラクト内の任意のモデルで、enum 名をフィールド型として使用します。

enum user_type {
  @@type("pg/text@1")
  admin = "admin"
  user  = "user"
}

model User {
  id   String    @id @default(uuid())
  kind user_type
}

標準的な実例:examples/prisma-next-demo/src/prisma/contract.prisma。

ワークフロー — Namespace(Postgres スキーマ)

コンセプト:モデルを namespace <name> { ... } ブロックで囲むと、デフォルト以外の Postgres スキーマに配置できます。ブロックの外にあるモデルは、暗黙のデフォルト namespace に配置されます。

namespace public {
  model Profile {
    id       String @id @default(uuid())
    username String
    userId   String @unique
    @@map("profile")
  }
}

標準的な実例:examples/supabase/src/contract.prisma。

ワークフロー — コントラクト間の外部キー

コンセプト:リレーションフィールドでは、<space>:<namespace>.<Model> 形式を使って別のコントラクト空間にあるモデルを参照できます。また、コントラクトでは types {} ブロック内のトップレベルの名前付き型エイリアスもサポートされています。フィールドで使用するものと同じ、型位置で使用する型コンストラクターが基盤となっています。@db.X(args) チャネルは削除されました。@db.X は X に、@db.X(args) は X(args) に書き換えてください。それ以外の使用箇所は、置き換え方法を示す実行可能な診断とともにエラーになります。

types {
  AuthUserId = Uuid
}

namespace public {
  model Profile {
    id       String     @id @default(uuid())
    username String
    userId   AuthUserId @unique
    user     supabase:auth.AuthUser @relation(fields: [userId], references: [id], onDelete: Cascade)
    @@map("profile")
  }
}

supabase:auth.AuthUser は、コントラクト空間 supabase の namespace auth にあるモデル AuthUser を意味します。対象の空間は、登録済みの拡張パック(ここでは @prisma-next/extension-supabase/pack)によって提供されます。

標準的な実例:examples/supabase/src/contract.prisma。

ワークフロー — @@control(制御ポリシー)

コンセプト:モデルに @@control(<policy>) を指定すると、Prisma がマイグレーションでそのテーブルの DDL を管理するかどうかを設定できます。引数は位置指定の小文字リテラルで、managed、tolerated、external、observed のいずれかです。

model AuditLog {
  id        Int    @id
  message   String

  @@control(observed)
}

prismaContract(path, { defaultControlPolicy }) の defaultControlPolicy で、コントラクトレベルのデフォルトを設定できます。制御ポリシーが DDL 計画に与える影響については、prisma-next-migrations を参照してください。

ワークフロー — @prisma-next/extension-supabase

コンセプト:Supabase 拡張機能は、supabase コントラクト空間(external テーブルとしての auth/storage スキーマとプラットフォームロール)と、独自のロール優先ランタイムファクトリーを提供します。/control サブパスは公開されていないため、ユーザー向けの defineConfig({ extensions: [...] }) ファサード経由では登録できません。低レベル設定の extensions を通じて接続します。動作する一連のパターンについては、examples/supabase を参照してください。

prisma-next.config.ts(この例に対応):

import supabasePack from '@prisma-next/extension-supabase/pack';
import { defineConfig } from '@prisma-next/cli/config-types';
// ... other low-level imports

export default defineConfig({
  // ...
  extensions: [supabasePack],
});

db.ts では標準の postgres() ファクトリーを使用しません。Supabase アプリでは、@prisma-next/extension-supabase/runtime の supabase() ファクトリーを使ってクライアントを構築します(ロール優先:asUser(jwt)/asAnon()/asServiceRole()、JWT 検証、RLS)。このランタイムと RLS ポリシーの作成(policy_select/@@rls)については prisma-next-supabase で説明しています。設定の接続以外も利用する場合は、こちらを読み込んでください。

エクスポートされるサブパス:@prisma-next/extension-supabase/pack、@prisma-next/extension-supabase/runtime、@prisma-next/extension-supabase/contract。標準的な実例:examples/supabase。

ワークフロー — 既存データベースのイントロスペクション

コンセプト:既存のデータベースからコントラクトのソースを取り出し、そこから作業を続けます。prisma-next contract infer --db <url> は稼働中のスキーマを読み取り、contract.prisma ファイルを書き出します。ここで処理は終了します。続けて contract emit を実行し(スキーマがピン留めされたハッシュと一致する場合は)、別の手順として db sign を実行してください。

pnpm prisma-next contract infer --db $DATABASE_URL --output ./src/prisma/contract.prisma
pnpm prisma-next contract emit

よくある落とし穴

  1. 編集後に再出力し忘れる。 contract.json と contract.d.ts が古い状態になり、後続の型チェックと migration plan では古い形状が参照されます。再出力するか、Vite プラグイン(prisma-next-build)をインストールしてください。
  2. 出力された成果物を編集する。 contract.json と contract.d.ts は出力ファイルです。編集しても、次回の出力時に変更が失われます。ソースを編集してください。
  3. TS ビルダーのファクトリー/インポートパスを間違える。 defineContract、field、model、rel は @prisma-next/postgres/contract-builder(または @prisma-next/mongo/contract-builder)からインポートします。コールバックオーバーロード以外では、使用できるフィールドコンストラクターは field.column(...)、field.generated(...)、field.namedType(...) です。
  4. ユーザーコードから内部パッケージにアクセスする。 ユーザーが作成するファイル(prisma-next.config.ts、contract.ts、db.ts、制御クライアント)では、@prisma-next/<target>/<subpath> と @prisma-next/extension-<name>/<subpath> からのみインポートします。@prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*、@prisma-next/sql-contract-* からのインポートはフレームワーク内部向けです。これらはファサードが組み合わせてくれます。対象で必要なファサードのサブパスがない場合は、Prisma Next がまだ対応していない機能を参照し、prisma-next-feedback から要望を送ってください。標準的な実例は examples/multi-extension-monorepo/app/prisma-next.config.ts と examples/prisma-next-postgis-demo/prisma-next.config.ts です。
  5. 設定の extensions と TS ビルダーの extensions を混同する。 同じパックを扱いますが、2 つの異なるインターフェースで、フィールド名は同じでも形状が異なります。defineConfig({ extensions: [pgvector] }) は @prisma-next/extension-<name>/control からの制御ディスクリプターの配列で、defineContract({ extensions: { pgvector } }) は @prisma-next/extension-<name>/pack からのパックディスクリプターのレコードです。
  6. フィールド名を変更すればプランナーが検出すると期待する。 Prisma Next にはコントラクト内でのリネームヒントがなく、プランナーは破壊的な削除+追加として認識します。migration plan の後で migration.ts を手動編集するか(prisma-next-migrations を参照)、2 回のマイグレーションに分けて保持してから削除するパターンを使用してください。

Prisma Next がまだ対応していない機能

  • コントラクト内でのリネームヒント。 @@rename(old: ..., new: ...) などはありません。よくある落とし穴の #6 にある回避策を使用してください。正式なリネーム機能を要望する場合は、prisma-next-feedback から報告してください。
  • モデルのバリデーション。 宣言的な @validates(...) インターフェースはありません。アプリケーションコードで検証してください(arktype)。コントラクトでの宣言的なバリデーションを要望する場合は、prisma-next-feedback から報告してください。
  • ライフサイクルコールバック(beforeSave、afterCreate など)。サポートされていません。ミドルウェア(prisma-next-runtime)またはアプリケーションコードを使用してください。ライフサイクルコールバックを要望する場合は、prisma-next-feedback から報告してください。
  • 論理削除/paranoid: true。 組み込みの論理削除カラムはありません。NULL 許容の deletedAt DateTime? を追加し、クエリ(またはミドルウェア)で明示的にフィルターしてください。組み込みの論理削除機能を要望する場合は、prisma-next-feedback から報告してください。
  • スコープ/デフォルトフィルター。 ActiveRecord スタイルのスコープはありません。クエリヘルパーを自分で組み合わせてください。スコープ機能を要望する場合は、prisma-next-feedback から報告してください。
  • 暗黙的な Prisma-ORM の多対多リレーション。 明示的な結合モデルなしで両側にリストナビゲーションを定義すると、拒否されます。結合モデルを明示的に作成してください。暗黙的な M2M を要望する場合は、prisma-next-feedback から報告してください。

リファレンス

  • 実際に利用できるコマンドは pnpm prisma-next contract --help を実行して確認してください。
  • PSL の機能範囲とインタープリターが受け付ける内容:packages/2-sql/2-authoring/contract-psl/README.md。
  • TS ビルダーの機能範囲とコールバックヘルパーの用語:packages/2-sql/2-authoring/contract-ts/README.md。
  • レイアウト(contract.prisma、contract.json、contract.d.ts、migrations/ の配置場所):
    • アプリレイアウト(src/prisma/... + migrations/app/...)— examples/prisma-next-demo が実例を示す、利用側のアプリケーションが使う標準的な構成です。
    • コントラクトスペースパッケージレイアウト(src/contract.{prisma,ts} を直接配置、スペース ID セグメントのない migrations/<timestamp>_<slug>/)— 拡張機能および集約ルートパッケージ向けです。.cursor/rules/contract-space-package-layout.mdc および ADR 212 に記載されています。

チェックリスト

  • prisma-next.config.ts を読み、コントラクトソース(.prisma または .ts で終わるパス文字列)と、インストール済みの extensions: [...] を特定した。
  • ユーザーが作成したすべてのインポートが @prisma-next/<target>/<subpath>(例:@prisma-next/postgres/config)または @prisma-next/extension-<name>/<subpath> を参照している。ユーザーファイルから @prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*、@prisma-next/sql-contract-* をインポートしていない。
  • 出力されたアーティファクトではなく、コントラクトソース(contract.prisma または contract.ts)を編集した。
  • 新しい拡張機能の名前空間を追加する場合:パッケージを追加し、その制御記述子(@prisma-next/extension-<name>/control)をインポートして、defineConfig({...}) の extensions: [...] に追加した(TS ビルダーを使用する場合は、対応するパック記述子を defineContract({extensions: {...}}) に追加した)。
  • 名前を変更する場合:migration plan の後に migration.ts を手動で編集した(または、保持してから削除する 2 段階のマイグレーションパターンを使用した)。Prisma Next には現在、名前変更のヒント機能がありません。
  • 編集後に pnpm prisma-next contract emit を実行した(または、保存時の Vite プラグインによる再出力に任せた)。
  • ソースと同じ場所にある contract.json と contract.d.ts が更新されたことを確認した。
  • contract.json / contract.d.ts を手動で編集していない。
  • 存在しない機能(バリデーション、コールバック、論理削除、スコープ、コントラクト内の名前変更ヒント)を捏造していない。「Prisma Next がまだ対応していないこと」および prisma-next-feedback をユーザーに案内した。

コメント