JSON-SERVER

MongoJSON SDK

MongoJSON is a MongoDB-compatible SDK for JSON Server. Use the same MongoClient, Collection, and query syntax you know — it maps to REST endpoints under the hood.

Installation

npm install mongojson
# or
bun add mongojson

Quick Start

import { MongoClient } from "mongojson"

const uri = "mongodb://<dbuser>:<dbpass>@yourusername.json.shahriyar.dev/mydb"
const client = new MongoClient(uri)
await client.connect()

const db = client.db()
const users = db.collection("users")

// Create
await users.insertOne({ name: "Alice", age: 30 })

// Read
const all = await users.find().toArray()
const adult = await users.findOne({ age: { $gte: 18 } })

// Update
await users.updateOne({ name: "Alice" }, { $set: { age: 31 } })

// Delete
await users.deleteOne({ name: "Alice" })

// Count
const total = await users.countDocuments()

Connection URI

mongodb://<dbuser>:<dbpass>@<username>.<domain>[:port]/<database>
PartDescription
dbuser:dbpassDatabase user credentials (create in Dashboard → MongoDB → Authentication)
usernameYour platform username (subdomain)
domainServer domain — json.shahriyar.dev or localhost for local dev
portOptional (e.g. 3000 for local dev)
databaseDefault database name (used by client.db() with no args)

Collection Operations

Create

// Single document
const { insertedId } = await collection.insertOne({ name: "Jane", age: 25 })

// Multiple documents
const { insertedIds } = await collection.insertMany([
  { name: "Bob" },
  { name: "Alice" },
])

Read

// All documents
const docs = await collection.find({}).toArray()

// With filter, sort, limit
const results = await collection
  .find({ age: { $gt: 20 } })
  .sort({ age: -1 })
  .limit(10)
  .skip(5)
  .project({ name: 1 })
  .toArray()

// Single document
const user = await collection.findOne({ name: "Jane" })

// By ID
const user = await collection.findById("user_123")

Update

// Update first match
const { matchedCount, modifiedCount } = await collection.updateOne(
  { name: "Jane" },
  { $set: { age: 26 } },
)

// Update all matches
await collection.updateMany(
  { role: "guest" },
  { $set: { role: "user" } },
)

// Upsert (insert if not found)
await collection.updateOne(
  { name: "NewUser" },
  { $set: { age: 20 } },
  { upsert: true },
)

Delete

const { deletedCount } = await collection.deleteOne({ name: "Bob" })
const { deletedCount } = await collection.deleteMany({ status: "inactive" })

Replace

const { modifiedCount } = await collection.replaceOne(
  { name: "Jane" },
  { name: "Janet", age: 27 },
)

Count

const total = await collection.countDocuments()
const filtered = await collection.countDocuments({ role: "admin" })
const estimated = await collection.estimatedDocumentCount()

Distinct

const values = await collection.distinct("category")
const filtered = await collection.distinct("category", { active: true })

Atomic Find-and-Modify

// Find and update (returns document before update by default)
const old = await collection.findOneAndUpdate(
  { _id: 1 },
  { $set: { status: "processed" } },
)

// Find and delete
const deleted = await collection.findOneAndDelete({ _id: 1 })

// Find and replace
const replaced = await collection.findOneAndReplace(
  { _id: 1 },
  { name: "New", v: 2 },
)

// With options
const updated = await collection.findOneAndUpdate(
  { _id: 1 },
  { $set: { v: 99 } },
  { returnDocument: "after", upsert: true },
)

Bulk Write

const result = await collection.bulkWrite([
  { insertOne: { document: { name: "New", v: 2 } } },
  { updateOne: { filter: { _id: "existing" }, update: { $set: { v: 99 } } } },
  { deleteOne: { filter: { name: "old" } } },
  { updateMany: { filter: { status: "pending" }, update: { $set: { status: "done" } } } },
  { deleteMany: { filter: { expired: true } } },
])

Filter Operators

OperatorExampleDescription
$eq{ age: { $eq: 25 } }Equal (also plain value)
$ne{ age: { $ne: 25 } }Not equal
$gt{ age: { $gt: 18 } }Greater than
$gte{ age: { $gte: 18 } }Greater than or equal
$lt{ age: { $lt: 18 } }Less than
$lte{ age: { $lte: 18 } }Less than or equal
$in{ age: { $in: [18, 21] } }In array
$nin{ age: { $nin: [18, 21] } }Not in array
$exists{ email: { $exists: true } }Field exists
$regex{ name: { $regex: "^A" } }Pattern match
$or{ $or: [{ status: "a" }, { status: "b" }] }Logical OR
$and{ $and: [{ age: { $gt: 18 } }, { status: "active" }] }Logical AND
$nor{ $nor: [{ status: "deleted" }] }Logical NOR

Update Operators

OperatorExampleDescription
$set{ $set: { name: "New" } }Set field value
$unset{ $unset: { tmp: "" } }Remove field
$inc{ $inc: { count: 1 } }Increment (negative to decrement)
$mul{ $mul: { price: 1.1 } }Multiply
$min{ $min: { score: 100 } }Set if lower
$max{ $max: { score: 100 } }Set if higher
$rename{ $rename: { oldName: "newName" } }Rename field
$push{ $push: { items: "new" } }Append to array
$addToSet{ $addToSet: { tags: "unique" } }Add unique to array
$pull{ $pull: { items: "value" } }Remove from array

Drop-in Replacement

MongoJSON accepts the same MongoClientOptions as the official MongoDB driver (as no-ops), so you can swap it in without TypeScript errors:

import { MongoClient, ServerApiVersion } from "mongojson"

const client = new MongoClient(uri, {
  serverApi: {
    version: ServerApiVersion.v1,
    strict: true,
  },
  connectTimeoutMS: 5000,
  maxPoolSize: 10,
})

Error Handling

import { MongojsonServerError, MongojsonBulkWriteError } from "mongojson"

try {
  await collection.insertOne({ _id: 1 })
} catch (err) {
  if (err instanceof MongojsonServerError) {
    console.log(err.status, err.code, err.errmsg)
    // e.g. 409, 11000, "E11000 duplicate key error"
  }
}

Errors include MongoDB-style code and codeName:

HTTP StatusCodecodeName
4018000MongojsonError
40313Unauthorized
40426NamespaceNotFound
40911000DuplicateKey
4222BadValue
Other0UnknownError