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

@datrix/adapter-mongodb

v0.2.0

Published

MongoDB adapter for Datrix framework

Readme

Datrix MongoDB Adapter

MongoDB adapter for the Datrix framework. Provides full CRUD, relation population, migration support, and manual referential integrity enforcement since MongoDB lacks native FK constraints and JOINs.

Installation

pnpm add @datrix/adapter-mongodb

Requires mongodb driver as a peer dependency.

Configuration

import { createMongoDBAdapter } from "@datrix/adapter-mongodb";

const adapter = createMongoDBAdapter({
  uri: "mongodb://localhost:27017",
  database: "myapp",
  maxPoolSize: 10,
  minPoolSize: 2,
  connectTimeoutMS: 10000,
  serverSelectionTimeoutMS: 5000,
  appName: "myapp",
  // Optional
  replicaSet: "rs0",
  authSource: "admin",
  tls: false,
  tlsCAFile: "/path/to/ca.pem",
});

Requirements

  • MongoDB 6.0+
  • Replica set required for transaction support. Standalone MongoDB instances cannot use multi-document transactions, which are needed for migration operations.

Architecture

src/
├── adapter.ts           # Main adapter + MongoDBTransaction implementation
├── query-translator.ts  # QueryObject → MongoDB operation descriptors
├── mongo-client.ts      # Db wrapper with debug logging and error handling
├── helpers.ts           # Auto-increment ID generation, error mapping
├── types.ts             # Type definitions for translated operations
├── fk-validator.ts      # Manual FK reference validation on insert/update
├── on-delete.ts         # Manual ON DELETE actions (restrict/setNull/cascade)
├── nested-where.ts      # Cross-collection relation WHERE resolution
├── test-utils.ts        # Test database setup helpers
├── index.ts             # Public exports
└── populate/
    ├── index.ts
    └── populator.ts     # Relation population ($lookup + batched strategies)

Migration

Migration operations are split into 3 phases due to MongoDB not supporting DDL inside transactions:

  1. Pre-transaction — createTable (collection creation)
  2. Transaction — alterTable, dataTransfer, createIndex, dropIndex
  3. Post-transaction — dropTable, renameTable

This split is handled by the core migration runner and applies to all adapters, but is specifically designed around MongoDB's limitations. SQL adapters are unaffected since their DDL is transaction-safe.

On failure during phase 2, tables created in phase 1 may remain as empty leftovers. No data loss occurs.

Populate Strategies

Two strategies are used depending on relation depth:

  • $lookup aggregation — Used for depth-1 relations. Performs a server-side join via aggregation pipeline. Handles belongsTo, hasOne, hasMany, and manyToMany (with double $lookup through junction table).

  • Batched $in queries — Used for depth 2+. Collects IDs from parent rows, queries the target collection with { id: { $in: [...] } }, then stitches results in memory. Supports nested populate recursively.

FK columns needed for belongsTo relations (e.g. authorId) are automatically injected into projections even when not explicitly selected, to ensure population works correctly.

Per-relation limit/offset are applied per parent row in both strategies. In the batched strategy this happens in memory: all related rows for the parent batch are fetched first (the where filter still applies server-side), then each parent's group is windowed. With very large child sets this intermediate fetch is unbounded — prefer filtering via where when children are numerous. For single-row relations (belongsTo/hasOne) limit/offset are meaningless and ignored.

distinct / groupBy / having

Implemented via aggregation pipelines ($group), mirroring the postgres adapter's SQL semantics:

  • distinct — deduplicates on the selected field list.
  • groupBy — every selected field must appear in groupBy (as in SQL); violations throw.
  • having — may only reference grouped fields (core's WhereClause cannot express aggregates).
  • count with groupBy returns the first group's count in metadata.count (postgres parity).
  • None of these can be combined with populate (throws).

Export / Import

Export and import only touch datrix-managed collections (those with a schema entry in _datrix, plus _datrix itself). Foreign collections in a shared database are never exported, dropped, or overwritten. Collections that lost their _datrix entry are treated as foreign.

Import is staged: all archive data lands in _import_tmp_* collections first, and only after every collection imported successfully are they renamed into place (dropTarget: true). A failure during staging drops the temps and leaves existing data untouched. The rename swap is atomic per collection, but there is a small window between renames in which some collections are already replaced and others are not — stop writers during import if that matters.

Known Limitations

  • Transaction rollback does not undo DDL. If a migration fails after createTable (phase 1), the created collection remains. This is a MongoDB limitation.
  • No partial indexes or expression indexes. Only simple field indexes with optional unique constraint.
  • Auto-increment IDs are not gap-free. Counter increments are atomic but failed inserts do not reclaim IDs.
  • limit(0) returns empty. MongoDB treats cursor.limit(0) as unlimited; the adapter intercepts this and returns an empty result to match SQL behavior.