rembrembdocs

Client Extensions

Advanced type safety: improve type safety in your custom model methods

Several type utilities exist within Prisma Client that can assist in the creation of highly type-safe extensions.

Prisma Client type utilities are utilities available within your application and Prisma Client extensions and provide useful ways of constructing safe and extendable types for your extension.

The type utilities available are:

The following example creates a new operation, exists, based on findFirst. It has all of the arguments that findFirst.

const prisma = new PrismaClient().$extends({
  model: {
    $allModels: {
      // Define a new `exists` operation on all models
      // T is a generic type that corresponds to the current model
      async exists<T>(
        // `this` refers to the current type, e.g. `prisma.user` at runtime
        this: T,

        // The `exists` function will use the `where` arguments from the current model, `T`, and the `findFirst` operation
        where: Prisma.Args<T, "findFirst">["where"],
      ): Promise<boolean> {
        // Retrieve the current model at runtime
        const context = Prisma.getExtensionContext(this);

        // Prisma Client query that retrieves data based
        const result = await (context as any).findFirst({ where });
        return result !== null;
      },
    },
  },
});

async function main() {
  const user = await prisma.user.exists({ name: "Alice" });
  const post = await prisma.post.exists({
    OR: [{ title: { contains: "Prisma" } }, { content: { contains: "Prisma" } }],
  });
}

The following example illustrates how you can add custom arguments, to a method in an extension:

type CacheStrategy = {
  swr: number;
  ttl: number;
};

const prisma = new PrismaClient().$extends({
  model: {
    $allModels: {
      findMany<T, A>(
        this: T,
        args: Prisma.Exact<
          A,
          // For the `findMany` method, use the arguments from model `T` and the `findMany` method
          // and intersect it with `CacheStrategy` as part of `findMany` arguments
          Prisma.Args<T, "findMany"> & CacheStrategy
        >,
      ): Prisma.Result<T, A, "findMany"> {
        // method implementation with the cache strategy
      },
    },
  },
});

async function main() {
  await prisma.post.findMany({
    cacheStrategy: {
      ttl: 360,
      swr: 60,
    },
  });
}

The example here is only conceptual. For the actual caching to work, you will have to implement the logic. If you're interested in a caching extension/ service, we recommend taking a look at Prisma Accelerate.