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 🙏

© 2024 – Pkg Stats / Ryan Hefner

mongodb-rest-relay

v1.11.0

Published

Relay mongodb queries over HTTP REST. Great for Edge.

Downloads

659

Readme

mongodb-rest-relay

Relay mongodb queries over HTTP REST. Great for Edge.

Copyright (c) 2023 by Gadi Cohen. MIT Licensed.

npm GitHub Workflow Status (with event) Coverage semantic-release TypeScript MIT License

Intro

mongodb-rest-relay is meant to be a drop-in replacement for mongodb, that sends the actual request to the real mongodb elsewhere over HTTP. It may be a better fit for edge and serverless, depending on your use case. You get the advantages of MongoDB's own REST service but with the same fixed and predictable pricing (but no elastic scaling).

Quick Start

  1. Modify an existing edge or serverless function (or create one as usual):
- import { MongoClient } from "mongodb";
+ import { MongoClient } from "mongodb-rest-relay"

- const MONGO_URL = process.env.MONGO_URL;
+ const MONGO_URL = "http://localhost:3000/api/mongoRelay.ts"
+
+ // Optional: only if Mongo's ObjectId doesn't work in your edge environment.
+ // Before this, try set `{ browser: { crypto: false }}` in your app's package.json
- import { ObjectId } from "mongodb" // "bson"
+ import { ObjectId } from "mongodb-rest-relay"
+
+ export const runtime = 'edge' // if relevant (e.g. on Vercel)

// Then use as usual.
const client = new MongoClient(MONGO_URL);

That's it! Since the API is the same, there's nothing else to do. Note: only basic functionality / simple CRUD operations are supported (see notes at the end of the README).

See also the section on Caching below.

  1. You can run the other side of the relay as serverless or servered (near your database), e.g. pages/api/mongoRelay.ts:
import { MongoClient } from "mongodb";
// There is also server/{nextServerless{App,Pages},vercelServerlessOther}
import makeExpressRelay from "mongodb-rest-relay/lib/server/express";

const MONGO_URL = process.env.MONGO_URL || "mongodb://127.0.0.1";
const client = new MongoClient(MONGO_URL);

export default makeExpressRelay((await client.connect()).db(/* dbName? */));
// or next app router: export const POST = makeRelay.... with correct import.
  1. Set the MONGODB_RELAY_PASSWORD environment variable to the same value on both sides.

Notes

  • Supported functionality:

    • insertOne(), insertMany()
    • find() - with sort(), limit(), skip(), project().
      • toArray(), stream() (yes! streaming!)
    • updateOne(), updateMany()
    • replaceOne()
    • bulkWrite()
    • deleteOne(), deleteMany()
    • countDocuments(), estimatedDocumentCount()
    • Open an issue or submit a PR for more :)

Init Options

new MongoClient(url, {
  fetch: {}, // Additional options to past to ALL fetch requests (RequestInit)
});

Caching

mongodb-rest-relay can take advantage of the NextJS Cache and Vercel's Data Cache for significantly faster repeat results and lower load on your database. You should read these docs for a full picture but the basics are (for NextJS):

  1. You need to call mongodb-rest-relay from within the app router, the functionality does not exist in pages. So instead of e.g. pages/api/something.ts, you want app/api/something/route.ts, with the necessary changes.

  2. You can set your GLOBAL cache policy for ALL (internal) fetch() requests, using:

    new MongoClient(url, {
      fetch: {
        next: {
          revalidate: 1, // revalidate after this amount of time (in seconds)
          tags: ["myTag"], // can use revalidateTag("myTag") later.
        },
        // or
        cache: "force-cache", // this lasts a long time, probably you don't want it :)
      },
    });

    Note: after revalidate seconds, the stale cache is still returned, and fresh data will be fetched in the background. For more info, see NextJS time-based revalidation.

  3. You can also set these options PER REQUEST. This involves a separate API call, so that you can still switch back between the original mongodb driver without polluting the real mongo options or failing type validation.

    - import { MongoClient } from "mongodb";
    + import { MongoClient, setOptionsOnce } from "mongodb-rest-relay";
    
    // ... setup the client, etc.
    
    + setOptionsOnce({ fetch: { next: { revalidate: 1 } } });
    const result = await db.collection("test").find().toArray();

    You can call setOptionsOnce() multiple times and the options will be used in that order (think of Jest's mockImplementationOnce()).

The result is that even in next dev you'll get output like this:

-  ┌ POST /api/something 200 in 148ms
   │
   ├──── POST http://localhost:3000/api/mongoRelay?coll=accounts&o.. 200 in 6ms (cache: HIT)
   │
   ├──── POST http://localhost:3000/api/mongoRelay?coll=stars&op=f.. 200 in 3ms (cache: HIT)
   │
   ├──── POST http://localhost:3000/api/mongoRelay?coll=sessions&o.. 200 in 2ms (cache: HIT)
   │
   ├── 1 level ── POST http://localhost:3000/api/mongoRelay?coll=users&op=f.. 200 in 1ms (cache: HIT)
   │
   └── 1 level ── POST http://localhost:3000/api/mongoRelay?coll=likes&op=f.. 200 in 1ms (cache: HIT)

Note:

  1. Mutations (insert, update, delete, etc) will always set { cache: "no-store" }. So caching is only applied to: find(), findOne(), estimatedDocumentCount(), countDocuments().

TODO

  • [x] ObjectID / Date support `:) - in next release!
  • [x] streaming!
  • [ ] aggregation - ask for it.
  • [ ] Instead of sending MONGODB_RELAY_PASSWORD, just use it to sign requests.
  • [x] Caching
    • [x] Global options
    • [x] Per-request options