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

@niscorp/vex

v0.2.3

Published

Declarative query synthesis — intent to SQL with caching and scope policies

Readme

@niscorp/vex

Declarative query synthesis. Describe the data you want in plain English and the shape you want it in; Vex generates a constrained query DSL, compiles it to parameterized SQL, runs it, reshapes the result, and caches every generation under a fingerprint so replaying it costs zero LLM calls.

The LLM never writes SQL. It fills in a validated JSON DSL; a deterministic pipeline does the rest. Server-side scope policies enforce access control the model can't see or bypass.

Install

pnpm add @niscorp/vex @niscorp/prism @niscorp/strata zod
# prism (mappings), strata (the cache table's ledger) and zod are required
# peers. Add the others for the paths you use:
pnpm add pg                               # a Postgres pool for the adapter and the cache
pnpm add hono                             # the Hono adapter (or: express)
pnpm add @niscorp/cortex @niscorp/signal  # only if you wire the bundled LLM agents

Quick Example

import pg from 'pg';
import { createQueryEngine, createPostgresAdapter } from '@niscorp/vex';

const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
const adapter = createPostgresAdapter({ pool });
const engine = createQueryEngine({ adapter });

await engine.introspect(); // discover tables, columns, relations, indexes — and their
                           // COMMENTs, as descriptions the query writer reads

// Generate once — the intent + the shape drive the DSL and the mapping.
// No fingerprint given, so the engine mints one and returns it.
const first = await engine.execute({
  intent: 'a customer\'s orders, newest first',
  shape: [{ id: '', total: 0, createdAt: '' }],
  context: { customerId: 'cust-42' },
});
const fp = first.meta.cache.fingerprint; // 'fp_…' — the replayable identity

// Replay by fingerprint — same DSL + mapping, zero LLM, context varies per call.
const again = await engine.execute({ fingerprint: fp, context: { customerId: 'cust-99' } });
// again.result (array | object | scalar), again.meta.cache.hit === true

Generating needs an LLM-backed generateDsl hook — see DOCS.md. Without one, the engine still serves any request that replays a fingerprint (a named slot or a seeded read), and the compile/test APIs work with no model: both need the introspected schema, and test runs the query against the database.

The production shape

Most apps use Vex in two moves, then leave one door open:

  1. Author the API as fingerprints. Seed each read and write as a named cache entry (orders/recent, tasks/setDone) — generation happens once, at build time, and the fingerprint is the whole wire contract. The wire carries { fingerprint, context } and nothing else.
  2. Lock the endpoint. locked: true makes it replay-only: a seeded fingerprint replays with zero LLM; an unknown or changed one is refused (locked). The model cannot generate ad-hoc SQL against your data.

Then keep one unlocked endpoint (wired with generateDsl) for genuine ad-hoc queries — an agent, an admin console — under its own scope policy. Built surfaces are locked; exploration is open and scoped.

Documentation

  • DOCS.md — Full usage guide: configuration, DSL reference, scope, caching, framework adapters, error handling, local dev.
  • DESIGN.md — Architecture, the pipeline, and the reasoning behind each decision.

API

const engine = createQueryEngine(config);

engine.introspect();              // Promise<DatabaseSchema> — load + cache schema
engine.execute(request, options); // Promise<QueryResponse> — the full pipeline
engine.compile(dsl);             // CompiledQuery — DSL → SQL, no LLM, no execution
engine.test(dsl, scope?);         // Promise<TestResult> — compile + run with synthetic params (LIMIT 5)
engine.getDslSchema();            // object — the DSL as JSON Schema (draft-7)
engine.getSchema();               // DatabaseSchema | undefined — last introspected schema
engine.cache;                     // CacheBackend — the live cache

What's in the box

| Area | Provided | |------|----------| | Database adapters | PostgreSQL (createPostgresAdapter) — pluggable DatabaseAdapter interface for others. createPglitePool (@niscorp/vex/pglite) shapes a PGlite database as the pool it takes | | Cache backends | In-memory, Postgres (durable), tiered L1/L2 with warm-up | | Framework adapters | Hono (@niscorp/vex/hono), Express (@niscorp/vex/express) — discovery + query endpoints | | LLM integration | generateDsl / mapToShape hooks; reference agents built on @niscorp/cortex (@niscorp/vex/agent: createQueryDsl, createShapeMapper) | | Writes | Mutation entries in the same cache — a closed grammar, replay-only by fingerprint, never generated; lintMutation checks a statement at seed | | Seeding and freshness | seedCache turns authored SeedEntry / SeedMutation rows into protected cache entries; an entry's refresh is 'snapshot' or 'reactive' | | Safety | Server-side scope policies, query analyzer (cartesian/nesting/index checks), parameterized SQL only | | Its own table | The Postgres cache's table is a strata sequence (cache.sequence, nisc.vex.cache): cache.init() applies it through the ledger once, instead of IF NOT EXISTS on every boot. Requires a pool with transaction (the PGlite pool has one). |

License

Apache-2.0