UNPKG

@jsprismarine/logger

Version:
164 lines (163 loc) 17.2 kB
import { PrismarineTransport } from "./transport.es.js"; import colorParser from "@jsprismarine/color-parser"; import * as winston from "winston"; import { format } from "winston"; //#region src/logger.ts /** * Helper class for general logging. * @document ../../../docs/log-levels.md * @class * @public */ var Logger = class { /** * The internal logger instance. * @type {Winston} * @private * @internal */ logger = null; /** * Create a new logger instance * @param {LogLevel} level - The log level to use. * @param {TransportStream[]} transports - The transports to use. * @returns {Logger} The logger instance. */ constructor(level = "info", transports = []) { this.createLogger(level, transports); } /** * Create a new logger instance * * @returns {void} */ createLogger(level = "info", transports = []) { if (this.logger && !this.logger.closed) return; this.logger = winston.createLogger({ level, format: format.combine(format.timestamp({ format: "HH:mm:ss" }), format((info) => { info.level = info.level.toUpperCase(); return info; })(), format.colorize(), format.simple()), transports: [new PrismarineTransport({ format: format.printf(({ level, message, timestamp, namespace: ns }) => { return colorParser(`[${`${timestamp} ${level}${ns ? ` ${ns}` : ""}`}§r]: ${message}§r`); }) }), ...transports] }); } /** * On enable hook. * @group Lifecycle */ async enable() { this.createLogger(); } /** * On disable hook. * @group Lifecycle */ async disable() { this.logger.close(); this.logger = null; } /** * Listen for log messages. * @param {(level: LogLevel, message: string) => void} listener - The listener to call when a log message is received. * @event */ onLine(listener) { this.logger.on("data", (data) => listener(data.message.toString())); } /** * Set the console instance to use. * @param {ConsoleLike} console - The console instance to use. */ setConsole(console) { if (!console) return; this.logger.transports[0].console = console; } /** * Get callee's namespace from the stack trace. * @private * @internal */ getNamespace = () => { const stack = (/* @__PURE__ */ new Error()).stack.replaceAll("\\", "/"); if (!stack) return ""; const caller = (stack.split("\n")[3] || "").trim(); if (!caller) return ""; const file = caller.match(/\(([^)]+)\)/)?.[1]?.split("src/")[1] || ""; if (!file) return ""; const path = file.split(":").slice(0, -2).join(":").slice(0, -3); if (!path) return ""; const lineCol = file.split(":").slice(-2).join(":"); if (!lineCol) return ""; if (this.logger.level === "silly" || this.logger.level === "debug" || this.logger.level === "verbose") return `${path}.ts:${lineCol}`; return path.split("/").at(-1) || ""; }; /** * @private * @internal */ parseMessage = (input) => { const output = input.join("§r "); if ([ ".", "!", "?" ].includes(output.charAt(-1))) return `${output}.`; return output; }; /** * Log information messages. * @param {...string} message - The message to log. */ info = (...message) => { this.logger.log("info", this.parseMessage(message), { namespace: this.getNamespace() }); }; /** * Log warning messages. * @param {...string} message - The message to log. */ warn = (...message) => { this.logger.log("warn", this.parseMessage(message), { namespace: this.getNamespace() }); }; /** * Log error messages. * @param {string | Error | any} message - The message to log. */ error = (message) => { if (typeof message === "string") { this.logger.log("error", message, { namespace: this.getNamespace() }); return; } if (message.stack) { this.logger.error(`${message.stack.split("\n")[0] !== message.toString() ? `${message.toString()}\n` : ""}${message.stack}`); return; } this.logger.error(message.toString()); }; /** * Log verbose messages. * @param {...string} message - The message to log. */ verbose = (...message) => { this.logger.log("verbose", this.parseMessage(message), { namespace: this.getNamespace() }); }; /** * Log debug messages. * @param {...string} message - The message to log. */ debug = (...message) => { this.logger.log("debug", this.parseMessage(message), { namespace: this.getNamespace() }); }; /** * Log silly messages. * @param {...string} message - The message to log. */ silly = (...message) => { this.logger.log("silly", this.parseMessage(message), { namespace: this.getNamespace() }); }; }; //#endregion export { Logger }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmVzLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2dnZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNvbG9yUGFyc2VyIGZyb20gJ0Bqc3ByaXNtYXJpbmUvY29sb3ItcGFyc2VyJztcblxuaW1wb3J0IHR5cGUgeyBMb2dnZXIgYXMgV2luc3RvbiB9IGZyb20gJ3dpbnN0b24nO1xuaW1wb3J0ICogYXMgd2luc3RvbiBmcm9tICd3aW5zdG9uJztcbmltcG9ydCB7IGZvcm1hdCB9IGZyb20gJ3dpbnN0b24nO1xuXG5pbXBvcnQgdHlwZSBUcmFuc3BvcnRTdHJlYW0gZnJvbSAnd2luc3Rvbi10cmFuc3BvcnQnO1xuaW1wb3J0IHR5cGUgeyBDb25zb2xlTGlrZSB9IGZyb20gJy4vdHJhbnNwb3J0JztcbmltcG9ydCB7IFByaXNtYXJpbmVUcmFuc3BvcnQgfSBmcm9tICcuL3RyYW5zcG9ydCc7XG5cbi8qKlxuICogQSBsb2cgbGV2ZWwuXG4gKiBAdHlwZSB7TG9nTGV2ZWx9XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCB0eXBlIExvZ0xldmVsID0gJ2Vycm9yJyB8ICd3YXJuJyB8ICdpbmZvJyB8ICd2ZXJib3NlJyB8ICdkZWJ1ZycgfCAnc2lsbHknO1xuXG4vKipcbiAqIEhlbHBlciBjbGFzcyBmb3IgZ2VuZXJhbCBsb2dnaW5nLlxuICogQGRvY3VtZW50IC4uLy4uLy4uL2RvY3MvbG9nLWxldmVscy5tZFxuICogQGNsYXNzXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2dnZXIge1xuICAgIC8qKlxuICAgICAqIFRoZSBpbnRlcm5hbCBsb2dnZXIgaW5zdGFuY2UuXG4gICAgICogQHR5cGUge1dpbnN0b259XG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvZ2dlcjogV2luc3RvbiB8IG51bGwgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IGxvZ2dlciBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB7TG9nTGV2ZWx9IGxldmVsIC0gVGhlIGxvZyBsZXZlbCB0byB1c2UuXG4gICAgICogQHBhcmFtIHtUcmFuc3BvcnRTdHJlYW1bXX0gdHJhbnNwb3J0cyAtIFRoZSB0cmFuc3BvcnRzIHRvIHVzZS5cbiAgICAgKiBAcmV0dXJucyB7TG9nZ2VyfSBUaGUgbG9nZ2VyIGluc3RhbmNlLlxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihsZXZlbDogTG9nTGV2ZWwgPSAnaW5mbycsIHRyYW5zcG9ydHM6IFRyYW5zcG9ydFN0cmVhbVtdID0gW10pIHtcbiAgICAgICAgdGhpcy5jcmVhdGVMb2dnZXIobGV2ZWwsIHRyYW5zcG9ydHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBsb2dnZXIgaW5zdGFuY2VcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVMb2dnZXIobGV2ZWw6IExvZ0xldmVsID0gJ2luZm8nLCB0cmFuc3BvcnRzOiBUcmFuc3BvcnRTdHJlYW1bXSA9IFtdKTogdm9pZCB7XG4gICAgICAgIC8vIElmIHRoZSBsb2dnZXIgaXMgYWxyZWFkeSBjcmVhdGVkIGFuZCBub3QgY2xvc2VkLCByZXR1cm4uXG4gICAgICAgIGlmICgodGhpcy5sb2dnZXIhIGFzIGFueSkgJiYgIXRoaXMubG9nZ2VyIS5jbG9zZWQpIHJldHVybjtcblxuICAgICAgICB0aGlzLmxvZ2dlciEgPSB3aW5zdG9uLmNyZWF0ZUxvZ2dlcih7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGZvcm1hdDogZm9ybWF0LmNvbWJpbmUoXG4gICAgICAgICAgICAgICAgZm9ybWF0LnRpbWVzdGFtcCh7IGZvcm1hdDogJ0hIOm1tOnNzJyB9KSxcbiAgICAgICAgICAgICAgICBmb3JtYXQoKGluZm8pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaW5mby5sZXZlbCA9IGluZm8ubGV2ZWwudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluZm87XG4gICAgICAgICAgICAgICAgfSkoKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQuY29sb3JpemUoKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQuc2ltcGxlKClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB0cmFuc3BvcnRzOiBbXG4gICAgICAgICAgICAgICAgbmV3IFByaXNtYXJpbmVUcmFuc3BvcnQoe1xuICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6IGZvcm1hdC5wcmludGYoKHsgbGV2ZWwsIG1lc3NhZ2UsIHRpbWVzdGFtcCwgbmFtZXNwYWNlOiBucyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmVmaXggPSBgJHt0aW1lc3RhbXB9ICR7bGV2ZWx9JHtucyA/IGAgJHtuc31gIDogJyd9YDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyKGBbJHtwcmVmaXh9wqdyXTogJHttZXNzYWdlfcKncmApO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIC4uLnRyYW5zcG9ydHNcbiAgICAgICAgICAgIF1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZW5hYmxlIGhvb2suXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBlbmFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuY3JlYXRlTG9nZ2VyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZGlzYWJsZSBob29rLlxuICAgICAqIEBncm91cCBMaWZlY3ljbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZGlzYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5sb2dnZXIhLmNsb3NlKCk7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIGxvZyBtZXNzYWdlcy5cbiAgICAgKiBAcGFyYW0geyhsZXZlbDogTG9nTGV2ZWwsIG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZH0gbGlzdGVuZXIgLSBUaGUgbGlzdGVuZXIgdG8gY2FsbCB3aGVuIGEgbG9nIG1lc3NhZ2UgaXMgcmVjZWl2ZWQuXG4gICAgICogQGV2ZW50XG4gICAgICovXG4gICAgcHVibGljIG9uTGluZShsaXN0ZW5lcjogKGxpbmU6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvZ2dlciEub24oJ2RhdGEnLCAoZGF0YSkgPT4gbGlzdGVuZXIoZGF0YS5tZXNzYWdlLnRvU3RyaW5nKCkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGNvbnNvbGUgaW5zdGFuY2UgdG8gdXNlLlxuICAgICAqIEBwYXJhbSB7Q29uc29sZUxpa2V9IGNvbnNvbGUgLSBUaGUgY29uc29sZSBpbnN0YW5jZSB0byB1c2UuXG4gICAgICovXG4gICAgcHVibGljIHNldENvbnNvbGUoY29uc29sZT86IENvbnNvbGVMaWtlKTogdm9pZCB7XG4gICAgICAgIGlmICghY29uc29sZSkgcmV0dXJuO1xuICAgICAgICAodGhpcy5sb2dnZXIhLnRyYW5zcG9ydHNbMF0gYXMgUHJpc21hcmluZVRyYW5zcG9ydCkuY29uc29sZSA9IGNvbnNvbGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGNhbGxlZSdzIG5hbWVzcGFjZSBmcm9tIHRoZSBzdGFjayB0cmFjZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHByaXZhdGUgZ2V0TmFtZXNwYWNlID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFjayA9IChuZXcgRXJyb3IoKS5zdGFjayBhcyBzdHJpbmcpLnJlcGxhY2VBbGwoJ1xcXFwnLCAnLycpO1xuICAgICAgICBpZiAoIXN0YWNrKSByZXR1cm4gJyc7XG5cbiAgICAgICAgY29uc3QgY2FsbGVyID0gKHN0YWNrLnNwbGl0KCdcXG4nKVszXSB8fCAnJykudHJpbSgpO1xuICAgICAgICBpZiAoIWNhbGxlcikgcmV0dXJuICcnO1xuXG4gICAgICAgIC8vIEdldCBwYXRoIGluc2lkZSBvZiB0aGUgcGFyZW50aGVzZXMgaW4gdGhlIGNhbGxlciBzdHJpbmcsIGV4Y2x1ZGluZyB0aGUgbGluZTpjb2wuXG4gICAgICAgIGNvbnN0IGZpbGUgPSBjYWxsZXIubWF0Y2goL1xcKChbXildKylcXCkvKT8uWzFdPy5zcGxpdCgnc3JjLycpWzFdIHx8ICcnO1xuICAgICAgICBpZiAoIWZpbGUpIHJldHVybiAnJztcblxuICAgICAgICAvLyBHZXQgcGF0aCBhbmQgbGluZTpjb2wgZnJvbSB0aGUgZmlsZSBzdHJpbmcsIHRoZW4gcmVtb3ZlIHRoZSBmaWxlIGV4dGVuc2lvbi5cbiAgICAgICAgY29uc3QgcGF0aCA9IGZpbGUuc3BsaXQoJzonKS5zbGljZSgwLCAtMikuam9pbignOicpLnNsaWNlKDAsIC0zKTtcbiAgICAgICAgaWYgKCFwYXRoKSByZXR1cm4gJyc7XG5cbiAgICAgICAgY29uc3QgbGluZUNvbCA9IGZpbGUuc3BsaXQoJzonKS5zbGljZSgtMikuam9pbignOicpO1xuICAgICAgICBpZiAoIWxpbmVDb2wpIHJldHVybiAnJztcblxuICAgICAgICBpZiAodGhpcy5sb2dnZXIhLmxldmVsID09PSAnc2lsbHknIHx8IHRoaXMubG9nZ2VyIS5sZXZlbCA9PT0gJ2RlYnVnJyB8fCB0aGlzLmxvZ2dlciEubGV2ZWwgPT09ICd2ZXJib3NlJykge1xuICAgICAgICAgICAgcmV0dXJuIGAke3BhdGh9LnRzOiR7bGluZUNvbH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhdGguc3BsaXQoJy8nKS5hdCgtMSkgfHwgJyc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHJpdmF0ZSBwYXJzZU1lc3NhZ2UgPSAoaW5wdXQ6IHN0cmluZ1tdKSA9PiB7XG4gICAgICAgIGNvbnN0IG91dHB1dCA9IGlucHV0LmpvaW4oJ8KnciAnKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgbG9nIG1lc3NhZ2VzIGVuZCB3aXRoIGEgcGVyaW9kLlxuICAgICAgICBpZiAoWycuJywgJyEnLCAnPyddLmluY2x1ZGVzKG91dHB1dC5jaGFyQXQoLTEpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGAke291dHB1dH0uYDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvZyBpbmZvcm1hdGlvbiBtZXNzYWdlcy5cbiAgICAgKiBAcGFyYW0gey4uLnN0cmluZ30gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGxvZy5cbiAgICAgKi9cbiAgICBwdWJsaWMgaW5mbyA9ICguLi5tZXNzYWdlOiBzdHJpbmdbXSk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlciEubG9nKCdpbmZvJywgdGhpcy5wYXJzZU1lc3NhZ2UobWVzc2FnZSksIHtcbiAgICAgICAgICAgIG5hbWVzcGFjZTogdGhpcy5nZXROYW1lc3BhY2UoKVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9nIHdhcm5pbmcgbWVzc2FnZXMuXG4gICAgICogQHBhcmFtIHsuLi5zdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBsb2cuXG4gICAgICovXG4gICAgcHVibGljIHdhcm4gPSAoLi4ubWVzc2FnZTogc3RyaW5nW10pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5sb2dnZXIhLmxvZygnd2FybicsIHRoaXMucGFyc2VNZXNzYWdlKG1lc3NhZ2UpLCB7XG4gICAgICAgICAgICBuYW1lc3BhY2U6IHRoaXMuZ2V0TmFtZXNwYWNlKClcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvZyBlcnJvciBtZXNzYWdlcy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZyB8IEVycm9yIHwgYW55fSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gbG9nLlxuICAgICAqL1xuICAgIHB1YmxpYyBlcnJvciA9IChtZXNzYWdlOiBzdHJpbmcgfCBFcnJvciB8IGFueSk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlciEubG9nKCdlcnJvcicsIG1lc3NhZ2UsIHtcbiAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHRoaXMuZ2V0TmFtZXNwYWNlKClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1lc3NhZ2Uuc3RhY2spIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyIS5lcnJvcihcbiAgICAgICAgICAgICAgICBgJHttZXNzYWdlLnN0YWNrLnNwbGl0KCdcXG4nKVswXSAhPT0gbWVzc2FnZS50b1N0cmluZygpID8gYCR7bWVzc2FnZS50b1N0cmluZygpfVxcbmAgOiAnJ30ke21lc3NhZ2Uuc3RhY2t9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubG9nZ2VyIS5lcnJvcihtZXNzYWdlLnRvU3RyaW5nKCkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2cgdmVyYm9zZSBtZXNzYWdlcy5cbiAgICAgKiBAcGFyYW0gey4uLnN0cmluZ30gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGxvZy5cbiAgICAgKi9cbiAgICBwdWJsaWMgdmVyYm9zZSA9ICguLi5tZXNzYWdlOiBzdHJpbmdbXSk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlciEubG9nKCd2ZXJib3NlJywgdGhpcy5wYXJzZU1lc3NhZ2UobWVzc2FnZSksIHtcbiAgICAgICAgICAgIG5hbWVzcGFjZTogdGhpcy5nZXROYW1lc3BhY2UoKVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9nIGRlYnVnIG1lc3NhZ2VzLlxuICAgICAqIEBwYXJhbSB7Li4uc3RyaW5nfSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gbG9nLlxuICAgICAqL1xuICAgIHB1YmxpYyBkZWJ1ZyA9ICguLi5tZXNzYWdlOiBzdHJpbmdbXSk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlciEubG9nKCdkZWJ1ZycsIHRoaXMucGFyc2VNZXNzYWdlKG1lc3NhZ2UpLCB7XG4gICAgICAgICAgICBuYW1lc3BhY2U6IHRoaXMuZ2V0TmFtZXNwYWNlKClcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvZyBzaWxseSBtZXNzYWdlcy5cbiAgICAgKiBAcGFyYW0gey4uLnN0cmluZ30gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGxvZy5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2lsbHkgPSAoLi4ubWVzc2FnZTogc3RyaW5nW10pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5sb2dnZXIhLmxvZygnc2lsbHknLCB0aGlzLnBhcnNlTWVzc2FnZShtZXNzYWdlKSwge1xuICAgICAgICAgICAgbmFtZXNwYWNlOiB0aGlzLmdldE5hbWVzcGFjZSgpXG4gICAgICAgIH0pO1xuICAgIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBdUJBLElBQWEsU0FBYixNQUFvQjs7Ozs7OztDQU9oQixTQUFpQzs7Ozs7OztDQVFqQyxZQUFtQixRQUFrQixRQUFRLGFBQWdDLENBQUMsR0FBRztFQUM3RSxLQUFLLGFBQWEsT0FBTyxVQUFVO0NBQ3ZDOzs7Ozs7Q0FPQSxhQUF1QixRQUFrQixRQUFRLGFBQWdDLENBQUMsR0FBUztFQUV2RixJQUFLLEtBQUssVUFBbUIsQ0FBQyxLQUFLLE9BQVEsUUFBUTtFQUVuRCxLQUFLLFNBQVUsUUFBUSxhQUFhO0dB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