Files
2025-01-04 00:34:03 +01:00

61 lines
2.5 KiB
JavaScript

import {COMPATIBILITY_MODES} from "../constants.mjs";
/**
* The messages that have been logged already and should not be logged again.
* @type {Set<string>}
*/
const loggedCompatibilityWarnings = new Set();
/**
* Log a compatibility warning which is filtered based on the client's defined compatibility settings.
* @param {string} message The original warning or error message
* @param {object} [options={}] Additional options which customize logging
* @param {number} [options.mode] A logging level in COMPATIBILITY_MODES which overrides the configured default
* @param {number|string} [options.since] A version identifier since which a change was made
* @param {number|string} [options.until] A version identifier until which a change remains supported
* @param {string} [options.details] Additional details to append to the logged message
* @param {boolean} [options.stack=true] Include the message stack trace
* @param {boolean} [options.once=false] Log this the message only once?
* @throws An Error if the mode is ERROR
*/
export function logCompatibilityWarning(message, {mode, since, until, details, stack=true, once=false}={}) {
// Determine the logging mode
const modes = COMPATIBILITY_MODES;
const compatibility = globalThis.CONFIG?.compatibility || {
mode: modes.WARNING,
includePatterns: [],
excludePatterns: []
};
mode ??= compatibility.mode;
if ( mode === modes.SILENT ) return;
// Compose the message
since = since ? `Deprecated since Version ${since}` : null;
until = until ? `Backwards-compatible support will be removed in Version ${until}`: null;
message = [message, since, until, details].filterJoin("\n");
// Filter the message by its stack trace
const error = new Error(message);
if ( compatibility.includePatterns.length ) {
if ( !compatibility.includePatterns.some(rgx => rgx.test(error.message) || rgx.test(error.stack)) ) return;
}
if ( compatibility.excludePatterns.length ) {
if ( compatibility.excludePatterns.some(rgx => rgx.test(error.message) || rgx.test(error.stack)) ) return;
}
// Log the message
const log = !(once && loggedCompatibilityWarnings.has(error.stack));
switch ( mode ) {
case modes.WARNING:
if ( log ) globalThis.logger.warn(stack ? error : error.message);
break;
case modes.ERROR:
if ( log ) globalThis.logger.error(stack ? error : error.message);
break;
case modes.FAILURE:
throw error;
}
if ( log && once ) loggedCompatibilityWarnings.add(error.stack);
}