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

dexie-typed-query

v1.0.1

Published

A type-safe query interface for Dexie

Readme

Branches Functions Lines Statements Coverage total

Dexie Typed Query

Dexie is great, but its TypeScript support and query interface leave something to be desired.

This project aims to alleviate this by offering a lightweight, type-safe query wrapper.

Introduction

Example

With vanilla Dexie:

const query = await db.users.where('name')
  .startsWith('T')
  .and(u => u.createdAt < new Date())
  .reverse()
  .sortBy('createdAt')

const result = query.slice(10, 20)

With dexie-typed-query:

const result = await typedQuery(db.users).where({
  and: [{
    name: { startsWith: 'T' },
  }, {
    createdAt: { below: new Date() },
  }],
}, { offset: 10, limit: 10, orderBy: { createdAt: 'desc' } })

Features

  • Declarative query interface: Replace complex method chains with a single, readable query object.
  • Simplified Pagination: Specify offsets and limits for your queries.
  • Easy Adoption: Drop it into an existing Dexie project without refactoring your entire database layer.
  • Deep Type Safety:
    • Property-aware operators: Only see operators that make sense for your data type (e.g., no startsWith on numbers/dates).
    • Validated condition values: The type system takes into account both the property type and the selected operator. For example, using between on a date property will require a tuple of dates.
  • Lightweight: Zero dependencies (only a peer dependency on Dexie).
  • Production Ready: 100% test coverage.

Caveats

This is not a complete replacement for Dexie. It should work for most everyday queries, but you may still need to use vanilla Dexie for more advanced queries.

Installation

Requirements: dexie@^4.0.0

npm install dexie-typed-query

Usage

Note: This assumes you are using TypeScript to define your Dexie table interfaces.

Basic Querying

import { typedQuery } from 'dexie-typed-query'

const query = typedQuery(db.someTable)

const result = await query.where({ someField: { equals: 'test' } })

Note: The queried field must be an indexed field. If a non-indexed field is used, Dexie will throw an error.

Query Options

An optional QueryOptions object can be passed as the second argument to the where function to handle pagination (offset, limit) and sorting (orderBy, ascending or descending).

const result = await typedQuery(db.someTable).where({
  someField: { equals: 'test' }
}, { offset: 5, limit 5, orderBy: { createdAt: 'desc' } })

Retrieving All

Retreive all objects in a table by calling the all function.

await typedQuery(db.someTable).all()

Also accepts an optional query options object, e.g.:

await typedQuery(db.someTable).all({ orderBy: { createdAt: 'desc' } })

Note: The orderBy field must be an indexed field. If a non-indexed field is used, Dexie will throw an error.

ANDing

Multiple query objects can be ANDed together.

const result = await typedQuery(db.users).where({
  and: [{
    name: { startsWith: 'T' },
  }, {
    createdAt: { below: new Date() },
  }],
})

Note: The first query object must be for an indexed field. If a non-indexed field is used, Dexie will throw an error. Under the hood, all subsequent query objects will use Dexie's filter function.

ORing

Multiple query objects can be ORed together.

const result = await typedQuery(db.users).where({
  or: [{
    createdAt: { below: new Date('03/01/2026') },
  }, {
    name: { startsWith: 'Test' },
  }],
})

Note: Each query object must be for an indexed field. If a non-indexed field is used, Dexie will throw an error.

Available Operators

| Operator | Description | Supported Types | | ------------ | --------------------------------------------------- | --------------- | | above | Selects items where the field value is above the given lower bound | number, Date | | aboveOrEqual | Selects items where the field value is above or equal to the given lower bound | number, Date | | anyOf | Selects items where the field value contains any of the given values | string, number, Date, array of string/number/Date | | anyOfIgnoreCase | Selects items where the field value contains any of the given values, ignoring case | string | | below | Selects items where the field value is below the given upper bound | number, Date | | belowOrEqual | Selects items where the field value is below or equal to the given upper bound | number, Date | | between | Selects items where the field value is between the given lower and upper bounds, not including the lower and upper bounds | number, Date | | betweenIncludeLower | Selects items where the field value is between the given lower and upper bounds, including the lower bound and excluding the upper bound | number, Date | | betweenIncludeLowerAndUpper | Selects items where the field value is between the given lower and upper bounds, including the lower and upper bound | number, Date | | betweenIncludeUpper | Selects items where the field value is between the given lower and upper bounds, including the upper bound and excluding the lower bound | number, Date | | equals | Selects items where the field value is equal to the given value | string, number, Date, array of string/number/Date | | equalsIgnoreCase | Selects items where the field value is equal to the given value, ignoring case | string | | noneOf | Selects items where the field value is NOT equal to the given value | string, number, Date, array of string/number/Date | | startsWith | Selects items where the field value starts with the given prefix | string | | startsWithIgnoreCase | Selects items where the field value starts with the given prefix, ignoring case | string |

License

This project is licensed under the MIT License - see the LICENSE file for details