@ucast/mongo2js

Evaluate MongoDB-style query conditions against plain JavaScript objects with a single guard() call.

Library
npm
v2.0.0
268stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
57/100Fair
Development Activity32
Maintenance60
Community56
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
70/100Good
Architecture75
Code Quality78
Innovation68
Learning Curve60

@ucast/mongo2js combines @ucast/mongo’s MongoDB query parser with @ucast/js’s JavaScript interpreter to let you test whether a plain object matches a MongoDB-style query, entirely in-process and without a database connection. Its main export, guard(), takes a Mongo query object and returns a predicate function you can call against any object, with the parsed condition AST attached as .ast for introspection or serialization.

Beyond the common object-matching case, the package ships squire() for testing primitive values directly (numbers, strings) against operator-only queries, and createFactory() for defining entirely custom operators that plug into the same parsing/interpretation pipeline — used, for example, to add a $jsonSchema operator backed by Ajv. It re-exports @ucast/core, @ucast/mongo, and @ucast/js, so consumers only need to install this one package to get the full Mongo-query-to-JS-predicate pipeline.

What You Get

  • guard() — parses a Mongo-style query and returns a typed predicate function, with the parsed condition tree exposed as .ast
  • squire() — the same predicate-building API scoped to primitive values ($lt, $gt, etc. against numbers/strings directly)
  • createFactory() — build your own guard/squire variant with custom parsing instructions and JS interpreters for non-standard operators
  • Built-in handling for Date comparisons, bigint equality, and objects exposing toJSON() (e.g., ObjectId-like wrappers)
  • Full TypeScript generics support so the queried object’s shape is checked against the query object at compile time
  • Zero runtime dependencies outside the ucast family — @ucast/core, @ucast/js, and @ucast/mongo are re-exported, so one install covers the whole pipeline

Common Use Cases

  • Client-side or in-memory filtering of already-fetched records using the same Mongo query syntax used server-side
  • Implementing attribute-based access control / permission checks by compiling a stored Mongo-style rule into a JS predicate (the pattern used by the CASL authorization library, which is built on ucast)
  • Validating or testing objects against conditions in unit tests without spinning up a MongoDB instance
  • Adding custom, domain-specific query operators (e.g., JSON Schema validation, geospatial checks) on top of a familiar Mongo query syntax

Under The Hood

Architecture The mongo2js package composes @ucast/core (the Condition AST and translator abstraction), @ucast/mongo (MongoQueryParser plus the Mongo operator parsing instructions), and @ucast/js (the JsInterpreter that walks a Condition tree against a runtime object) through a single composition point in src/factory.ts: createFactory() instantiates a MongoQueryParser, wraps a JS interpreter with comparePrimitives (a Date/toJSON-aware equality helper), and joins them via createTranslatorFactory from @ucast/core to produce a filter function with an attached .ast. The package’s own src/index.ts is a thin re-export barrel over factory.ts and the three sibling packages, meaning almost all domain logic — operator parsing, compound-condition handling, JS interpretation — lives elsewhere in the pnpm monorepo (packages/core, packages/mongo, packages/js); mongo2js’s distinct contribution is the guard/squire/filter factories and the primitive-comparison helpers. Because createFactory is a thin composition layer with no independent AST or interpretation logic, changes to @ucast/core’s Condition/parser/interpreter contracts ripple directly into this package.

Tech Stack Written in TypeScript (^5.9.2) and built with tsdown (an esbuild-based bundler) for dual ESM/CJS output alongside tsc-generated type declarations; the monorepo uses pnpm workspaces with workspace:* protocol links to @ucast/core, @ucast/js, and @ucast/mongo. Tests run under mocha with ts-node/register, asserted with chai and chai-spies, and measured with nyc for coverage. Linting uses ESLint 9’s flat config with typescript-eslint and @stylistic plugins, enforced pre-commit via husky + lint-staged. Releases are automated with release-please and GitHub Actions CI. The package has no runtime dependencies outside the ucast family, keeping its footprint minimal, and targets ES2020-compatible runtimes.

Code Quality The spec/ directory covers guard() and squire() with mocha/chai specs exercising type inference, Date comparisons, toJSON-based equality (ObjectId-style wrappers), bigint support, and custom-operator factories — a reasonable but not exhaustive suite for a package of this scope. TypeScript typing is thorough throughout (conditional FilterType, generic Filter/PrimitiveFilter types propagating the queried shape), and ESLint plus CI enforce style and correctness on every change. Error handling within this package itself is minimal and implicit — invalid queries are expected to throw from the delegate parsing instructions in @ucast/mongo rather than being caught or wrapped here — which is a deliberate thinness rather than an oversight, since mongo2js is a composition layer.

API Design The public surface is intentionally small: guard(query) is the entire entry point for the common case, returning a ready-to-call predicate with the parsed AST attached for introspection, with zero configuration required. squire() extends the identical API to primitive-only queries, and createFactory() lets consumers register fully custom operators (demonstrated in the README with a $jsonSchema operator backed by Ajv) while reusing the same typed Filter/ThingFilter contracts. TypeScript generics flow the queried object’s type through to the returned filter, so field names and value types in the query are checked at compile time. The ergonomics are strong for a query-condition evaluator, though the underlying idea — translating Mongo-style queries into JS predicates — isn’t unique to this package (similar functionality exists in sift.js); ucast’s differentiation is the pluggable AST/translator architecture shared across its mongo/sql targets, not something exclusive to mongo2js.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search