UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

258 lines (257 loc) 9.65 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LogItem = exports.LogItemLevel = void 0; const CreatorToolsHost_1 = __importDefault(require("../app/CreatorToolsHost")); const AppServiceProxy_1 = __importDefault(require("./AppServiceProxy")); const Utilities_1 = __importDefault(require("./Utilities")); const ste_events_1 = require("ste-events"); var LogItemLevel; (function (LogItemLevel) { LogItemLevel[LogItemLevel["debug"] = 0] = "debug"; LogItemLevel[LogItemLevel["verbose"] = 1] = "verbose"; LogItemLevel[LogItemLevel["message"] = 2] = "message"; LogItemLevel[LogItemLevel["error"] = 3] = "error"; LogItemLevel[LogItemLevel["important"] = 4] = "important"; LogItemLevel[LogItemLevel["operationStarted"] = 10] = "operationStarted"; LogItemLevel[LogItemLevel["operationEnded"] = 11] = "operationEnded"; })(LogItemLevel || (exports.LogItemLevel = LogItemLevel = {})); class LogItem { level; message; created; operId; category; context; static alertFunction; constructor(message, level, context, category) { this.level = level; this.message = message; this.created = new Date(); this.context = context; this.category = category; if (this.level === LogItemLevel.operationStarted) { this.operId = Log.items.length; } } } exports.LogItem = LogItem; class Log { static _suppressedLogs = {}; static _log = []; static _onItemAdded = new ste_events_1.EventDispatcher(); static get items() { return Log._log; } static get onItemAdded() { return this._onItemAdded.asEvent(); } static message(message, context, category) { this.log(message, LogItemLevel.message, context, category); } static important(message, context, category) { this.log(message, LogItemLevel.important, context, category); } static verbose(message, context, category) { this.log(message, LogItemLevel.verbose, context, category); } static error(message, context, category) { this.log(message, LogItemLevel.error, context, category); } static unexpectedUndefined(token) { Log.fail("Unexpected undefined condition found." + (token ? " (" + token + ")" : "")); } static unexpectedIsDisposed(token) { Log.fail("Unexpected usage of a disposed object." + (token ? " (" + token + ")" : "")); } static throwIsDisposed(token) { this.unexpectedIsDisposed(token); throw new Error("Unexpected usage of a disposed object." + (token ? " (" + token + ")" : "")); } static throwUnexpectedUndefined(token) { this.unexpectedUndefined(token); throw new Error("Unexpected undefined condition found." + (token ? " (" + token + ")" : "")); } static unexpectedNull(token) { Log.fail("Unexpected null condition found." + (token ? " (" + token + ")" : "")); } static unexpectedContentState(token) { Log.fail("Unexpected state of content." + (token ? " (" + token + ")" : "")); } static unexpectedState(token) { Log.fail("Unexpected state of internal variables." + (token ? " (" + token + ")" : "")); } static unexpectedArguments(token) { Log.fail("Unexpected arguments found." + (token ? " (" + token + ")" : "")); } static log(message, level, context, category) { if (typeof message !== "string") { if (message.message) { message = message.message; } else { message = JSON.stringify(message); } } const logItem = new LogItem(message, level, context, category); this._log.push(logItem); Log._onItemAdded.dispatch(this, logItem); // Output to browser console for visibility during debugging // In browser context, this helps developers see logs in DevTools // eslint-disable-next-line @typescript-eslint/no-explicit-any if (typeof globalThis.window !== "undefined") { const prefix = context ? `[${context}] ` : ""; const fullMessage = prefix + message; switch (level) { case LogItemLevel.error: console.error(fullMessage); break; case LogItemLevel.important: console.warn(fullMessage); break; case LogItemLevel.message: // Only message level goes to console.log by default console.log(fullMessage); break; // verbose and debug are only shown in console when ?debug=true case LogItemLevel.verbose: case LogItemLevel.debug: if (Utilities_1.default.isDebug) { console.log(fullMessage); } break; // operation started/ended don't need console output } } return logItem.operId; } static debug(message, context) { this.log(message, LogItemLevel.debug, context); // Console output is now handled in the log() method for browser contexts. // In Node.js contexts (window undefined), only print directly if there are // no event subscribers — otherwise the subscriber (e.g. LocalEnvironment) // already handles console output and we'd get duplicate lines. // eslint-disable-next-line @typescript-eslint/no-explicit-any if (typeof globalThis.window === "undefined" && this._onItemAdded.count === 0) { console.log(message); } } static assertIsInt(number, message) { if (number !== Math.round(number)) { Log.debugAlert("Unexpectedly found number " + number + " is not an integer. " + (message ? message : "")); } } static getStack() { let stack = ""; try { throw new Error(); } catch (e) { stack = e.stack ? e.stack : ""; } const startOfLog = stack.lastIndexOf("\n at Log."); if (startOfLog >= 0) { stack = stack.substring(startOfLog); } return stack; } static assert(condition, message, context) { if (!condition) { if (!message) { Log.debugAlert("Assertion failed. - " + this.getStack(), context); } else { Log.debugAlert("Assertion failed: " + message + " - " + this.getStack(), context); } } } static assertDefined(obj, message) { if (!obj) { Log.unexpectedUndefined("LAD." + (message ? message : "")); debugger; } return obj !== undefined && obj !== null; } static fail(message, context) { Log.debugAlert("Failure case: " + message, context); } static unsupportedToken(token, context) { if (Utilities_1.default.isDebug) { Log.debugAlert("Unsupported token: " + token, context); } } static unexpectedError(errorMessage, context) { if (Utilities_1.default.isDebug) { Log.debugAlert(errorMessage, context); } throw new Error(errorMessage); } static debugAlert(message, context) { if (Log._suppressedLogs["all"] === true) { return; } Log.debug(message, context); if (!Utilities_1.default.isDebug) { return; } let stack = ""; let header = ""; const err = new Error(); if (err.stack !== undefined) { stack = err.stack; } if (!stack || stack === "") { stack = this.getStack(); } let i = stack.lastIndexOf("at Function."); if (i >= 0) { i = stack.indexOf("at ", i + 1); if (i >= 4) { // i -= 4; stack = stack.substring(i, stack.length); const nextSpace = stack.indexOf(" ", 8); if (nextSpace >= 0) { header = "=== " + stack.substring(7, nextSpace) + " ===\n\n"; } } } const wholeMessage = header + message + "\n" + stack; if (LogItem.alertFunction) { let stackTrim = stack; if (stackTrim.length > 80) { stackTrim = stackTrim.substring(0, 80); } LogItem.alertFunction(message + "\n\n" + stackTrim); // debugger; return; } else if (AppServiceProxy_1.default.hasAppService && CreatorToolsHost_1.default.isWeb) { // @ts-ignore alert(header + message + "\n\n" + stack); debugger; return; // @ts-ignore } else if (typeof window === "undefined") { console.log(header + message + "\n\n" + stack); return; } // @ts-ignore const val = prompt(wholeMessage, "b to break, s to suppress, a to suppress all"); if (val === "s") { Log._suppressedLogs[message] = true; return; } else if (val === "b") { debugger; } else if (val === "a") { Log._suppressedLogs["all"] = true; } } } exports.default = Log;