ForerunnerDB
ForerunnerDB is a NoSQL JSON document database designed for both browser-based and Node.js applications, offering a MongoDB-like query language. The current stable version is 2.0.24, with a significant rewrite for version 3.0 actively under development in a separate repository (forerunnerdb-core). Key differentiators include its dual-environment support, advanced features like data views, joins, sub-queries, and collection groups, along with optional modules for AngularJS/Ionic integration, real-time data binding to the DOM (browser-only), persistent storage, data compression and encryption, and a built-in REST API server for Node.js. It is production-ready, battle-tested in applications serving millions of users daily, and maintained by Irrelon Software Limited. While no explicit release cadence is published, development is ongoing for the next major version.
Common errors
-
TypeError: ForerunnerDB is not a constructor
cause Attempting to call `ForerunnerDB()` directly without the `new` keyword.fixUse `const fdb = new ForerunnerDB();` to instantiate the database constructor. -
TypeError: Cannot read properties of undefined (reading 'collection')
cause Attempting to call `.collection()` directly on the imported `ForerunnerDB` constructor without first getting a database instance via `fdb.db()`.fixFirst, instantiate ForerunnerDB with `new ForerunnerDB()`, then call `.db('yourDbName')` on the instance to get a database object: `const fdb = new ForerunnerDB(); const db = fdb.db('myDb');` -
Error: unable to load data (Path does not exist / permission denied)
cause In Node.js, the configured `dataDir` for persistence either does not exist, or the application lacks write permissions to that directory.fixEnsure the directory specified in `db.persist.dataDir('/your/path')` exists and that your Node.js process has read/write permissions to it. Create the directory manually if necessary.
Warnings
- breaking ForerunnerDB 3.0 is a complete rewrite being developed in a separate repository (`irrelon/forerunnerdb-core`). It is built with a modular architecture and is expected to introduce significant breaking changes, although specific migration paths are not yet defined as it's still in active development. Do not expect direct compatibility with 2.x APIs.
- gotcha Persistence in ForerunnerDB v2.x requires explicit `db.load()` and `db.save()` calls. Data is not automatically saved on every change, and forgetting to call `db.save()` will result in data loss upon application shutdown or page refresh.
- gotcha Optional features like data binding, persistence, and the REST server are modules that must be explicitly loaded or configured. For example, persistence needs a `dataDir` configured in Node.js.
Install
-
npm install forerunnerdb -
yarn add forerunnerdb -
pnpm add forerunnerdb
Imports
- ForerunnerDB
import { ForerunnerDB } from 'forerunnerdb';import ForerunnerDB from 'forerunnerdb';
- ForerunnerDB
const ForerunnerDB = require('forerunnerdb'); - db instance
const db = require('forerunnerdb').db('myDbName');const fdb = new ForerunnerDB(); const db = fdb.db('myDbName');
Quickstart
import ForerunnerDB from 'forerunnerdb';
interface User {
_id?: string;
name: string;
age: number;
city: string;
}
// Initialize ForerunnerDB and get a database instance
const fdb = new ForerunnerDB();
const db = fdb.db('myApplicationDB');
// To enable persistence in Node.js, specify a path
// ForerunnerDB also supports localStorage in browsers automatically
if (typeof window === 'undefined') { // Node.js environment
const path = require('path');
db.persist.dataDir(path.resolve(__dirname, 'data'));
}
async function runDbOperations() {
// Load existing data if any
await db.load();
console.log('Database loaded.');
// Get or create a collection
const users = db.collection<User>('users');
// Clear collection for a clean start (optional)
users.remove({});
// Insert some documents
const insertedUsers = await users.insert([
{ name: 'Alice', age: 30, city: 'New York' },
{ name: 'Bob', age: 24, city: 'London' },
{ name: 'Charlie', age: 30, city: 'Paris' },
{ name: 'David', age: 28, city: 'New York' }
]);
console.log('Inserted users:', insertedUsers.length);
// Find all users
const allUsers = users.find();
console.log('All users:', allUsers);
// Find users older than 25
const olderUsers = users.find({ age: { '$gt': 25 } });
console.log('Users older than 25:', olderUsers);
// Update a user
await users.update({ name: 'Bob' }, { $set: { age: 25, city: 'Berlin' } });
const updatedBob = users.find({ name: 'Bob' });
console.log('Updated Bob:', updatedBob);
// Save the database state
await db.save();
console.log('Database saved.');
// Demonstrate a View (virtual collection)
const nyUsersView = db.view('nyUsersView')
.from('users')
.query({ city: 'New York' });
console.log('Users in New York (via View):', nyUsersView.find());
}
runDbOperations().catch(console.error);