prisma-extension-pagination

repository·main·Indexed 43 days ago

https://github.com/deptyped/prisma-extension-pagination

A Prisma Client extension providing page number and cursor-based pagination for Prisma models. It includes methods like .withPages() and .withCursor() to handle result slicing and metadata generation, such as page counts, total records, and cursor serialization/deserialization for composite keys. Version 0.7.6.

Tokens
5.2K
Snippets
23
Records
23
Agent score
5%

What's inside prisma-extension-pagination

  1. Install the extension on specific models

    main

    To limit pagination capabilities to only certain models, use the paginate function inside a model-specific extension configuration.

    import { PrismaClient } from "@prisma/client";
    import { paginate } from "prisma-extension-pagination";
    
    const prisma = new PrismaClient().$extends({
      model: {
        user: {
          paginate,
        },
      },
    });
  2. Install the extension to all models

    main

    To enable pagination on every model in your Prisma Client, use the pagination() function within the $extends method.

    import { PrismaClient } from "@prisma/client";
    import { pagination } from "prisma-extension-pagination";
    
    const prisma = new PrismaClient().$extends(pagination());
  3. Implement custom cursor serialization/deserialization

    main

    If your cursor requires multiple fields (e.g., a composite key), you can provide getCursor and parseCursor functions directly within the .withCursor() call to handle serialization and deserialization.

    const getCustomCursor = (postId: number, userId: number) =>
      [postId, userId].join(":");
    
    const parseCustomCursor = (cursor: string) =>
      cursor.split(":");
    
    const [results, meta] = await prisma.postOnUser
      .paginate({
        select: {
          postId: true,
          userId: true,
        },
      })
      .withCursor({
        limit: 10,
        after: getCustomCursor(1, 1), // "1:1"
    
        // custom cursor serialization
        getCursor({ postId, userId }) {
          return getCustomCursor(postId, userId)
        },
    
        // custom cursor deserialization
        parseCursor(cursor) {
          const [postId, userId] = parseCustomCursor(cursor);
    
          return {
            userId_postId: {
              postId: parseInt(postId),
              userId: parseInt(userId),
            },
          };
        },
      });
  4. Use cursor-based pagination with withCursor

    main

    Cursor-based pagination uses limit and either before or after to return results relative to a cursor. Use the .withCursor() method.

    Loading first records:

    const [users, meta] = await prisma.user
      .paginate({ select: { id: true } })
      .withCursor({ limit: 10 });

    Loading the next page:

    const [users, meta] = await prisma.user
      .paginate()
      .withCursor({ limit: 10, after: "10" });

    Loading the previous page:

    const [users, meta] = await prisma.user
      .paginate()
      .withCursor({ limit: 10, before: "11" });

    Metadata returned by withCursor:

    • hasPreviousPage: Boolean.
    • hasNextPage: Boolean.
    • startCursor: The cursor of the first item in the result set.
    • endCursor: The cursor of the last item in the result set.
    // Example: Loading next page
    const [users, meta] = await prisma.user
      .paginate()
      .withCursor({
        limit: 10,
        after: "10"
      });
  5. Use page number pagination with withPages

    main

    Page number pagination uses limit to select a range and page to load a specific page. Use the .withPages() method to execute the query.

    Loading the first page:

    const [users, meta] = await prisma.user
      .paginate({ select: { id: true } })
      .withPages({ limit: 10 });

    Loading a specific page:

    const [users, meta] = await prisma.user
      .paginate()
      .withPages({ limit: 10, page: 2 });

    Including page counts: To get pageCount and totalCount, set includePageCount: true in the options.

    const [users, meta] = await prisma.user
      .paginate()
      .withPages({ limit: 10, page: 2, includePageCount: true });

    Metadata returned by withPages:

    • currentPage: The current page number.
    • isFirstPage: Boolean indicating if it's the first page.
    • isLastPage: Boolean indicating if it's the last page.
    • previousPage: The previous page number (or null).
    • nextPage: The next page number (or null).
    • pageCount: Total number of pages (if includePageCount is true).
    • totalCount: Total number of results (if includePageCount is true).
    // Example: Loading a specific page
    const [users, meta] = await prisma.user
      .paginate()
      .withPages({
        limit: 10,
        page: 2,
      });
  6. Configure default pagination settings

    main

    You can define global default settings for both page-based and cursor-based pagination when initializing the extension with pagination().

    Page settings:

    • limit: Default number of items per page.
    • includePageCount: Whether to include pageCount and totalCount in the metadata by default.

    Cursor settings:

    • limit: Default number of items per cursor window.
    • getCursor: Function to serialize a record into a cursor.
    • parseCursor: Function to deserialize a cursor string back into a Prisma-compatible object.
    import { PrismaClient } from "@prisma/client";
    import { pagination } from "prisma-extension-pagination";
    
    const prisma = new PrismaClient().$extends(
      pagination({
        pages: {
          limit: 10, // set default limit to 10
          includePageCount: true, // include counters by default
        },
        cursor: {
          limit: 10, // set default limit to 10
    
          // set default cursor serialization/deserialization
          getCursor(user: UserType) {
            // ...
          },
          parseCursor(cursor) {
            // ...
          },
        },
      })
    );
  7. Install the pagination extension to Prisma

    main

    To use the pagination extension, use the extension function to create a Prisma extension. This attaches the pagination methods to all models in your Prisma client.

    import { PrismaClient } from '@prisma/client'
    import { extension } from 'prisma-extension-pagination'
    
    const prisma = new PrismaClient().$extends(extension({
      pages: {
        limit: 10,
        includePageCount: true
      },
      cursor: {
        limit: 10
      }
    }))
  8. Install the pagination extension

    main

    The extension is exported as the default export from the package. You can use it to extend your Prisma client instance by passing it to the .$extends method.

    import { PrismaClient } from '@prisma/client';
    import pagination from 'prisma-extension-pagination';
    
    const prisma = new PrismaClient().$extends(pagination);
  9. Create reusable paginators with createPaginator

    main

    When installing the extension on specific models, use createPaginator to define a reusable pagination configuration. This allows you to create multiple paginators with different settings and apply them to different models.

    import { PrismaClient } from "@prisma/client";
    import { createPaginator } from "prisma-extension-pagination";
    
    const paginate = createPaginator({
      // available settings are the same as above
      pages: {
        // ...
      },
      cursor: {
        //...
      },
    });
    
    // You can create many paginators with different settings.
    // They can be reused for different models.
    
    const prisma = new PrismaClient().$extends({
      model: {
        user: {
          paginate,
        },
        post: {
          paginate,
        },
      },
    });
  10. Configure the Prisma Pagination Extension via defineConfig

    main

    The prisma/config module provides a defineConfig function to set up the environment for the extension. You can specify the path to your Prisma schema and the datasource URL used for testing or development purposes.

    import { defineConfig } from 'prisma/config'
    
    export default defineConfig({
      schema: 'prisma/schema.prisma',
      datasource: {
        url: 'file:./prisma/test.db',
      },
    })