Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

A simple, robust, and thread-safe CRUD library for managing JSON objects in files with TypeScript support, auto-ID, unique fields validation, and zero dependencies.

License

Notifications You must be signed in to change notification settings

r-el/json-file-crud

Open more actions menu

Repository files navigation

JsonFileCRUD

A simple, robust, and thread-safe CRUD library for managing JSON objects in files using Node.js.

Features

  • Simple API - Easy to use CRUD operations
  • Promise/Async Support - Full async/await API alongside callback methods ✨ New in v1.3
  • Thread-safe - Sequential operations with automatic queuing
  • Auto-ID assignment - Automatic ID generation for new items (configurable)
  • Unique Fields - Prevent duplicate values in specified fields ✨ New in v1.1
  • Concurrent Operations - Thread-safe operations with automatic queuing
  • Custom ID Fields - Use any field name as the primary key (default: 'id')
  • Directory Creation - Automatically creates directories if they don't exist ✨ New in v1.1
  • Convenience Functions - Helper functions for quick setup ✨ New in v1.1
  • TypeScript Support - Full TypeScript definitions for IDE support ✨ New in v1.2
  • Error Handling - Comprehensive error handling and detailed error messages
  • Zero dependencies - Built with only Node.js built-in modules
  • ESM support - Full ES modules support

Installation

npm install json-file-crud

Quick Start

import JsonFileCRUD, { createCrud } from 'json-file-crud';

// Standard usage
const db = new JsonFileCRUD('./data.json');

// Quick setup with convenience function
const db2 = createCrud('./users.json');

// Advanced configuration with unique fields
const userDb = new JsonFileCRUD('./users.json', {
  uniqueFields: ['email', 'username'],
  autoId: true
});

// Create a new item
db.create({ name: 'John', age: 30 }, (err, result) => {
  if (err) {
    console.error('Error:', err.message);
    return;
  }
  console.log('Created:', result); // { name: 'John', age: 30, id: 1 }
});

// Read all items
db.readAll((err, items) => {
  if (err) throw err;
  console.log('All items:', items);
});

// Find by ID
db.findById(1, (err, item) => {
  if (err) throw err;
  console.log('Found:', item);
});

// Update an item
db.update(1, { age: 31 }, (err, updatedItem) => {
  if (err) throw err;
  console.log('Updated:', updatedItem);
});

// Delete an item
db.delete(1, (err, deletedItem) => {
  if (err) throw err;
  console.log('Deleted:', deletedItem);
});

Async/Await Usage

// Same operations using async/await
try {
  const user = await db.createAsync({ name: 'John', age: 30 });
  console.log('Created:', user);
  
  const foundUser = await db.findByIdAsync(user.id);
  console.log('Found:', foundUser);
  
  const updatedUser = await db.updateAsync(user.id, { age: 31 });
  console.log('Updated:', updatedUser);
  
  const deletedUser = await db.deleteAsync(user.id);
  console.log('Deleted:', deletedUser);
} catch (error) {
  console.error('Error:', error.message);
}

API Reference

Constructor

new JsonFileCRUD(filePath, options)

