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

@softwareone-platform/rql-client

v0.1.1

Published

TypeScript library for building and evaluating RQL (Resource Query Language) queries, with ESLint integration.

Readme

@softwareone-platform/rql-client

A TypeScript library for building and evaluating RQL (Resource Query Language) queries. Combines the former @swo/rql-client (query builder + ESLint rules) and @swo/rql-parser (RQL expression evaluator) into a single package.

Installation

npm install @softwareone-platform/rql-client

Entry points

| Import | Purpose | | ------------------------------------------------ | ------------------------------------------------------------ | | @softwareone-platform/rql-client | Query builder (RqlQuery, operators, helpers) + test() | | @softwareone-platform/rql-client/parser | test(expression, data) — parser-only subpath | | @softwareone-platform/rql-client/eslint-rules | ESLint rules for the immutable RqlQuery API |

test is re-exported from the root for convenience, so import { RqlQuery, test } from '@softwareone-platform/rql-client' works out of the box. The ./parser subpath remains available for consumers that only need the evaluator and want the smallest possible dependency surface.

Building queries

import { RqlQuery } from '@softwareone-platform/rql-client';

const query = new RqlQuery()
  .expand('id', 'name', 'email')
  .filter(new RqlQuery().operators.eq('status', 'active'))
  .orderBy(['createdAt', 'desc'])
  .paging(0, 20);

query.toString();
// select=id,name,email&eq(status,"active")&order=-createdAt&offset=0&limit=20

Evaluating RQL expressions

The parser subpath exposes a single test(expression, data) function that checks whether a JavaScript object satisfies an RQL expression. It parses the RQL string into an AST and compiles it into a predicate at runtime, returning true / false. On any parsing or evaluation error the function logs the error and returns false — it never throws.

import { test } from '@softwareone-platform/rql-client/parser';

const user = { name: 'John', status: 'Active', age: 20 };

test('(name=John)&status=Active', user); // true
test('status=Active&age>18', user);      // true
test('status=Pending', user);            // false

Supported syntax

Both the shorthand form (e.g. status=Active) and the function form (e.g. eq(status,Active)) are supported.

| Category | Operators | Example | | ----------- | -------------------------------------------------------------------- | ------------------------------------------------------- | | Equality | = / eq, != / ne | status=Active, ne(status,Active) | | Comparison | > / gt, >= / ge, < / lt, <= / le | age>18, ge(age,18) | | Logical | & / and, \| / or, ! / not | status=Active&age>18, !verified=true | | Membership | in=(...) / in, out=(...) / out | in(country,(US,CA)), country in=(US,CA) | | Pattern | like, ilike (case-insensitive); * = any chars, ? = one char | like(name,Jo*), ilike(code,a?c) | | Collections | any(field,expr), all(field,expr) — operate on array fields | any(lines, id=A), all(lines, type=A) |

Nested object paths are supported using dot notation inside field names (e.g. user.profile.name=John). Values may be quoted ("..." / '...'), numeric, or boolean; escape characters inside quoted strings follow JSON conventions.

// Arrays with any / all
test('any(lines, id=A)', { lines: [{ id: 'A' }, { id: 'B' }] }); // true
test('all(lines, type=A)', { lines: [{ type: 'A' }, { type: 'A' }] }); // true

// Nested paths
test('user.profile.role=admin', { user: { profile: { role: 'admin' } } }); // true

// Wildcards (like / ilike)
test('like(name,Jo*)', { name: 'John' });  // true
test('ilike(code,a?c)', { code: 'ABC' });  // true

ESLint rules

// eslint.config.js
import rqlRules from '@softwareone-platform/rql-client/eslint-rules';

export default [
  {
    plugins: { rql: rqlRules },
    rules: {
      'rql/no-unused-return': 'error',
      'rql/no-clone-method': 'error',
    },
  },
];

@typescript-eslint/utils is an optional peer dependency — only required when you enable the ESLint rules.

Development

npm install
npm run build     # esbuild (ESM + CJS) + tsc (types)
npm test          # jest
npm run typecheck # tsc --noEmit

The build pipeline (scripts/build.mjs) produces:

dist/
├── index.{mjs,cjs,d.ts}               # query builder
├── parser/index.{mjs,cjs,d.ts}        # RQL evaluator
└── eslint-rules/index.{mjs,cjs,d.ts}  # ESLint rules