Real-World Examples
The Quick Start showed the basic API. This page walks through complete, realistic applications you can adapt for your own projects.
1. Issue / task tracker
A small team tracker with users and issues, indexes, and status workflows.
const { JSONDB } = require('file-json-db');
const path = require('path');
const db = new JSONDB(path.join(__dirname, 'data'));
const users = db.collection({
name: 'users',
autoId: true,
indexes: ['email', 'username']
});
const issues = db.collection({
name: 'issues',
autoId: true,
idType: 'uuid',
indexes: ['status', 'assigneeId', 'priority']
});
// Seed team (run once)
if (users.find({}).count() === 0) {
users.insertMany([
{ username: 'alice', email: 'alice@acme.dev', role: 'lead', active: true },
{ username: 'bob', email: 'bob@acme.dev', role: 'dev', active: true },
{ username: 'carol', email: 'carol@acme.dev', role: 'qa', active: true }
]);
}
const alice = users.findOne({ username: 'alice' });
const bob = users.findOne({ username: 'bob' });
// Create an issue
const bug = issues.insert({
title: 'Login crashes on Safari',
description: 'TypeError when submitting the form on iOS Safari 17',
status: 'open',
priority: 'high',
assigneeId: bob._id,
reporterId: alice._id,
labels: ['bug', 'frontend'],
createdAt: new Date().toISOString()
});
// Move to in-progress
issues.updateOne(
{ _id: bug._id },
{
$set: {
status: 'in-progress',
updatedAt: new Date().toISOString()
},
$push: { labels: 'ios' }
}
);
// Dashboard queries
const urgent = issues.find({
status: { $in: ['open', 'in-progress'] },
priority: 'high'
}).sort({ createdAt: -1 }).toArray();
const byStatus = issues.aggregate([
{ $group: { _id: '$status', count: { $sum: 1 } } }
]);
console.log('Urgent issues:', urgent.length);
console.log('By status:', byStatus);
2. Simple blog / CMS
const posts = db.collection({
name: 'posts',
autoId: true,
indexes: ['slug', 'authorId', 'status']
});
const comments = db.collection({
name: 'comments',
autoId: true,
indexes: ['postId']
});
// Publish a post
const post = posts.insert({
title: 'Introducing file-json-db',
slug: 'introducing-file-json-db',
body: 'A resilient zero-dependency JSON database…',
authorId: alice._id,
status: 'published',
tags: ['nodejs', 'database'],
publishedAt: new Date().toISOString(),
views: 0
});
// Increment view count
posts.updateOne(
{ slug: 'introducing-file-json-db' },
{ $inc: { views: 1 } }
);
// Add a comment
comments.insert({
postId: post._id,
author: 'Reader',
body: 'Great article!',
createdAt: new Date().toISOString()
});
// Load post + its comments
const article = posts.findOne({ slug: 'introducing-file-json-db' });
const articleComments = comments.find({ postId: article._id })
.sort({ createdAt: 1 })
.toArray();
3. Inventory / small e-commerce
const products = db.collection({
name: 'products',
autoId: true,
indexes: ['sku', 'category']
});
const orders = db.collection({
name: 'orders',
autoId: true,
idType: 'uuid',
indexes: ['status', 'customerEmail']
});
// Stock a product
products.insert({
sku: 'WIDGET-001',
name: 'Wireless Widget',
category: 'electronics',
price: 29.99,
stock: 100
});
// Place an order inside a transaction so stock and order stay consistent
async function placeOrder(sku, qty, customerEmail) {
const product = products.findOne({ sku });
if (!product || product.stock < qty) {
throw new Error('Insufficient stock');
}
const txProducts = products.startTransaction();
const txOrders = orders.startTransaction(); // note: separate collections
try {
// In a real multi-collection transaction you would need external coordination.
// Here we keep the critical stock update transactional on the products side.
txProducts.updateOne(
{ sku },
{ $inc: { stock: -qty } }
);
const order = orders.insert({
customerEmail,
items: [{ sku, qty, price: product.price }],
total: product.price * qty,
status: 'pending',
createdAt: new Date().toISOString()
});
await txProducts.commit();
return order;
} catch (err) {
await txProducts.rollback();
throw err;
}
}
Note on multi-collection transactions
Transactions are per-collection. For true multi-collection atomicity
you need application-level compensation or a different database.
4. CLI configuration / local cache
// config-store.js – used by a CLI tool
const { JSONDB } = require('file-json-db');
const os = require('os');
const path = require('path');
const db = new JSONDB(path.join(os.homedir(), '.my-cli'));
const settings = db.collection({
name: 'settings',
autoId: false // we use fixed keys
});
function getSetting(key, defaultValue) {
const doc = settings.findOne({ key });
return doc ? doc.value : defaultValue;
}
function setSetting(key, value) {
const existing = settings.findOne({ key });
if (existing) {
settings.updateOne({ key }, { $set: { value, updatedAt: Date.now() } });
} else {
settings.insert({ key, value, updatedAt: Date.now() });
}
}
module.exports = { getSetting, setSetting };
5. Electron main-process store
// main.js (Electron)
const { app } = require('electron');
const { JSONDB } = require('file-json-db');
const path = require('path');
const db = new JSONDB(path.join(app.getPath('userData'), 'db'));
const windows = db.collection({
name: 'windowState',
autoId: false
});
function saveWindowState(bounds) {
const existing = windows.findOne({ id: 'main' });
if (existing) {
windows.updateOne({ id: 'main' }, { $set: { bounds } });
} else {
windows.insert({ id: 'main', bounds });
}
}
function loadWindowState() {
const doc = windows.findOne({ id: 'main' });
return doc ? doc.bounds : { width: 1200, height: 800 };
}
6. Express REST API sketch
const express = require('express');
const { JSONDB } = require('file-json-db');
const app = express();
app.use(express.json());
const db = new JSONDB('./data');
const users = db.collection({
name: 'users',
autoId: true,
indexes: ['email']
});
app.get('/users', async (req, res) => {
const list = (await users.findAsync({}))
.project({ passwordHash: 0 })
.toArray();
res.json(list);
});
app.post('/users', async (req, res) => {
const existing = await users.findOneAsync({ email: req.body.email });
if (existing) return res.status(409).json({ error: 'Email taken' });
const user = await users.insertAsync({
...req.body,
createdAt: new Date().toISOString()
});
res.status(201).json(user);
});
app.patch('/users/:id', async (req, res) => {
const updated = await users.updateOneAsync(
{ _id: Number(req.params.id) },
{ $set: req.body }
);
if (!updated) return res.status(404).end();
res.json(updated);
});
app.listen(3000);