MarsDB Client-Side Database

raw JSON →
0.6.11 verified Thu Apr 23 auth: no javascript maintenance

MarsDB is a lightweight client-side database inspired by Meteor's minimongo implementation, providing a MongoDB-like API for JavaScript environments. It offers a Promise-based interface, observable cursors, and reactive joins, making it well-suited for applications requiring real-time data reactivity. Written in ES6, it operates across various JavaScript platforms including browsers, Electron, NW.js, and Node.js. The current stable version is 0.6.11. The project appears to be in a maintenance phase, with recent activity primarily focused on bug fixes rather than significant new feature development. Its key differentiators include a flexible pluggable storage architecture (supporting in-memory, LocalStorage, LevelUP, and even MongoDB wrappers), a powerful pipeline for data transformation, and compatibility with a wide range of MongoDB query and modifier operations.

error ReferenceError: Promise is not defined
cause Running MarsDB in an environment that lacks native Promise support (e.g., older browsers or Node.js without specific flags) without including the necessary polyfills.
fix
Add import 'marsdb/polyfills'; or require('marsdb/polyfills'); at the top of your main application file to ensure Promises are available.
error TypeError: users.count is not a function
cause Attempting to call `.count()` on a cursor and expecting a direct number return value. Since v0.5.0, `count()` returns another observable cursor, not the number directly.
fix
Chain .fetch() to the count() call to retrieve the actual number: await users.find({}).count().fetch().
error Error: Cursor is executing, cannot modify
cause A MarsDB Cursor object was modified (e.g., its query or sorting parameters were changed) while it was actively processing a previous data operation.
fix
Use the whenNotExecuting() method to safely queue changes: await cursor.whenNotExecuting(); cursor.sort({ name: 1 });
error TypeError: Cannot read property 'setStorageManager' of undefined
cause Attempting to use a storage manager like `LocalForageManager` without installing and importing the corresponding `marsdb-localforage` package.
fix
Install the specific storage plugin (e.g., npm install marsdb-localforage) and import it separately, then apply it to your collection: import LocalForageManager from 'marsdb-localforage'; const users = new Collection('users', { StorageManager: LocalForageManager });
breaking The `static` and `method` methods were removed from the Collection class. The internal Document wrapping of objects was also removed for performance improvements.
fix Remove usages of `static` and `method`. Direct object manipulation is now standard. Adjust code that relied on `Document` wrapping.
breaking The `count()` and `ids()` methods of a Cursor no longer return direct values (a number or an array of IDs) but now return observable cursors themselves.
fix To retrieve the actual value, you must now call `.fetch()` on the result, e.g., `await users.find({}).count().fetch()`.
breaking Core storage implementations (e.g., LevelUP, LocalStorage) and the AngularJS binding were refactored into separate, dedicated npm packages (e.g., `marsdb-levelup`, `marsdb-angular`). They are no longer bundled with the main `marsdb` package.
fix Install the specific plugin packages you need (e.g., `npm install marsdb-levelup`) and import them separately from `marsdb`.
gotcha Modifying a Cursor object while it is actively executing (e.g., changing its query or sort parameters) will throw an error. This is to prevent inconsistent states.
fix Ensure the cursor is not executing by awaiting its `whenNotExecuting()` method before applying changes: `await cursor.whenNotExecuting(); cursor.sort({ name: 1 });`
gotcha For JavaScript environments that lack native ES6 features like `Promise`, `Set`, and `Symbol`, the `marsdb/polyfills` module must be explicitly imported to provide these globals.
fix Add `import 'marsdb/polyfills';` (ESM) or `require('marsdb/polyfills');` (CommonJS) at the entry point of your application, before any MarsDB usage.
npm install marsdb
yarn add marsdb
pnpm add marsdb

Demonstrates creating a MarsDB collection, inserting multiple documents, performing find operations with filters and sorting, and updating a document, all using the Promise-based API.

import Collection from 'marsdb';

async function runMarsDBExample() {
  // Create a new collection named 'users'
  const users = new Collection('users');

  // Clear existing data for a clean run
  await users.remove({});

  // Insert documents
  const insertResult = await users.insert([
    { _id: '1', name: 'Alice', age: 30, city: 'New York' },
    { _id: '2', name: 'Bob', age: 24, city: 'Los Angeles' },
    { _id: '3', name: 'Charlie', age: 30, city: 'Chicago' },
    { _id: '4', name: 'Diana', age: 28, city: 'New York' }
  ]);
  console.log(`Inserted ${insertResult.length} users.`);

  // Find users aged 30
  const agedThirty = await users.find({ age: 30 }).fetch();
  console.log('Users aged 30:', agedThirty);

  // Find users in New York, sorted by name
  const nyUsers = await users.find({ city: 'New York' })
    .sort({ name: 1 })
    .fetch();
  console.log('Users in New York (sorted):', nyUsers);

  // Update Alice's age
  await users.update({ name: 'Alice' }, { $set: { age: 31 } });
  const updatedAlice = await users.findOne({ name: 'Alice' });
  console.log('Updated Alice:', updatedAlice);

  // In a real application, observable cursors would react to changes.
  // For a quickstart, we just fetch all current users.
  const allUsers = await users.find({}).fetch();
  console.log('All current users:', allUsers);
}

runMarsDBExample().catch(console.error);