jdb-lite
Version:
A lightweight schema-based JSON database library with validation
219 lines • 8.43 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DatabaseManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const objectid_1 = require("./objectid");
class DatabaseManager {
constructor(dbPath = '.db_json') {
this.collections = new Map();
this.dbPath = path.resolve(dbPath);
this.ensureDbDirectory();
}
ensureDbDirectory() {
if (!fs.existsSync(this.dbPath)) {
fs.mkdirSync(this.dbPath, { recursive: true });
}
}
getCollectionPath(collectionName) {
return path.join(this.dbPath, `${collectionName}.json`);
}
loadCollection(collectionName) {
if (this.collections.has(collectionName)) {
return this.collections.get(collectionName);
}
const filePath = this.getCollectionPath(collectionName);
if (!fs.existsSync(filePath)) {
// Create empty collection file immediately
const emptyCollection = [];
this.collections.set(collectionName, emptyCollection);
this.saveCollection(collectionName);
return emptyCollection;
}
try {
const data = fs.readFileSync(filePath, 'utf-8');
const collection = JSON.parse(data);
this.collections.set(collectionName, collection);
return collection;
}
catch (error) {
console.warn(`Failed to load collection ${collectionName}:`, error);
const emptyCollection = [];
this.collections.set(collectionName, emptyCollection);
this.saveCollection(collectionName);
return emptyCollection;
}
}
saveCollection(collectionName) {
const collection = this.collections.get(collectionName);
if (!collection)
return;
const filePath = this.getCollectionPath(collectionName);
try {
fs.writeFileSync(filePath, JSON.stringify(collection, null, 2), 'utf-8');
}
catch (error) {
console.error(`Failed to save collection ${collectionName}:`, error);
throw error;
}
}
async insertOne(collectionName, doc) {
const collection = this.loadCollection(collectionName);
// Generate _id if not provided
if (!doc._id) {
doc._id = new objectid_1.ObjectId().toString();
}
// Add timestamps if they don't exist
const now = new Date();
if (!doc.createdAt)
doc.createdAt = now;
if (!doc.updatedAt)
doc.updatedAt = now;
collection.push({ ...doc });
this.saveCollection(collectionName);
return doc;
}
async insertMany(collectionName, docs) {
const collection = this.loadCollection(collectionName);
const insertedDocs = [];
for (const doc of docs) {
if (!doc._id) {
doc._id = new objectid_1.ObjectId().toString();
}
const now = new Date();
if (!doc.createdAt)
doc.createdAt = now;
if (!doc.updatedAt)
doc.updatedAt = now;
const insertedDoc = { ...doc };
collection.push(insertedDoc);
insertedDocs.push(insertedDoc);
}
this.saveCollection(collectionName);
return insertedDocs;
}
async find(collectionName, filter = {}) {
const collection = this.loadCollection(collectionName);
if (Object.keys(filter).length === 0) {
return [...collection];
}
return collection.filter(doc => this.matchesFilter(doc, filter));
}
async findOne(collectionName, filter = {}) {
const collection = this.loadCollection(collectionName);
if (Object.keys(filter).length === 0) {
return collection[0] || null;
}
return collection.find(doc => this.matchesFilter(doc, filter)) || null;
}
async findById(collectionName, id) {
return this.findOne(collectionName, { _id: id });
}
async updateOne(collectionName, filter, update) {
const collection = this.loadCollection(collectionName);
const docIndex = collection.findIndex(doc => this.matchesFilter(doc, filter));
if (docIndex === -1) {
return { modifiedCount: 0 };
}
// Apply update
const updatedDoc = { ...collection[docIndex], ...update };
updatedDoc.updatedAt = new Date();
collection[docIndex] = updatedDoc;
this.saveCollection(collectionName);
return { modifiedCount: 1 };
}
async updateMany(collectionName, filter, update) {
const collection = this.loadCollection(collectionName);
let modifiedCount = 0;
for (let i = 0; i < collection.length; i++) {
if (this.matchesFilter(collection[i], filter)) {
collection[i] = { ...collection[i], ...update };
collection[i].updatedAt = new Date();
modifiedCount++;
}
}
if (modifiedCount > 0) {
this.saveCollection(collectionName);
}
return { modifiedCount };
}
async deleteOne(collectionName, filter) {
const collection = this.loadCollection(collectionName);
const docIndex = collection.findIndex(doc => this.matchesFilter(doc, filter));
if (docIndex === -1) {
return { deletedCount: 0 };
}
collection.splice(docIndex, 1);
this.saveCollection(collectionName);
return { deletedCount: 1 };
}
async deleteMany(collectionName, filter) {
const collection = this.loadCollection(collectionName);
const initialLength = collection.length;
const filteredCollection = collection.filter(doc => !this.matchesFilter(doc, filter));
this.collections.set(collectionName, filteredCollection);
this.saveCollection(collectionName);
return { deletedCount: initialLength - filteredCollection.length };
}
async countDocuments(collectionName, filter = {}) {
const docs = await this.find(collectionName, filter);
return docs.length;
}
async dropCollection(collectionName) {
const filePath = this.getCollectionPath(collectionName);
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
this.collections.delete(collectionName);
}
matchesFilter(doc, filter) {
for (const [key, value] of Object.entries(filter)) {
if (doc[key] !== value) {
return false;
}
}
return true;
}
ensureCollection(collectionName) {
this.loadCollection(collectionName);
}
getCollectionNames() {
const files = fs.readdirSync(this.dbPath);
return files.filter(file => file.endsWith('.json')).map(file => file.replace('.json', ''));
}
}
exports.DatabaseManager = DatabaseManager;
//# sourceMappingURL=database.js.map