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

@nestjs-filter-grammar/core

v0.1.3

Published

Chevrotain-based filter DSL parser for NestJS with decorator-based column/operator declarations

Readme

@nestjs-filter-grammar/core

Core package for nestjs-filter-grammar. Provides the Chevrotain-based filter/sort parser, NestJS decorators, validation, and Swagger description generation.

Installation

npm install @nestjs-filter-grammar/core

Peer Dependencies

  • @nestjs/common >= 10.0.0
  • @nestjs/core >= 10.0.0
  • reflect-metadata >= 0.1.13
  • @nestjs/swagger >= 7.0.0 (optional — for Swagger descriptions)

API

Decorators

@Filterable()

Class decorator — marks a query DTO as filterable.

@Filterable()
class UserQuery { ... }

@FilterableColumn(operators, options?)

Property decorator — declares which filter operators a column supports.

@FilterableColumn([FilterOperator.eq, FilterOperator.neq, FilterOperator.iContains])
name!: string;

The optional options.type parameter controls value coercion and validation. By default, values are strings.

// Number — coerces "30" to 30, rejects "abc"
@FilterableColumn([FilterOperator.gte, FilterOperator.lte], { type: 'number' })
age!: number;

// Boolean — accepts "true"/"false" only
@FilterableColumn([FilterOperator.eq], { type: 'boolean' })
active!: boolean;

// Enum — validates value is one of the enum members
enum Status { active = 'active', inactive = 'inactive', pending = 'pending' }
@FilterableColumn([FilterOperator.eq, FilterOperator.neq], { type: Status })
status!: Status;

// String array — same as enum but without defining one
@FilterableColumn([FilterOperator.eq], { type: ['red', 'green', 'blue'] })
color!: string;

// Numeric enum — coerces "1" to 1, validates against allowed values
enum Priority { low = 0, medium = 1, high = 2 }
@FilterableColumn([FilterOperator.eq], { type: Priority })
priority!: Priority;

Quoted values (field="123") are never coerced and always stay as strings, regardless of the declared type.

@SortableColumn()

Property decorator — marks a column as sortable.

@SortableColumn()
name!: string;

@Filter(queryClass, options?)

NestJS parameter decorator — parses and validates filter/sort from query params.

@Get()
findAll(@Filter(UserQuery) result: FilterResult) {
  const { filter, sort, query } = result;
}

Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | queryParam | string | 'filter' | Name of the filter query parameter | | sortParam | string | 'sort' | Name of the sort query parameter | | optional | boolean | false | Whether the filter param is optional |

Parser

parseFilter(input: string): FilterTree

Parses a filter string into a FilterTree (AST). Throws on syntax errors.

import { parseFilter } from '@nestjs-filter-grammar/core';

const tree = parseFilter('status=active;age>=18');
// { type: 'AND', conditions: [
//   { field: 'status', operator: '=', values: [{ type: 'string', value: 'active' }], ... },
//   { field: 'age', operator: '>=', values: [{ type: 'string', value: '18' }], ... },
// ]}

parseSortString(input: string): SortEntry[]

Parses a sort string into an array of sort entries.

import { parseSortString } from '@nestjs-filter-grammar/core';

const entries = parseSortString('+name,-age');
// [{ field: 'name', direction: 'asc' }, { field: 'age', direction: 'desc' }]

Validation

validateFilter(tree, metadata): FilterError[]

Validates a FilterTree against column metadata. Returns an array of errors (empty if valid).

validateSort(entries, metadata): FilterError[]

Validates sort entries against sortable column metadata.

Types

FilterOperator

Enum of all supported operators: eq, neq, gt, lt, gte, lte, iEq, iNeq, startsWith, endsWith, contains, iStartsWith, iEndsWith, iContains.

FilterTree

Union of FilterGroup | FilterCondition — the parsed AST.

FilterResult<T>

Returned by the @Filter() decorator:

interface FilterResult<T = Record<string, never>> {
  filter?: FilterTree;
  sort?: SortEntry[];
  query: T;
}

SortDirection

Enum: asc, desc.

SortEntry

interface SortEntry {
  field: string;
  direction: SortDirection;
}

Coercion

coerceFilterValues(tree, metadata): CoerceResult

Walks a FilterTree and converts string values to their declared types based on ColumnMetadata.valueType. Called automatically by @Filter(), but available for manual use when calling parseFilter() directly.

import { parseFilter, coerceFilterValues } from '@nestjs-filter-grammar/core';

const tree = parseFilter('age>=30');
const { tree: coerced, errors } = coerceFilterValues(tree, metadata);
// coerced values: { type: 'number', value: 30 } instead of { type: 'string', value: '30' }

Quoted values (field="123") are never coerced — they always remain strings.

Swagger & OpenAPI

When @nestjs/swagger is installed, @Filter() automatically:

  1. Adds @ApiQuery decorators with generated descriptions listing available columns and operators
  2. Emits an x-filter-grammar extension on the operation with structured metadata for codegen:
{
  "x-filter-grammar": {
    "filterParam": "filter",
    "sortParam": "sort",
    "fields": {
      "name": { "operators": ["=", "!=", "*~"], "type": "string" },
      "status": { "operators": ["=", "!="], "type": "enum", "values": ["active", "inactive"] },
      "age": { "operators": [">=", "<="], "type": "number" }
    },
    "sortable": ["name", "status", "age"]
  }
}

This extension is consumed by @nestjs-filter-grammar/client-query-builder to generate type-safe query builders.

Parenthesized Expressions

The grammar supports parentheses for grouping:

(status=active|status=pending);age>=18
name=admin|(status=active;age>=18)
(a=1;b=2)|(c=3;d=4)