UNPKG

@trap_stevo/star-vault

Version:

Unleash the future of data management with the ultimate platform for secure, scalable, and dynamic data operations. Power the next generation of applications by combining advanced encryption, revolutionary real-time querying, and seamless synchronization

342 lines (341 loc) 15.2 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var StorageEngine = require("./HUDControllers/StorageEngine"); var SecurityCore = require("./HUDControllers/SecurityCore"); var QueryEngine = require("./HUDControllers/QueryEngine"); var StarLogger = require("./HUDControllers/StarLogger"); var StarCache = require("./HUDControllers/StarCache"); var StarVault = /*#__PURE__*/function () { function StarVault(dbPath, logPath) { var shardCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 4; var maxLogSize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "869MB"; var logRetention = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : "1w"; var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; _classCallCheck(this, StarVault); var _options$enableEncryp = options.enableEncryption, enableEncryption = _options$enableEncryp === void 0 ? false : _options$enableEncryp, _options$vaultPath = options.vaultPath, vaultPath = _options$vaultPath === void 0 ? "./star-vault.json" : _options$vaultPath, _options$masterKey = options.masterKey, masterKey = _options$masterKey === void 0 ? null : _options$masterKey, _options$authHandler = options.authHandler, authHandler = _options$authHandler === void 0 ? null : _options$authHandler, _options$dirMode = options.dirMode, dirMode = _options$dirMode === void 0 ? 448 : _options$dirMode, _options$fileMode = options.fileMode, fileMode = _options$fileMode === void 0 ? 384 : _options$fileMode; this.storage = new StorageEngine(dbPath, shardCount, { dirMode: dirMode, fileMode: fileMode }); this.security = enableEncryption ? new SecurityCore({ masterKey: masterKey, vaultPath: vaultPath, dirMode: dirMode, fileMode: fileMode }) : null; this.cache = new StarCache(1000); this.wal = new StarLogger(logPath, maxLogSize, logRetention, dirMode, fileMode); this.authHandler = authHandler; this.listeners = new Map(); } return _createClass(StarVault, [{ key: "authenticate", value: function authenticate(clientAuth) { if (!this.authHandler) { return; } if (!this.authHandler(clientAuth)) { throw new Error("Unauthorized access."); } } }, { key: "secureData", value: function secureData(data, collection) { return this.security ? this.security.lock(data, collection) : data; } }, { key: "unsecureData", value: function unsecureData(data, collection) { if (!this.security || !data) { return data; } try { return this.security.unlock(data, collection); } catch (error) { console.error("Error decrypting data for collection ~ \"".concat(collection, "\" ~"), error.message); throw new Error("Did not decrypt data for collection ~ \"".concat(collection, "\".")); } } }, { key: "create", value: function create(collection, data) { var actionInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var clientAuth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; this.authenticate(clientAuth); var id = data.id || Date.now().toString(); var record = { id: id, data: data, timestamp: Date.now() }; var securedData = this.secureData(record, collection); this.wal.logWrite(collection, securedData, actionInfo); this.storage.write(collection, id, securedData); this.cache.set("".concat(collection, ":").concat(id), securedData); console.log("Emitting create event for path ~ ".concat(collection, "/").concat(id)); this.emit("create", "".concat(collection, "/").concat(id), record); return record; } }, { key: "update", value: function update(collection, id, updates) { var actionInfo = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; var clientAuth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; this.authenticate(clientAuth); var records = this.storage.read(collection).filter(function (r) { return r.id === id; }); if (records.length === 0) { throw new Error("Record ~ ".concat(id, " not found.")); } var currentRecord = this.unsecureData(records[0].data, collection); var updatedData = _objectSpread(_objectSpread({}, currentRecord.data), updates); var updatedRecord = { id: currentRecord.id, data: updatedData, lastModified: Date.now(), timestamp: currentRecord.timestamp }; var securedData = this.secureData(updatedRecord, collection); this.storage.write(collection, id, securedData); this.wal.logWrite(collection, securedData, actionInfo, "UPDATE"); console.log("Emitting update event for path ~ ".concat(collection, "/").concat(id)); this.emit("update", "".concat(collection, "/").concat(id), updatedRecord); return updatedRecord; } }, { key: "deleteCollection", value: function deleteCollection(collection) { var actionInfo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var clientAuth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; this.authenticate(clientAuth); var success = this.storage.deleteCollection(collection); if (!success) { console.log("Collection ~ ".concat(collection, " not found.")); return { wholeCollection: true, deleted: false }; } console.log("Emitting delete event for path ~ ".concat(collection)); this.wal.logSystemAction("DELETE", collection, { wholeCollection: true }, actionInfo); this.emit("delete", "".concat(collection), { wholeCollection: true, deleted: true }); return { wholeCollection: true, deleted: true }; } }, { key: "deleteRecord", value: function deleteRecord(collection, id) { var actionInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var clientAuth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; this.authenticate(clientAuth); var success = this.storage["delete"](collection, id); if (!success) { console.log("Record ~ ".concat(id, " not found in collection ~ ").concat(collection, ".")); return { id: id, deleted: false }; } console.log("Emitting delete event for path ~ ".concat(collection, "/").concat(id)); this.wal.logSystemAction("DELETE", collection, { id: id }, actionInfo); this.emit("delete", "".concat(collection, "/").concat(id), { id: id, deleted: true }); return { id: id, deleted: true }; } }, { key: "delete", value: function _delete(collection, id) { var actionInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var clientAuth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; this.authenticate(clientAuth); var records = this.storage.read(collection).filter(function (r) { return r.id !== id; }); var newRecords = records.map(function (r) { return JSON.stringify(r); }).join("\n"); this.storage.overwrite(collection, newRecords); console.log("Emitting delete event for path ~ ".concat(collection, "/").concat(id)); this.wal.logSystemAction("DELETE", collection, { id: id }, actionInfo); this.emit("delete", "".concat(collection, "/").concat(id), { id: id, deleted: true }); return { id: id, deleted: true }; } }, { key: "getByID", value: function getByID(collection, id) { var actionInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return this.query(collection, actionInfo).where("id", id).limit(1).execute()[0] || null; } }, { key: "query", value: function query(collection) { var _this = this; var actionInfo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var queryEngine = new QueryEngine(this.storage, this.security).from(collection); var queryObject = { where: function where(criteria) { queryEngine.where(criteria); return queryObject; }, search: function search(field, text) { queryEngine.search(field, text); return queryObject; }, recent: function recent(field, duration) { queryEngine.recent(field, duration); return queryObject; }, near: function near(field, center, radius) { queryEngine.near(field, center, radius); return queryObject; }, sort: function sort(criteria) { queryEngine.sort(criteria); return queryObject; }, contains: function contains(value) { queryEngine.contains(value); return queryObject; }, select: function select(fields) { queryEngine.select(fields); return queryObject; }, limit: function limit(value) { queryEngine.limit(value); return queryObject; }, offset: function offset(value) { queryEngine.offset(value); return queryObject; }, filterBy: function filterBy(fn) { queryEngine.filterBy(fn); return queryObject; }, callback: function callback(fn) { queryEngine.callback(fn); return queryObject; }, execute: function execute() { var collections = _this.getMatchingCollections(collection); queryEngine.from(collections); var results = queryEngine.execute(); _this.wal.logSystemAction("QUERY", collection, { collectionsQueried: collections, results: results }, actionInfo); return results; } }; return queryObject; } }, { key: "listen", value: function listen(event, nodePath, callback) { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event).push({ nodePath: nodePath, callback: callback }); console.log("Listener added for event ~ \"".concat(event, "\" on path ~ \"").concat(nodePath, "\"")); } }, { key: "emit", value: function emit(event, nodePath, data) { var _this2 = this; if (this.listeners.has(event)) { console.log("Processing emit for event ~ \"".concat(event, "\" on path ~ \"").concat(nodePath, "\"")); this.listeners.get(event).forEach(function (_ref) { var listenerPath = _ref.nodePath, callback = _ref.callback; console.log("Matching listener path ~ \"".concat(listenerPath, "\" with node path ~ \"").concat(nodePath, "\"")); if (_this2.matchesPath(listenerPath, nodePath)) { console.log("Listener triggered for path ~ \"".concat(listenerPath, "\"")); callback(nodePath, data); } }); } } }, { key: "getMatchingCollections", value: function getMatchingCollections(basePath) { var allCollections = this.storage.listCollections(); var containsWildcard = basePath.includes("*"); var normalizedBase = basePath.replace(/\\/g, "/"); var regex = containsWildcard ? new RegExp("^" + normalizedBase.replace("*", ".*") + "$") : new RegExp("^" + normalizedBase.replace(/\/$/, "") + "(?:\/.*)?$"); var matchedCollections = allCollections.filter(function (collection) { var normalized = collection.replace(/\\/g, "/"); return regex.test(normalized) || normalized.startsWith(normalizedBase); }); console.log("Matched Collections for \"".concat(basePath, "\" ~"), matchedCollections); return matchedCollections; } }, { key: "matchesPath", value: function matchesPath(listenerPath, nodePath) { var listenerSegments = listenerPath.split("/"); var nodeSegments = nodePath.split("/"); if (listenerSegments.length > nodeSegments.length) { console.log("Path mismatch: Listener path ~ \"".concat(listenerPath, "\" longer than node path ~ \"").concat(nodePath, "\"")); return false; } var match = listenerSegments.every(function (seg, idx) { return seg === "*" || seg === nodeSegments[idx]; }); console.log("Path match result for \"".concat(listenerPath, "\" and \"").concat(nodePath, "\" ~ ").concat(match)); return match; } }], [{ key: "range", value: function range(min, max) { return QueryEngine.range(min, max); } }]); }(); ; module.exports = StarVault;