npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cursopag

v0.1.2-3

Published

GraphQL cursor-based for Mongoose

Downloads

10

Readme

Cursopag

Cursopag is an npm package designed to simplify cursor-based pagination with GraphQL using Mongoose. It offers support for both forward and backward pagination.

Installation

You can install cursopag via npm:

npm install cursopag

Usage

Function

import { cursopag } from 'cursopag';
import { EJSON } from 'bson';
import mongoose, { HydratedDocument, Types, Document } from 'mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

type PlanetDocument = HydratedDocument<Planet>;

@Schema({
  minimize: false,
})
class Planet {
  _id: Types.ObjectId;

  @Prop({ unique: true })
  name: string;

  @Prop()
  equatorialRadius: number;

  @Prop()
  gravity: number;

  @Prop({ unique: true })
  solarPosition: number;

  @Prop({ type: [MoonSchema], default: [] })
  moons: Moon[];

  @Prop({ select: false })
  isTerrestrial: boolean;
}

const PlanetSchema = SchemaFactory.createForClass(Planet);

const planetModel = mongoose.model<Planet>(Planet.name, PlanetSchema);

const result = await cursopag({
  model: planetModel,
  filter: {},
  sort: `-isTerrestrial name`,
  first: 4,
  after: cursorEncoder(
    EJSON.stringify(
      {
        _id: neptune._id,
        name: neptune.name,
        isTerrestrial: neptune.isTerrestrial,
      },
      { relaxed: false },
    ),
  ),
});

console.log(result);

/*
{
  totalCount: 8,
  edges: [
    {
      node: {
        _id: '6564bd5862bd3f3c3084ed98',
        name: 'Saturn',
        equatorialRadius: 60268,
        gravity: 8.96,
        solarPosition: 5,
        moons: [...],
      },
      cursor: 'eyJfaWQiOnsiJG9pZCI6IjY1NjRiZDU4NjJiZDNmM2MzMDg0ZWQ5OCJ9LCJuYW1lIjoiU2F0dXJuIiwiaXNUZXJyZXN0cmlhbCI6ZmFsc2V9'
    },
    {
      node: {
        _id: '6564bd602d3c1271c6bde575',
        name: 'Uranus',
        equatorialRadius: 25559,
        gravity: 8.69,
        solarPosition: 6,
        moons: [...],
        
      },
      cursor: 'eyJfaWQiOnsiJG9pZCI6IjY1NjRiZDYwMmQzYzEyNzFjNmJkZTU3NSJ9LCJuYW1lIjoiVXJhbnVzIiwiaXNUZXJyZXN0cmlhbCI6ZmFsc2V9'
    }
  ],
  pageInfo: {
    hasPreviousPage: true,
    hasNextPage: false,
    startCursor: 'eyJfaWQiOnsiJG9pZCI6IjY1NjRiZDU4NjJiZDNmM2MzMDg0ZWQ5OCJ9LCJuYW1lIjoiU2F0dXJuIiwiaXNUZXJyZXN0cmlhbCI6ZmFsc2V9',
    endCursor: 'eyJfaWQiOnsiJG9pZCI6IjY1NjRiZDYwMmQzYzEyNzFjNmJkZTU3NSJ9LCJuYW1lIjoiVXJhbnVzIiwiaXNUZXJyZXN0cmlhbCI6ZmFsc2V9'
  }
}
*/

Parameters

  • model: The Mongoose model.
  • filter: The filter query used for pagination.
  • after: Cursor indicating the starting point for forward pagination.
  • before: Cursor indicating the starting point for backward pagination.
  • first: The number of items to fetch in forward pagination.
  • last: The number of items to fetch in backward pagination.
  • sort: The sorting criteria.
  • projection: The projection fields.
  • queryOptions: Additional query options.
  • cursorDecoder: The cursor decoder function.
  • cursorEncoder: The cursor encoder function.

Response Structure

The cursopag function returns a CursopagResponse object with the following structure:

interface Edge<T> {
  node: Document<T>;
  cursor: string;
}

interface PageInfo {
  startCursor?: string;
  hasPreviousPage: boolean;
  endCursor?: string;
  hasNextPage: boolean;
}

interface CursopagResponse<T> {
  totalCount: number;
  edges: Edge<T>[];
  pageInfo: PageInfo;
}

ref :

Options

Sorting Flexibility

One of the key features of cursopag is its ability to handle multiple levels of sorting across all Mongoose types. This functionality allows for versatile and intricate sorting criteria, enabling users to define complex sorting orders based on various fields and their types within a Mongoose schema.

Sorting Unselected Fields

cursopag empowers users to sort results based on fields that are not selected by default. This functionality allows for sorting based on fields that might not be included in the selected projection of queried documents. Even though these fields are used for sorting, they remain unselected in the returned results.

This feature is particularly advantageous in scenarios where sorting criteria involve sensitive or unnecessary fields that should not be exposed in the final result set. Users can seamlessly apply sorting logic to these unselected fields without revealing their values in the retrieved data, ensuring a balance between sorting flexibility and data confidentiality.

Customizable Cursor Encoding

Cursors in cursopag are crucial identifiers that mark specific positions in paginated data. They are constructed through a series of steps to ensure efficiency and usability in handling pagination.

  1. Lean Document: Initially, a cursor represents a lean document, minimized to its essential components for efficient processing. It consists of the _id (as an ObjectId) and sorted fields, offering a lightweight identifier of a specific record in the dataset.

  2. EJSON Stringification: The cursor is then converted into a string format using EJSON (Extended JSON) stringification. This step captures the cursor's state in a readable JSON-like format, preserving the essential information required to resume pagination from a specific point.

  3. Base64 Encoding: Following the EJSON stringification , the cursor is encoded into a Base64 format. This encoding process serves as a secure and compact representation of the cursor, suitable for transmission and storage while maintaining its integrity.

While this encoding process provides a default mechanism for cursor creation, cursopag offers the flexibility to substitute these steps with custom _cursorEncoder_ and cursorDecoder functions. This customization enables users to replace the default encoding and decoding process with their implementation, facilitating scenarios where sorting might involve fields not visible to end-users. For instance, by encoding the cursor with a private key, users can securely manage and encode the cursor's sensitive information, enhancing data privacy and control.

Minimize Mongoose options

It's highly advisable to disable the minimize option within the Mongoose schema used with Cursopag. Enabling this option can alter the sorting order of documents, potentially causing inconsistencies in the sorting logic utilized by the package. By keeping the minimize option disabled, the sorting results remain consistent with the user-defined logic, ensuring accurate and reliable pagination.

License

This package is released under the MIT License.