API documentation

Matches the npm package exports. For a live REPL, use the playground.

Installation

Requires Node.js 18+.

npm install mongo-query-tools

Basic Usage

Pass HTTP-shaped query params and a configuration object — you get a filter, sort, page, limit, and skip ready for MongoDB Driver or Mongoose.

typescript
import { buildMongoQuery } from "mongo-query-tools";

const options = buildMongoQuery(
  req.query as Record<string, string | string[] | undefined>,
  {
    searchableFields: ["name", "email"],
    allowedFilters: ["status", "role"],
    allowedSorts: ["createdAt", "name"],
    defaultFilters: { isDeleted: false },
    defaultSort: "-createdAt",
    maxLimit: 100,
    defaultPage: 1,
    defaultLimit: 10,
  },
);

Config Options

  • searchableFields — applied to case-insensitive substring search (OR combination).
  • allowedFilters — allow-list for filter keys originating from query params.
  • allowedSorts — field names allowed in sort tokens (omit + / - prefixes from this array).
  • defaultFilters — always merged. Unexpected query keys do not erase these predicates.
  • defaultSort — used when sortis missing or invalid (same string syntax: field asc, -field desc).
  • maxLimit — clamps resolved limit.
  • defaultPage, defaultLimit — fallbacks when pagination params absent or malformed. defaultLimit honours maxLimit.
  • conditionalFilters / conditionalFilter — branching merge via when / filter — later merges win on key clashes (Object.assign).

Conditional Filters

Layer tenancy or auth predicates without stuffing framework globals into the parser. when and filter receive the identical query forwarded to buildMongoQuery.

typescript
import { buildMongoQuery, type QueryParams } from "mongo-query-tools";

type AppQuery = QueryParams & { mode?: string };

const options = buildMongoQuery(req.query as AppQuery, {
  defaultFilters: { isDeleted: false },
  searchableFields: ["name", "email"],
  allowedFilters: ["role"],
  conditionalFilters: [
    {
      when: (query) => query.mode === "personal",
      filter: () => ({ ownerId: "current-user" }),
    },
  ],
});

Reserved Query Keys

Parsed as controls — never surfaced as standalone filter props even if accidentally listed inside allowedFilters.

  • page
  • limit
  • skip
  • sort
  • search

Sorting Format

Comma-separated segments. Prefix with - for descending, + for explicit ascending, or omit the prefix for ascending shorthand.

  • name { name: 1 }
  • -createdAt { createdAt: -1 }
  • -createdAt,name { createdAt: -1, name: 1 }

If any segment violates allowedSorts, the entire sort clause is discarded and defaultSort resumes when present.

Pagination Behavior

  • page 1; else defaultPage (fallback 1) applies.
  • limit 1; else defaultLimit (fallback 10) then clamps through maxLimit.
  • Present skip overrides canonical (page − 1) × limit.

TypeScript Exports

Consume whatever your bundler tree-shakes from the barrel:

typescript
import { buildMongoQuery } from "mongo-query-tools";
import type {
  BuildMongoQueryConfig,
  BuildMongoQueryResult,
  ConditionalFilterQuery,
  ConditionalFilterRule,
  QueryParams,
  SortSpec,
} from "mongo-query-tools";