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

@metreeca/qest

v0.9.1

Published

Minimalist foundations for client-driven, queryable REST/JSON APIs

Readme

@metreeca/qest

npm

Minimalist foundations for client-driven, queryable REST/JSON APIs.

@metreeca/qest standardizes critical capabilities that vanilla REST/JSON APIs typically lack or implement in ad‑hoc, non‑portable ways:

  • Client-driven — clients specify what they need, retrieving complex envelopes in a single call
  • Queryable — advanced filtering and aggregation, supporting faceted search and analytics

Developers seek these features in frameworks like GraphQL; @metreeca/qest brings them to REST/JSON, achieving:

  • Familiar patterns — standard REST and JSON conventions, no new paradigms to learn
  • Simple clients — no specialized libraries, preprocessors, or code generators
  • Automated servers — model-driven development, dramatically reducing implementation effort
  • Standard caching — compatibility with CDNs and browser caches using standard GET requests
  • URL-based versioning — standard REST versioning without field deprecation complexity

Installation

npm install @metreeca/qest

[!WARNING]

TypeScript consumers must use "moduleResolution": "nodenext"/"node16"/"bundler" in tsconfig.json. The legacy "node" resolver is not supported.

Usage

[!NOTE]

This section introduces essential concepts; for complete coverage, see the API reference:

@metreeca/qest types define payload semantics and formats for standard REST operations:

| Method | Type | Description | |--------|-----------------------------------------------------------------------|----------------------------------| | GET | Resource | Resource retrieval | | GET | Query | Client-driven resource retrieval | | POST | Resource | Resource creation | | PUT | Resource | Complete resource state update | | PATCH | Patch | Partial resource state update | | DELETE | IRI | Resource deletion |

Resources and Patches

A Resource is a property map describing data returned by a REST endpoint, with optional links to other endpoints:

GET https://data.example.com/products/123
{
  "id": "https://data.example.com/products/123",
  "name": "Widget",
  "category": "Electronics",
  "tags": [
    "gadget",
    "featured"
  ],
  "vendor": "https://data.example.com/vendors/456",
  "price": 99.99,
  "inStock": true
}

The same format is used for complete resource updates:

PUT https://data.example.com/products/123
({
    "name": "Widget",
    "category": "Electronics",
    "tags": ["gadget", "premium"],
    "vendor": "https://data.example.com/vendors/456",
    "price": 79.99
    // inStock                     // not included → deleted
})

A Patch describes partial updates with the same effect:

PATCH https://data.example.com/products/123
({
    "tags": ["gadget", "premium"], // updated
    "price": 79.99,                // updated
    "inStock": null                // deleted
})

Properties set to null are deleted; properties not included are unchanged.

Client-Driven Retrieval

A Query is a declarative specification that controls how resources are retrieved: which properties to include and how deeply to expand linked resources. For collections, queries also support filtering, sorting, pagination, and computed projections including aggregates supporting faceted search and analytics.

GET https://data.example.com/products/?<query>

where <query> is the following URL-encoded JSON:

({
    "items": [
        {
            "id": "",
            "name": "",
            "price": 0,
            "vendor": {
                "id": "",
                "name": ""
            },
            ">=price": 50,     // filter: price ≥ 50
            "<=price": 150,    // filter: price ≤ 150
            "^price": "asc",   // sort: by price ascending
            "#": 25            // limit: 25 results
        }
    ]
})

A single call returns exactly what the client requested:

  • projected: product id, name, price
  • expanded: linked vendor with only id and name (not its full state)
  • filtered: price between 50 and 150
  • sorted: by price ascending
  • paginated: up to 25 results

Expansions and nested queries can be arbitrarily deep. No over-fetching of unwanted fields, no under-fetching requiring additional calls to resolve linked resources:

{
  "items": [
    {
      "id": "https://data.example.com/products/456",
      "name": "Gadget",
      "price": 59.99,
      "vendor": {
        "id": "https://data.example.com/vendors/145",
        "name": "Acme"
      }
    },
    {
      "id": "https://data.example.com/products/123",
      "name": "Widget",
      "price": 99.99,
      "vendor": {
        "id": "https://data.example.com/vendors/145",
        "name": "Acme"
      }
    },
    {
      "id": "https://data.example.com/products/789",
      "name": "Gizmo",
      "price": 129.99,
      "vendor": {
        "id": "https://data.example.com/vendors/236",
        "name": "Globex"
      }
    }
  ]
}

This is the core contribution of @metreeca/qest: vanilla REST/JSON APIs lack a standard way for clients to control retrieval, forcing them to accept fixed server responses or rely on ad-hoc query parameters. The Query model fills this gap, giving clients precise control over responses while remaining fully compatible with standard HTTP caching.

[!IMPORTANT]

Client-driven retrieval is fully optional. When clients don't provide a query, servers may provide a default one, typically derived from the underlying data model. This preserves standard REST/JSON behavior while enabling advanced retrieval capabilities when needed.

Integrated Ecosystem

[!IMPORTANT]

@metreeca/qest defines data types only; applications are absolutely free to handle validation, storage, and publishing as they see fit.

But @metreeca/qest is also the foundation of an integrated ecosystem for rapid application development, turning those same types into a complete model-driven stack:

| Package | Description | |-----------------------------|------------------------------------------------------------| | @metreeca/qest | Data types for client-driven, queryable REST/JSON APIs | | @metreeca/blue (upcoming) | Shape-based validation for resources, patches, and queries | | @metreeca/keep (upcoming) | Shape-driven storage across various backends | | @metreeca/gate (upcoming) | Shape-driven REST/JSON API publishing |

JSON-LD Interoperability

@metreeca/qest is built on a controlled subset of JSON-LD (JSON for Linked Data), a W3C standard that extends JSON with web identifiers (IRIs). This enables property names and values to reference shared vocabularies, giving data a precise, machine-readable meaning that survives when combined with data from other sources — a capability at the heart of the Web Data Activity (Semantic Web) and modern knowledge graphs.

The subset is designed to feel like plain idiomatic JSON, letting JavaScript developers work with linked data using familiar REST/JSON patterns without mastering JSON-LD technicalities, while retaining full compatibility with standard JSON-LD processors.

The JSON-LD subset is defined by the following constraints:

  • only the compacted document form is supported, using short property names and nested objects just like regular JSON

  • property names (JSON-LD terms) are restricted to ECMAScript identifiers, enabling property access with dot notation; this excludes JSON-LD keywords (@id, @type, etc.), blank node identifiers (_:), and arbitrary property names; mapping from property names to IRIs and keywords may still be managed by an application-provided @context object

  • values are native JSON primitives (boolean, number, string) without support for typed literals with arbitrary datatypes; property-specific datatype coercion may still be handled by an application-provided @context object

  • JSON-LD @language containers, don't support @none keys for plain literals; for mixed non-localized/localized content use string | Dictionary union types or zxx tags

Support

  • open an issue to report a problem or to suggest a new feature
  • start a discussion to ask a how-to question or to share an idea

License

This project is licensed under the Apache 2.0 License – see LICENSE file for details.