simple-json-db-lite 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/index.cjs +256 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +256 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# Simple JSON DB Lite
|
2
|
+
|
3
|
+
A lightweight JSON database with CRUD operations and pagination. This package allows you to use a JSON file as a simple database with collections and documents.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- Simple API for CRUD operations
|
8
|
+
- Support for collections (similar to tables in SQL)
|
9
|
+
- Query filtering with `where` conditions
|
10
|
+
- Pagination support
|
11
|
+
- Sorting capabilities
|
12
|
+
- Works with ES modules, CommonJS, and TypeScript
|
13
|
+
- MIT licensed
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
```bash
|
18
|
+
npm install simple-json-db-lite
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### ES Modules
|
24
|
+
|
25
|
+
```javascript
|
26
|
+
import { JsonDB } from 'simple-json-db-lite';
|
27
|
+
|
28
|
+
const db = new JsonDB('./data/database.json');
|
29
|
+
```
|
30
|
+
|
31
|
+
### CommonJS
|
32
|
+
|
33
|
+
```javascript
|
34
|
+
const { JsonDB } = require('simple-json-db-lite');
|
35
|
+
|
36
|
+
const db = new JsonDB('./data/database.json');
|
37
|
+
```
|
38
|
+
|
39
|
+
### Basic Operations
|
40
|
+
|
41
|
+
```javascript
|
42
|
+
// Create a collection (if it doesn't exist)
|
43
|
+
db.createCollection('users');
|
44
|
+
|
45
|
+
// Insert a document
|
46
|
+
const user = db.insert('users', {
|
47
|
+
name: 'John Doe',
|
48
|
+
email: 'john@example.com',
|
49
|
+
age: 30
|
50
|
+
});
|
51
|
+
console.log(user.id); // Automatically generated ID
|
52
|
+
|
53
|
+
// Find documents
|
54
|
+
const allUsers = db.find('users');
|
55
|
+
const youngUsers = db.find('users', {
|
56
|
+
where: { age: 30 }
|
57
|
+
});
|
58
|
+
|
59
|
+
// Find by ID
|
60
|
+
const john = db.findById('users', user.id);
|
61
|
+
|
62
|
+
// Update documents
|
63
|
+
const updatedCount = db.update('users',
|
64
|
+
{ status: 'active' },
|
65
|
+
{ where: { age: 30 } }
|
66
|
+
);
|
67
|
+
|
68
|
+
// Delete documents
|
69
|
+
const deletedCount = db.delete('users', {
|
70
|
+
where: { status: 'inactive' }
|
71
|
+
});
|
72
|
+
|
73
|
+
// Delete by ID
|
74
|
+
const deleted = db.deleteById('users', user.id);
|
75
|
+
|
76
|
+
// Count documents
|
77
|
+
const totalUsers = db.count('users');
|
78
|
+
const activeUsers = db.count('users', { status: 'active' });
|
79
|
+
```
|
80
|
+
|
81
|
+
### Pagination
|
82
|
+
|
83
|
+
```javascript
|
84
|
+
const { data, pagination } = db.paginate('users', 1, 10, { status: 'active' });
|
85
|
+
|
86
|
+
console.log(data); // Array of users for page 1
|
87
|
+
console.log(pagination);
|
88
|
+
// {
|
89
|
+
// total: 25,
|
90
|
+
// page: 1,
|
91
|
+
// pageSize: 10,
|
92
|
+
// totalPages: 3,
|
93
|
+
// hasNext: true,
|
94
|
+
// hasPrev: false
|
95
|
+
// }
|
96
|
+
```
|
97
|
+
|
98
|
+
### Sorting
|
99
|
+
|
100
|
+
```javascript
|
101
|
+
const sortedUsers = db.find('users', {
|
102
|
+
orderBy: {
|
103
|
+
field: 'age',
|
104
|
+
direction: 'desc'
|
105
|
+
}
|
106
|
+
});
|
107
|
+
```
|
108
|
+
|
109
|
+
## API Reference
|
110
|
+
|
111
|
+
### Constructor
|
112
|
+
|
113
|
+
```typescript
|
114
|
+
new JsonDB(filePath: string)
|
115
|
+
```
|
116
|
+
|
117
|
+
### Methods
|
118
|
+
|
119
|
+
- `createCollection(collectionName: string): void`
|
120
|
+
- `insert<T>(collectionName: string, document: T): T & { id: string }`
|
121
|
+
- `find<T>(collectionName: string, options?: QueryOptions): T[]`
|
122
|
+
- `findById<T>(collectionName: string, id: string): T | null`
|
123
|
+
- `update(collectionName: string, update: Record<string, any>, options?: UpdateOptions): number`
|
124
|
+
- `delete(collectionName: string, options?: DeleteOptions): number`
|
125
|
+
- `deleteById(collectionName: string, id: string): boolean`
|
126
|
+
- `count(collectionName: string, where?: Record<string, any>): number`
|
127
|
+
- `paginate<T>(collectionName: string, page?: number, pageSize?: number, where?: Record<string, any>): { data: T[], pagination: { ... } }`
|
128
|
+
|
129
|
+
## Development
|
130
|
+
|
131
|
+
```bash
|
132
|
+
# Install dependencies
|
133
|
+
npm install
|
134
|
+
|
135
|
+
# Run tests
|
136
|
+
npm test
|
137
|
+
|
138
|
+
# Build the package
|
139
|
+
npm run build
|
140
|
+
```
|
141
|
+
|
142
|
+
## License
|
143
|
+
|
144
|
+
MIT
|
package/dist/index.cjs
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __defProp = Object.defineProperty;
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
4
|
+
var __publicField = (obj, key, value) => {
|
5
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
6
|
+
return value;
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
9
|
+
const fs = require("fs");
|
10
|
+
const path = require("path");
|
11
|
+
class JsonDB {
|
12
|
+
/**
|
13
|
+
* Initialize the JSON database
|
14
|
+
* @param filePath Path to the JSON file
|
15
|
+
*/
|
16
|
+
constructor(filePath) {
|
17
|
+
__publicField(this, "filePath");
|
18
|
+
__publicField(this, "data", {});
|
19
|
+
this.filePath = path.resolve(filePath);
|
20
|
+
this.loadData();
|
21
|
+
}
|
22
|
+
/**
|
23
|
+
* Load data from the JSON file
|
24
|
+
* @private
|
25
|
+
*/
|
26
|
+
loadData() {
|
27
|
+
try {
|
28
|
+
if (fs.existsSync(this.filePath)) {
|
29
|
+
const fileContent = fs.readFileSync(this.filePath, "utf-8");
|
30
|
+
this.data = JSON.parse(fileContent);
|
31
|
+
} else {
|
32
|
+
this.saveData();
|
33
|
+
}
|
34
|
+
} catch (error) {
|
35
|
+
throw new Error(
|
36
|
+
`Failed to load data: ${error instanceof Error ? error.message : String(error)}`
|
37
|
+
);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
/**
|
41
|
+
* Save data to the JSON file
|
42
|
+
* @private
|
43
|
+
*/
|
44
|
+
saveData() {
|
45
|
+
try {
|
46
|
+
const dirPath = path.dirname(this.filePath);
|
47
|
+
if (!fs.existsSync(dirPath)) {
|
48
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
49
|
+
}
|
50
|
+
fs.writeFileSync(
|
51
|
+
this.filePath,
|
52
|
+
JSON.stringify(this.data, null, 2),
|
53
|
+
"utf-8"
|
54
|
+
);
|
55
|
+
} catch (error) {
|
56
|
+
throw new Error(
|
57
|
+
`Failed to save data: ${error instanceof Error ? error.message : String(error)}`
|
58
|
+
);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
/**
|
62
|
+
* Create a collection if it doesn't exist
|
63
|
+
* @param collectionName Name of the collection
|
64
|
+
*/
|
65
|
+
createCollection(collectionName) {
|
66
|
+
if (!this.data[collectionName]) {
|
67
|
+
this.data[collectionName] = [];
|
68
|
+
this.saveData();
|
69
|
+
}
|
70
|
+
}
|
71
|
+
/**
|
72
|
+
* Insert a document into a collection
|
73
|
+
* @param collectionName Name of the collection
|
74
|
+
* @param document Document to insert
|
75
|
+
* @returns The inserted document with ID
|
76
|
+
*/
|
77
|
+
insert(collectionName, document) {
|
78
|
+
this.createCollection(collectionName);
|
79
|
+
const id = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).substring(2);
|
80
|
+
const newDocument = { ...document, id };
|
81
|
+
this.data[collectionName].push(newDocument);
|
82
|
+
this.saveData();
|
83
|
+
return newDocument;
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* Find documents in a collection
|
87
|
+
* @param collectionName Name of the collection
|
88
|
+
* @param options Query options
|
89
|
+
* @returns Array of matching documents
|
90
|
+
*/
|
91
|
+
find(collectionName, options = {}) {
|
92
|
+
if (!this.data[collectionName]) {
|
93
|
+
return [];
|
94
|
+
}
|
95
|
+
let result = [...this.data[collectionName]];
|
96
|
+
if (options.where) {
|
97
|
+
result = result.filter(
|
98
|
+
(item) => Object.entries(options.where || {}).every(
|
99
|
+
([key, value]) => item[key] === value
|
100
|
+
)
|
101
|
+
);
|
102
|
+
}
|
103
|
+
if (options.orderBy) {
|
104
|
+
const { field, direction } = options.orderBy;
|
105
|
+
result.sort((a, b) => {
|
106
|
+
const valueA = a[field];
|
107
|
+
const valueB = b[field];
|
108
|
+
if (valueA < valueB)
|
109
|
+
return direction === "asc" ? -1 : 1;
|
110
|
+
if (valueA > valueB)
|
111
|
+
return direction === "asc" ? 1 : -1;
|
112
|
+
return 0;
|
113
|
+
});
|
114
|
+
}
|
115
|
+
if (options.offset !== void 0) {
|
116
|
+
result = result.slice(options.offset);
|
117
|
+
}
|
118
|
+
if (options.limit !== void 0) {
|
119
|
+
result = result.slice(0, options.limit);
|
120
|
+
}
|
121
|
+
return result;
|
122
|
+
}
|
123
|
+
/**
|
124
|
+
* Find a single document by ID
|
125
|
+
* @param collectionName Name of the collection
|
126
|
+
* @param id Document ID
|
127
|
+
* @returns The document or null if not found
|
128
|
+
*/
|
129
|
+
findById(collectionName, id) {
|
130
|
+
if (!this.data[collectionName]) {
|
131
|
+
return null;
|
132
|
+
}
|
133
|
+
const document = this.data[collectionName].find((item) => item.id === id);
|
134
|
+
return document ? document : null;
|
135
|
+
}
|
136
|
+
/**
|
137
|
+
* Update documents in a collection
|
138
|
+
* @param collectionName Name of the collection
|
139
|
+
* @param update Update object
|
140
|
+
* @param options Update options
|
141
|
+
* @returns Number of updated documents
|
142
|
+
*/
|
143
|
+
update(collectionName, update, options = {}) {
|
144
|
+
if (!this.data[collectionName]) {
|
145
|
+
return 0;
|
146
|
+
}
|
147
|
+
let updatedCount = 0;
|
148
|
+
this.data[collectionName] = this.data[collectionName].map((item) => {
|
149
|
+
if (options.where && !Object.entries(options.where).every(
|
150
|
+
([key, value]) => item[key] === value
|
151
|
+
)) {
|
152
|
+
return item;
|
153
|
+
}
|
154
|
+
updatedCount++;
|
155
|
+
return { ...item, ...update };
|
156
|
+
});
|
157
|
+
if (updatedCount > 0) {
|
158
|
+
this.saveData();
|
159
|
+
}
|
160
|
+
return updatedCount;
|
161
|
+
}
|
162
|
+
/**
|
163
|
+
* Delete documents from a collection
|
164
|
+
* @param collectionName Name of the collection
|
165
|
+
* @param options Delete options
|
166
|
+
* @returns Number of deleted documents
|
167
|
+
*/
|
168
|
+
delete(collectionName, options = {}) {
|
169
|
+
if (!this.data[collectionName]) {
|
170
|
+
return 0;
|
171
|
+
}
|
172
|
+
const originalLength = this.data[collectionName].length;
|
173
|
+
if (options.where) {
|
174
|
+
this.data[collectionName] = this.data[collectionName].filter(
|
175
|
+
(item) => !Object.entries(options.where || {}).every(
|
176
|
+
([key, value]) => item[key] === value
|
177
|
+
)
|
178
|
+
);
|
179
|
+
} else {
|
180
|
+
this.data[collectionName] = [];
|
181
|
+
}
|
182
|
+
const deletedCount = originalLength - this.data[collectionName].length;
|
183
|
+
if (deletedCount > 0) {
|
184
|
+
this.saveData();
|
185
|
+
}
|
186
|
+
return deletedCount;
|
187
|
+
}
|
188
|
+
/**
|
189
|
+
* Delete a document by ID
|
190
|
+
* @param collectionName Name of the collection
|
191
|
+
* @param id Document ID
|
192
|
+
* @returns True if document was deleted, false otherwise
|
193
|
+
*/
|
194
|
+
deleteById(collectionName, id) {
|
195
|
+
if (!this.data[collectionName]) {
|
196
|
+
return false;
|
197
|
+
}
|
198
|
+
const originalLength = this.data[collectionName].length;
|
199
|
+
this.data[collectionName] = this.data[collectionName].filter(
|
200
|
+
(item) => item.id !== id
|
201
|
+
);
|
202
|
+
const deleted = originalLength > this.data[collectionName].length;
|
203
|
+
if (deleted) {
|
204
|
+
this.saveData();
|
205
|
+
}
|
206
|
+
return deleted;
|
207
|
+
}
|
208
|
+
/**
|
209
|
+
* Count documents in a collection
|
210
|
+
* @param collectionName Name of the collection
|
211
|
+
* @param where Optional filter
|
212
|
+
* @returns Number of documents
|
213
|
+
*/
|
214
|
+
count(collectionName, where) {
|
215
|
+
if (!this.data[collectionName]) {
|
216
|
+
return 0;
|
217
|
+
}
|
218
|
+
if (where) {
|
219
|
+
return this.data[collectionName].filter(
|
220
|
+
(item) => Object.entries(where).every(([key, value]) => item[key] === value)
|
221
|
+
).length;
|
222
|
+
}
|
223
|
+
return this.data[collectionName].length;
|
224
|
+
}
|
225
|
+
/**
|
226
|
+
* Get pagination information
|
227
|
+
* @param collectionName Name of the collection
|
228
|
+
* @param page Page number (1-based)
|
229
|
+
* @param pageSize Number of items per page
|
230
|
+
* @param where Optional filter
|
231
|
+
* @returns Pagination information and data
|
232
|
+
*/
|
233
|
+
paginate(collectionName, page = 1, pageSize = 10, where) {
|
234
|
+
const offset = (page - 1) * pageSize;
|
235
|
+
const total = this.count(collectionName, where);
|
236
|
+
const totalPages = Math.ceil(total / pageSize);
|
237
|
+
const data = this.find(collectionName, {
|
238
|
+
where,
|
239
|
+
limit: pageSize,
|
240
|
+
offset
|
241
|
+
});
|
242
|
+
return {
|
243
|
+
data,
|
244
|
+
pagination: {
|
245
|
+
total,
|
246
|
+
page,
|
247
|
+
pageSize,
|
248
|
+
totalPages,
|
249
|
+
hasNext: page < totalPages,
|
250
|
+
hasPrev: page > 1
|
251
|
+
}
|
252
|
+
};
|
253
|
+
}
|
254
|
+
}
|
255
|
+
exports.JsonDB = JsonDB;
|
256
|
+
//# sourceMappingURL=index.cjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import fs from \"fs\";\r\nimport path from \"path\";\r\n\r\nexport interface QueryOptions {\r\n where?: Record<string, any>;\r\n limit?: number;\r\n offset?: number;\r\n orderBy?: {\r\n field: string;\r\n direction: \"asc\" | \"desc\";\r\n };\r\n}\r\n\r\nexport interface UpdateOptions {\r\n where?: Record<string, any>;\r\n}\r\n\r\nexport interface DeleteOptions {\r\n where?: Record<string, any>;\r\n}\r\n\r\nexport class JsonDB {\r\n private filePath: string;\r\n private data: Record<string, any[]> = {};\r\n\r\n /**\r\n * Initialize the JSON database\r\n * @param filePath Path to the JSON file\r\n */\r\n constructor(filePath: string) {\r\n this.filePath = path.resolve(filePath);\r\n this.loadData();\r\n }\r\n\r\n /**\r\n * Load data from the JSON file\r\n * @private\r\n */\r\n private loadData(): void {\r\n try {\r\n if (fs.existsSync(this.filePath)) {\r\n const fileContent = fs.readFileSync(this.filePath, \"utf-8\");\r\n this.data = JSON.parse(fileContent);\r\n } else {\r\n // Create the file if it doesn't exist\r\n this.saveData();\r\n }\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to load data: ${\r\n error instanceof Error ? error.message : String(error)\r\n }`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Save data to the JSON file\r\n * @private\r\n */\r\n private saveData(): void {\r\n try {\r\n const dirPath = path.dirname(this.filePath);\r\n\r\n // Create directory if it doesn't exist\r\n if (!fs.existsSync(dirPath)) {\r\n fs.mkdirSync(dirPath, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(\r\n this.filePath,\r\n JSON.stringify(this.data, null, 2),\r\n \"utf-8\"\r\n );\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to save data: ${\r\n error instanceof Error ? error.message : String(error)\r\n }`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Create a collection if it doesn't exist\r\n * @param collectionName Name of the collection\r\n */\r\n public createCollection(collectionName: string): void {\r\n if (!this.data[collectionName]) {\r\n this.data[collectionName] = [];\r\n this.saveData();\r\n }\r\n }\r\n\r\n /**\r\n * Insert a document into a collection\r\n * @param collectionName Name of the collection\r\n * @param document Document to insert\r\n * @returns The inserted document with ID\r\n */\r\n public insert<T extends Record<string, any>>(\r\n collectionName: string,\r\n document: T\r\n ): T & { id: string } {\r\n this.createCollection(collectionName);\r\n\r\n const id = crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Date.now().toString(36) + Math.random().toString(36).substring(2);\r\n const newDocument = { ...document, id };\r\n\r\n this.data[collectionName].push(newDocument);\r\n this.saveData();\r\n\r\n return newDocument as T & { id: string };\r\n }\r\n\r\n /**\r\n * Find documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param options Query options\r\n * @returns Array of matching documents\r\n */\r\n public find<T>(collectionName: string, options: QueryOptions = {}): T[] {\r\n if (!this.data[collectionName]) {\r\n return [];\r\n }\r\n\r\n let result = [...this.data[collectionName]] as T[];\r\n\r\n // Apply where filter\r\n if (options.where) {\r\n result = result.filter((item) =>\r\n Object.entries(options.where || {}).every(\r\n ([key, value]) => item[key as keyof T] === value\r\n )\r\n );\r\n }\r\n\r\n // Apply orderBy\r\n if (options.orderBy) {\r\n const { field, direction } = options.orderBy;\r\n result.sort((a, b) => {\r\n const valueA = a[field as keyof T];\r\n const valueB = b[field as keyof T];\r\n\r\n if (valueA < valueB) return direction === \"asc\" ? -1 : 1;\r\n if (valueA > valueB) return direction === \"asc\" ? 1 : -1;\r\n return 0;\r\n });\r\n }\r\n\r\n // Apply pagination\r\n if (options.offset !== undefined) {\r\n result = result.slice(options.offset);\r\n }\r\n\r\n if (options.limit !== undefined) {\r\n result = result.slice(0, options.limit);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Find a single document by ID\r\n * @param collectionName Name of the collection\r\n * @param id Document ID\r\n * @returns The document or null if not found\r\n */\r\n public findById<T>(collectionName: string, id: string): T | null {\r\n if (!this.data[collectionName]) {\r\n return null;\r\n }\r\n\r\n const document = this.data[collectionName].find((item) => item.id === id);\r\n return document ? (document as T) : null;\r\n }\r\n\r\n /**\r\n * Update documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param update Update object\r\n * @param options Update options\r\n * @returns Number of updated documents\r\n */\r\n public update(\r\n collectionName: string,\r\n update: Record<string, any>,\r\n options: UpdateOptions = {}\r\n ): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n let updatedCount = 0;\r\n\r\n this.data[collectionName] = this.data[collectionName].map((item) => {\r\n // Check if the item matches the where condition\r\n if (\r\n options.where &&\r\n !Object.entries(options.where).every(\r\n ([key, value]) => item[key] === value\r\n )\r\n ) {\r\n return item;\r\n }\r\n\r\n updatedCount++;\r\n return { ...item, ...update };\r\n });\r\n\r\n if (updatedCount > 0) {\r\n this.saveData();\r\n }\r\n\r\n return updatedCount;\r\n }\r\n\r\n /**\r\n * Delete documents from a collection\r\n * @param collectionName Name of the collection\r\n * @param options Delete options\r\n * @returns Number of deleted documents\r\n */\r\n public delete(collectionName: string, options: DeleteOptions = {}): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n const originalLength = this.data[collectionName].length;\r\n\r\n if (options.where) {\r\n this.data[collectionName] = this.data[collectionName].filter(\r\n (item) =>\r\n !Object.entries(options.where || {}).every(\r\n ([key, value]) => item[key] === value\r\n )\r\n );\r\n } else {\r\n // Delete all documents if no where clause\r\n this.data[collectionName] = [];\r\n }\r\n\r\n const deletedCount = originalLength - this.data[collectionName].length;\r\n\r\n if (deletedCount > 0) {\r\n this.saveData();\r\n }\r\n\r\n return deletedCount;\r\n }\r\n\r\n /**\r\n * Delete a document by ID\r\n * @param collectionName Name of the collection\r\n * @param id Document ID\r\n * @returns True if document was deleted, false otherwise\r\n */\r\n public deleteById(collectionName: string, id: string): boolean {\r\n if (!this.data[collectionName]) {\r\n return false;\r\n }\r\n\r\n const originalLength = this.data[collectionName].length;\r\n this.data[collectionName] = this.data[collectionName].filter(\r\n (item) => item.id !== id\r\n );\r\n\r\n const deleted = originalLength > this.data[collectionName].length;\r\n\r\n if (deleted) {\r\n this.saveData();\r\n }\r\n\r\n return deleted;\r\n }\r\n\r\n /**\r\n * Count documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param where Optional filter\r\n * @returns Number of documents\r\n */\r\n public count(collectionName: string, where?: Record<string, any>): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n if (where) {\r\n return this.data[collectionName].filter((item) =>\r\n Object.entries(where).every(([key, value]) => item[key] === value)\r\n ).length;\r\n }\r\n\r\n return this.data[collectionName].length;\r\n }\r\n\r\n /**\r\n * Get pagination information\r\n * @param collectionName Name of the collection\r\n * @param page Page number (1-based)\r\n * @param pageSize Number of items per page\r\n * @param where Optional filter\r\n * @returns Pagination information and data\r\n */\r\n public paginate<T>(\r\n collectionName: string,\r\n page = 1,\r\n pageSize = 10,\r\n where?: Record<string, any>\r\n ): {\r\n data: T[];\r\n pagination: {\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n totalPages: number;\r\n hasNext: boolean;\r\n hasPrev: boolean;\r\n };\r\n } {\r\n const offset = (page - 1) * pageSize;\r\n const total = this.count(collectionName, where);\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const data = this.find<T>(collectionName, {\r\n where,\r\n limit: pageSize,\r\n offset,\r\n });\r\n\r\n return {\r\n data,\r\n pagination: {\r\n total,\r\n page,\r\n pageSize,\r\n totalPages,\r\n hasNext: page < totalPages,\r\n hasPrev: page > 1,\r\n },\r\n };\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
export interface QueryOptions {
|
2
|
+
where?: Record<string, any>;
|
3
|
+
limit?: number;
|
4
|
+
offset?: number;
|
5
|
+
orderBy?: {
|
6
|
+
field: string;
|
7
|
+
direction: "asc" | "desc";
|
8
|
+
};
|
9
|
+
}
|
10
|
+
export interface UpdateOptions {
|
11
|
+
where?: Record<string, any>;
|
12
|
+
}
|
13
|
+
export interface DeleteOptions {
|
14
|
+
where?: Record<string, any>;
|
15
|
+
}
|
16
|
+
export declare class JsonDB {
|
17
|
+
private filePath;
|
18
|
+
private data;
|
19
|
+
/**
|
20
|
+
* Initialize the JSON database
|
21
|
+
* @param filePath Path to the JSON file
|
22
|
+
*/
|
23
|
+
constructor(filePath: string);
|
24
|
+
/**
|
25
|
+
* Load data from the JSON file
|
26
|
+
* @private
|
27
|
+
*/
|
28
|
+
private loadData;
|
29
|
+
/**
|
30
|
+
* Save data to the JSON file
|
31
|
+
* @private
|
32
|
+
*/
|
33
|
+
private saveData;
|
34
|
+
/**
|
35
|
+
* Create a collection if it doesn't exist
|
36
|
+
* @param collectionName Name of the collection
|
37
|
+
*/
|
38
|
+
createCollection(collectionName: string): void;
|
39
|
+
/**
|
40
|
+
* Insert a document into a collection
|
41
|
+
* @param collectionName Name of the collection
|
42
|
+
* @param document Document to insert
|
43
|
+
* @returns The inserted document with ID
|
44
|
+
*/
|
45
|
+
insert<T extends Record<string, any>>(collectionName: string, document: T): T & {
|
46
|
+
id: string;
|
47
|
+
};
|
48
|
+
/**
|
49
|
+
* Find documents in a collection
|
50
|
+
* @param collectionName Name of the collection
|
51
|
+
* @param options Query options
|
52
|
+
* @returns Array of matching documents
|
53
|
+
*/
|
54
|
+
find<T>(collectionName: string, options?: QueryOptions): T[];
|
55
|
+
/**
|
56
|
+
* Find a single document by ID
|
57
|
+
* @param collectionName Name of the collection
|
58
|
+
* @param id Document ID
|
59
|
+
* @returns The document or null if not found
|
60
|
+
*/
|
61
|
+
findById<T>(collectionName: string, id: string): T | null;
|
62
|
+
/**
|
63
|
+
* Update documents in a collection
|
64
|
+
* @param collectionName Name of the collection
|
65
|
+
* @param update Update object
|
66
|
+
* @param options Update options
|
67
|
+
* @returns Number of updated documents
|
68
|
+
*/
|
69
|
+
update(collectionName: string, update: Record<string, any>, options?: UpdateOptions): number;
|
70
|
+
/**
|
71
|
+
* Delete documents from a collection
|
72
|
+
* @param collectionName Name of the collection
|
73
|
+
* @param options Delete options
|
74
|
+
* @returns Number of deleted documents
|
75
|
+
*/
|
76
|
+
delete(collectionName: string, options?: DeleteOptions): number;
|
77
|
+
/**
|
78
|
+
* Delete a document by ID
|
79
|
+
* @param collectionName Name of the collection
|
80
|
+
* @param id Document ID
|
81
|
+
* @returns True if document was deleted, false otherwise
|
82
|
+
*/
|
83
|
+
deleteById(collectionName: string, id: string): boolean;
|
84
|
+
/**
|
85
|
+
* Count documents in a collection
|
86
|
+
* @param collectionName Name of the collection
|
87
|
+
* @param where Optional filter
|
88
|
+
* @returns Number of documents
|
89
|
+
*/
|
90
|
+
count(collectionName: string, where?: Record<string, any>): number;
|
91
|
+
/**
|
92
|
+
* Get pagination information
|
93
|
+
* @param collectionName Name of the collection
|
94
|
+
* @param page Page number (1-based)
|
95
|
+
* @param pageSize Number of items per page
|
96
|
+
* @param where Optional filter
|
97
|
+
* @returns Pagination information and data
|
98
|
+
*/
|
99
|
+
paginate<T>(collectionName: string, page?: number, pageSize?: number, where?: Record<string, any>): {
|
100
|
+
data: T[];
|
101
|
+
pagination: {
|
102
|
+
total: number;
|
103
|
+
page: number;
|
104
|
+
pageSize: number;
|
105
|
+
totalPages: number;
|
106
|
+
hasNext: boolean;
|
107
|
+
hasPrev: boolean;
|
108
|
+
};
|
109
|
+
};
|
110
|
+
}
|
package/dist/index.js
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
var __defProp = Object.defineProperty;
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
3
|
+
var __publicField = (obj, key, value) => {
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
5
|
+
return value;
|
6
|
+
};
|
7
|
+
import fs from "fs";
|
8
|
+
import path from "path";
|
9
|
+
class JsonDB {
|
10
|
+
/**
|
11
|
+
* Initialize the JSON database
|
12
|
+
* @param filePath Path to the JSON file
|
13
|
+
*/
|
14
|
+
constructor(filePath) {
|
15
|
+
__publicField(this, "filePath");
|
16
|
+
__publicField(this, "data", {});
|
17
|
+
this.filePath = path.resolve(filePath);
|
18
|
+
this.loadData();
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* Load data from the JSON file
|
22
|
+
* @private
|
23
|
+
*/
|
24
|
+
loadData() {
|
25
|
+
try {
|
26
|
+
if (fs.existsSync(this.filePath)) {
|
27
|
+
const fileContent = fs.readFileSync(this.filePath, "utf-8");
|
28
|
+
this.data = JSON.parse(fileContent);
|
29
|
+
} else {
|
30
|
+
this.saveData();
|
31
|
+
}
|
32
|
+
} catch (error) {
|
33
|
+
throw new Error(
|
34
|
+
`Failed to load data: ${error instanceof Error ? error.message : String(error)}`
|
35
|
+
);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
/**
|
39
|
+
* Save data to the JSON file
|
40
|
+
* @private
|
41
|
+
*/
|
42
|
+
saveData() {
|
43
|
+
try {
|
44
|
+
const dirPath = path.dirname(this.filePath);
|
45
|
+
if (!fs.existsSync(dirPath)) {
|
46
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
47
|
+
}
|
48
|
+
fs.writeFileSync(
|
49
|
+
this.filePath,
|
50
|
+
JSON.stringify(this.data, null, 2),
|
51
|
+
"utf-8"
|
52
|
+
);
|
53
|
+
} catch (error) {
|
54
|
+
throw new Error(
|
55
|
+
`Failed to save data: ${error instanceof Error ? error.message : String(error)}`
|
56
|
+
);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
/**
|
60
|
+
* Create a collection if it doesn't exist
|
61
|
+
* @param collectionName Name of the collection
|
62
|
+
*/
|
63
|
+
createCollection(collectionName) {
|
64
|
+
if (!this.data[collectionName]) {
|
65
|
+
this.data[collectionName] = [];
|
66
|
+
this.saveData();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
/**
|
70
|
+
* Insert a document into a collection
|
71
|
+
* @param collectionName Name of the collection
|
72
|
+
* @param document Document to insert
|
73
|
+
* @returns The inserted document with ID
|
74
|
+
*/
|
75
|
+
insert(collectionName, document) {
|
76
|
+
this.createCollection(collectionName);
|
77
|
+
const id = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).substring(2);
|
78
|
+
const newDocument = { ...document, id };
|
79
|
+
this.data[collectionName].push(newDocument);
|
80
|
+
this.saveData();
|
81
|
+
return newDocument;
|
82
|
+
}
|
83
|
+
/**
|
84
|
+
* Find documents in a collection
|
85
|
+
* @param collectionName Name of the collection
|
86
|
+
* @param options Query options
|
87
|
+
* @returns Array of matching documents
|
88
|
+
*/
|
89
|
+
find(collectionName, options = {}) {
|
90
|
+
if (!this.data[collectionName]) {
|
91
|
+
return [];
|
92
|
+
}
|
93
|
+
let result = [...this.data[collectionName]];
|
94
|
+
if (options.where) {
|
95
|
+
result = result.filter(
|
96
|
+
(item) => Object.entries(options.where || {}).every(
|
97
|
+
([key, value]) => item[key] === value
|
98
|
+
)
|
99
|
+
);
|
100
|
+
}
|
101
|
+
if (options.orderBy) {
|
102
|
+
const { field, direction } = options.orderBy;
|
103
|
+
result.sort((a, b) => {
|
104
|
+
const valueA = a[field];
|
105
|
+
const valueB = b[field];
|
106
|
+
if (valueA < valueB)
|
107
|
+
return direction === "asc" ? -1 : 1;
|
108
|
+
if (valueA > valueB)
|
109
|
+
return direction === "asc" ? 1 : -1;
|
110
|
+
return 0;
|
111
|
+
});
|
112
|
+
}
|
113
|
+
if (options.offset !== void 0) {
|
114
|
+
result = result.slice(options.offset);
|
115
|
+
}
|
116
|
+
if (options.limit !== void 0) {
|
117
|
+
result = result.slice(0, options.limit);
|
118
|
+
}
|
119
|
+
return result;
|
120
|
+
}
|
121
|
+
/**
|
122
|
+
* Find a single document by ID
|
123
|
+
* @param collectionName Name of the collection
|
124
|
+
* @param id Document ID
|
125
|
+
* @returns The document or null if not found
|
126
|
+
*/
|
127
|
+
findById(collectionName, id) {
|
128
|
+
if (!this.data[collectionName]) {
|
129
|
+
return null;
|
130
|
+
}
|
131
|
+
const document = this.data[collectionName].find((item) => item.id === id);
|
132
|
+
return document ? document : null;
|
133
|
+
}
|
134
|
+
/**
|
135
|
+
* Update documents in a collection
|
136
|
+
* @param collectionName Name of the collection
|
137
|
+
* @param update Update object
|
138
|
+
* @param options Update options
|
139
|
+
* @returns Number of updated documents
|
140
|
+
*/
|
141
|
+
update(collectionName, update, options = {}) {
|
142
|
+
if (!this.data[collectionName]) {
|
143
|
+
return 0;
|
144
|
+
}
|
145
|
+
let updatedCount = 0;
|
146
|
+
this.data[collectionName] = this.data[collectionName].map((item) => {
|
147
|
+
if (options.where && !Object.entries(options.where).every(
|
148
|
+
([key, value]) => item[key] === value
|
149
|
+
)) {
|
150
|
+
return item;
|
151
|
+
}
|
152
|
+
updatedCount++;
|
153
|
+
return { ...item, ...update };
|
154
|
+
});
|
155
|
+
if (updatedCount > 0) {
|
156
|
+
this.saveData();
|
157
|
+
}
|
158
|
+
return updatedCount;
|
159
|
+
}
|
160
|
+
/**
|
161
|
+
* Delete documents from a collection
|
162
|
+
* @param collectionName Name of the collection
|
163
|
+
* @param options Delete options
|
164
|
+
* @returns Number of deleted documents
|
165
|
+
*/
|
166
|
+
delete(collectionName, options = {}) {
|
167
|
+
if (!this.data[collectionName]) {
|
168
|
+
return 0;
|
169
|
+
}
|
170
|
+
const originalLength = this.data[collectionName].length;
|
171
|
+
if (options.where) {
|
172
|
+
this.data[collectionName] = this.data[collectionName].filter(
|
173
|
+
(item) => !Object.entries(options.where || {}).every(
|
174
|
+
([key, value]) => item[key] === value
|
175
|
+
)
|
176
|
+
);
|
177
|
+
} else {
|
178
|
+
this.data[collectionName] = [];
|
179
|
+
}
|
180
|
+
const deletedCount = originalLength - this.data[collectionName].length;
|
181
|
+
if (deletedCount > 0) {
|
182
|
+
this.saveData();
|
183
|
+
}
|
184
|
+
return deletedCount;
|
185
|
+
}
|
186
|
+
/**
|
187
|
+
* Delete a document by ID
|
188
|
+
* @param collectionName Name of the collection
|
189
|
+
* @param id Document ID
|
190
|
+
* @returns True if document was deleted, false otherwise
|
191
|
+
*/
|
192
|
+
deleteById(collectionName, id) {
|
193
|
+
if (!this.data[collectionName]) {
|
194
|
+
return false;
|
195
|
+
}
|
196
|
+
const originalLength = this.data[collectionName].length;
|
197
|
+
this.data[collectionName] = this.data[collectionName].filter(
|
198
|
+
(item) => item.id !== id
|
199
|
+
);
|
200
|
+
const deleted = originalLength > this.data[collectionName].length;
|
201
|
+
if (deleted) {
|
202
|
+
this.saveData();
|
203
|
+
}
|
204
|
+
return deleted;
|
205
|
+
}
|
206
|
+
/**
|
207
|
+
* Count documents in a collection
|
208
|
+
* @param collectionName Name of the collection
|
209
|
+
* @param where Optional filter
|
210
|
+
* @returns Number of documents
|
211
|
+
*/
|
212
|
+
count(collectionName, where) {
|
213
|
+
if (!this.data[collectionName]) {
|
214
|
+
return 0;
|
215
|
+
}
|
216
|
+
if (where) {
|
217
|
+
return this.data[collectionName].filter(
|
218
|
+
(item) => Object.entries(where).every(([key, value]) => item[key] === value)
|
219
|
+
).length;
|
220
|
+
}
|
221
|
+
return this.data[collectionName].length;
|
222
|
+
}
|
223
|
+
/**
|
224
|
+
* Get pagination information
|
225
|
+
* @param collectionName Name of the collection
|
226
|
+
* @param page Page number (1-based)
|
227
|
+
* @param pageSize Number of items per page
|
228
|
+
* @param where Optional filter
|
229
|
+
* @returns Pagination information and data
|
230
|
+
*/
|
231
|
+
paginate(collectionName, page = 1, pageSize = 10, where) {
|
232
|
+
const offset = (page - 1) * pageSize;
|
233
|
+
const total = this.count(collectionName, where);
|
234
|
+
const totalPages = Math.ceil(total / pageSize);
|
235
|
+
const data = this.find(collectionName, {
|
236
|
+
where,
|
237
|
+
limit: pageSize,
|
238
|
+
offset
|
239
|
+
});
|
240
|
+
return {
|
241
|
+
data,
|
242
|
+
pagination: {
|
243
|
+
total,
|
244
|
+
page,
|
245
|
+
pageSize,
|
246
|
+
totalPages,
|
247
|
+
hasNext: page < totalPages,
|
248
|
+
hasPrev: page > 1
|
249
|
+
}
|
250
|
+
};
|
251
|
+
}
|
252
|
+
}
|
253
|
+
export {
|
254
|
+
JsonDB
|
255
|
+
};
|
256
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import fs from \"fs\";\r\nimport path from \"path\";\r\n\r\nexport interface QueryOptions {\r\n where?: Record<string, any>;\r\n limit?: number;\r\n offset?: number;\r\n orderBy?: {\r\n field: string;\r\n direction: \"asc\" | \"desc\";\r\n };\r\n}\r\n\r\nexport interface UpdateOptions {\r\n where?: Record<string, any>;\r\n}\r\n\r\nexport interface DeleteOptions {\r\n where?: Record<string, any>;\r\n}\r\n\r\nexport class JsonDB {\r\n private filePath: string;\r\n private data: Record<string, any[]> = {};\r\n\r\n /**\r\n * Initialize the JSON database\r\n * @param filePath Path to the JSON file\r\n */\r\n constructor(filePath: string) {\r\n this.filePath = path.resolve(filePath);\r\n this.loadData();\r\n }\r\n\r\n /**\r\n * Load data from the JSON file\r\n * @private\r\n */\r\n private loadData(): void {\r\n try {\r\n if (fs.existsSync(this.filePath)) {\r\n const fileContent = fs.readFileSync(this.filePath, \"utf-8\");\r\n this.data = JSON.parse(fileContent);\r\n } else {\r\n // Create the file if it doesn't exist\r\n this.saveData();\r\n }\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to load data: ${\r\n error instanceof Error ? error.message : String(error)\r\n }`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Save data to the JSON file\r\n * @private\r\n */\r\n private saveData(): void {\r\n try {\r\n const dirPath = path.dirname(this.filePath);\r\n\r\n // Create directory if it doesn't exist\r\n if (!fs.existsSync(dirPath)) {\r\n fs.mkdirSync(dirPath, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(\r\n this.filePath,\r\n JSON.stringify(this.data, null, 2),\r\n \"utf-8\"\r\n );\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to save data: ${\r\n error instanceof Error ? error.message : String(error)\r\n }`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Create a collection if it doesn't exist\r\n * @param collectionName Name of the collection\r\n */\r\n public createCollection(collectionName: string): void {\r\n if (!this.data[collectionName]) {\r\n this.data[collectionName] = [];\r\n this.saveData();\r\n }\r\n }\r\n\r\n /**\r\n * Insert a document into a collection\r\n * @param collectionName Name of the collection\r\n * @param document Document to insert\r\n * @returns The inserted document with ID\r\n */\r\n public insert<T extends Record<string, any>>(\r\n collectionName: string,\r\n document: T\r\n ): T & { id: string } {\r\n this.createCollection(collectionName);\r\n\r\n const id = crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Date.now().toString(36) + Math.random().toString(36).substring(2);\r\n const newDocument = { ...document, id };\r\n\r\n this.data[collectionName].push(newDocument);\r\n this.saveData();\r\n\r\n return newDocument as T & { id: string };\r\n }\r\n\r\n /**\r\n * Find documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param options Query options\r\n * @returns Array of matching documents\r\n */\r\n public find<T>(collectionName: string, options: QueryOptions = {}): T[] {\r\n if (!this.data[collectionName]) {\r\n return [];\r\n }\r\n\r\n let result = [...this.data[collectionName]] as T[];\r\n\r\n // Apply where filter\r\n if (options.where) {\r\n result = result.filter((item) =>\r\n Object.entries(options.where || {}).every(\r\n ([key, value]) => item[key as keyof T] === value\r\n )\r\n );\r\n }\r\n\r\n // Apply orderBy\r\n if (options.orderBy) {\r\n const { field, direction } = options.orderBy;\r\n result.sort((a, b) => {\r\n const valueA = a[field as keyof T];\r\n const valueB = b[field as keyof T];\r\n\r\n if (valueA < valueB) return direction === \"asc\" ? -1 : 1;\r\n if (valueA > valueB) return direction === \"asc\" ? 1 : -1;\r\n return 0;\r\n });\r\n }\r\n\r\n // Apply pagination\r\n if (options.offset !== undefined) {\r\n result = result.slice(options.offset);\r\n }\r\n\r\n if (options.limit !== undefined) {\r\n result = result.slice(0, options.limit);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Find a single document by ID\r\n * @param collectionName Name of the collection\r\n * @param id Document ID\r\n * @returns The document or null if not found\r\n */\r\n public findById<T>(collectionName: string, id: string): T | null {\r\n if (!this.data[collectionName]) {\r\n return null;\r\n }\r\n\r\n const document = this.data[collectionName].find((item) => item.id === id);\r\n return document ? (document as T) : null;\r\n }\r\n\r\n /**\r\n * Update documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param update Update object\r\n * @param options Update options\r\n * @returns Number of updated documents\r\n */\r\n public update(\r\n collectionName: string,\r\n update: Record<string, any>,\r\n options: UpdateOptions = {}\r\n ): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n let updatedCount = 0;\r\n\r\n this.data[collectionName] = this.data[collectionName].map((item) => {\r\n // Check if the item matches the where condition\r\n if (\r\n options.where &&\r\n !Object.entries(options.where).every(\r\n ([key, value]) => item[key] === value\r\n )\r\n ) {\r\n return item;\r\n }\r\n\r\n updatedCount++;\r\n return { ...item, ...update };\r\n });\r\n\r\n if (updatedCount > 0) {\r\n this.saveData();\r\n }\r\n\r\n return updatedCount;\r\n }\r\n\r\n /**\r\n * Delete documents from a collection\r\n * @param collectionName Name of the collection\r\n * @param options Delete options\r\n * @returns Number of deleted documents\r\n */\r\n public delete(collectionName: string, options: DeleteOptions = {}): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n const originalLength = this.data[collectionName].length;\r\n\r\n if (options.where) {\r\n this.data[collectionName] = this.data[collectionName].filter(\r\n (item) =>\r\n !Object.entries(options.where || {}).every(\r\n ([key, value]) => item[key] === value\r\n )\r\n );\r\n } else {\r\n // Delete all documents if no where clause\r\n this.data[collectionName] = [];\r\n }\r\n\r\n const deletedCount = originalLength - this.data[collectionName].length;\r\n\r\n if (deletedCount > 0) {\r\n this.saveData();\r\n }\r\n\r\n return deletedCount;\r\n }\r\n\r\n /**\r\n * Delete a document by ID\r\n * @param collectionName Name of the collection\r\n * @param id Document ID\r\n * @returns True if document was deleted, false otherwise\r\n */\r\n public deleteById(collectionName: string, id: string): boolean {\r\n if (!this.data[collectionName]) {\r\n return false;\r\n }\r\n\r\n const originalLength = this.data[collectionName].length;\r\n this.data[collectionName] = this.data[collectionName].filter(\r\n (item) => item.id !== id\r\n );\r\n\r\n const deleted = originalLength > this.data[collectionName].length;\r\n\r\n if (deleted) {\r\n this.saveData();\r\n }\r\n\r\n return deleted;\r\n }\r\n\r\n /**\r\n * Count documents in a collection\r\n * @param collectionName Name of the collection\r\n * @param where Optional filter\r\n * @returns Number of documents\r\n */\r\n public count(collectionName: string, where?: Record<string, any>): number {\r\n if (!this.data[collectionName]) {\r\n return 0;\r\n }\r\n\r\n if (where) {\r\n return this.data[collectionName].filter((item) =>\r\n Object.entries(where).every(([key, value]) => item[key] === value)\r\n ).length;\r\n }\r\n\r\n return this.data[collectionName].length;\r\n }\r\n\r\n /**\r\n * Get pagination information\r\n * @param collectionName Name of the collection\r\n * @param page Page number (1-based)\r\n * @param pageSize Number of items per page\r\n * @param where Optional filter\r\n * @returns Pagination information and data\r\n */\r\n public paginate<T>(\r\n collectionName: string,\r\n page = 1,\r\n pageSize = 10,\r\n where?: Record<string, any>\r\n ): {\r\n data: T[];\r\n pagination: {\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n totalPages: number;\r\n hasNext: boolean;\r\n hasPrev: boolean;\r\n };\r\n } {\r\n const offset = (page - 1) * pageSize;\r\n const total = this.count(collectionName, where);\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const data = this.find<T>(collectionName, {\r\n where,\r\n limit: pageSize,\r\n offset,\r\n });\r\n\r\n return {\r\n data,\r\n pagination: {\r\n total,\r\n page,\r\n pageSize,\r\n totalPages,\r\n hasNext: page < totalPages,\r\n hasPrev: page > 1,\r\n },\r\n };\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"name": "simple-json-db-lite",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "A lightweight JSON database with CRUD operations and pagination",
|
5
|
+
"type": "module",
|
6
|
+
"main": "./dist/index.cjs",
|
7
|
+
"module": "./dist/index.js",
|
8
|
+
"types": "./dist/index.d.ts",
|
9
|
+
"exports": {
|
10
|
+
".": {
|
11
|
+
"import": "./dist/index.js",
|
12
|
+
"require": "./dist/index.cjs",
|
13
|
+
"types": "./dist/index.d.ts"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"files": [
|
17
|
+
"dist",
|
18
|
+
"LICENSE"
|
19
|
+
],
|
20
|
+
"scripts": {
|
21
|
+
"dev": "vite build --watch",
|
22
|
+
"build": "vite build",
|
23
|
+
"test": "vitest run",
|
24
|
+
"test:watch": "vitest",
|
25
|
+
"prepublishOnly": "npm run build"
|
26
|
+
},
|
27
|
+
"keywords": [
|
28
|
+
"json",
|
29
|
+
"database",
|
30
|
+
"db",
|
31
|
+
"crud",
|
32
|
+
"file",
|
33
|
+
"storage",
|
34
|
+
"lightweight"
|
35
|
+
],
|
36
|
+
"license": "MIT",
|
37
|
+
"repository": {
|
38
|
+
"type": "git",
|
39
|
+
"url": "git+https://github.com/iiniit/simple-json-db-lite.git"
|
40
|
+
},
|
41
|
+
"bugs": {
|
42
|
+
"url": "https://github.com/iiniit/simple-json-db-lite/issues"
|
43
|
+
},
|
44
|
+
"publishConfig": {
|
45
|
+
"access": "public"
|
46
|
+
},
|
47
|
+
"homepage": "https://github.com/iiniit/simple-json-db-lite#readme",
|
48
|
+
"devDependencies": {
|
49
|
+
"@types/node": "^18.0.0",
|
50
|
+
"typescript": "^5.0.4",
|
51
|
+
"vite": "^4.3.9",
|
52
|
+
"vite-plugin-dts": "^2.3.0",
|
53
|
+
"vitest": "^0.32.0"
|
54
|
+
},
|
55
|
+
"engines": {
|
56
|
+
"node": ">=14.0.0"
|
57
|
+
}
|
58
|
+
}
|