UNPKG

@showcomposer/broker

Version:

communication core for ShowComposer

208 lines (207 loc) 7.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // Logging const nodelogging_1 = require("@hibas123/nodelogging"); const json = require("big-json"); const deepForEach = require("deep-for-each"); const fs = require("fs"); const get = require("get-value"); const merge = require("merge-deep"); const os = require("os"); const PubSub = require("pubsub-js"); const set = require("set-value"); class SCData { constructor() { this.file = ""; this.fileLoaded = false; this.staticChanged = false; this.data = {}; this.static = {}; this.subscribers = []; this.file = os.homedir() + "/SCProject.json"; this.load(); this.staticLastChange = Date.now(); this.lastSave = Date.now(); setInterval(() => { if (this.staticChanged) { if (Date.now() - this.lastSave > 10000) { this.save(); } } }, 5000); } set(type, cmd) { const p = cmd.split(":"); this.setPlain(type, cmd, this.base64toString(p[1])); } setPlain(type, cmd, value = true) { const p = cmd.split(":"); const key = p[0]; // Switch between different set-types switch (type) { case "LIVE": set(this.data, key, value); PubSub.publish(key, "SET LIVE " + key + ":" + this.stringToBase64(value)); break; case "STATIC": set(this.data, key, value); PubSub.publish(key, "SET STATIC " + key + ":" + this.stringToBase64(value)); set(this.static, key, value); // Save file if necessary and set flags this.staticChanged = true; if ((Date.now() - this.staticLastChange) > 250) { this.save(); } this.staticLastChange = Date.now(); break; case "LINK": // ToDo break; case "TICK": set(this.data, key, value); PubSub.publish(key, "SET TICK " + key + ":" + this.stringToBase64(value)); break; } nodelogging_1.Logging.debug("SET " + key + " to " + value + " (" + type + ")"); return "0"; } assign(type, key, value = "e30=") { // Build POJO from encoded string const assObject = this.base64toPOJO(value); // Prepare object with nested key to merge at root level const deepAssObject = {}; set(deepAssObject, key, assObject); // Switch between different assign-types switch (type) { case "LIVE": this.data = merge(this.data, deepAssObject); PubSub.publish(key, "ASSIGN LIVE " + key + " " + value); break; case "STATIC": this.data = merge(this.data, deepAssObject); PubSub.publish(key, "ASSIGN STATIC " + key + " " + value); this.static = merge(this.static, deepAssObject); // Save file if necessary and set flags this.staticChanged = true; if ((Date.now() - this.staticLastChange) > 250) { this.save(); } this.staticLastChange = Date.now(); break; case "LINK": // ToDo break; case "TICK": this.data = merge(this.data, deepAssObject); PubSub.publish(key, "ASSIGN TICK " + key + " " + value); break; } nodelogging_1.Logging.debug("ASSIGN " + JSON.stringify(assObject) + " to " + key + " (" + type + ")"); return "0"; } sub(key, cb, t) { const id = this.subscribers.length; const token = PubSub.subscribe(key, (m, d) => { cb(m, d, id, t); }); nodelogging_1.Logging.log("New subscription to " + key); this.subscribers[id] = token; return { t: token, id }; } unsub(token) { PubSub.unsubscribe(token); } unsubId(id) { if (this.subscribers[id]) { PubSub.unsubscribe(this.subscribers[id]); this.subscribers[id] = false; return true; } return false; } dump(key) { const d = get(this.data, key); nodelogging_1.Logging.debug("DUMP " + key); return this.POJOtoBase64(d); } save() { if (this.fileLoaded) { nodelogging_1.Logging.log("Saving project into " + this.file); const wstream = fs.createWriteStream(this.file); const stringifyStream = json.createStringifyStream({ body: this.static, }); stringifyStream.pipe(wstream); stringifyStream.on("end", () => { wstream.end(); this.lastSave = Date.now(); this.staticChanged = false; }); wstream.on("finish", () => { fs.appendFile(this.file, os.EOL, "utf8", (err) => { if (err) { nodelogging_1.Logging.error(err); } }); }); wstream.on("error", (err) => { nodelogging_1.Logging.error("Error Saving project: " + err); }); } else { nodelogging_1.Logging.error("Cannot save to unloaded file!"); } } load() { if (fs.existsSync(this.file)) { nodelogging_1.Logging.log("Loading project from " + this.file); const readStream = fs.createReadStream(this.file); const parseStream = json.createParseStream(); parseStream.on("data", (pojo) => { deepForEach(pojo, (v, k, s, p) => { if (typeof v !== "object") { this.setPlain("STATIC", p, v); } }); this.fileLoaded = true; }); readStream.pipe(parseStream); } else { this.fileLoaded = true; nodelogging_1.Logging.log("No File, start project with file " + this.file); } } // Base 64 helper methods base64toPOJO(encoded) { const buff = Buffer.from(encoded, "base64"); const text = buff.toString("utf8"); return JSON.parse(text); } POJOtoBase64(obj) { const str = JSON.stringify(obj); if (typeof str !== "string") { nodelogging_1.Logging.error("Invalid object on POJOtoBase64"); return; } const buff = Buffer.from(str, "utf8"); const b64 = buff.toString("base64"); return b64; } base64toString(encoded) { const buff = Buffer.from(encoded, "base64"); return buff.toString("utf8"); } stringToBase64(str) { if (typeof str !== "string") { if (!(str = str.toString())) { nodelogging_1.Logging.error("Invalid value on stringToBase64"); return; } } const buff = Buffer.from(str, "utf8"); const b64 = buff.toString("base64"); return b64; } } exports.SCData = SCData;