共有Prisma Client拡張機能
ユーザーは、自身のPrisma Client拡張機能をパッケージまたはモジュールとして他のユーザーと共有したり、他のユーザーが作成した拡張機能をプロジェクトにインポートしたりできます。
共有可能な拡張機能を作成したい場合は、prisma-client-extension-starter
テンプレートを使用することをお勧めします。
Prismaの公式Client拡張機能とコミュニティによって作成された拡張機能の例を見るには、このページをご覧ください。
共有パッケージ拡張機能をインストールする
プロジェクトでは、他のユーザーがnpm
に公開したPrisma Client拡張機能をインストールできます。それには、次のコマンドを実行します。
npm install prisma-extension-<package-name>
例えば、利用可能な拡張機能のパッケージ名がprisma-extension-find-or-create
の場合、次のようにインストールできます。
npm install prisma-extension-find-or-create
上記の例からfind-or-create
拡張機能をインポートし、それでクライアントインスタンスをラップするには、次のコードを使用できます。この例では、拡張機能名がfindOrCreate
であると仮定しています。
import findOrCreate from 'prisma-extension-find-or-create'
const prisma = new PrismaClient().$extends(findOrCreate)
const user = await prisma.user.findOrCreate()
拡張機能でメソッドを呼び出すときは、prisma
ではなく、$extends
ステートメントの定数名を使用してください。上記の例では、xprisma.user.findOrCreate
は機能しますが、元のprisma
は変更されないため、prisma.user.findOrCreate
は機能しません。
共有可能な拡張機能を作成する
他のユーザーが使用でき、かつ自身のスキーマに特化していない拡張機能を作成したい場合、Prisma ORMは共有可能な拡張機能を作成するためのユーティリティを提供します。
共有可能な拡張機能を作成するには
Prisma.defineExtension
を使用して拡張機能をモジュールとして定義する$allModels
や$allOperations
など、$all
プレフィックスで始まるメソッドのいずれかを使用する
拡張機能を定義する
Prisma.defineExtension
メソッドを使用して拡張機能を共有可能にします。これを使用して、拡張機能を別ファイルに分離したり、npmパッケージとして他のユーザーと共有したりできます。
Prisma.defineExtension
の利点は、拡張機能の作成者と共有拡張機能のユーザーに対して、開発中に厳密な型チェックと自動補完を提供することです。
ジェネリックメソッドを使用する
$allModels
下のメソッドを含む拡張機能は、特定のモデルではなくすべてのモデルに適用されます。同様に、$allOperations
下のメソッドは、result
やquery
といった名前付きコンポーネントではなく、クライアントインスタンス全体に適用されます。
client
コンポーネントでは$all
プレフィックスを使用する必要はありません。なぜなら、client
コンポーネントは常にクライアントインスタンスに適用されるからです。
例えば、ジェネリック拡張機能は次の形式をとることができます。
export default Prisma.defineExtension({
name: 'prisma-extension-find-or-create', //Extension name
model: {
$allModels: {
// new method
findOrCreate(/* args */) {
/* code for the new method */
return query(args)
},
},
},
})
Prisma Client操作を変更するさまざまな方法については、以下のページを参照してください。
バージョン4.16.0以前の場合
Prisma
のインポートは、以下のスニペットに示す別のパスから利用可能です。
import { Prisma } from '@prisma/client/scripts/default-index'
export default Prisma.defineExtension({
name: 'prisma-extension-<extension-name>',
})
共有可能な拡張機能をnpmに公開する
その後、拡張機能をnpm
で共有できます。パッケージ名を選択する際は、検索しやすくインストールしやすいため、prisma-extension-<package-name>
の命名規則を使用することをお勧めします。
パッケージ拡張機能からクライアントレベルのメソッドを呼び出す
現在、PrismaClient
を参照し、以下の例のようにクライアントレベルのメソッドを呼び出す拡張機能には制限があります。
トランザクション(インタラクティブまたはバッチ)の内部から拡張機能をトリガーすると、拡張機能コードは新しい接続でクエリを発行し、現在のトランザクションコンテキストを無視します。
この問題についてGitHubで詳しく学ぶ: クライアントレベルのメソッドの使用を必要とするクライアント拡張機能がトランザクションを黙って無視する。
以下の状況では、拡張機能がラップするPrisma Clientインスタンスを参照する必要があります。
- パッケージ化された拡張機能で
$queryRaw
などのクライアントレベルのメソッドを使用したい場合。 - パッケージ化された拡張機能で複数の
$extends
呼び出しをチェーンしたい場合。
しかし、誰かがあなたのパッケージ化された拡張機能を自分のプロジェクトに含める場合、あなたのコードはPrisma Clientインスタンスの詳細を知ることはできません。
このクライアントインスタンスは次のように参照できます。
Prisma.defineExtension((client) => {
// The Prisma Client instance that the extension user applies the extension to
return client.$extends({
name: 'prisma-extension-<extension-name>',
})
})
例:
export default Prisma.defineExtension((client) => {
return client.$extends({
name: 'prisma-extension-find-or-create',
query: {
$allModels: {
async findOrCreate({ args, query, operation }) {
return (await client.$transaction([query(args)]))[0]
},
},
},
})
})
高度な型安全性: ジェネリック拡張機能を定義するための型ユーティリティ
型ユーティリティを使用して、共有拡張機能の型安全性を向上させることができます。