axiodb
Version:
The Pure JavaScript Alternative to SQLite. Embedded NoSQL database for Node.js with MongoDB-style queries, zero native dependencies, built-in InMemoryCache, and web GUI. Perfect for desktop apps, CLI tools, and embedded systems. No compilation, no platfor
309 lines • 14.2 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/no-unused-vars */
const promises_1 = __importDefault(require("fs/promises"));
const response_helper_1 = __importDefault(require("../../Helper/response.helper"));
const worker_process_1 = __importDefault(require("../cli/worker_process"));
const FolderManager_1 = __importDefault(require("./FolderManager"));
class FileManager {
constructor() {
this.responseHelper = new response_helper_1.default();
this.WorkerProcess = new worker_process_1.default();
}
/**
* Writes data to a file at the specified path.
*
* @param path - The path where the file will be written.
* @param data - The data to be written to the file.
* @returns A promise that resolves to a SuccessInterface if the file is written successfully,
* or an ErrorInterface if an error occurs.
*/
WriteFile(path, data) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.writeFile(path, data, "utf-8");
return this.responseHelper.Success("File written successfully.");
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Reads the content of a file at the specified path.
*
* @param path - The path to the file to be read.
* @returns A promise that resolves to a SuccessInterface containing the file data if the read operation is successful,
* or an ErrorInterface if an error occurs.
*/
ReadFile(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield promises_1.default.readFile(path, "utf-8");
return this.responseHelper.Success(data);
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Deletes a file at the specified path.
*
* @param {string} path - The path to the file to be deleted.
* @returns {Promise<SuccessInterface | ErrorInterface>} A promise that resolves to a SuccessInterface if the file is deleted successfully, or an ErrorInterface if an error occurs.
*/
DeleteFile(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.unlink(path);
return this.responseHelper.Success("File deleted successfully.");
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Checks if a file exists at the given path.
*
* @param path - The path to the file.
* @returns A promise that resolves to a SuccessInterface if the file exists,
* or an ErrorInterface if the file does not exist.
*/
FileExists(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.access(path);
return this.responseHelper.Success(true);
}
catch (_a) {
return this.responseHelper.Error(false);
}
});
}
/**
* Creates a new file at the specified path.
*
* @param path - The path where the new file will be created.
* @returns A promise that resolves to a SuccessInterface if the file is created successfully,
* or an ErrorInterface if there is an error during file creation.
*/
CreateFile(path) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.WriteFile(path, "");
});
}
/**
* Locks the specified file by changing its permissions to read-only.
*
* @param path - The path to the file to be locked.
* @returns A promise that resolves to a SuccessInterface if the file is locked successfully,
* or an ErrorInterface if an error occurs.
*/
LockFile(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.chmod(path, 0o400);
return this.responseHelper.Success("File locked successfully.");
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Unlocks the file at the specified path by changing its permissions to 777.
*
* @param {string} path - The path to the file to be unlocked.
* @returns {Promise<SuccessInterface | ErrorInterface>} A promise that resolves to a SuccessInterface if the file is unlocked successfully, or an ErrorInterface if an error occurs.
*/
UnlockFile(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.chmod(path, 0o777);
return this.responseHelper.Success("File unlocked successfully.");
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Moves a file from the specified old path to the new path.
*
* @param oldPath - The current path of the file to be moved.
* @param newPath - The destination path where the file should be moved.
* @returns A promise that resolves to a SuccessInterface if the file is moved successfully,
* or an ErrorInterface if an error occurs during the file move operation.
*/
MoveFile(oldPath, newPath) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield promises_1.default.rename(oldPath, newPath);
return this.responseHelper.Success("File moved successfully.");
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Checks if the file at the given path is locked.
*
* A file is considered locked if its permissions are set to read-only for the owner (mode 0o400).
*
* @param path - The path to the file to check.
* @returns A promise that resolves to a SuccessInterface if the file is locked, or an ErrorInterface if an error occurs.
*/
IsFileLocked(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
const stats = yield promises_1.default.stat(path);
return this.responseHelper.Success((stats.mode & 0o777) === 0o400);
}
catch (error) {
return this.responseHelper.Error(error);
}
});
}
/**
* Retrieves the size of a file in bytes.
*
* @param path - The path to the file.
* @returns A promise that resolves to a SuccessInterface containing the file size in bytes,
* or an ErrorInterface if an error occurs.
*/
GetFileSize(path) {
return __awaiter(this, void 0, void 0, function* () {
try {
// Try using native Node.js first (most reliable)
try {
// Check file permissions before reading
let originalMode = null;
try {
const stats = yield promises_1.default.stat(path);
originalMode = stats.mode;
// If file isn't readable, temporarily make it readable
if ((stats.mode & 0o444) !== 0o444) {
yield promises_1.default.chmod(path, 0o644);
}
}
catch (permError) {
// Continue with attempt to read the file even if we couldn't modify permissions
}
try {
const stats = yield promises_1.default.stat(path);
// Restore original permissions if they were modified
if (originalMode !== null && (originalMode & 0o444) !== 0o444) {
yield promises_1.default.chmod(path, originalMode);
}
return this.responseHelper.Success(stats.size);
}
catch (statError) {
// Fall back to system commands if native method fails
const osType = worker_process_1.default.getOS();
if (osType === "windows") {
const stdout = yield this.WorkerProcess.execCommand(`powershell -command "(Get-Item '${path}').length"`);
const size = parseInt(stdout, 10) || 0;
// Restore original permissions if they were modified
if (originalMode !== null && (originalMode & 0o444) !== 0o444) {
yield promises_1.default.chmod(path, originalMode);
}
return this.responseHelper.Success(size);
}
else {
// For Unix-like systems
const stdout = yield this.WorkerProcess.execCommand(`wc -c < "${path}" 2>/dev/null || echo 0`);
const size = parseInt(stdout, 10) || 0;
// Restore original permissions if they were modified
if (originalMode !== null && (originalMode & 0o444) !== 0o444) {
yield promises_1.default.chmod(path, originalMode);
}
return this.responseHelper.Success(size);
}
}
}
catch (err) {
// Try to restore original permissions if they were saved, even if an error occurred
try {
const stats = yield promises_1.default.stat(path);
const originalMode = stats.mode;
if ((originalMode & 0o444) !== 0o444) {
yield promises_1.default.chmod(path, originalMode);
}
}
catch (_a) {
// Ignore errors in the final cleanup attempt
}
return this.responseHelper.Error(`Failed to get file size: ${err}`);
}
}
catch (err) {
return this.responseHelper.Error(`Failed to get file size: ${err}`);
}
});
}
/**
* Safely deletes a file with directory lock management.
*
* This method handles file deletion with proper directory lock/unlock sequences:
* - If directory is unlocked: deletes file directly
* - If directory is locked: unlocks, deletes file, then relocks directory
*
* @param collectionPath - The path to the collection directory
* @param fileName - The name of the file to delete
* @returns A promise that resolves to a SuccessInterface if the file is deleted successfully,
* or an ErrorInterface if an error occurs during the deletion process.
*/
DeleteFileWithLock(collectionPath, fileName) {
return __awaiter(this, void 0, void 0, function* () {
const folderManager = new FolderManager_1.default();
const filePath = `${collectionPath}/${fileName}`;
// Check if directory is locked
const isLocked = yield folderManager.IsDirectoryLocked(collectionPath);
if (!("data" in isLocked)) {
return this.responseHelper.Error("Failed to check directory lock status");
}
if (isLocked.data === false) {
// Directory not locked - delete directly
const deleteResponse = yield this.DeleteFile(filePath);
return "data" in deleteResponse
? this.responseHelper.Success("File deleted successfully")
: this.responseHelper.Error("Failed to delete file");
}
else {
// Directory locked - unlock, delete, relock
const unlockResponse = yield folderManager.UnlockDirectory(collectionPath);
if (!("data" in unlockResponse)) {
return this.responseHelper.Error("Failed to unlock directory");
}
const deleteResponse = yield this.DeleteFile(filePath);
if (!("data" in deleteResponse)) {
// Attempt to relock even if delete failed
yield folderManager.LockDirectory(collectionPath);
return this.responseHelper.Error("Failed to delete file");
}
const lockResponse = yield folderManager.LockDirectory(collectionPath);
if (!("data" in lockResponse)) {
return this.responseHelper.Error("File deleted but failed to relock directory");
}
return this.responseHelper.Success("File deleted successfully");
}
});
}
}
exports.default = FileManager;
//# sourceMappingURL=FileManager.js.map