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

@alexrr2iggs/ssr

v2.0.0

Published

Tiny TypeScript typings to describe search filters, selected fields, ordering, and pagination for repositories. It’s runtime-agnostic (ORM/DB/framework independent) and focuses on strong compile-time safety for your query shape.

Readme

@bitbeater/ssr — Type-safe search, fields, order, and pagination

Tiny TypeScript typings to describe search filters, selected fields, ordering, and pagination for repositories. It’s runtime-agnostic (ORM/DB/framework independent) and focuses on strong compile-time safety for your query shape.

Key ideas:

  • Search: deep, type-safe filters with operators (equal, like, greater, lesser, between, not)
  • Fields: precise field selection, including nested objects and arrays
  • Order: multi-field ordering with direction, nulls handling, and priority
  • Pagination: page + pageSize with optional search/order/fields
  • Repository: a minimal interface to wire your data source

Install

npm i @bitbeater/ssr

Quick start

import {
	Fields,
	Order,
	PaginatedResult,
	PaginatedSearch,
	Repository,
	Search,
} from '@bitbeater/ssr';

Person model used in examples

Includes number, string, object, date, array, and boolean types.

type Contact = {
	type: 'email' | 'phone';
	value: string;
	verified: boolean;
};

type Person = {
	id: number;            // number
	name: string;          // string
	age: number;           // number
	isActive: boolean;     // boolean
	createdAt: Date;       // date
	tags: string[];        // array of scalar
	address: {             // object
		city: string;
		zip: number;
	};
	contacts: Contact[];   // array of objects
	notes?: string | null; // nullable field
};

Search — type-safe filters

Operator shape for scalar fields:

  • equal: T | T[]
  • like: T
  • range: { greater: T; lesser: T }
  • not?: boolean (negate any of the above)

You can pass either a raw scalar (shorthand for equal) or a Find object with one operator. Nested objects and arrays are supported recursively.

import { Search } from '@bitbeater/ssr';

const search: Search<Person> = {
	// scalars
	name: { like: 'ali' },
	age: { greater: 18 },
	isActive: true, // shorthand for { equal: true }
	createdAt: {  greater: new Date('2024-01-01'), lesser: new Date('2024-12-31') },
	// array of scalars -> filter by an element match
	tags: { like: 'script' },
	// or shorthand equal
	// tags: 'typescript',

	// nested object
	address: {
		city: { like: 'York' },
	},

	// array of objects -> filter by fields on the element type
	contacts: {
		verified: { equal: true },
		type: { equal: ['email', 'phone'] },
	},
};

Notes:

  • Arrays use the element type for filtering (semantics like “any element matches” are up to your implementation).
  • Functions are excluded by design and cannot be filtered.
  • Nullable fields are treated as their non-nullable type for filtering (i.e., string | null is filtered as string). If you need explicit null checks, model them in your repository implementation or extend the types to support it.

Fields — shape the returned data

Rules:

  • true includes the field
  • object selects nested fields recursively
  • arrays accept either true (whole element) or a nested object describing the element shape
  • functions are excluded
import { Fields } from '@bitbeater/ssr';

const fields: Fields<Person> = {
	id: true,
	name: true,
	address: { city: true },
	tags: true, // include array values
	contacts: { type: true, verified: true },
	// Omitting a key excludes it (unless the root is set to true)
};

Order — multi-field ordering

Each ordered field accepts a strategy:

  • direction: 'ASC' | 'DESC'
  • nulls?: 'FIRST' | 'LAST'
  • priority?: number (lower number = higher precedence)
import { Order } from '@bitbeater/ssr';

const order: Order<Person> = {
	createdAt: { direction: 'DESC', nulls: 'LAST', priority: 1 },
	name: { direction: 'ASC', priority: 2 },
	// order within arrays-of-objects is expressed over the element type
	contacts: { verified: { direction: 'DESC', priority: 1 } },
};

PaginatedSearch and PaginatedResult

import { PaginatedSearch, PaginatedResult } from '@bitbeater/ssr';

const query: PaginatedSearch<Person> = {
	page: 0,        // default 0
	pageSize: 20,   // omit to fetch until the end
	fields,         // optional: return all when omitted/empty
	order,          // optional
	search,         // optional: match-all when omitted
};

// Your data source returns this shape
const result: PaginatedResult<Person> = {
	page: 0,
	pageSize: 20,
	totalCount: 2,
	items: [/* persons */],
};

Repository interface

Bring your own persistence. These types describe a minimal repo surface.

import { Repository } from '@bitbeater/ssr';

const peopleRepo: Repository<Person> = {
	save: async (people) => people, // create/update
	search: async (q) => ({ page: q?.page ?? 0, pageSize: q?.pageSize, totalCount: 0, items: [] }),
	remove: async (s) => [],
};

Type-only package

This library exports TypeScript types with no runtime. Use them to type your query-building and repository contracts in any stack (SQL, NoSQL, REST, GraphQL, ORM, etc.).

API surface

  • Fields: describe selected fields
  • Search: describe filters by field with operators
  • Order: describe ordering with direction/nulls/priority
  • PaginatedSearch: page, pageSize, order, fields, search
  • PaginatedResult: page, pageSize, totalCount, items
  • Repository: save, search, remove function types

License

ISC