UNPKG

@iobroker/db-objects-file

Version:

The Library contains the Database classes for File based objects database client and server.

823 lines (822 loc) 33.6 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var objectsInMemFileDB_exports = {}; __export(objectsInMemFileDB_exports, { ObjectsInMemoryFileDB: () => ObjectsInMemoryFileDB }); module.exports = __toCommonJS(objectsInMemFileDB_exports); var import_fs_extra = __toESM(require("fs-extra"), 1); var import_node_path = __toESM(require("node:path"), 1); var import_db_base = require("@iobroker/db-base"); var import_db_base2 = require("@iobroker/db-base"); var import_db_objects_redis = require("@iobroker/db-objects-redis"); var import_deep_clone = __toESM(require("deep-clone"), 1); class ObjectsInMemoryFileDB extends import_db_base.InMemoryFileDB { constructor(settings) { settings = settings || {}; settings.fileDB = settings.fileDB || { fileName: "objects.json", backupDirName: "backup-objects" }; super(settings); if (!this.change) { this.change = (id) => { this.log.silly(`${this.namespace} objects change: ${id} ${JSON.stringify(this.change)}`); }; } this.META_ID = "**META**"; this.fileOptions = {}; this.files = {}; this.writeTimer = null; this.writeIds = []; this.preserveSettings = ["custom"]; this.defaultNewAcl = this.settings.defaultNewAcl || null; this.namespace = this.settings.namespace || this.settings.hostname || ""; this.writeFileInterval = this.settings.connection && typeof this.settings.connection.writeFileInterval === "number" ? parseInt(this.settings.connection.writeFileInterval) : 5e3; if (!settings.jsonlDB) { this.log.silly(`${this.namespace} Objects DB uses file write interval of ${this.writeFileInterval} ms`); } this.objectsDir = import_node_path.default.join(this.dataDir, "files"); this.existingMetaObjects = {}; for (const obj of Object.values(this.dataset)) { if (import_db_base2.tools.isObject(obj) && obj.acl && obj.acl.permissions && !obj.acl.object) { obj.acl.object = obj.acl.permissions; delete obj.acl.permissions; } } const configObj = this.dataset["system.config"]; if (configObj && configObj.common && configObj.common.defaultNewAcl) { this.defaultNewAcl = (0, import_deep_clone.default)(configObj.common.defaultNewAcl); } } // internal functionality _normalizeFilename(name) { return name ? name.replace(/[/\\]+/g, "/") : name; } // -------------- FILE FUNCTIONS ------------------------------------------- // internal functionality _saveFileSettings(id, force) { if (typeof id === "boolean") { force = id; id = void 0; } id !== void 0 && !this.writeIds.includes(id) && this.writeIds.push(id); this.writeTimer && clearTimeout(this.writeTimer); if (force) { this.writeTimer = null; for (const writeId of this.writeIds) { const location = import_node_path.default.join(this.objectsDir, writeId, "_data.json"); try { if (import_fs_extra.default.existsSync(import_node_path.default.join(this.objectsDir, writeId))) { import_fs_extra.default.writeFileSync(location, JSON.stringify(this.fileOptions[writeId])); } } catch (e) { this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`); } } this.writeIds = []; } else { this.writeTimer = setTimeout(() => { for (const writeId of this.writeIds) { const location = import_node_path.default.join(this.objectsDir, writeId, "_data.json"); try { import_fs_extra.default.writeFileSync(location, JSON.stringify(this.fileOptions[writeId])); } catch (e) { this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`); } } this.writeIds = []; }, 1e3); } } // internal functionality _loadFileSettings(id) { if (!this.fileOptions[id]) { const location = import_node_path.default.join(this.objectsDir, id, "_data.json"); if (import_fs_extra.default.existsSync(location)) { try { this.fileOptions[id] = import_fs_extra.default.readJSONSync(location); } catch (e) { this.log.error(`${this.namespace} Cannot parse ${location}: ${e.message}`); this.fileOptions[id] = {}; } let corrected = false; Object.keys(this.fileOptions[id]).forEach((filename) => { const normalized = this._normalizeFilename(filename); if (normalized !== filename) { const options = this.fileOptions[id][filename]; delete this.fileOptions[id][filename]; this.fileOptions[id][normalized] = options; corrected = true; } if (corrected) { try { import_fs_extra.default.writeFileSync(location, JSON.stringify(this.fileOptions[id])); } catch (e) { this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`); } } }); } else { this.fileOptions[id] = {}; } } } // server only functionality syncFileDirectory(limitId) { const resNotifies = []; let resSynced = 0; function getAllFiles(dir) { let results = []; const list = import_fs_extra.default.readdirSync(dir); list.forEach((file) => { file = `${dir}/${file}`; const stat = import_fs_extra.default.statSync(file); if (stat && stat.isDirectory()) { results = results.concat(getAllFiles(file)); } else { results.push(file); } }); return results; } const res = this._getObjectView("system", "meta", null); const metaIds = res.rows.map((obj) => obj.id).filter((id) => !limitId || limitId === id); if (!import_fs_extra.default.existsSync(this.objectsDir)) { return { numberSuccess: resSynced, notifications: resNotifies }; } const baseDirs = import_fs_extra.default.readdirSync(this.objectsDir); baseDirs.forEach((dir) => { let dirSynced = 0; if (dir === ".." || dir === ".") { return; } const dirPath = import_node_path.default.join(this.objectsDir, dir); const stat = import_fs_extra.default.statSync(dirPath); if (!stat.isDirectory()) { return; } if (limitId && dir !== limitId) { return; } if (!metaIds.includes(dir)) { resNotifies.push(`Ignoring Directory "${dir}" because officially not created as meta object. Please remove directory!`); return; } this._loadFileSettings(dir); const files = getAllFiles(dirPath); files.forEach((file) => { const localFile = file.substr(dirPath.length + 1); if (localFile === "_data.json") { return; } if (!this.fileOptions[dir][localFile]) { const fileStat = import_fs_extra.default.statSync(file); const ext = import_node_path.default.extname(localFile); const mime = import_db_objects_redis.objectsUtils.getMimeType(ext); const _mimeType = mime.mimeType; const isBinary = mime.isBinary; this.fileOptions[dir][localFile] = { createdAt: fileStat.ctimeMs, acl: { owner: this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: this.defaultNewAcl && this.defaultNewAcl.file || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_RW | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_READ | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_READ // 0x644 }, mimeType: _mimeType, binary: isBinary, modifiedAt: fileStat.mtimeMs }; dirSynced++; } }); this._saveFileSettings(dir); resSynced += dirSynced; dirSynced && resNotifies.push(`Added ${dirSynced} Files in Directory "${dir}"`); }); return { numberSuccess: resSynced, notifications: resNotifies }; } // needed by server _writeFile(id, name, data, options) { if (typeof options === "string") { options = { mimeType: options }; } if (options && options.acl) { options.acl = null; } const _path = import_db_objects_redis.objectsUtils.sanitizePath(id, name); id = _path.id; name = _path.name; options = options || {}; this._loadFileSettings(id); this.files[id] = this.files[id] || {}; try { if (!import_fs_extra.default.existsSync(this.objectsDir)) { import_fs_extra.default.mkdirSync(this.objectsDir); } if (!import_fs_extra.default.existsSync(import_node_path.default.join(this.objectsDir, id))) { import_fs_extra.default.mkdirSync(import_node_path.default.join(this.objectsDir, id)); } } catch (e) { this.log.error(`${this.namespace} Cannot create directories: ${import_node_path.default.join(this.objectsDir, id)}: ${e.message}`); this.log.error(`${this.namespace} Check the permissions! Or run installation fixer or "iobroker fix" command!`); throw e; } const ext = import_node_path.default.extname(name); const mime = import_db_objects_redis.objectsUtils.getMimeType(ext); const _mimeType = mime.mimeType; const isBinary = mime.isBinary; this.fileOptions[id][name] = this.fileOptions[id][name] || { createdAt: Date.now() }; this.fileOptions[id][name].acl = this.fileOptions[id][name].acl || { owner: options.user || this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: options.group || this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: options.mode || this.defaultNewAcl && this.defaultNewAcl.file || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_RW | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_READ | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_READ // 0x644 }; this.fileOptions[id][name].mimeType = options.mimeType || _mimeType; this.fileOptions[id][name].binary = isBinary; this.fileOptions[id][name].acl.ownerGroup = this.fileOptions[id][name].acl.ownerGroup || this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP; this.fileOptions[id][name].modifiedAt = Date.now(); try { import_fs_extra.default.ensureDirSync(import_node_path.default.join(this.objectsDir, id, import_node_path.default.dirname(name))); import_fs_extra.default.writeFileSync(import_node_path.default.join(this.objectsDir, id, name), data, { flag: "w", encoding: isBinary ? "binary" : "utf8" }); if (isBinary) { delete this.files[id][name]; } else { this.files[id][name] = data; } this._saveFileSettings(id); } catch (e) { this.log.error(`${this.namespace} Cannot write files: ${import_node_path.default.join(this.objectsDir, id, name)}: ${e.message}`); throw e; } setImmediate((name2, size) => { this.log.silly(`${this.namespace} memory publish ${id} ${JSON.stringify({ name: name2, file: true, size })}`); this.publishAll("files", `${id}$%$${name2}`, size); }, name, data.byteLength); } // needed by server _readFile(id, name, options) { if (options && options.acl) { options.acl = null; } const _path = import_db_objects_redis.objectsUtils.sanitizePath(id, name); id = _path.id; name = _path.name; options = options || {}; try { this._loadFileSettings(id); this.files[id] = this.files[id] || {}; if (!this.files[id][name] || this.settings.connection.noFileCache || options.noFileCache) { const location = import_node_path.default.join(this.objectsDir, id, name); if (import_fs_extra.default.existsSync(location)) { this.fileOptions[id][name] = this.fileOptions[id][name] || { acl: { owner: this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: this.defaultNewAcl && this.defaultNewAcl.file.permissions || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_ALL // 777 } }; if (typeof this.fileOptions[id][name] !== "object") { this.fileOptions[id][name] = { mimeType: this.fileOptions[id][name], acl: { owner: this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: this.defaultNewAcl && this.defaultNewAcl.file.permissions || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_ALL // 777 } }; } this.files[id][name] = import_fs_extra.default.readFileSync(location); if (this.fileOptions[id][name].binary === void 0) { const ext = import_node_path.default.extname(name); const mimeType = import_db_objects_redis.objectsUtils.getMimeType(ext); this.fileOptions[id][name].binary = mimeType.isBinary; this.fileOptions[id][name].mimeType = mimeType.mimeType; } if (!this.fileOptions[id][name].binary) { if (this.files[id][name]) { this.files[id][name] = this.files[id][name].toString(); } } } else { if (this.fileOptions[id][name] !== void 0) { delete this.fileOptions[id][name]; } if (this.files[id][name] !== void 0) { delete this.files[id][name]; } } } if (this.fileOptions[id][name] && !this.fileOptions[id][name].acl) { this.fileOptions[id][name].acl = { owner: this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: this.defaultNewAcl && this.defaultNewAcl.file.permissions || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_RW // 776 }; } if (this.fileOptions[id][name] !== null && this.fileOptions[id][name] !== void 0) { if (!this.fileOptions[id][name].mimeType) { const _ext = import_node_path.default.extname(name); const _mimeType = import_db_objects_redis.objectsUtils.getMimeType(_ext); this.fileOptions[id][name].mimeType = _mimeType.mimeType; } return { fileContent: this.files[id][name], fileMime: this.fileOptions[id][name].mimeType }; } } catch (e) { this.log.warn(`${this.namespace} Cannot read file ${id} / ${name}: ${e.message}`); throw e; } throw new Error(import_db_objects_redis.objectsUtils.ERRORS.ERROR_NOT_FOUND); } /** * Check if given object exists * * @param id id of the object * @returns if the object exists */ // needed by server _objectExists(id) { if (!id || typeof id !== "string") { throw new Error(`invalid id ${JSON.stringify(id)}`); } try { return Object.prototype.hasOwnProperty.call(this.dataset, id); } catch (e) { this.log.error(`${this.namespace} Cannot check object existence of "${id}": ${e.message}`); throw new Error(`Cannot check object existence of "${id}": ${e.message}`); } } /** * Check if given file exists * * @param id id of the namespace * @param [name] name of the file * @returns */ // needed by server _fileExists(id, name) { if (typeof name !== "string") { name = ""; } const location = import_node_path.default.join(this.objectsDir, id, name); try { const stat = import_fs_extra.default.statSync(location); return stat.isFile(); } catch (e) { if (e.code !== "ENOENT") { this.log.error(`${this.namespace} Cannot check file existence of "${location}": ${e.message}`); throw new Error(`Cannot check file existence of "${location}": ${e.message}`); } return false; } } /** * Check if given directory exists * * @param id id of the namespace * @param [name] name of the directory * @returns */ // special functionality only for Server (used together with SyncFileDirectory) dirExists(id, name) { if (typeof name !== "string") { name = ""; } const location = import_node_path.default.join(this.objectsDir, id, name); try { const stat = import_fs_extra.default.statSync(location); return stat.isDirectory(); } catch (e) { if (e.code !== "ENOENT") { this.log.error(`${this.namespace} Cannot check directory existence of "${location}": ${e.message}`); throw new Error(`Cannot check directory existence of "${location}": ${e.message}`); } return false; } } // needed by server _unlink(id, name) { const _path = import_db_objects_redis.objectsUtils.sanitizePath(id, name); id = _path.id; name = _path.name; this._loadFileSettings(id); const location = import_node_path.default.join(this.objectsDir, id, name); if (import_fs_extra.default.existsSync(location)) { const stat = import_fs_extra.default.statSync(location); if (stat.isDirectory()) { import_fs_extra.default.readdirSync(location).forEach((dir) => this._unlink(id, `${name}/${dir}`)); this.log.debug(`Delete directory ${import_node_path.default.join(id, name)}`); try { import_fs_extra.default.removeSync(location); } catch (e) { this.log.error(`${this.namespace} Cannot delete directory "${import_node_path.default.join(id, name)}": ${e.message}`); throw e; } if (this.fileOptions[id]) { delete this.fileOptions[id]; } if (this.files[id] && this.files[id]) { delete this.files[id]; } } else { this.log.debug(`Delete file ${import_node_path.default.join(id, name)}`); try { import_fs_extra.default.removeSync(location); } catch (e) { this.log.error(`${this.namespace} Cannot delete file "${import_node_path.default.join(id, name)}": ${e.message}`); throw e; } if (this.fileOptions[id][name]) { delete this.fileOptions[id][name]; } if (this.files[id] && this.files[id][name]) { delete this.files[id][name]; } this._saveFileSettings(id, true); } setImmediate((id2, name2) => { this.log.silly(`${this.namespace} memory publish ${id2} ${JSON.stringify({ name: name2, file: true, size: null })}`); this.publishAll("files", `${id2}$%$${name2}`, null); }, id, name); } } // needed by server _readDir(id, name, options) { if (options && options.acl) { options.acl = null; } if ((id === "" || id === "/" || id === "*") && (name === "" || name === "*")) { } else { const _path = import_db_objects_redis.objectsUtils.sanitizePath(id, name); id = _path.id; name = _path.name; } options = options || {}; const _files = []; if (id && id === "*") { id = ""; } if (name && name[name.length - 1] !== "/") { name += "/"; } this._loadFileSettings(id); const len = name ? name.length : 0; for (const f2 of Object.keys(this.fileOptions[id])) { if (!name || f2.substring(0, len) === name) { let rest = f2.substring(len); rest = rest.split("/", 2); if (rest[0] && _files.indexOf(rest[0]) === -1) { _files.push(rest[0]); } } } const location = import_node_path.default.join(this.objectsDir, id, name); if (import_fs_extra.default.existsSync(location) && import_fs_extra.default.statSync(location).isDirectory()) { const dirFiles = import_fs_extra.default.readdirSync(location); for (let i = 0; i < dirFiles.length; i++) { if (dirFiles[i] === ".." || dirFiles[i] === ".") { continue; } if (dirFiles[i] !== "_data.json" && _files.indexOf(dirFiles[i]) === -1) { _files.push(dirFiles[i]); } } } else { throw new Error(import_db_objects_redis.objectsUtils.ERRORS.ERROR_NOT_FOUND); } _files.sort(); const res = []; for (const file of _files) { if (file === ".." || file === ".") { continue; } if (import_fs_extra.default.existsSync(import_node_path.default.join(location, file))) { try { const stats = import_fs_extra.default.statSync(import_node_path.default.join(location, file)); const acl = this.fileOptions[id][name + file] && this.fileOptions[id][name + file].acl ? (0, import_deep_clone.default)(this.fileOptions[id][name + file].acl) : { read: true, write: true, owner: this.defaultNewAcl && this.defaultNewAcl.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER, ownerGroup: this.defaultNewAcl && this.defaultNewAcl.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP, permissions: this.defaultNewAcl && this.defaultNewAcl.file.permissions || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_RW | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_READ | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_READ }; if (options.filter && acl) { if (!options.acl.file.write) { acl.permissions &= ~(import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_WRITE | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_WRITE | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_WRITE); } if (!options.acl.file.read) { acl.permissions &= ~(import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_READ | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_READ | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_READ); } if (options.user !== import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER && options.groups.includes(import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP)) { if (acl.owner !== options.user) { if (options.groups.includes(acl.ownerGroup)) { if (!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_RW)) { continue; } acl.read = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_READ); acl.write = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_WRITE); } else { if (!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_RW)) { continue; } acl.read = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_READ); acl.write = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_WRITE); } } else { if (!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_RW)) { continue; } acl.read = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_READ); acl.write = !!(acl.permissions & import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_WRITE); } } else { acl.read = true; acl.write = true; } } res.push({ file, stats, isDir: stats.isDirectory(), acl, modifiedAt: this.fileOptions[id][name + file] ? this.fileOptions[id][name + file].modifiedAt : void 0, createdAt: this.fileOptions[id][name + file] ? this.fileOptions[id][name + file].createdAt : void 0 }); } catch (e) { this.log.error(`${this.namespace} Cannot read permissions of ${import_node_path.default.join(this.objectsDir, id, name, file)}: ${e.message}`); } } } return res; } // needed by server _rename(id, oldName, newName) { const _path = import_db_objects_redis.objectsUtils.sanitizePath(id, oldName); id = _path.id; oldName = _path.name; if (newName[0] === "/") { newName = newName.substring(1); } this._loadFileSettings(id); if (import_fs_extra.default.existsSync(import_node_path.default.join(this.objectsDir, id, oldName))) { import_fs_extra.default.renameSync(import_node_path.default.join(this.objectsDir, id, oldName), import_node_path.default.join(this.objectsDir, id, newName)); } else { throw new Error(import_db_objects_redis.objectsUtils.ERRORS.ERROR_NOT_FOUND); } Object.keys(this.fileOptions[id]).forEach((name) => { const type = this.fileOptions[id][name]; if (name.startsWith(oldName)) { delete this.fileOptions[id][name]; this.fileOptions[id][name.replace(oldName, newName)] = type; } }); Object.keys(this.files[id]).forEach((name) => { const data = this.files[id][name]; if (name.startsWith(oldName)) { delete this.files[id][name]; this.files[id][name.replace(oldName, newName)] = data; } }); this._saveFileSettings(id, true); } // internal functionality _clone(obj) { if (obj === null || obj === void 0 || !import_db_base2.tools.isObject(obj)) { return obj; } const temp = obj.constructor(); for (const key of Object.keys(obj)) { temp[key] = this._clone(obj[key]); } return temp; } _subscribeMeta(client, pattern) { this.handleSubscribe(client, "meta", pattern); } // needed by server _subscribeConfigForClient(client, pattern) { this.handleSubscribe(client, "objects", pattern); } // needed by server _unsubscribeConfigForClient(client, pattern) { this.handleUnsubscribe(client, "objects", pattern); } // needed by server _subscribeFileForClient(client, id, pattern) { if (Array.isArray(pattern)) { pattern.forEach((pattern2) => this.handleSubscribe(client, "files", `${id}$%$${pattern2}`)); } else { this.handleSubscribe(client, "files", `${id}$%$${pattern}`); } } // needed by server _unsubscribeFileForClient(client, id, pattern) { if (Array.isArray(pattern)) { pattern.forEach((pattern2) => this.handleUnsubscribe(client, "files", `${id}$%$${pattern2}`)); } else { this.handleUnsubscribe(client, "files", `${id}$%$${pattern}`); } } // needed by server _getObject(id) { return this.dataset[id]; } // needed by server _getKeys(pattern) { const r = new RegExp(import_db_base2.tools.pattern2RegEx(pattern)); const result2 = Object.keys(this.dataset).filter((id) => r.test(id) && id !== this.META_ID); result2.sort(); return result2; } // needed by server _getObjects(keys) { if (!keys) { throw new Error("no keys"); } return keys.map((id) => this.dataset[id]); } _ensureMetaDict() { let meta = this.dataset[this.META_ID]; if (!meta) { meta = {}; this.dataset[this.META_ID] = meta; } return meta; } /** * Get value of given meta id * * @param id * @returns */ getMeta(id) { const meta = this._ensureMetaDict(); return meta[id]; } /** * Sets given value to id in metaNamespace * * @param id * @param value */ setMeta(id, value) { const meta = this._ensureMetaDict(); meta[id] = value; this.dataset[this.META_ID] = meta; setImmediate(() => { this.log.silly(`${this.namespace} memory publish meta ${id} ${value}`); this.publishAll("meta", id, value); }); if (!this.stateTimer) { this.stateTimer = setTimeout(() => this.saveState(), this.writeFileInterval); } } // needed by server _setObjectDirect(id, obj) { this.dataset[id] = obj; if (obj.type === "meta" && this.existingMetaObjects[id] === false) { this.existingMetaObjects[id] = true; } setImmediate(() => this.publishAll("objects", id, obj)); this.stateTimer = this.stateTimer || setTimeout(() => this.saveState(), this.writeFileInterval); } /** * Delete the given object from the dataset * * @param id unique id of the object */ _delObject(id) { const obj = this.dataset[id]; if (!obj) { return; } if (obj.common?.dontDelete) { throw new Error("Object is marked as non deletable"); } delete this.dataset[id]; if (this.existingMetaObjects[id]) { this.existingMetaObjects[id] = false; } setImmediate(() => this.publishAll("objects", id, null)); if (!this.stateTimer) { this.stateTimer = setTimeout(() => this.saveState(), this.writeFileInterval); } } // internal functionality _applyView(func, params) { const result = { rows: [] }; function _emit_(id, obj) { result.rows.push({ id, value: obj }); } const f = eval(`(${func.map.replace(/emit/g, "_emit_")})`); for (const [id, obj] of Object.entries(this.dataset)) { if (params) { if (params.startkey && id < params.startkey) { continue; } if (params.endkey && id > params.endkey) { continue; } } if (obj) { try { f(obj); } catch (e) { this.log.warn(`${this.namespace} Cannot execute map: ${e.message}`); } } } if (func.reduce === "_stats") { let max = null; for (const row of result.rows) { if (max === null || row.value > max) { max = row.value; } } if (max !== null) { result.rows = [{ id: "_stats", value: { max } }]; } else { result.rows = []; } } return result; } // needed by server _getObjectView(design, search, params2) { const designObj = this.dataset[`_design/${design}`]; if (!designObj) { this.log.error(`${this.namespace} Cannot find view "${design}"`); throw new Error(`Cannot find view "${design}"`); } if (!(designObj.views && designObj.views[search])) { this.log.warn(`${this.namespace} Cannot find search "${search}" in "${design}"`); throw new Error(`Cannot find search "${search}" in "${design}"`); } return this._applyView(designObj.views[search], params2); } /** * Destructor of the class. Called by shutting down. */ async destroy() { await super.destroy(); this._saveFileSettings(true); if (this.stateTimer) { clearTimeout(this.stateTimer); this.stateTimer = null; } if (this.writeTimer) { clearTimeout(this.writeTimer); this.writeTimer = null; } } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ObjectsInMemoryFileDB }); //# sourceMappingURL=objectsInMemFileDB.js.map