Skip to content

Commit de64340

Browse files
authored
Merge pull request #7 from r-el/feature/examples-and-docs
feature/examples and docs
2 parents 9340a17 + c4fcbf6 commit de64340

File tree

6 files changed

+809
-16
lines changed

6 files changed

+809
-16
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ node_modules/
55
test-data/
66
*.log
77

8+
# Example data files (generated by running examples)
9+
examples/data/*.json
10+
811
# OS generated files
912
.DS_Store
1013
Thumbs.db

README.md

Lines changed: 293 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,323 @@
11
# JsonFileCRUD
22

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

5-
## Install
5+
## Features
6+
7+
- **Simple API** - Easy to use CRUD operations
8+
- **Thread-safe** - Sequential operations with automatic queuing
9+
- **Auto-ID assignment** - Automatic ID generation for new items
10+
- **Configurable ID field** - Use any field name as the primary key
11+
- **Comprehensive error handling** - Detailed error messages and validation
12+
- **Zero dependencies** - Built with only Node.js built-in modules
13+
- **ESM support** - Full ES modules support
14+
15+
## Installation
616

717
```bash
818
npm install json-file-crud
919
```
1020

11-
## Usage
21+
## Quick Start
1222

1323
```javascript
1424
import JsonFileCRUD from 'json-file-crud';
1525

1626
const db = new JsonFileCRUD('./data.json');
1727

18-
// Create
28+
// Create a new item
1929
db.create({ name: 'John', age: 30 }, (err, result) => {
20-
console.log('Created:', result);
21-
});
22-
23-
// Read by ID
24-
db.findById(1, (err, item) => {
25-
console.log('Item:', item);
30+
if (err) {
31+
console.error('Error:', err.message);
32+
return;
33+
}
34+
console.log('Created:', result); // { name: 'John', age: 30, id: 1 }
2635
});
2736

28-
// Read all
37+
// Read all items
2938
db.readAll((err, items) => {
39+
if (err) throw err;
3040
console.log('All items:', items);
3141
});
3242

33-
// Update
34-
db.update(1, { age: 31 }, (err, result) => {
35-
console.log('Updated:', result);
43+
// Find by ID
44+
db.findById(1, (err, item) => {
45+
if (err) throw err;
46+
console.log('Found:', item);
47+
});
48+
49+
// Update an item
50+
db.update(1, { age: 31 }, (err, updatedItem) => {
51+
if (err) throw err;
52+
console.log('Updated:', updatedItem);
3653
});
3754

38-
// Delete
55+
// Delete an item
3956
db.delete(1, (err, deletedItem) => {
57+
if (err) throw err;
4058
console.log('Deleted:', deletedItem);
4159
});
4260
```
4361

62+
## API Reference
63+
64+
### Constructor
65+
66+
#### `new JsonFileCRUD(filePath, options)`
67+
68+
Creates a new JsonFileCRUD instance.
69+
70+
- `filePath` (string): Path to the JSON file
71+
- `options` (object, optional):
72+
- `idField` (string): Name of the ID field (default: 'id')
73+
74+
```javascript
75+
// Default ID field
76+
const db = new JsonFileCRUD('./data.json');
77+
78+
// Custom ID field
79+
const products = new JsonFileCRUD('./products.json', { idField: 'productId' });
80+
```
81+
82+
### CRUD Operations
83+
84+
#### `create(item, callback)`
85+
86+
Creates a new item. Auto-assigns an ID if not provided.
87+
88+
- `item` (object): The item to create
89+
- `callback` (function): `(error, createdItem) => {}`
90+
91+
```javascript
92+
db.create({ name: 'Alice', email: 'alice@example.com' }, (err, result) => {
93+
// result: { name: 'Alice', email: 'alice@example.com', id: 1 }
94+
});
95+
```
96+
97+
#### `readAll(callback)`
98+
99+
Reads all items from the file.
100+
101+
- `callback` (function): `(error, items) => {}`
102+
103+
```javascript
104+
db.readAll((err, items) => {
105+
// items: array of all items
106+
});
107+
```
108+
109+
#### `findById(id, callback)`
110+
111+
Finds an item by its ID.
112+
113+
- `id` (any): The ID to search for
114+
- `callback` (function): `(error, item) => {}`
115+
116+
```javascript
117+
db.findById(1, (err, item) => {
118+
// item: the found item or null if not found
119+
});
120+
```
121+
122+
#### `findBy(filterFunction, callback)`
123+
124+
Finds items that match a filter function.
125+
126+
- `filterFunction` (function): Function that returns true for matching items
127+
- `callback` (function): `(error, items) => {}`
128+
129+
```javascript
130+
// Find all adults
131+
db.findBy(item => item.age >= 18, (err, adults) => {
132+
// adults: array of matching items
133+
});
134+
135+
// Find by name
136+
db.findBy(item => item.name === 'John', (err, johns) => {
137+
// johns: array of items named John
138+
});
139+
```
140+
141+
#### `update(id, data, callback)`
142+
143+
Updates an existing item.
144+
145+
- `id` (any): The ID of the item to update
146+
- `data` (object): The data to update (merged with existing item)
147+
- `callback` (function): `(error, updatedItem) => {}`
148+
149+
```javascript
150+
db.update(1, { age: 25, city: 'New York' }, (err, updated) => {
151+
// updated: the item with merged data
152+
});
153+
```
154+
155+
#### `delete(id, callback)`
156+
157+
Deletes an item by ID.
158+
159+
- `id` (any): The ID of the item to delete
160+
- `callback` (function): `(error, deletedItem) => {}`
161+
162+
```javascript
163+
db.delete(1, (err, deleted) => {
164+
// deleted: the item that was removed
165+
});
166+
```
167+
168+
#### `count(callback)`
169+
170+
Returns the total number of items.
171+
172+
- `callback` (function): `(error, count) => {}`
173+
174+
```javascript
175+
db.count((err, total) => {
176+
console.log('Total items:', total);
177+
});
178+
```
179+
180+
#### `writeAll(items, callback)`
181+
182+
Replaces all data in the file with a new array of items.
183+
184+
- `items` (array): Array of items to write
185+
- `callback` (function): `(error) => {}`
186+
187+
```javascript
188+
const newData = [
189+
{ name: 'Item 1', id: 1 },
190+
{ name: 'Item 2', id: 2 }
191+
];
192+
193+
db.writeAll(newData, (err) => {
194+
if (!err) console.log('Data replaced successfully');
195+
});
196+
```
197+
198+
## Advanced Features
199+
200+
### Auto-ID Assignment
201+
202+
When creating items without an ID, JsonFileCRUD automatically assigns the next available numeric ID:
203+
204+
```javascript
205+
db.create({ name: 'John' }, (err, result) => {
206+
// result: { name: 'John', id: 1 }
207+
});
208+
209+
db.create({ name: 'Jane' }, (err, result) => {
210+
// result: { name: 'Jane', id: 2 }
211+
});
212+
```
213+
214+
### Concurrent Operations
215+
216+
All write operations are automatically queued to prevent race conditions:
217+
218+
```javascript
219+
// These will be executed sequentially, not simultaneously
220+
db.create({ name: 'User 1' }, callback1);
221+
db.create({ name: 'User 2' }, callback2);
222+
db.update(1, { active: true }, callback3);
223+
```
224+
225+
### Custom ID Fields
226+
227+
You can use any field name as the primary key:
228+
229+
```javascript
230+
const products = new JsonFileCRUD('./products.json', { idField: 'productId' });
231+
232+
products.create({ name: 'Laptop', price: 999 }, (err, product) => {
233+
// product: { name: 'Laptop', price: 999, productId: 1 }
234+
});
235+
```
236+
237+
### Error Handling
238+
239+
JsonFileCRUD provides detailed error messages for common scenarios:
240+
241+
```javascript
242+
// Validation errors
243+
db.create(null, (err) => {
244+
// err.message: "Item must be an object"
245+
});
246+
247+
// Not found errors
248+
db.findById(999, (err) => {
249+
// err.message: "Item with id 999 not found"
250+
});
251+
252+
// Duplicate ID errors
253+
db.create({ id: 1, name: 'Duplicate' }, (err) => {
254+
// err.message: "Item with id 1 already exists"
255+
});
256+
```
257+
258+
## Examples
259+
260+
For comprehensive examples, see the [examples](./examples/) directory:
261+
262+
- **[Basic Usage](./examples/basic-usage.js)** - Simple CRUD operations
263+
- **[Advanced Features](./examples/advanced-usage.js)** - Concurrent operations, filtering, custom ID fields
264+
- **[User Management](./examples/user-management.js)** - Real-world application example
265+
266+
To run examples:
267+
268+
```bash
269+
cd examples
270+
node basic-usage.js
271+
```
272+
273+
## TypeScript Support
274+
275+
While this library is written in JavaScript, you can use it in TypeScript projects. Type definitions may be added in future versions.
276+
277+
## File Format
278+
279+
JsonFileCRUD stores data as a JSON array in the specified file:
280+
281+
```json
282+
[
283+
{ "id": 1, "name": "John", "age": 30 },
284+
{ "id": 2, "name": "Jane", "age": 25 }
285+
]
286+
```
287+
288+
If the file doesn't exist, it will be created automatically on the first write operation.
289+
290+
## Performance Considerations
291+
292+
- **Small to medium datasets**: JsonFileCRUD is ideal for applications with up to ~10,000 items
293+
- **File I/O**: Every operation reads/writes the entire file, so performance scales with file size
294+
- **Memory usage**: The entire dataset is loaded into memory during operations
295+
- **Concurrent access**: Operations are queued, so high-concurrency scenarios may experience delays
296+
297+
For larger datasets or high-performance requirements, consider using a dedicated database.
298+
299+
## Contributing
300+
301+
Contributions are welcome! Here are some ways you can help improve JsonFileCRUD:
302+
303+
### Ideas for Contributions
304+
305+
- **TypeScript Support**: Add TypeScript type definitions (.d.ts files)
306+
- **Async/Await Support**: Add Promise-based API alongside callbacks
307+
- **Batch Operations**: Add bulk insert/update/delete operations
308+
- **File Locking**: Add file locking for multi-process safety
309+
- **Documentation**: Improve documentation and add more examples
310+
311+
### How to Contribute
312+
313+
1. **Fork the Repository**: Create your own fork of the project
314+
2. **Create a Feature Branch**: `git checkout -b feature/your-feature-name`
315+
3. **Write Tests**: Ensure your changes are well-tested
316+
4. **Follow Code Style**: Keep the code clean and consistent
317+
5. **Update Documentation**: Add or update relevant documentation
318+
6. **Submit a Pull Request**: Describe your changes clearly
319+
44320
## License
45321

46-
MIT
322+
MIT License - see [LICENSE](./LICENSE) file for details.
323+

0 commit comments

Comments
 (0)