Minimongo

7.1.1 · active · verified Wed Apr 22

Minimongo is a client-side, in-memory MongoDB clone designed for browser and Node.js environments, offering a MongoDB-like API for CRUD operations and query syntax. It supports various local storage backends including IndexedDB, WebSQL (legacy), LocalStorage, and a purely in-memory option, with an autoselection utility. Currently at version 7.1.1, the project aims for stable releases without a strict public cadence, evolving from a 2014 fork of Meteor.js's minimongo package to incorporate more geospatial queries and npm-friendliness. Its key differentiators include hybrid local/remote synchronization with conflict resolution using base documents, replication between database instances, and support for Extended JSON (EJSON). While it offers a substantial subset of MongoDB query features, it does not support the full aggregation pipeline or all operators.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates initializing an IndexedDb locally, setting up a mock RemoteDb, creating a HybridDb for combined local/remote operations, and performing basic CRUD and queries with synchronization.

import { IndexedDb, HybridDb, RemoteDb, MemoryDb } from 'minimongo';

interface MyDocument {
  _id?: string;
  name: string;
  age: number;
  tags?: string[];
}

async function setupDatabase() {
  return new Promise<IndexedDb<MyDocument>>((resolve, reject) => {
    const indexedDb = new IndexedDb<MyDocument>(
      { namespace: 'myAppDb', autoCreate: true },
      () => {
        console.log('IndexedDb initialized successfully.');
        resolve(indexedDb);
      },
      (error: Error) => {
        console.error('IndexedDb initialization failed:', error);
        reject(error);
      }
    );
  });
}

async function runApp() {
  try {
    const localDb = await setupDatabase();
    const remoteDb = new RemoteDb('/api/collections', 'myAppDb', {
      // For a real application, replace with a proper HTTP client
      // This is a minimal mock for demonstration
      httpClient: {
        get: async (url: string) => {
          console.log(`[RemoteDb] GET ${url}`);
          if (url.includes('myAppDb/items')) {
            return { status: 200, data: [{ _id: 'remote1', name: 'Remote Item', age: 30 }] };
          }
          return { status: 404, data: { message: 'Not Found' } };
        },
        put: async (url: string, data: any) => {
          console.log(`[RemoteDb] PUT ${url}`, data);
          return { status: 200, data: { ...data, _id: data._id || 'newRemoteId' } };
        }
      },
      useQuickFind: true
    });

    const hybridDb = new HybridDb(localDb, remoteDb);
    hybridDb.addCollection('items');
    const itemsCollection = hybridDb.getCollection('items');

    // Insert a document locally
    const newItem: MyDocument = { name: 'Local Item', age: 25, tags: ['frontend'] };
    await itemsCollection.upsert(newItem, null, (doc: MyDocument) => {
      console.log('Inserted local item:', doc);
    });

    // Query local and remote (hybrid sync)
    console.log('\nQuerying all items (local and remote sync):');
    itemsCollection.find({}).fetch((docs: MyDocument[]) => {
      console.log('Found items:', docs);
    });

    // Demonstrate another local operation
    const anotherItem: MyDocument = { name: 'Another Item', age: 40 };
    await itemsCollection.upsert(anotherItem, null, (doc: MyDocument) => {
      console.log('Inserted another local item:', doc);
    });

    // Query with selector
    console.log('\nQuerying items with age > 25:');
    itemsCollection.find({ age: { $gt: 25 } }).fetch((docs: MyDocument[]) => {
      console.log('Found items (age > 25):', docs);
    });

  } catch (error) {
    console.error('Application failed:', error);
  }
}

runApp();

view raw JSON →