Creates a new JsonFileCRUD instance.

  • filePath (string): Path to the JSON file (directories will be created if they don't exist)
  • options (object, optional):
    • idField (string): Name of the ID field (default: 'id')
    • uniqueFields (array): Array of field names that must be unique (default: [])
    • autoId (boolean): Enable automatic ID assignment (default: true)
// Default settings
const db = new JsonFileCRUD('./data.json');

// Custom ID field
const products = new JsonFileCRUD('./products.json', { idField: 'productId' });

// Unique fields validation
const users = new JsonFileCRUD('./users.json', { 
  uniqueFields: ['email', 'username'] 
});

// Disable auto-ID
const manualDb = new JsonFileCRUD('./manual.json', { autoId: false });

// Deep directory path (automatically created)
const deepDb = new JsonFileCRUD('./data/nested/deep/file.json');

Convenience Functions

createCrud(filePath, options)

Quick way to create a JsonFileCRUD instance.

import { createCrud } from 'json-file-crud';

const db = createCrud('./data.json', { uniqueFields: ['email'] });

CRUD Operations

create(item, callback)

Creates a new item. Auto-assigns an ID if not provided.

  • item (object): The item to create
  • callback (function): (error, createdItem) => {}
db.create({ name: 'Alice', email: 'alice@example.com' }, (err, result) => {
  // result: { name: 'Alice', email: 'alice@example.com', id: 1 }
});

readAll(callback)

Reads all items from the file.

  • callback (function): (error, items) => {}
db.readAll((err, items) => {
  // items: array of all items
});

findById(id, callback)

Finds an item by its ID.

  • id (any): The ID to search for
  • callback (function): (error, item) => {}
db.findById(1, (err, item) => {
  // item: the found item or null if not found
});

findBy(filterFunction, callback)

Finds items that match a filter function.

  • filterFunction (function): Function that returns true for matching items
  • callback (function): (error, items) => {}
// Find all adults
db.findBy(item => item.age >= 18, (err, adults) => {
  // adults: array of matching items
});

// Find by name
db.findBy(item => item.name === 'John', (err, johns) => {
  // johns: array of items named John
});

update(id, data, callback)

Updates an existing item.

  • id (any): The ID of the item to update
  • data (object): The data to update (merged with existing item)
  • callback (function): (error, updatedItem) => {}
db.update(1, { age: 25, city: 'New York' }, (err, updated) => {
  // updated: the item with merged data
});

delete(id, callback)

Deletes an item by ID.

  • id (any): The ID of the item to delete
  • callback (function): (error, deletedItem) => {}
db.delete(1, (err, deleted) => {
  // deleted: the item that was removed
});

deleteAll(callback)

Deletes all items from the database.

  • callback (function): (error) => {}
db.deleteAll((err) => {
  if (err) throw err;
  console.log('All items deleted');
});

count(callback)

Returns the total number of items.

  • callback (function): (error, count) => {}
db.count((err, total) => {
  console.log('Total items:', total);
});

writeAll(items, callback)

Replaces all data in the file with a new array of items.

  • items (array): Array of items to write
  • callback (function): (error) => {}
const newData = [
  { name: 'Item 1', id: 1 },
  { name: 'Item 2', id: 2 }
];

db.writeAll(newData, (err) => {
  if (!err) console.log('Data replaced successfully');
});

Promise-based API

All methods have async counterparts that return Promises. Simply add Async to the method name:

Async Method Names

All callback methods have async counterparts. Add Async to the method name:

// Using async/await
try {
  const user = await db.createAsync({ name: 'John', age: 30 });
  const allUsers = await db.readAllAsync();
  const foundUser = await db.findByIdAsync(user.id);
  const updatedUser = await db.updateAsync(user.id, { age: 31 });
  await db.deleteAsync(user.id);
} catch (error) {
  console.error('Operation failed:', error.message);
}

// Using Promises
db.createAsync({ name: 'Jane', age: 25 })
  .then(user => db.findByIdAsync(user.id))
  .then(foundUser => console.log('Found:', foundUser))
  .catch(error => console.error('Error:', error.message));

Advanced Features

Unique Fields

Prevent duplicate values in specified fields:

const userDb = new JsonFileCRUD('./users.json', {
  uniqueFields: ['email', 'username']
});

// This will fail if email already exists
userDb.create({ 
  name: 'John', 
  email: 'john@example.com' 
}, (err, user) => {
  // err.message: "Item with email 'john@example.com' already exists"
});

Auto-ID Control

Disable automatic ID assignment:

const db = new JsonFileCRUD('./data.json', { autoId: false });

// No ID will be auto-generated
db.create({ name: 'Test' }, (err, item) => {
  // item: { name: 'Test' } (no id field)
});

Directory Creation

Automatically creates directories for deep paths:

// This will create ./data/users/ directories if they don't exist
const db = new JsonFileCRUD('./data/users/profiles.json');

Examples

For comprehensive examples, see the examples directory:

Quick Examples

// Basic usage with unique fields
import JsonFileCRUD, { createCrud } from 'json-file-crud';

const userDb = createCrud('./users.json', {
  uniqueFields: ['email', 'username']
});

// Delete all users
userDb.deleteAll((err) => {
  console.log('All users deleted');
});

// Example with auto-ID disabled
const manualDb = new JsonFileCRUD('./manual.json', { autoId: false });
manualDb.create({ name: 'Test' }, (err, item) => {
  // item: { name: 'Test' } (no auto-generated ID)
});

To run examples:

npm run examples
# or individually:
node examples/basic-usage.js

TypeScript Support

Type definitions are provided via lib/json-file-crud.d.ts so the library can be used comfortably in TypeScript projects with autocompletion and compile-time checks.

File Format

JsonFileCRUD stores data as a JSON array in the specified file:

[
  { "id": 1, "name": "John", "age": 30 },
  { "id": 2, "name": "Jane", "age": 25 }
]

If the file doesn't exist, it will be created automatically on the first write operation.

Performance Considerations

  • Small to medium datasets: JsonFileCRUD is ideal for applications with up to ~10,000 items
  • File I/O: Every operation reads/writes the entire file, so performance scales with file size
  • Memory usage: The entire dataset is loaded into memory during operations
  • Concurrent access: Operations are queued, so high-concurrency scenarios may experience delays

For larger datasets or high-performance requirements, consider using a dedicated database.

Contributing

Contributions are welcome! Here are some ways you can help improve JsonFileCRUD:

Ideas for Contributions

  • Batch Operations: Add bulk insert/update/delete operations
  • File Locking: Add file locking for multi-process safety
  • Enhanced Documentation: Improve documentation and add more examples

How to Contribute

  1. Fork the Repository: Create your own fork of the project
  2. Create a Feature Branch: git checkout -b feature/your-feature-name
  3. Write Tests: Ensure your changes are well-tested
  4. Follow Code Style: Keep the code clean and consistent
  5. Update Documentation: Add or update relevant documentation
  6. Submit a Pull Request: Describe your changes clearly

License

MIT License - see LICENSE file for details.

About

A simple, robust, and thread-safe CRUD library for managing JSON objects in files with TypeScript support, auto-ID, unique fields validation, and zero dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  
Morty Proxy This is a proxified and sanitized view of the page, visit original site.