From 71b8457030b13c02503742b131ee8df1d51623e1 Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 10:19:13 +0300 Subject: [PATCH 1/9] Add async wrapper utilities for JsonFileCRUD with Promise-based API --- lib/async-wrapper.js | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 lib/async-wrapper.js diff --git a/lib/async-wrapper.js b/lib/async-wrapper.js new file mode 100644 index 0000000..cc68029 --- /dev/null +++ b/lib/async-wrapper.js @@ -0,0 +1,56 @@ +/** + * Async wrapper utilities for JsonFileCRUD + * Provides Promise-based API alongside callback-based methods + */ + +/** + * Converts a callback-based method to Promise-based + * @param {Function} method - The callback-based method to wrap + * @param {Object} context - The context (this) to bind to the method + * @returns {Function} Promise-based version of the method + */ +export function promisify(method, context) { + return function (...args) { + return new Promise((resolve, reject) => { + // Add callback that resolves or rejects the promise + const callback = (error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }; + + // Call the original method with callback + method.call(context, ...args, callback); + }); + }; +} + +/** + * Creates async versions of all CRUD methods + * @param {Object} crudInstance - Instance of JsonFileCRUD + * @returns {Object} Object with async method variants + */ +export function createAsyncMethods(crudInstance) { + return { + // Create methods + createAsync: promisify(crudInstance.create, crudInstance), + + // Read methods + readAllAsync: promisify(crudInstance.readAll, crudInstance), + findByIdAsync: promisify(crudInstance.findById, crudInstance), + findByAsync: promisify(crudInstance.findBy, crudInstance), + countAsync: promisify(crudInstance.count, crudInstance), + + // Update methods + updateAsync: promisify(crudInstance.update, crudInstance), + + // Delete methods + deleteAsync: promisify(crudInstance.delete, crudInstance), + deleteAllAsync: promisify(crudInstance.deleteAll, crudInstance), + + // Utility methods + writeAllAsync: promisify(crudInstance.writeAll, crudInstance), + }; +} From 7d5166a09fd88d4b171ffab3c603ad3524f4c99c Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 10:36:47 +0300 Subject: [PATCH 2/9] Add async method variants to JsonFileCRUD for improved usability --- lib/json-file-crud.js | 170 ++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 72 deletions(-) diff --git a/lib/json-file-crud.js b/lib/json-file-crud.js index 939c668..211dec4 100644 --- a/lib/json-file-crud.js +++ b/lib/json-file-crud.js @@ -1,22 +1,28 @@ /** * JsonFileCRUD - A generic CRUD library for managing JSON objects in text files - * + * * Features: * - Sequential operation processing with write queue * - Auto-ID assignment for new items * - Duplicate ID prevention * - Configurable ID field * - Comprehensive error handling - * + * * @version 1.0.0 * @author REL */ import path from "path"; -import { OPERATION_TYPES, ERROR_MESSAGES, DEFAULT_CONFIG } from './constants.js'; -import { validateItem, createNotFoundError, createDuplicateIdError, createCannotChangeIdError } from './validators.js'; -import { readAllFromFile, writeItemsToFile } from './file-operations.js'; -import { QueueManager } from './queue-manager.js'; +import { OPERATION_TYPES, ERROR_MESSAGES, DEFAULT_CONFIG } from "./constants.js"; +import { + validateItem, + createNotFoundError, + createDuplicateIdError, + createCannotChangeIdError, +} from "./validators.js"; +import { readAllFromFile, writeItemsToFile } from "./file-operations.js"; +import { QueueManager } from "./queue-manager.js"; +import { createAsyncMethods } from "./async-wrapper.js"; class JsonFileCRUD { /** @@ -36,6 +42,10 @@ class JsonFileCRUD { this.autoId = options.autoId !== false; // default to true this.uniqueFields = options.uniqueFields || []; // Array of field names that should be unique this.queueManager = new QueueManager(this.filePath); + + // Add async method variants + const asyncMethods = createAsyncMethods(this); + Object.assign(this, asyncMethods); } //#region CREATE @@ -52,39 +62,43 @@ class JsonFileCRUD { return callback(validationError); } - this.queueManager.queueOperation(OPERATION_TYPES.CREATE, { item }, callback, (items) => { - // Auto-assign ID if enabled and not provided - if (this.autoId && !item[this.idField]) { - item[this.idField] = this._generateNextId(items); - } - - // Check for duplicate ID - if (item[this.idField]) { - const existingItem = items.find(existingItem => - existingItem[this.idField] === item[this.idField] - ); - if (existingItem) { - return callback(createDuplicateIdError(this.idField, item[this.idField])); + this.queueManager.queueOperation( + OPERATION_TYPES.CREATE, + { item }, + callback, + (items) => { + // Auto-assign ID if enabled and not provided + if (this.autoId && !item[this.idField]) { + item[this.idField] = this._generateNextId(items); } - } - // Check for duplicates in unique fields - for (const fieldName of this.uniqueFields) { - if (item[fieldName] !== undefined && item[fieldName] !== null) { - const duplicate = items.find(existingItem => - existingItem[fieldName] === item[fieldName] + // Check for duplicate ID + if (item[this.idField]) { + const existingItem = items.find( + (existingItem) => existingItem[this.idField] === item[this.idField] ); - if (duplicate) { - return callback(new Error(`Item with ${fieldName} '${item[fieldName]}' already exists`)); + if (existingItem) { + return callback(createDuplicateIdError(this.idField, item[this.idField])); } } - } - // Add new item to array - items.push(item); + // Check for duplicates in unique fields + for (const fieldName of this.uniqueFields) { + if (item[fieldName] !== undefined && item[fieldName] !== null) { + const duplicate = items.find((existingItem) => existingItem[fieldName] === item[fieldName]); + if (duplicate) { + return callback(new Error(`Item with ${fieldName} '${item[fieldName]}' already exists`)); + } + } + } + + // Add new item to array + items.push(item); - return { items, result: item }; - }, this); + return { items, result: item }; + }, + this + ); } /** @@ -95,13 +109,13 @@ class JsonFileCRUD { */ _generateNextId(items) { if (items.length === 0) return 1; - + // Find the highest numeric ID const numericIds = items - .map(item => item[this.idField]) - .filter(id => typeof id === 'number' && !isNaN(id)) + .map((item) => item[this.idField]) + .filter((id) => typeof id === "number" && !isNaN(id)) .sort((a, b) => b - a); - + return numericIds.length > 0 ? numericIds[0] + 1 : 1; } @@ -182,31 +196,37 @@ class JsonFileCRUD { return callback(createCannotChangeIdError(this.idField)); } - this.queueManager.queueOperation(OPERATION_TYPES.UPDATE, { id, data }, callback, (items) => { - // Find item to update - const itemIndex = this._findItemIndex(items, id); - if (itemIndex === -1) { - return callback(createNotFoundError(this.idField, id)); - } + this.queueManager.queueOperation( + OPERATION_TYPES.UPDATE, + { id, data }, + callback, + (items) => { + // Find item to update + const itemIndex = this._findItemIndex(items, id); + if (itemIndex === -1) { + return callback(createNotFoundError(this.idField, id)); + } - // Check for duplicates in unique fields (exclude current item) - for (const fieldName of this.uniqueFields) { - if (data[fieldName] !== undefined && data[fieldName] !== null) { - const duplicate = items.find((existingItem, index) => - index !== itemIndex && existingItem[fieldName] === data[fieldName] - ); - if (duplicate) { - return callback(new Error(`Item with ${fieldName} '${data[fieldName]}' already exists`)); + // Check for duplicates in unique fields (exclude current item) + for (const fieldName of this.uniqueFields) { + if (data[fieldName] !== undefined && data[fieldName] !== null) { + const duplicate = items.find( + (existingItem, index) => index !== itemIndex && existingItem[fieldName] === data[fieldName] + ); + if (duplicate) { + return callback(new Error(`Item with ${fieldName} '${data[fieldName]}' already exists`)); + } } } - } - // Update item (merge data with existing item) - const updatedItem = { ...items[itemIndex], ...data }; - items[itemIndex] = updatedItem; + // Update item (merge data with existing item) + const updatedItem = { ...items[itemIndex], ...data }; + items[itemIndex] = updatedItem; - return { items, result: updatedItem }; - }, this); + return { items, result: updatedItem }; + }, + this + ); } //#endregion UPDATE @@ -219,21 +239,27 @@ class JsonFileCRUD { * @param {Function} callback - Called with (error, deletedItem) */ delete(id, callback) { - this.queueManager.queueOperation(OPERATION_TYPES.DELETE, { id }, callback, (items) => { - // Find item to delete - const itemIndex = this._findItemIndex(items, id); - if (itemIndex === -1) { - return callback(createNotFoundError(this.idField, id)); - } + this.queueManager.queueOperation( + OPERATION_TYPES.DELETE, + { id }, + callback, + (items) => { + // Find item to delete + const itemIndex = this._findItemIndex(items, id); + if (itemIndex === -1) { + return callback(createNotFoundError(this.idField, id)); + } + + // Store deleted item for return + const deletedItem = items[itemIndex]; - // Store deleted item for return - const deletedItem = items[itemIndex]; - - // Remove item from array - items.splice(itemIndex, 1); + // Remove item from array + items.splice(itemIndex, 1); - return { items, result: deletedItem }; - }, this); + return { items, result: deletedItem }; + }, + this + ); } //#endregion DELETE @@ -271,10 +297,10 @@ class JsonFileCRUD { writeAll(items, callback) { // Add to queue if already writing if (this.queueManager.isWriting) { - this.queueManager.writeQueue.push({ + this.queueManager.writeQueue.push({ type: OPERATION_TYPES.WRITE_ALL, - params: { items }, - callback: callback + params: { items }, + callback: callback, }); return; } From 0646645268630a5198c7c612f85e4d26ed27492c Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 10:37:27 +0300 Subject: [PATCH 3/9] Add callback-based methods to JsonFileCRUD interface for improved functionality --- lib/json-file-crud.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/json-file-crud.d.ts b/lib/json-file-crud.d.ts index dfc92ea..785a03d 100644 --- a/lib/json-file-crud.d.ts +++ b/lib/json-file-crud.d.ts @@ -14,6 +14,7 @@ export default class JsonFileCRUD { readonly autoId: boolean; readonly uniqueFields: string[]; + // Callback-based methods create(item: T, callback: Callback): void; readAll(callback: Callback): void; findById(id: any, callback: Callback): void; @@ -24,6 +25,17 @@ export default class JsonFileCRUD { deleteAll(callback: (err: Error | null) => void): void; writeAll(items: T[], callback: (err: Error | null) => void): void; processWriteQueue(): void; + + // Promise-based methods + createAsync(item: T): Promise; + readAllAsync(): Promise; + findByIdAsync(id: any): Promise; + findByAsync(filterFn: (item: T) => boolean): Promise; + countAsync(): Promise; + updateAsync(id: any, data: Partial): Promise; + deleteAsync(id: any): Promise; + deleteAllAsync(): Promise; + writeAllAsync(items: T[]): Promise; } export function createCrud(filePath: string, options?: CrudOptions): JsonFileCRUD; From bb6e3e964ff2d0ee6e531121f49ae3b987c7527d Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 10:37:49 +0300 Subject: [PATCH 4/9] Add async demo example to showcase Promise-based API usage --- examples/async-demo.js | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/async-demo.js diff --git a/examples/async-demo.js b/examples/async-demo.js new file mode 100644 index 0000000..be8ea39 --- /dev/null +++ b/examples/async-demo.js @@ -0,0 +1,68 @@ +/** + * Async/Await Usage Example + * + * This example demonstrates the new Promise-based API + * alongside the traditional callback-based methods + */ + +import JsonFileCRUD from "../lib/json-file-crud.js"; + +const crud = new JsonFileCRUD("./examples/data/async-demo.json"); + +console.log("Async/Await API Demo\n"); + +async function asyncDemo() { + try { + // Clean start + await crud.writeAllAsync([]); + + // Create items using async/await + console.log("Creating users with async/await..."); + const user1 = await crud.createAsync({ name: "Ariel", age: 30 }); + console.log("Created:", user1); + + const user2 = await crud.createAsync({ name: "John", age: 25 }); + console.log("Created:", user2); + + // Read all users + console.log("\nReading all users..."); + const allUsers = await crud.readAllAsync(); + console.log("All users:", allUsers); + + // Find by ID + console.log("\nFinding user by ID..."); + const foundUser = await crud.findByIdAsync(user1.id); + console.log("Found user:", foundUser); + + // Update user + console.log("\nUpdating user..."); + const updatedUser = await crud.updateAsync(user1.id, { age: 31 }); + console.log("Updated user:", updatedUser); + + // Filter users + console.log("\nFiltering users over 30..."); + const adults = await crud.findByAsync((user) => user.age > 30); + console.log("Adults:", adults); + + // Count users + console.log("\nCounting users..."); + const count = await crud.countAsync(); + console.log("Total users:", count); + + // Delete user + console.log("\nDeleting user..."); + const deletedUser = await crud.deleteAsync(user2.id); + console.log("Deleted user:", deletedUser); + + // Final count + const finalCount = await crud.countAsync(); + console.log("Final count:", finalCount); + + console.log("\nAsync/Await demo completed successfully!"); + } catch (error) { + console.error("Error in async demo:", error.message); + } +} + +// Run the async demo +asyncDemo(); From 2e28b24ed4c90764d7231da6e28edd696b5aa0ea Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 11:58:31 +0300 Subject: [PATCH 5/9] Add async tests for JsonFileCRUD methods to validate functionality --- test/test-async.js | 105 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 test/test-async.js diff --git a/test/test-async.js b/test/test-async.js new file mode 100644 index 0000000..d5bab7f --- /dev/null +++ b/test/test-async.js @@ -0,0 +1,105 @@ +import JsonFileCRUD from "../lib/json-file-crud.js"; +import fs from "fs"; + +// Test setup +const testFile = "./test-async-data.json"; + +function cleanup() { + if (fs.existsSync(testFile)) { + fs.unlinkSync(testFile); + } +} + +// Clean up and start fresh +cleanup(); +const crud = new JsonFileCRUD(testFile); + +// Run tests sequentially +async function runAllTests() { + try { + // Test 1: Create + const item1 = await crud.createAsync({ name: "Test User" }); + console.log("✓ createAsync works"); + + // Test 2: Create another + const item2 = await crud.createAsync({ name: "User 2" }); + console.log("✓ createAsync works (second item)"); + + // Test 3: Read all + const allItems = await crud.readAllAsync(); + if (allItems.length === 2) { + console.log("✓ readAllAsync works"); + } else { + console.log("✗ readAllAsync failed"); + } + + // Test 4: Find by ID + const foundItem = await crud.findByIdAsync(item1.id); + if (foundItem && foundItem.name === "Test User") { + console.log("✓ findByIdAsync works"); + } else { + console.log("✗ findByIdAsync failed"); + } + + // Test 5: Find by filter + const filteredItems = await crud.findByAsync((item) => item.name.includes("User")); + if (filteredItems.length === 2) { + console.log("✓ findByAsync works"); + } else { + console.log("✗ findByAsync failed"); + } + + // Test 6: Count + const count = await crud.countAsync(); + if (count === 2) { + console.log("✓ countAsync works"); + } else { + console.log("✗ countAsync failed"); + } + + // Test 7: Update + const updated = await crud.updateAsync(item1.id, { age: 25 }); + if (updated.age === 25) { + console.log("✓ updateAsync works"); + } else { + console.log("✗ updateAsync failed"); + } + + // Test 8: Delete + const deleted = await crud.deleteAsync(item2.id); + if (deleted.name === "User 2") { + console.log("✓ deleteAsync works"); + } else { + console.log("✗ deleteAsync failed"); + } + + // Test 9: Delete all + await crud.deleteAllAsync(); + const finalCount = await crud.countAsync(); + if (finalCount === 0) { + console.log("✓ deleteAllAsync works"); + } else { + console.log("✗ deleteAllAsync failed"); + } + + // Test 10: Error handling + try { + await crud.findByIdAsync(999); + console.log("✗ error handling failed"); + } catch (error) { + if (error.message.includes("not found")) { + console.log("✓ error handling works"); + } else { + console.log("✗ error handling failed"); + } + } + + console.log("\nAll async tests completed"); + } catch (error) { + console.error("Test error:", error.message); + } finally { + cleanup(); + } +} + +runAllTests(); From 71106c3a14f5e3e97f36a29e19d1e08c39b3822d Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 11:59:25 +0300 Subject: [PATCH 6/9] Add async/await usage examples to README for enhanced clarity --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index e60bc59..ff94d34 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ A simple, robust, and thread-safe CRUD library for managing JSON objects in file ## 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* @@ -74,6 +75,27 @@ db.delete(1, (err, deletedItem) => { }); ``` +### Async/Await Usage + +```javascript +// 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 From ab8c7c8aa15fe5e9ed66368a436e3a55b14869e7 Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 11:59:54 +0300 Subject: [PATCH 7/9] Update CHANGELOG.md for version 1.3.0: Add async/await API support and enhanced examples --- CHANGELOG.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00a6ff3..fdc5c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,19 +2,30 @@ All notable changes to this project will be documented in this file. - The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.3.0] - 2025-09-11 + +### Added + +- **Promise/Async Support** - Full async/await API alongside callback methods + - All CRUD methods now have async variants (createAsync, readAllAsync, etc.) + - Automatic promisification wrapper for callback-based methods + - Complete TypeScript definitions for async methods + - New async usage examples and comprehensive test coverage +- **Enhanced Examples** - Added async/await usage demonstration + ## [1.2.0] - 2025-07-08 ### Added -- **TypeScript Definitions** - Bundled `lib/json-file-crud.d.ts` for IDE support +- **TypeScript Definitions** - Bundled `lib/json-file-crud.d.ts` for IDE support ## [1.1.0] - 2025-07-07 ### Added + - **Unique Fields Support** - Prevent duplicate values in specified fields - Configure unique fields via `uniqueFields` option - Automatic validation on create and update operations @@ -33,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - No need to manually create directories before using the library ### Enhanced + - **Test Suite Reorganization** - Improved test structure - Split tests into logical files by functionality - `test-basic.js` - Basic functionality and convenience features @@ -45,10 +57,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Backward compatible with existing code ### Changed + - Package description updated to reflect new features - Test scripts updated for reorganized test structure ### Technical Details + - All new features maintain backward compatibility - Thread-safe operations through existing queue system - Comprehensive error handling for all new features @@ -57,6 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0] - 2025-07-07 ### Added + - Initial release of JsonFileCRUD - Complete CRUD operations (Create, Read, Update, Delete) - Auto-ID assignment with duplicate prevention @@ -74,6 +89,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Contributing guidelines with improvement ideas ### Features + - **create(item, callback)** - Create new items with auto-ID - **readAll(callback)** - Read all items from file - **findById(id, callback)** - Find item by ID @@ -84,12 +100,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **writeAll(items, callback)** - Replace all data ### Performance + - Optimized for small to medium datasets (up to ~10,000 items) - Sequential operations prevent race conditions - Automatic file creation on first write - Memory-efficient data handling ### Documentation + - Complete README with API reference - Multiple practical examples - Error handling guide @@ -99,6 +117,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Future Improvements + - Promise-based API (async/await) - Batch operations (createMany, updateMany, deleteMany) - File locking for multi-process safety From 33914b46e7e86765b0ef9f49a75bacffbb13b534 Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 11:59:58 +0300 Subject: [PATCH 8/9] Update package.json for version 1.3.0: Add async tests and examples to improve coverage and clarity --- package.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index e8ea4bc..9f24f82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "json-file-crud", - "version": "1.2.0", + "version": "1.3.0", "title": "JsonFileCRUD", "description": "A simple, robust, and thread-safe CRUD library for managing JSON objects in files with unique fields, auto-ID, and advanced features", "main": "./lib/json-file-crud.js", @@ -8,17 +8,19 @@ "type": "module", "scripts": { "start": "node .", - "test": "node test/test-basic.js && node test/test-read.js && node test/test-create.js && node test/test-update.js && node test/test-delete.js && node test/test-advanced-create.js && node test/test-config-options.js", + "test": "node test/test-basic.js && node test/test-read.js && node test/test-create.js && node test/test-update.js && node test/test-delete.js && node test/test-advanced-create.js && node test/test-config-options.js && node test/test-async.js", "test:basic": "node test/test-basic.js", "test:read": "node test/test-read.js", "test:create": "node test/test-create.js", "test:update": "node test/test-update.js", "test:delete": "node test/test-delete.js", "test:config-options": "node test/test-config-options.js", - "examples": "node examples/basic-usage.js && node examples/advanced-usage.js && node examples/user-management.js", + "test:async": "node test/test-async.js", + "examples": "node examples/basic-usage.js && node examples/advanced-usage.js && node examples/user-management.js && node examples/async-demo.js", "examples:basic": "node examples/basic-usage.js", "examples:advanced": "node examples/advanced-usage.js", "examples:user": "node examples/user-management.js", + "examples:async": "node examples/async-demo.js", "version": "npm test && npm run examples && git add CHANGELOG.md", "preversion": "npm test", "postversion": "git push && git push --tags", From 78b010c38c1edde50b2bde86bc9af76b640767c4 Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 11 Sep 2025 12:06:15 +0300 Subject: [PATCH 9/9] Add Promise-based API section to README with async method examples --- README.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ff94d34..d191704 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,33 @@ db.writeAll(newData, (err) => { }); ``` +### 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: + +```javascript +// 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 @@ -319,6 +346,7 @@ For comprehensive examples, see the [examples](./examples/) directory: - **[Basic Usage](./examples/basic-usage.js)** - Simple CRUD operations - **[Advanced Features](./examples/advanced-usage.js)** - Concurrent operations, filtering, custom ID fields - **[User Management](./examples/user-management.js)** - Real-world application with unique fields validation +- **[Async/Await Demo](./examples/async-demo.js)** - Promise-based API usage with async/await ### Quick Examples @@ -382,7 +410,6 @@ Contributions are welcome! Here are some ways you can help improve JsonFileCRUD: ### Ideas for Contributions -- **Async/Await Support**: Add Promise-based API alongside callbacks - **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 @@ -399,4 +426,3 @@ Contributions are welcome! Here are some ways you can help improve JsonFileCRUD: ## License MIT License - see [LICENSE](./LICENSE) file for details. -