Database using JSON file as storage for Node.JS
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Flexible configuration system with built-in file storage adapter and support for custom storage backends through the adapter pattern.
Standard configuration class that uses file-based JSON storage with built-in adapters.
/**
* Standard configuration using file-based storage
* @param filename - Database filename (automatically adds .json if no extension)
* @param saveOnPush - Whether to save automatically after each push operation (default: true)
* @param humanReadable - Format JSON with indentation for readability (default: false)
* @param separator - DataPath separator character (default: "/")
* @param syncOnSave - Use synchronous file operations for guaranteed persistence (default: false)
*/
class Config implements JsonDBConfig {
constructor(
filename: string,
saveOnPush?: boolean,
humanReadable?: boolean,
separator?: string,
syncOnSave?: boolean
);
readonly filename: string;
readonly adapter: IAdapter<any>;
readonly saveOnPush: boolean;
readonly separator: string;
}Usage Examples:
import { JsonDB, Config } from "node-json-db";
// Basic configuration
const db1 = new JsonDB(new Config("database.json"));
// With custom settings
const db2 = new JsonDB(new Config(
"users", // filename (will become users.json)
true, // saveOnPush - auto-save on changes
true, // humanReadable - formatted JSON
"/", // separator for DataPaths
false // syncOnSave - async file operations
));
// Production config with sync saves for data integrity
const db3 = new JsonDB(new Config(
"/var/data/production.json",
true, // auto-save
false, // compact JSON
"/", // standard separator
true // sync saves for guaranteed persistence
));Configuration class for use with custom adapters, providing full control over storage backend.
/**
* Configuration with custom adapter
* @param adapter - Custom storage adapter implementing IAdapter interface
* @param saveOnPush - Whether to save automatically after each push operation (default: true)
* @param separator - DataPath separator character (default: "/")
*/
class ConfigWithAdapter implements JsonDBConfig {
constructor(
adapter: IAdapter<any>,
saveOnPush?: boolean,
separator?: string
);
readonly adapter: IAdapter<any>;
readonly saveOnPush: boolean;
readonly separator: string;
}Usage Examples:
import { JsonDB, ConfigWithAdapter, JsonAdapter, FileAdapter } from "node-json-db";
// Custom adapter configuration
const fileAdapter = new FileAdapter("/custom/path/data.json", true);
const jsonAdapter = new JsonAdapter(fileAdapter, true); // human readable
const config = new ConfigWithAdapter(jsonAdapter, false, "|"); // custom separator
const db = new JsonDB(config);Base interface for all storage adapters, defining the contract for reading and writing data.
/**
* Base adapter interface for data storage
* Use to read and write data of type T
*/
interface IAdapter<T> {
/**
* Read the data from the storage medium
* @returns Promise resolving to data of type T or null if no data exists
*/
readAsync(): Promise<T | null>;
/**
* Write data into the storage medium
* @param data - Data to write to storage
* @returns Promise that resolves when write operation completes
*/
writeAsync(data: T): Promise<void>;
}Handles JSON serialization and deserialization, including automatic date parsing and formatting options.
/**
* JSON serialization adapter with date handling and formatting options
* @param adapter - Underlying string-based adapter (typically FileAdapter)
* @param humanReadable - Format JSON with indentation (default: false)
*/
class JsonAdapter implements IAdapter<any> {
constructor(adapter: IAdapter<string>, humanReadable?: boolean);
/**
* Read and parse JSON data with automatic date parsing
* @returns Promise resolving to parsed JavaScript object
*/
readAsync(): Promise<any>;
/**
* Stringify and write JSON data
* @param data - JavaScript object to serialize
* @returns Promise that resolves when write completes
*/
writeAsync(data: any): Promise<void>;
}Usage Examples:
import { JsonAdapter, FileAdapter } from "node-json-db";
// Basic JSON adapter
const fileAdapter = new FileAdapter("data.json", false);
const jsonAdapter = new JsonAdapter(fileAdapter);
// Human readable JSON with indentation
const readableAdapter = new JsonAdapter(fileAdapter, true);
// Custom usage
await jsonAdapter.writeAsync({ users: [], posts: [] });
const data = await jsonAdapter.readAsync();Date Handling: The JsonAdapter automatically converts ISO date strings back to Date objects when reading:
// Writing
await db.push("/created", new Date());
// Reading - automatically converted back to Date object
const created = await db.getData("/created");
console.log(created instanceof Date); // trueFile system storage adapter that handles reading from and writing to files with directory creation and error handling.
/**
* File system storage adapter
* @param filename - Path to the file for storage
* @param fsync - Use synchronous file operations for guaranteed persistence
*/
class FileAdapter implements IAdapter<string> {
constructor(filename: string, fsync: boolean);
readonly filename: string;
/**
* Read file content as string
* @returns Promise resolving to file content or null if file doesn't exist
*/
readAsync(): Promise<string | null>;
/**
* Write string content to file, creating directories as needed
* @param data - String data to write to file
* @returns Promise that resolves when write operation completes
*/
writeAsync(data: string): Promise<void>;
}Usage Examples:
import { FileAdapter } from "node-json-db";
// Basic file adapter
const adapter = new FileAdapter("database.json", false);
// With sync operations for data integrity
const syncAdapter = new FileAdapter("/critical/data.json", true);
// Directory creation is automatic
const nestedAdapter = new FileAdapter("data/backups/db.json", false);
// Read/write operations
await adapter.writeAsync('{"test": "data"}');
const content = await adapter.readAsync(); // '{"test": "data"}'Features:
You can implement custom adapters for different storage backends:
import { IAdapter } from "node-json-db";
// Example: Memory adapter
class MemoryAdapter implements IAdapter<any> {
private data: any = null;
async readAsync(): Promise<any> {
return this.data;
}
async writeAsync(data: any): Promise<void> {
this.data = data;
}
}
// Example: Redis adapter
class RedisAdapter implements IAdapter<any> {
constructor(private client: RedisClient, private key: string) {}
async readAsync(): Promise<any> {
const data = await this.client.get(this.key);
return data ? JSON.parse(data) : null;
}
async writeAsync(data: any): Promise<void> {
await this.client.set(this.key, JSON.stringify(data));
}
}
// Usage with custom adapter
const config = new ConfigWithAdapter(new MemoryAdapter());
const db = new JsonDB(config);Base configuration interface that all configuration classes must implement.
/**
* Database configuration interface
*/
interface JsonDBConfig {
/**
* Storage adapter for reading/writing data
*/
readonly adapter: IAdapter<any>;
/**
* Whether to automatically save after push operations
*/
readonly saveOnPush: boolean;
/**
* Character used to separate DataPath segments
*/
readonly separator: string;
}// Development - readable JSON, auto-save, async operations
const devConfig = new Config("dev-database.json", true, true, "/", false);
// Production - compact JSON, manual saves, sync operations for reliability
const prodConfig = new Config("prod-database.json", false, false, "/", true);// For caching or temporary data
const memoryConfig = new ConfigWithAdapter(new MemoryAdapter());
// For persistent data
const diskConfig = new Config("persistent.json", true, false, "/", true);// Windows-style paths
const windowsConfig = new Config("database.json", true, false, "\\");
// Dot notation
const dotConfig = new Config("database.json", true, false, ".");
// Usage with custom separator
await db.getData("\\users\\1\\name"); // Windows style
await db.getData(".users.1.name"); // Dot notation