Working with Client Extensions
1. Creating Client Extensions
const xprisma = prisma.$extends({
name: "audited",
query: {
$allModels: {
async $allOperations({ model, operation, args, query }) {
const start = Date.now();
const res = await query(args);
console.log(`${model}.${operation}: ${Date.now() - start}ms`);
return res;
}
}
}
});
| Section | Use |
query | Intercept operations |
model | Add custom methods |
result | Add computed fields |
client | Add top-level methods |
2. Adding Custom Model Methods
const xprisma = prisma.$extends({
model: {
user: {
async findByEmail(email: string) {
return prisma.user.findUnique({ where: { email } });
}
}
}
});
await xprisma.user.findByEmail("a@b.io");
| Aspect | Detail |
| Scope | Per model or $allModels |
| Inherits | Original API still available |
3. Implementing Query Extensions
| Hook | Use |
$allOperations | All actions across models |
findMany | Single action override |
create | Wrap inserts |
4. Using Result Extensions
const xprisma = prisma.$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(u) { return `${u.firstName} ${u.lastName}`; }
}
}
}
});
| Aspect | Detail |
needs | Auto-select dependencies |
compute | Derived field |
5. Creating Reusable Extensions
import { Prisma } from "@prisma/client";
export const softDelete = Prisma.defineExtension({ name: "softDelete", model: { /* ... */ } });
const xprisma = prisma.$extends(softDelete);
| Helper | Use |
Prisma.defineExtension | Type-safe reusable factory |
6. Composing Multiple Extensions
| Aspect | Detail |
| Chain | prisma.$extends(a).$extends(b) |
| Conflicts | Last extension wins on name collisions |
| Package | Use |
@prisma/extension-accelerate | Edge caching |
@prisma/extension-pulse | Real-time subscriptions |
prisma-extension-soft-delete | Soft delete |
prisma-extension-pagination | Cursor helpers |
8. Testing Custom Extensions
| Tip | Detail |
| Unit test | Mock query function |
| Integration test | Real DB + transaction rollback |
9. Publishing Extension Packages
| Step | Detail |
Use defineExtension | For typed re-use |
| Peer deps | @prisma/client |
| Docs | Document required schema fields |
10. Managing Extension Lifecycle
| Aspect | Detail |
| Singleton-friendly | Extend once, reuse client |
| Hot reload | Re-apply on dev client recreation |