Prisma Nested Middleware

4.0.0 · active · verified Wed Apr 22

Prisma Nested Middleware is a utility library designed to extend Prisma's native middleware capabilities, specifically for handling nested write operations and relations within queries. While standard Prisma middleware (version 4.0.0 is the latest as of January 2024, with a consistent release cadence) is effective for top-level queries, it lacks the ability to intercept and modify operations on nested relations. This library addresses that limitation by providing a `createNestedMiddleware` function that wraps your middleware, allowing it to be called for every nested relation in a Prisma query. It exposes an enhanced `NestedParams` object, which includes critical context like `scope`, `modifier`, `logicalOperators`, and `relations` that are unavailable in standard Prisma middleware, enabling fine-grained control over complex data manipulations.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to apply `prisma-nested-middleware` to your Prisma client and shows an example of intercepting and modifying nested 'create' operations on 'Post' models, logging parameters and results. It also includes handling for varying `params.args` structures across major versions for nested 'create' actions.

import { PrismaClient } from '@prisma/client';
import { createNestedMiddleware, NestedParams } from 'prisma-nested-middleware';

const prisma = new PrismaClient();

prisma.$use(createNestedMiddleware(async (params: NestedParams, next) => {
  console.log(`[${params.model}] Action: ${params.action}`);
  if (params.scope) {
    console.log('  Scope:', params.scope.parentParams?.model, '->', params.scope.relation?.to);
  }
  
  // Example: Modify 'create' args for a nested operation
  if (params.action === 'create' && params.model === 'Post' && params.scope) {
    console.log('  Intercepted nested Post create:', params.args);
    // Ensure params.args structure for nested creates, which can vary by version
    if ('data' in params.args && typeof params.args.data === 'object') {
      // For v2.x to <v3.0.0, data was inside params.args.data
      params.args.data.title = `[Nested] ${params.args.data.title}`;
    } else if (typeof params.args === 'object') {
      // For v3.x onwards, data is directly in params.args
      params.args.title = `[Nested] ${params.args.title}`;
    }
  }

  const result = await next(params);

  if (result) {
    console.log(`[${params.model}] Result for ${params.action}:`, result);
  }
  return result;
}));

async function main() {
  await prisma.user.deleteMany({});
  await prisma.post.deleteMany({});

  const user = await prisma.user.create({
    data: {
      email: 'test@example.com',
      name: 'Test User',
      posts: {
        create: [
          { title: 'First Post', content: 'Content 1' },
          { title: 'Second Post', content: 'Content 2' }
        ],
      },
    },
    include: { posts: true },
  });
  console.log('\nCreated user with nested posts:', JSON.stringify(user, null, 2));
}

main().catch(console.error).finally(() => prisma.$disconnect());

view raw JSON →