@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
258 lines (257 loc) • 9.65 kB
JavaScript
;
// 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;