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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@azhulin/pagination-nestjs-graphql

v1.2.0

Published

NestJS code-first GraphQL connection types for @azhulin/pagination-core.

Readme

Pagination (NestJS GraphQL)

NestJS code-first GraphQL types for @azhulin/pagination-core connections — connection, edge, page-info, and the connection arguments, wired to the core shapes.

npm i @azhulin/pagination-nestjs-graphql

Peer dependencies: @nestjs/graphql, @nestjs/common, class-validator, reflect-metadata.

Exports

| Export | Kind | Use | |----------------------------|-------------------------|----------------------------------------------------------------| | ConnectionOutput(Edge) | @ObjectType mixin | Build a connection type for an edge type. | | ConnectionEdgeOutput(N) | @ObjectType mixin | Build an edge type for a node type. | | ConnectionPageInfoOutput | @ObjectType | Page-info type; registers as schema type ConnectionPageInfo. | | ConnectionArgsInput | @ArgsType | The validated connection arguments as nullable GraphQL fields. | | PaginationModeEnum | registered GraphQL enum | The core PaginationMode, registered for the schema. |

Define the types

GraphQL output classes carry an Output suffix and register their schema name without it via the @ObjectType(name) argument (UserOutputUser), keeping them distinct from the domain User the paginator returns. Build the edge and connection with the mixin functions, mapping the framework-neutral node up through each constructor:

import type { Connection, ConnectionEdge } from '@azhulin/pagination-core'
import { ArgsType, Field, ObjectType } from '@nestjs/graphql'
import { IsNotEmpty } from 'class-validator'
import { ConnectionArgsInput, ConnectionEdgeOutput, ConnectionOutput } from '@azhulin/pagination-nestjs-graphql'
import { User } from './user.model' // your domain entity — the node the paginator emits

@ObjectType('User')
export class UserOutput {
  @Field()
  public readonly id!: string

  public constructor(user: User) {
    this.id = user.id
  }
}

@ObjectType('UserEdge')
export class UserEdgeOutput extends ConnectionEdgeOutput(UserOutput) {
  public constructor(edge: ConnectionEdge<User>) {
    super(edge.cursor, new UserOutput(edge.node))
  }
}

@ObjectType('UserConnection')
export class UserConnectionOutput extends ConnectionOutput(UserEdgeOutput) {
  public constructor(connection: Connection<ConnectionEdge<User>>) {
    super(connection.pageInfo, connection.edges.map((edge) => new UserEdgeOutput(edge)))
  }
}

// Add your own filters — ConnectionArgsDto validation comes along.
@ArgsType()
export class UserConnectionArgs extends ConnectionArgsInput {
  @Field()
  @IsNotEmpty()
  public readonly groupId!: string
}

The constructors are only there to map the node; when the node the paginator emits is already your GraphQL @ObjectType, extend with an empty body (class UserEdgeOutput extends ConnectionEdgeOutput(UserOutput) {}).

The page-info type and enum register themselves, producing:

type UserConnection {
  pageInfo: ConnectionPageInfo!
  edges: [UserEdge!]!
}

type UserEdge {
  cursor: String!
  node: User!
}

type ConnectionPageInfo {
  mode: PaginationMode!
  hasPreviousPage: Boolean!
  hasNextPage: Boolean!
  startCursor: String
  endCursor: String
  totalCount: Int
  page: Int # offset mode only
  pageSize: Int # offset mode only
  totalPages: Int # offset mode only
}

enum PaginationMode {
  Cursor
  Offset
}

Resolver

The UserConnectionOutput constructor maps the framework-neutral Connection onto the GraphQL types, so the resolver stays thin — no pagination logic:

import { Args, Query, Resolver } from '@nestjs/graphql'

@Resolver()
export class UserResolver {
  public constructor(private readonly users: UserRepository) {}

  @Query(() => UserConnectionOutput)
  public async usersByGroup(@Args() args: UserConnectionArgs): Promise<UserConnectionOutput> {
    // The repository builds a framework-neutral Connection<User> with a core Paginator (+ an adapter such as
    // @azhulin/pagination-typeorm); the constructor maps it onto the GraphQL types.
    return new UserConnectionOutput(await this.users.paginateByGroup(args, args.groupId))
  }
}

Clients send after/before/first/last or page/pageSize, plus your own arguments:

query {
  usersByGroup(groupId: "g1", first: 20, after: "eyJlbWFpbCI6…") {
    pageInfo { hasNextPage endCursor mode }
    edges { cursor node { id email } }
  }
}

Extra edge / connection fields

Widen a type, then populate it by overriding the matching core hook (createConnectionEdge / createConnection) on your Paginator subclass — or with a standard @ResolveField:

@ObjectType('UserEdge')
export class UserEdgeOutput extends ConnectionEdgeOutput(UserOutput) {
  @Field()
  public readonly highlighted!: boolean
}

License

MIT © 2022–2026 Alex Zhulin